🚀The world's best VBA AI has evolved. ExcelMaster is now an autonomous Agent.Read more →
Back to Blog

VBA EnableEvents in Excel — Stop Your Macro Triggering Its Own Events (and Why a Crash Leaves Them Dead)

|

VBA EnableEvents in Excel — Stop Your Macro Triggering Its Own Events (and Why a Crash Leaves Them Dead)

TL;DRApplication.EnableEvents = False stops your macro's writes from triggering event handlersWorksheet_Change, Workbook_Open, and the rest. Its main job is breaking the loop where a Worksheet_Change handler writes a cell, which fires Worksheet_Change again, forever. It is a correctness switch, not a speed switch. And it is the one you most need an error handler for, because EnableEvents is application-level and does not reset itself — crash with it off and every event in Excel stays dead until you restart:

Private Sub Worksheet_Change(ByVal Target As Range)
    If Intersect(Target, Me.Range("B:B")) Is Nothing Then Exit Sub
    Application.EnableEvents = False     ' our write below must NOT re-fire this handler
    On Error GoTo CleanExit
    Target.Offset(0, 1).Value = Now      ' write - would otherwise trigger Worksheet_Change again
CleanExit:
    Application.EnableEvents = True       ' restore, even after an error, or events stay dead app-wide
End Sub

The other two switches in this cluster are about speedScreenUpdating stops repaints, Calculation stops recalcs. EnableEvents is different. It is about correctness: stopping your own writes from ricocheting through the event handlers that watch the workbook. This guide is built on one idea — EnableEvents is the switch you flip so your changes don't trigger the code that reacts to changes. You flip it for control, not for speed — and because a crash leaves it off for the whole application, restoring it is not optional.

What you'll learn

  • The mental model — writing a cell can fire event handlers, which can write more cells
  • The classic bug — a Worksheet_Change handler that triggers itself into an infinite loop
  • The rule that matters most — EnableEvents is app-level and does not auto-reset
  • Why "my buttons stopped working" is almost always a stranded EnableEvents = False
  • The CleanExit restore, and why it matters more here than for the speed switches
  • How this pairs with Worksheet_Change and Intersect

The mental model: writes can fire events

Excel workbooks can carry event handlers — procedures that run automatically when something happens. Worksheet_Change runs when a cell changes; Workbook_Open runs when the file opens; Worksheet_SelectionChange runs when the selection moves. These are how a workbook reacts to the user.

The catch: your macro's actions count as "something happening" too. When your code writes to a cell, that is a change, so Excel fires Worksheet_Change — even though it was your macro, not the user, that made the edit. Usually you don't want your own automated writes to wake up the handlers that were written to respond to a human.

Application.EnableEvents = False turns off that firing. While it is False, changes still happen, but Excel does not run any event handlers in response. Set it back to True and events resume.

The classic bug: a handler that triggers itself

The failure this switch exists to prevent is the self-triggering Worksheet_Change. Consider a handler that stamps the time whenever column B is edited — by writing to column C:

' BROKEN - infinite recursion:
Private Sub Worksheet_Change(ByVal Target As Range)
    If Intersect(Target, Me.Range("B:B")) Is Nothing Then Exit Sub
    Target.Offset(0, 1).Value = Now       ' writing to C is itself a change...
End Sub                                     ' ...which fires Worksheet_Change again -> again -> crash

Writing to C is a change, which fires Worksheet_Change, which writes to C again, which fires it again. In practice you get a stack overflow (error 28) or Excel wedged in a loop. The fix is to wrap the write so it does not re-enter the handler:

Private Sub Worksheet_Change(ByVal Target As Range)
    If Intersect(Target, Me.Range("B:B")) Is Nothing Then Exit Sub
    Application.EnableEvents = False        ' the write below will not re-fire this
    On Error GoTo CleanExit
    Target.Offset(0, 1).Value = Now
CleanExit:
    Application.EnableEvents = True
End Sub

The Intersect guard and the EnableEvents guard are siblings — a Worksheet_Change handler that writes anything back to the sheet needs both, one to scope the trigger and one to stop the recursion.

The rule that matters most: it does not reset itself

