启动时UserForm中的复选框不起作用

时间:2019-03-25 16:37:00

标签: vba ms-word userform

我有一个带有2个下拉菜单的用户窗体,通常我不需要,因此我建立了一个复选框并隐藏了下拉菜单和文本标签。默认情况下,该复选框处于选中状态。但是,当我启动UserForm时,下拉菜单和标签不会被隐藏。当我手动取消选中并启动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

1 个答案:

答案 0 :(得分:0)

UserForm上的控件第一次显示时的状态默认为设计时状态;我们称其为“默认状态”。

您可以使用设计器的 properties 工具窗口(F4),通过配置每个控件的各个属性来定义默认状态

如果显示表单的默认实例,则其状态将在两次调用之间保留:

UserForm1.Show

...除非实例被重置-如果您Unload将该表单重置,或者如果用户单击红色的“ X”按钮以将其关闭,则很容易发生:实例被销毁,并且由于表单具有一个预先声明的ID(又称默认实例),则该对象在下一次被引用时会自动重新创建-无论其默认(设计时)状态如何。如果您在QueryCloseVbQueryClose.vbFormControlMenu的情况下处理Hide事件并以编程方式CloseMode的形式(并将Cancel参数设置为True,以防止销毁表单实例及其状态),则状态将被保留...这可能导致意外或不一致的行为。

解决方案是确保始终显示表单的新实例,而不是默认实例:

With New UserForm1
    .Show
End With

这样,可以确保每次显示时表单的状态始终是默认/预期的设计时状态,并且您可以在.ShowEnd With之间访问表单的状态。您需要做的就是处理QueryClose并在用户单击“表单控制菜单”或“ X按钮”时取消对表单的破坏。

初始化表单将引发Initialize事件;如果您使用的是表单的默认实例(即UserForm1.Show),那么您将无法真正控制发生的确切时间,但是如果您每次都显示一个新实例(例如With New UserForm1),则您确定每次需要显示表单时,都会触发一次该事件。

创建对象后立即引发Initialize事件,并且该事件在对该对象进行第一个成员调用之前发生(即,当New UserForm1返回时,该事件已经执行)。如果您需要选中一个框,然后相应地初始化表单,那么您可能想处理Activate事件,该事件将在实际显示表单时(即当.Show方法被调用):

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

看起来您想在显示表单之前运行CheckBox1_Click处理程序-问题是,事件处理程序不是Public您不希望它们出现

解决方案是将逻辑放入Public Sub中,从客户端代码中调用该过程,从复选框中调用它:

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

现在您的客户端代码可以如下所示:

With New UserForm1
    .InitializeFormState
    .Show
    'consume form state here
End With

或者,您可以根据需要从表单的InitializeFormStateInitialize处理程序中调用Activate

Private Sub UserForm_Initialize()
    InitializeFormState
End Sub

Private Sub UserForm_Activate()
    InitializeFormState
End Sub

在这种情况下,应该将该过程设为Private,并且不需要在.Show方法之前从客户端代码调用它。