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.
Trackbacks/Pingbacks