VBA - Loop through Controls on a form and read the value - vba

I would like to loop through controls on a form and read the value. However the Value and Checked properties are not available. My question is, how can I read the value of a control (in this case a checkbox) when I loop through them?
Dim Ctrl as Control
For Each Ctrl In frmMaintenance.Controls
If Left(Ctrl.Name, 7) = "chkType" And **Ctrl.Value = True** Then
End if
Next Ctrl

loop through the controls and check the TypeName.
Dim c As Control
For Each c In Me.Controls
If TypeName(c) = "CheckBox" Then
MsgBox c.Value
End If
Next

TypeName will work, but at the end of the day it's a string comparison.
The actual syntax for strongly-typed type checks in VBA goes like this:
TypeOf [object] Is [Type]
So:
Dim ctrl As Control
For Each ctrl In Me.Controls
If TypeOf ctrl Is MSForms.CheckBox Then
Debug.Print TypeName(ctrl), ctrl.Name, ctrl.Value
End If
Next
Now, somewhat awkwardly the MSForms library is making OptionButton and CheckBox implement the same interface (not all that surprising actually), so the above condition will be True for both types of controls; you can filter out the OptionButton with another type check:
If TypeOf ctrl Is MSForms.CheckBox And Not TypeOf ctrl Is MSForms.OptionButton Then
Arguably, using TypeName is simpler, at least in this case where MSForms is being annoying. But you have to know about TypeOf ... Is when you start needing to do type checks in VBA.

Related

Error using "MSForms.Control" type of variable

I have been trying to run this code to get the caption of each control (a combobox in this example) on my form. But it keeps telling me "type mismatch". Please help. Thank you.
Private Sub Command266_Click()
Dim ctrl As MSForms.Control
Dim x As Long
x = 0
For Each ctrl In Me.Controls
Select Case True
Case TypeOf ctrl Is MSForms.ComboBox
MsgBox "control caption is" & ctrl.Caption, vbOKOnly, " test"
End Select
Next ctrl
End Sub
"MS Access forms" are not "MSForms". MSForms is a separate UI technology that can be used, for example, to create UI windows for Excel.
You need to use the types Access.Control and Access.ComboBox instead. Unless you messed around with the order of references, you can just refer to them as Control and ComboBox.
In addition, ComboBox controls in Access don't have a Caption property. If you want to get the caption of the label associated with the combobox, you can use the Controls(0) property.
Thus, the following code should work:
Dim ctrl As Control
Dim lbl As Label
For Each ctrl In Me.Controls
Select Case True
Case TypeOf ctrl Is ComboBox
Set lbl = ctrl.Controls(0)
MsgBox "control caption is " & lbl.Caption, vbOKOnly, "test"
End Select
Next ctrl

Word VB, Clear all checked fields

i have a word with 15+ VB forms and 20-50 CheckBoxes in each.
How do i clear (if they are cheched) all the CheckBoxes in active form w/o having to write the name of each CheckBox?
Thank you
This code will do the job. It must be placed in the UserForm's code sheet.
Private Sub ClearCheckBoxes()
Dim Ctl As MSForms.Control
For Each Ctl In Me.Controls
If TypeName(Ctl) = "CheckBox" Then Ctl.Value = False
Next Ctl
End Sub

Setting same SelectedIndex value for multiple combobox

I have a form where i have 23 Comboboxes. Writing SelectedIndex=-1 for every combobox will definitely work but i want to know whether there's any other way of doing it as done in below given example. ?
For Each ctl As Control In (GroupBox1.Controls)
If TypeOf ctl Is TextBox Then
ctl.Text = ""
End If
Next
i tried this,
If TypeOf ctl Is ComboBox Then
ctl.selectedIndex=-1
End If but it doesn't works. Please help me out.
In your example your ctl variable is a Control and not a Combobox so it does not have the SelectIndex property - though you could have casted it back with DirectCast(ctl, Combobox).
For Each ctl As Control In (GroupBox1.Controls)
If TypeOf ctl Is Combobox Then
DirectCast(ctl, Combobox).SelectedIndex = -1
End If
Next
Or create a loop of type specific control for your loop. No need to check type here.
Dim cbs = GroupBox1.Controls.OfType(Of Combobox)()
For Each cb In cbs
cb.SelectedIndex = -1
Next

