Search code examples
vbavisio

How to Store / Groups together / manipulate Floating point Constants in VBA


I am using Visio-2016 VBA. In my Main Module I have to draw approx ten rectangle shapes per Visio page. 32 pages are iterated in a For Loop. Various properties for Rectangles also need to be set for each rectangle such as Border or borderless.

DrawRectangle() function needs to have rectangle's co-ordinate pairs in the form of X1, Y1, X2, Y2 My values are in Double(double-precision floating-point) CONSTANTS.

I have tried my best to store and group these co-ordinate pairs as constants but no avail.

Sample co-ordinate pair for one rectangle shape is:

X1 = 3.179133858

Y1 = 1.181102362

X2 = 6.131889764

Y2 = 1.57480315

I tried following things to group co-ordinate pairs for at least ten rectangles, no success: - Plain list of constants at top of Main sub (don't want it) - Enumerated list (works only for Long data types) - Array or two dimensional array (inconvenient, set/return val by Array index only) - Type ... End Type (works but Error when I create a collection/dictionary)

Here is portion of code from a Class I am trying to create

Public Type CoordRectType
          X1 As Double
          Y1 As Double
          X2 As Double
          Y2 As Double
End Type

Public RectLftBtm As CoordRectType
Public RectLftTop As CoordRectType
Public colRect As Collection

Sub TestIt()
' Create instances of UDT as required
' LEFT-BOTTOM BarCode     [vsoShape1]
      RectLftBtm.X1 = 3.179133858
      RectLftBtm.Y1 = 1.181102362
      RectLftBtm.X2 = 6.131889764
      RectLftBtm.Y2 = 1.57480315

' LEFT-TOP  BarCode     [vsoShape2]
      RectLftTop.X1 = 3.179133858
      RectLftTop.Y1 = 1.181102362
      RectLftTop.X2 = 6.131889764
      RectLftTop.Y2 = 1.57480315

colRect.Add RectLftBtm , "LeftBottomRect"   ''' Compiler Error here ''''''
colRect.Add RectLftTop , "LeftTopRect"      ''' Compiler Error here '''''' 

End Sub

''' .... REST OF THE CODE FOR CLASS ......
' ///////////////////////////////////////////

I also tried to replace Collection with Dictionary in above code but same compiler error

I want to store all co-ordinate pairs data preferably as Constants (if not possible than in variables) inside a Class module. From Main sub, I will then set Class properties and call methods in iteration to create rectangle shapes as needed and still my Main Module would be neat and clean

One supplementary question in last: Does a constant of any intrinsic(built-in VBA) data type have same memory usage as a variable of that data type?


Solution

  • You were so close. One way to tackle this problem is to create the rectangle class using the Create/Self methods for self instantiating objects

    This is the rectangle class

    Option Explicit
    
    Private Type Properties
    
        X1                      As Double
        X2                      As Double
        Y1                      As Double
        Y2                      As Double
        ' extend this pattern to include any other parameters relevant to drawing the rectangle
    End Type
    
    Private p                   As Properties
    
    Public Function Create _
    ( _
        ByVal X1 As Double, _
        ByVal Y1 As Double, _
        ByVal X2 As Double, _
        ByVal Y2 As Double _
    ) As Rectangle
    
        With New Rectangle
    
            Set Create = .Self(X1, Y1, X2, Y2)
    
        End With
    
    End Function
    
    Public Function Self _
    ( _
        ByVal X1 As Double, _
        ByVal Y1 As Double, _
        ByVal X2 As Double, _
        ByVal Y2 As Double _
    ) As Rectangle
    
        With p
    
            .X1 = X1
            .Y1 = Y1
            .X2 = X2
            .Y2 = Y2
            ' extend this pattern to include any other parameters relevant to drawing your rectangle
        End With
    
        Set Self = Me
    
    End Function
    
    
    Public Sub Draw()   ' You don't want to provide parameters when you call draw.  This should be done
                        ' when you create your rectangle
    
    ' Put the code to draw the rectangle here
    
    End Sub
    

    You'll note we have included the function for the rectangle to draw itself. You'll see why we have done this later.

    Now we create the pages of rectangles. So in a module include

    Public Function SetupPage1() As Collection
    ' In practise we would probably setup a Page class and register the rectangles with the page class instance
    Dim my_rectangles As Collection
    
        Set my_rectangles = New Collection
    
        With my_rectangles
            .Add Rectangle.Create(3.179133858, 1.181102362, 6.131889764, 1.57480315)
            .Add Rectangle.Create(3.179133858, 1.181102362, 6.131889764, 1.57480315)
            ' etc
    
        End With
    
        Set SetupPage1 = my_rectangles
    
    End Function
    

    And

    Public Function SetupAllPages() As Collection
    
    
    Dim my_pages As Collection
    
       Set my_pages = New Collection
    
       With my_pages
    
            .Add SetupPage1
            .Add SetupPage2
            .Add SetupPage3
            'etc
    
        End With
    
        Set SetupAllPages = my_pages
    
    End Function
    

    And finally, in the same or another module the code to draw the rectangles on all pages.

    Public Sub DrawPages()
    
    Dim PagesToDraw         As Collection
    Dim this_page           As Variant
    Dim this_rectangle      As Variant
    
        Set PagesToDraw = SetupAllPages
    
        For Each this_page In PagesToDraw ' this page takes a collection
    
            For Each this_rectangle In this_page
    
                this_rectangle.Draw
    
            Next
    
        Next
    
    End Sub
    

    With the sub above you can now see why we didn't want our Draw Sub to take parameters, it would mean that we lose the simplicity of the code here.

    The final step is to set the predeclared attribute of the Rectangle class. You can do this by exporting the class to Notepad++ setting the attribute to treu and reimporting. Or by using the '@PredeclaredId attribute offered by the Fantabulous RubberDuck addin.

    Come back here if you get stuck.

    The code above can be polished quite a bit more but I hope that you will now be able to see a way forward.