About this article
This article was created using an automated generation workflow utilizing generative AI. Based on the official VBA language references for Event, RaiseEvent, and WithEvents, it is structured so that you can observe the flow of a custom event being "raised and received" using minimal code.
Verification Status: 📘 Official information confirmed, Excel hardware execution not verified
VBA is not limited to receiving Worksheet Click or Change events. You can declare your own Event in a Class Module, raise it with RaiseEvent, and build a small event-driven flow received by WithEvents.
- Success criteria for this exercise
- Get it running first: Class Module
- The receiving Class Module
- Wiring from a Standard Module
- Look here
- Try changing one part
- . The key is mapping the event count to state changes.
- Initially, visualizing the firing order with Debug.Print makes it easier to understand.
- Microsoft Learn — WithEvents
Success criteria for this exercise
When you increment the Counter value by 1, the following sequence should appear in the Immediate Window for success.
[START] AddOne [EVENT] Changed = 1 [SUCCESS] event received
VBA event syntax can be checked in the Microsoft Learn language reference.
Get it running first: Class Module
Add a Class Module and name it 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 is the event declaration, and RaiseEvent Changed(...) is where the event is raised.
The receiving Class Module
Add another Class Module and name it CounterObserver.
Option Explicit
Public WithEvents Target As Counter
Private Sub Target_Changed(ByVal NewValue As Long)
Debug.Print "[EVENT] Changed = " & NewValue
End Sub
WithEventsVariables with the Target_Changed attribute can receive events exposed by that object. The handler name follows the format "variableName_eventName", such as
Wiring from a Standard Module
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]
Look here
In a regular function call, the caller explicitly specifies "who to call next." With events, the Counter side simply notifies that "Changed has occurred," and the subscribed side reacts.
Understanding this pattern on a small scale helps when reading event-driven code in GUIs, COM events, asynchronous HTTP, and more.
Try changing one part
AddOneCall
mCounter.AddOne mCounter.AddOne
Changed = 1、Changed = 2 twice. Observe whether the event is received twice along with
. The key is mapping the event count to state changes.
If you use this in production
Events are convenient, but they can sometimes make the control flow harder to follow.
Make the names clear regarding who is the publisher and who is the subscriber.
Avoid keeping objects only as local variables and destroying them prematurely.
Consider whether changing state again inside an event could cause re-entrancy issues.
Do not swallow errors.
Do not rely too heavily on the exact order of events.
Initially, visualizing the firing order with Debug.Print makes it easier to understand.
Microsoft Learn — WithEvents
ConclusionEvent、RaiseEvent、WithEventsYou can create custom events in VBA as well by using