How to change multiple comboboxes with little code

Here's my problem.
I have a userform with 10 comboBoxes.
Instead of Select Case al those comboboxes one by one is
there a smart way to change multiple combobox properties such as backcolor or fontcolor?
So for example:
Sub ChangeMultipleComboBoxes()
Dim comboB as control
For Each comboB In Me.Controls
If TypeName(comboB) = "ComboBox" Then
comboB.BackColor = vbRed
End If
Next comboB
End Sub
The problem is that for comboB I can't seem to find any properties for changing it's backcolor or whatsoever.
Can someone help me please?
As Zaider says, your code works. You just don't get the IntelliSense for the ComboBox-specific properties when it's declared as a Control, even though you can use the properties as you've done in your code. (Note that properties common to all controls, e.g., Caption are available.)
To get the Intellisense for all ComboBox properties, re-declare the Control as a ComboBox once you've determined that's what it is:
Private Sub UserForm_Click()
Dim ctl As MSForms.Control
Dim comboB As MSForms.ComboBox
For Each ctl In Me.Controls
If TypeName(ctl) = "ComboBox" Then
're-declare it as a ComboBox
Set comboB = ctl
'Now you get IntelliSens
comboB.BackColor = vbRed
End If
Next ctl
End Sub

setting button enabled state

I have a simple vb 2010 form that I want to be able to set the enabled stated of all buttons on.
I have made similar functions for checkboxes and numericalUpDown controls that function as required, but for buttons the function does not seem to operate correctly.
Private Sub setButtonsState(ByVal state As Boolean)
Dim cControl As Control
For Each cControl In Me.Controls
If (TypeOf cControl Is Button) Then
cControl.Enabled = state
End If
Next cControl
End Sub
Which is called like so: setButtonsState(True)
This doesnt seem to have any effect at all with buttons, though buttonName.Enabled = True works OK...
Im pretty much what you'd call a noob at VB, so anyone help me out?
Ta
Unless all of your buttons belong directly to the Form this is run in, then they won't be accessed because this doesn't cruise down through the control tree to get to them. A slightly different approach might be a more recursive method:
Private Sub setButtonsState(ByVal controls as System.Windows.Forms.Control.ControlCollection, ByVal state as Boolean)
For Each ctrl as Control in controls
If (ctrl.HasChildren) Then setButtonsState(ctrl.Controls, state)
If (TypeOf ctrl Is Button) Then ctrl.Enabled = state
Next
End Sub
It works on my form. Are you sure you are setting state to a true value? you many want to dim a variable called "state" inside the subroutine just to test it. Set state to true and disable all of your buttons.
Try to retrieve the count of controls returned. To make sure you are correctly referencing the controls.
Demonstrating set boolean to True for testing:
*Dim state As Boolean = True*
Dim cControl As Control
For Each cControl In Me.Controls
If (TypeOf cControl Is Button) Then
cControl.Enabled = state
End If
Next cControl
Check the count of controls:
For Each cControl In (Your Form Name Ex. FrmMain1).Controls
If (TypeOf cControl Is Button) Then
cControl.Enabled = state
*debug.writeline(cControl.Name)*
End If
Next cControl
I would suggest you avoid recursion, if possible. Below approach has a much better debug-ability.
First, Linearise ControlCollection tree into array of Control - generic extension method, no recursion, LINQ or GetNextControl.
Then you can write like this:
Private Sub setButtonsState(ByVal controls As ControlCollection, ByVal state As Boolean)
For Each ctrl As Control In controls.GetAllControlsOfType(Of Button)()
ctrl.Enabled = state
Next
End Sub