关于本文
本文是通过利用生成式 AI 的自动化生成流程创建的。以 VBA 的 Event / RaiseEvent / WithEvents 官方语言参考为基准,整理成了可以通过最少代码观察自定义事件“发生 → 接收”流程的形式。
验证状态:📘 已确认官方信息,未在 Excel 实机上验证
VBA 不仅能接收工作表的 Click 或 Change 事件。你还可以在类模块中声明自己的 Event,通过 RaiseEvent 触发,并通过 WithEvents 接收,从而创建一个小型事件驱动。
本次的成功条件
将 Counter 的值增加 1 时,如果在立即窗口中按以下顺序输出,即表示成功。
[START] AddOne [EVENT] Changed = 1 [SUCCESS] event received
VBA 的事件语法可以在 Microsoft Learn 的语言参考中进行确认。
首先运行:类模块
添加一个类模块,将其命名为 Counter。
Option Explicit
Public Event Changed(ByVal NewValue As Long)
Private mValue As Long
Public Sub AddOne()
mValue = mValue + 1
RaiseEvent Changed(mValue)
End Sub
Event Changed 是事件声明,RaiseEvent Changed(...) 是引发事件的地方。
接收方的类模块
再添加一个类模块,将其命名为 CounterObserver。
Option Explicit
Public WithEvents Target As Counter
Private Sub Target_Changed(ByVal NewValue As Long)
Debug.Print "[EVENT] Changed = " & NewValue
End Sub
WithEvents 带有该关键字的变量可以接收该对象公开的事件。处理程序名称形如 Target_Changed,即“变量名_事件名”。
从标准模块进行连接
Option Explicit
Private mCounter As Counter
Private mObserver As CounterObserver
Public Sub RunEventDemo()
Debug.Print "[START] AddOne"
Set mCounter = New Counter
Set mObserver = New CounterObserver
Set mObserver.Target = mCounter
mCounter.AddOne
Debug.Print "[SUCCESS] event received"
End Sub
sequenceDiagram
participant M as Standard Module
participant C as Counter
participant O as CounterObserver
M->>C: AddOne
C->>C: mValue = mValue + 1
C-->>O: RaiseEvent Changed(1)
O-->>M: Debug.Print [EVENT]
看这里
在普通的函数调用中,调用方直接指定“接下来调用谁”。而在事件中,Counter 方会通知“Changed 已发生”,由订阅方做出响应。
简要理解这种形式,有助于在阅读 GUI、COM 事件、异步 HTTP 等事件驱动代码时提供帮助。
尝试修改一个地方
AddOne 调用两次。
mCounter.AddOne mCounter.AddOne
Changed = 1、Changed = 2 观察事件是否会送达两次。关键是将事件次数与状态变化对应起来。
如果在工作中实际使用
事件虽然方便,但有时也会使执行流程变得难以追踪。
明确发布者(publisher)和订阅者(subscriber)的名称
不要将对象仅作为局部变量而导致其被过早销毁
考虑是否会在事件内部再次改变状态从而导致重入
不要吞掉错误
不要过度依赖事件的顺序
起初,通过 Debug.Print 将触发顺序可视化,会更容易理解。
官方信息与第一手资料
总结
在 VBA 中也可以使用 Event、RaiseEvent、WithEvents 创建自定义事件。通过极简的 Counter 观察“状态更改 → event → handler”的顺序后,再进入 GUI 或异步处理,将更容易理解事件驱动。
