来源和处理程序
什么是活动?
VBA 是事件驱动的 :VBA 代码运行以响应主机应用程序或主机文档引发的事件 - 了解事件是理解 VBA 的基础。
API 通常会公开引发响应各种状态的大量事件的对象。例如,只要创建,打开,激活或关闭新工作簿,Excel.Application 对象就会引发事件。或者每当计算工作表时。或者在文件保存之前。或者之后立即。当用户点击它时,表单上的按钮会引发 Click 事件,用户表单本身会在激活后立即引发一个事件,而另一个事件在它关闭之前引发。
从 API 的角度来看,事件是扩展点 :客户端代码可以选择实现处理这些事件的代码,并在触发这些事件时执行自定义代码:这就是每次选择在任何工作表上发生更改时自动执行自定义代码的方式 - 通过处理在任何工作表上选择更改时触发的事件。
公开事件的对象是事件源。处理事件的方法是处理程序。
处理程序
VBA 文档模块(例如 ThisDocument,ThisWorkbook,Sheet1 等)和 UserForm 模块是类模块,它们实现了暴露大量事件的特殊接口。你可以在代码窗格顶部的左侧下拉列表中浏览这些界面:

右侧下拉列表列出了左侧下拉列表中所选界面的成员:

当在右侧列表中选择项目时,VBE 自动生成事件处理程序存根,或者如果存在处理程序,则在那里导航。
你可以在任何模块中定义模块范围的 WithEvents 变量:
Private WithEvents Foo As Workbook
Private WithEvents Bar As Worksheet
每个 WithEvents 声明都可以从左侧下拉列表中进行选择。在右侧下拉列表中选择事件时,VBE 会生成一个以 WithEvents 对象命名的事件处理程序存根以及事件名称,并使用下划线连接:
Private WithEvents Foo As Workbook
Private WithEvents Bar As Worksheet
Private Sub Foo_Open()
End Sub
Private Sub Bar_SelectionChange(ByVal Target As Range)
End Sub
只有暴露至少一个事件的类型才能与 WithEvents 一起使用,并且 WithEvents 声明不能使用 New 关键字在现场分配参考。此代码是非法的:
Private WithEvents Foo As New Workbook 'illegal
对象引用必须是 Set 显式; 在类模块中,通常在 Class_Initialize 处理程序中执行此操作的好地方,因为只要该实例存在,该类就会处理该对象的事件。
来源
任何类模块(或文档模块或用户表单)都可以是事件源。使用 Event 关键字在模块的声明部分中定义事件的签名 : **
Public Event SomethingHappened(ByVal something As String)
事件的签名决定了事件的引发方式以及事件处理程序的外观。
事件只能在它们定义的类中引发 - 客户端代码只能处理它们。使用 RaiseEvent 关键字引发事件; 此时提供了事件的参数:
Public Sub DoSomething()
RaiseEvent SomethingHappened("hello")
End Sub
如果没有处理 SomethingHappened 事件的代码,运行 DoSomething 程序仍会引发事件,但不会发生任何事情。假设事件源是名为 Something 的类中的上述代码,ThisWorkbook 中的此代码将在 test.DoSomething 被调用时显示一个消息框,显示 hello:
Private WithEvents test As Something
Private Sub Workbook_Open()
Set test = New Something
test.DoSomething
End Sub
Private Sub test_SomethingHappened(ByVal bar As String)
'this procedure runs whenever 'test' raises the 'SomethingHappened' event
MsgBox bar
End Sub