This is where EnableEvents earns its reputation as the switch you must handle carefully. Unlike ScreenUpdating, which Excel sometimes restores when a macro ends, EnableEvents never resets on its own. And it is an Application property, not a per-workbook one — so it applies to every open workbook at once.

Put those two facts together and you get the nastiest leftover state in VBA. If a macro sets EnableEvents = False and then errors before restoring it, events are now off everywhere — in that workbook and every other one open — and they stay off until the user closes and reopens Excel. No error message, no visual cue. The workbook just quietly stops reacting.

"My buttons stopped working"

That leftover state has a signature complaint: "my macro buttons / my dropdowns / my automatic formatting stopped working, and I didn't change anything." Nine times out of ten, some earlier macro crashed with EnableEvents = False still in effect, and now Worksheet_Change, Workbook_Open, and every other handler are silently disabled.

The one-line rescue is to run this from the Immediate window (or any macro):

Application.EnableEvents = True

But the real fix is upstream: never set EnableEvents = False without an error handler that restores it. Because the damage is application-wide and invisible, the CleanExit discipline that is merely good practice for the speed switches is genuinely mandatory here.

Sub BulkImport()
    Application.EnableEvents = False
    On Error GoTo CleanExit
    ' ... writes that would otherwise trigger Worksheet_Change on every row ...
CleanExit:
    Application.EnableEvents = True   ' non-negotiable
End Sub

When to use it — and when not to

Reach for EnableEvents = False when your code writes to cells that have event handlers watching them, or during a bulk operation where you don't want per-row events firing hundreds of times. Do not reach for it as a general speed trick — if the sheet has no relevant event handlers, disabling events changes nothing, and you have taken on the restore risk for no benefit. It is a targeted correctness tool: use it exactly where your writes would otherwise ricochet, and leave it alone elsewhere.

How ExcelMaster helps

EnableEvents is deceptively risky: it is application-wide, it never resets, and a crash with it off silently kills every event in Excel until a restart. Using it safely means pairing it with an Intersect guard inside event handlers, wrapping bulk writes so they don't fire per-row events, and restoring it in a CleanExit handler every single time.

ExcelMaster builds the whole safe pattern for you. Ask for "stamp the time in column C when column B changes," and it writes the Worksheet_Change handler with the Intersect guard, the EnableEvents = False toggle around the write, and the CleanExit restore — so the handler never loops on itself and never strands events for the rest of the session. You get workbook automation that reacts correctly, not one that quietly breaks after the first error.

Frequently asked questions

What does Application.EnableEvents = False do in VBA?

It stops Excel from running event handlers in response to changes your code makes. While it is False, actions like writing to a cell still happen, but they do not trigger Worksheet_Change, Workbook_SheetChange, or other event procedures. Set it back to True to let events fire again.

How do I stop a Worksheet_Change event from triggering itself?

Set Application.EnableEvents = False before your handler writes to any cell, then restore it to True afterward. Without it, the handler's own write is a change that fires Worksheet_Change again, looping until Excel raises a stack-overflow error. Combine it with an Intersect guard so the handler only runs for the cells you care about.

Why did all my Excel events stop working?

Because some macro set Application.EnableEvents = False and never restored it — usually it errored before the restore line. EnableEvents is application-level and does not reset on its own, so events stay disabled for every open workbook until you set Application.EnableEvents = True or restart Excel.

Does EnableEvents reset automatically when the macro ends?

No. Unlike ScreenUpdating, which Excel may restore on its own, EnableEvents stays exactly where you left it — across macros and even after the macro ends — until you set it back or close Excel. That is why you must restore it in an error handler rather than relying on any automatic reset.

Is EnableEvents a speed optimization like ScreenUpdating?

Not really. ScreenUpdating and Calculation are about speed; EnableEvents is about correctness — stopping your writes from triggering the handlers that watch the workbook. It can avoid running event code hundreds of times during a bulk write, but its primary purpose is preventing loops and unwanted reactions, not raw speed.

Tested in

Tested in: Excel 365 (Windows 11), VBA 7.1 — last verified 2026-08-17.

Related guides: VBA ScreenUpdating · VBA Calculation · VBA Worksheet_Change · VBA Intersect · VBA On Error