Windows 10 Pro 64, Office 365 Excel vba
ClassCounter is a class that operates on a Long value it stores internally and then displays that value in a TextBox in an active UserForm. I want to be able to assign the TextBox to the ClassCounter object dynamically, so that I can use the same class to instantiate a number of objects, each of which references its own TextBox in the same UserForm.
It has the following private members declared at the class level:
Private mctrLinked As ClassCounter
Private mnCount As Long
Private mtbxDisplay As TextBox
The Initialize subroutine makes the connection between displayTextBox (the textbox used to display the value) and the object. linkCounter provides the opportunity to link to another object of the same class and fire off the same operation on it in a daisychain fashion.
Public Sub Initialize(ByRef displayTextBox As msforms.TextBox, Optional linkCounter As ClassCounter = Nothing)
Const kstrMethodName As String = "Initialize"
Set mtbxDisplay = displayTextBox
Set mctrLinked = linkCounter
Clear
End Sub ' Initialize
The class is instantiated in another class, as follows:
Private mobjAllBlankCounter As New ClassCounter
Private mobjAllEnteredCounter As New ClassCounter
Private mobjAllFoundCounter As New ClassCounter
Private mobjAllIssuesCounter As New ClassCounter
...
And the connection between the TextBox and the ClassCounter object is established by calling the Initialize subroutine in this way:
Public Sub InitializeAllCounters()
With mufMCP
mobjAllBlankCounter.Initialize .tbxBlankCountAll
mobjAllEnteredCounter.Initialize .tbxEnteredCountAll
mobjAllFoundCounter.Initialize .tbxFoundCountAll
mobjAllIssuesCounter.Initialize .tbxIssuesCountAll
End With
End Sub ' InitializeAllCounters
where mufMCP is the UserForm in which the TextBoxes are defined.
Ultimately, the Increment function (and others like it) will operate on the stored variable and then display it in the referenced TextBox as follows:
Public Sub Increment()
Const kstrMethodName As String = "Increment"
If (mtbxDisplay Is Nothing) Then
Err.Raise gknErrNoControlForCounter, mkstrModuleName & "." & kstrMethodName, "Attempt to Increment Counter with no associated control."
Else
mnCount = mnCount + 1
mtbxDisplay.Text = CStr(mnCount)
If (Not (mctrLinked Is Nothing)) Then
mctrLinked.Increment
End If
End If
End Sub ' Increment
The problem I'm having is in the Initialize
subroutine where I attempt to assign the value of the TextBox argument to the local variable. Instead of assigning a reference to the TextBox itself, the right side of the assignment is evaluating to the TextBox's default value, which is its Text
property. As a result, I get a type mismatch error.
How can I get it to evaluate to a reference to the TextBox itself? I've spent a couple of days searching for the answer and found several sources that said that using ByRef displayTextBox As msforms.TextBox
to define the parameter would do the trick, but I'm still getting the control's default value.
As FaneDuru writes, TextBox
and MsForms.TextBox
are two different object types. A TextBox
is a textbox (Form Control, not Active X Control) placed on a sheet. A MsForms.TextBox
is a textbox places on a user form.
Bad thing (1): The name "Form Control" related to sheet controls is misleading, it is not the same as a control placed on a user form.
Bad thing (2): As the Form Control Textbox is no longer available from the Developer menu, it is not easy to proof. If you are interested: You can still create them using VBA.
Dim tb1 As TextBox
Set tb1 = ActiveSheet.TextBoxes.Add(255, 243, 73.5, 22.5)
Dim tb2 As msforms.TextBox
UserForm1.Show False
Set tb2 = UserForm1.TextBox1
Checking both objects in the Locals window of the VBA editor, type for both is displayed as "Textbox/Textbox". However, when you look at the properties of the objects, you see that they are different.
So declare all your (userform) controls with the suffix msforms
to be sure that you are dealing with the right object types.