Reputation: 19628
I'm trying to iterate through the controls on a form to display the ControlSource properties of those controls that support ControlSource.
I've found it relatively easy to identify the controls that have ControlSource properties. The problem is in accessing the property for those controls. A generic Control object does not have a ControlSource property. If I was using another language I would simply cast a control that is a listbox to a ListBox object, for example, to access the ControlSource property. But my understanding is that in VBA there is no type inheritance so I can't cast one type of object to another.
So how do I access the ControlSource properties of those controls that support the property?
Here's my code so far:
Private Sub IterateControlsOnForm()
Dim frm As Form, formName As String
' The only controls that have a ControlSource property are either
' BoundObjectFrame controls or ListBox controls.
Dim ctrl As Control
Dim boundObjectFrame As boundObjectFrame, listBoxCtrl As listBox
Dim boundObjectFrameTypes() As String, listBoxTypes() As String
Dim ctrlType As String
formName = "MAINFORM"
' Useful way of populating a string array - use Split function.
' Array function only works with Variants.
boundObjectFrameTypes = _
Split("CheckBox,ComboBox,CustomControl,GroupLevel", ",")
listBoxTypes = Split("OptionButton,OptionGroup,TextBox,TextBox", ",")
' Assumes form is open.
Set frm = Forms(formName)
For Each ctrl In frm.Controls
' Ignore controls that do not have a ControlSource property.
ctrlType = TypeName(ctrl)
If IsStringInArray(ctrlType, boundObjectFrameTypes) Then
' **** FOLLOWING LINE FAILS ****
Set boundObjectFrame = ctrl
Debug.Print boundObjectFrame.Name & "(" & ctrlType & ") " & _
"ControlSource Property: " & boundObjectFrame.ControlSource
ElseIf IsStringInArray(ctrlType, listBoxTypes) Then
' **** FOLLOWING LINE FAILS ****
Set listBoxCtrl = frm.Controls(ctrl.Name)
Debug.Print listBoxCtrl.Name & "(" & ctrlType & ") " & _
"ControlSource Property: " & listBoxCtrl.ControlSource
End If
Next ctrl
End Sub
I've tried two methods of converting a generic Control object to a more specific control that has a ControlSource property. See the two comments "** FOLLOWING LINE FAILS **".
Upvotes: 2
Views: 15246
Reputation: 91316
How about using Object?
Private Sub IterateControlsOnForm()
Dim frm As Form, formName As String
' The only controls that have a ControlSource property are either
' BoundObjectFrame controls or ListBox controls.
Dim ctrl As Control
Dim boundObjectFrame As Object, listBoxCtrl As Object
Dim boundObjectFrameTypes As String, listBoxTypes As String
Dim ctrlType As String
formName = "MAINFORM"
' Useful way of populating a string array - use Split function.
' Array function only works with Variants.
boundObjectFrameTypes = _
",CheckBox,ComboBox,CustomControl,GroupLevel"
listBoxTypes = ",OptionButton,OptionGroup,TextBox,TextBox"
' Assumes form is open.
Set frm = Forms(formName)
For Each ctrl In frm.Controls
' Ignore controls that do not have a ControlSource property.
ctrlType = TypeName(ctrl)
If InStr(boundObjectFrameTypes, "," & ctrlType) Then
Set boundObjectFrame = ctrl
Debug.Print boundObjectFrame.Name & "(" & ctrlType & ") " & _
"ControlSource Property: " & boundObjectFrame.ControlSource
ElseIf InStr(listBoxTypes, "," & ctrlType) Then
Set listBoxCtrl = frm.Controls(ctrl.Name)
Debug.Print listBoxCtrl.Name & "(" & ctrlType & ") " & _
"ControlSource Property: " & listBoxCtrl.ControlSource
End If
Next ctrl
End Sub
With VBA, you can also use On Error Resume Next, though I agree it is generally best to avoid errors.
formName = "MAINFORM"
Set frm = Forms(formName)
For Each ctrl In frm.Controls
On Error Resume Next
Debug.Print ctrl.Name _
& " ControlSource Property: " & ctrl.ControlSource
If Err.Number = 438 Then
Err.Clear
End If
Next
Upvotes: 2