I have a userform with 2 dropdowns which I normally not need so I build a checkbox and hide the dropdown menu and the text label. The checkbox is checked by default. But the dropdown and label isn't hidden when I start the UserForm. When I manually uncheck and check the checkbox after UserForm is started it's working. So I dont know why the checkbox seems to work but I need to uncheck/check it manually after every start of the UserForm.
I think I have to do something at the initial start of the userform?
Private Sub SortCheckBox(blnChecked As Boolean)
Private Sub CheckBox1_Click()
ActiveDocument.Bookmarks("KurbeitragKinder").Range.Font.Hidden =
CheckBox1.Value
If CheckBox1.Value = True Then
Label8.Enabled = False
Label8.Visible = False
Label9.Enabled = False
Label9.Visible = False
ComboBox6.Enabled = False
ComboBox6.Visible = False
ComboBox7.Enabled = False
ComboBox7.Visible = False
Else
Label8.Enabled = True
Label8.Visible = True
Label9.Enabled = True
Label9.Visible = True
ComboBox6.Enabled = True
ComboBox6.Visible = True
ComboBox7.Enabled = True
ComboBox7.Visible = True
End If
End Sub
The state of the controls on a UserForm
when it is first displayed will be, by default, whatever the design-time state is; let's call this the "default state".
You can define what that default state is by configuring each control's individual properties, using the designer's properties toolwindow (F4).
If the form's default instance is shown, then its state will be preserved between calls:
UserForm1.Show
...unless the instance gets reset - which can easily happen if you Unload
that form, or if the user clicks the red "X" button to close it: the instance is destroyed, and since forms have a predeclared ID (aka default instance), the object is automatically re-created the next time it's referenced - with whatever the default (design-time) state is. If you handle the QueryClose
event and programmatically Hide
the form when CloseMode
is VbQueryClose.vbFormControlMenu
(and set the Cancel
parameter to True
, to prevent destroying the form instance and its state), then the state will be preserved ...and this can lead to unexpected or inconsistent behavior.
The solution is to make sure you always display a fresh new instance of the form, instead of the default one:
With New UserForm1
.Show
End With
That way the form's state is guaranteed to always be the default/intended design-time state every time it's displayed, and you can access the form's state between .Show
and End With
. All you need to do is to handle QueryClose
and cancel the form's destruction when the user clicks the "form control menu" aka "the X button".
Initializing a form will raise the Initialize
event; if you're using the form's default instance (i.e. UserForm1.Show
), then you can't really control exactly when this happens, but if you show a fresh new instance every time (i.e. With New UserForm1
), then you are certain that this event will be raised exactly once, every time you need to show the form.
The Initialize
event is raised as soon as the object is created, and that happens before the first member call is made against it (i.e. when the New UserForm1
returns, the event has already executed). If you need to check a box and then initialize the form accordingly, then you might want to handle the Activate
event instead, which will be raised when the form is actually displayed (i.e. when the .Show
method is called):
With New UserForm1 'UserForm_Initialize runs
.CheckBox1.Value = foo 'form state is accessible here
.Show 'UserForm_Activate runs
'UserForm_QueryClose runs
foo = .CheckBox1.Value 'form state is accessible here
End With 'UserForm_Terminate runs
Looks like you want to run that CheckBox1_Click
handler before the form is shown - problem is, event handlers aren't Public
, and you don't want them to be.
The solution is to pull the logic into a Public Sub
, invoke that procedure from the client code, and invoke it from the checkbox':
Public Sub InitializeFormState()
Dim isChecked As Boolean
isChecked = CheckBox1.Value
ActiveDocument.Bookmarks("KurbeitragKinder") _
.Range.Font.Hidden = isChecked
Label8.Enabled = isChecked
Label8.Visible = isChecked
Label9.Enabled = isChecked
Label9.Visible = isChecked
ComboBox6.Enabled = isChecked
ComboBox6.Visible = isChecked
ComboBox7.Enabled = isChecked
ComboBox7.Visible = isChecked
End Sub
Private Sub CheckBox1_Click()
InitializeFormState
End Sub
And now your client code can look like this:
With New UserForm1
.InitializeFormState
.Show
'consume form state here
End With
Or, you can invoke InitializeFormState
from the form's Initialize
or Activate
handler, as needed:
Private Sub UserForm_Initialize()
InitializeFormState
End Sub
Or
Private Sub UserForm_Activate()
InitializeFormState
End Sub
In which case the procedure should probably be made Private
, and there's no need to invoke it from the client code before the .Show
method.