VBA:在UserForms上使用WithEvents

use*_*498 19 forms events vba ms-word event-handling

我有一个Word用户表单,包含60多种不同类型的控件.我想在每次触发control_change事件时评估表单并更改表单的提交按钮的启用状态.但是,我真的不想在更改事件处理程序上编写和维护60.

Gar*_*ill 28

您可以创建一个事件接收器类,它将包含特定类型的所有控件的事件处理代码.

例如,创建一个名为的类TextBoxEventHandler,如下所示:

Private WithEvents m_oTextBox as TextBox

Public Property Set TextBox(ByVal oTextBox as TextBox)
    Set m_oTextBox = oTextBox
End Property

Private Sub m_oTextBox_Change()
    ' Do something
End Sub
Run Code Online (Sandbox Code Playgroud)

现在,您需要为表单上的相应类型的每个控件创建并连接该类的实例:

Private m_oCollectionOfEventHandlers As Collection

Private Sub UserForm_Initialise()

    Set m_oCollectionOfEventHandlers = New Collection

    Dim oControl As Control
    For Each oControl In Me.Controls

        If TypeName(oControl) = "TextBox" Then

            Dim oEventHandler As TextBoxEventHandler
            Set oEventHandler = New TextBoxEventHandler

            Set oEventHandler.TextBox = oControl

            m_oCollectionOfEventHandlers.Add oEventHandler

        End If

    Next oControl

End Sub
Run Code Online (Sandbox Code Playgroud)

请注意,您需要将事件处理程序实例添加到集合的原因只是为了确保它们仍然被引用,因此在完成它们之前不会被垃圾收集器丢弃.

显然,这种技术可以扩展到处理其他类型的控制.您可以为每种类型分别设置事件处理程序类,也可以为需要处理的每种控件类型使用一个具有成员变量(以及关联的属性和事件处理程序)的类.

  • 该代码非常适合文本框。尝试使其适用于复选框时,需要将“ CheckBox”指定为“ MSForms.CheckBox”。认为此信息可能对某人有用。 (2认同)

Dan*_*ski 2

在这种情况下,您几乎没有选择,因为事件处理程序无法在 VBA/VB6 中共享

选项 1:使用从每个事件处理程序调用的中央处理函数。

Sub Control1_ChangeEvent()
  CommonChangeEvent // Just call the common handler, parameters as needed
End Sub

Sub Control2_ChangeEvent()
  CommonChangeEvent
End Sub
...
Sub CommonChangeEvent(/* Add necessary parameters */)
  //Do the heavy lifting here
End Sub
Run Code Online (Sandbox Code Playgroud)

选项 2:在控件数组中组织控件。

Sub TextBox_ChangeEvent(Index As Integer)
  CommonChangeEvent
End Sub

Sub OtherControlType_ChangeEvent(Index As Integer)
  CommonChangeEvent
End Sub
Run Code Online (Sandbox Code Playgroud)

将这两个选项结合起来,您的事件处理程序总数将大大减少,而其余的处理程序只是一个真正的事件处理程序的无脑存根。

  • 在这种情况下,选项 2 不是一个选项。VBA 不支持控制数组。 (7认同)