Access JumpStart 2.0 | Blog

A Rapid Development Framework for Microsoft Access

I wrote a couple of times last week about custom tags and creating a class that could store custom tag information. I am further refining the requirements of the class using a real world example of something I will be using it for.

I’m bringing in an enum here that is being used inside the Form Resizing class that will end up utilizing these custom form fields. Here is the enum code:

Private Enum CtlPositionTag   ' for storing/retrieving positioning data out of Control "Tag" property
   FromLeft = 0
   FromTop
   ControlWidth
   ControlHeight
   ControlFontSize
End Enum

An enum is creating a set of numeric values from string names. I setup this sub in the class to print out the enum:

'This is inside the Form Resizing class module
Public Sub PrintCtlPositionTagEnum()
    Debug.Print CtlPositionTag.FromLeft
    Debug.Print CtlPositionTag.FromTop
    Debug.Print CtlPositionTag.ControlWidth
    Debug.Print CtlPositionTag.ControlHeight
    Debug.Print CtlPositionTag.ControlFontSize
End Sub

And in the immediate window I can setup and print the enum like this:

'This is inside the Immediate Window
Set frClass = New HAL_FormResizeCls: frClass.PrintCtlPositionTagEnum
 0 
 1 
 2 
 3 
 4 

So you can see the enumeration simply starts at 0 (because FromLeft was set to 0 in the definition) and then by default VBA just adds 1 for each additional defined element.

This is used to pull an element from the control’s tag property, split it into an array, and then access that particular array element.

I would like for this new custom tag class to simplify the process. So what is the process? How is the existing tag being set and called? With the following code:

'This is the associated code that is setting the ctl.Tag property and populating it with a string
   ' Now store the original size and location values for each control
   For Each ctl In frm.Controls
      ctlLeft = ctl.Left
      ctlTop = ctl.Top
      ctlWidth = ctl.Width
      ctlHeight = ctl.Height
      Select Case ctl.ControlType
         Case acLabel, acCommandButton, acTextBox, acComboBox, acListBox, acTabCtl, acToggleButton
            ctlOrigFontSize = ctl.FontSize
         Case acSubform
            If DoSubForms Then
               On Error Resume Next
               Set SubForm = ctl.Form
               errorNum = Err.Number
               On Error GoTo ProcError
               If errorNum <> 0 Then GoTo NextTag  ' must be a subReport so skip it
               SaveControlPositions SubForm  ' recursively calling self here
            End If
            ctlOrigFontSize = 0
         Case Else
            ctlOrigFontSize = 0
      End Select
      ctl.Tag = RsBeg & ctlLeft & ":" & ctlTop & ":" & ctlWidth & ":" & ctlHeight & ":" & ctlOrigFontSize & RsEnd
NextTag: Next


'This is the associated code from inside the class that is reading the information using ctl.Tag
' property.
         'Split the Tag property into an array
         TagStr = Mid(ctl.Tag, InStr(ctl.Tag, RsBeg) + 5, InStr(ctl.Tag, RsEnd) - 6)
         tagArray = Split(TagStr, ":")
         ctl.Move ScaleFactor * (CDbl(tagArray(CtlPositionTag.FromLeft))), _
            ScaleFactor * (CDbl(tagArray(CtlPositionTag.FromTop))), _
            ScaleFactor * (CDbl(tagArray(CtlPositionTag.ControlWidth))), _
            ScaleFactor * (CDbl(tagArray(CtlPositionTag.ControlHeight)))

And now my idea from a couple of days ago has evolved a bit to become something like this:

Dim ctlPositions As CustomCtlTags
Set ctlPositions = New CustomCtlTags

ctlPositions.Set ctl, "FromLeft", ctl.Left
Debug.Print ctlPositions.Get(ctl, "FromLeft")

This syntax feels simple and usable to me. I think it could really simplify the existing code. So now I get to sleep on it once more and see what happens. A quick note, it does feel a little clunky having to use the ctl as a parameter and I’d love some solution as well that would have some kind of autocomplete, but maybe that would be for another iteration, if it would even be possible.