TL;DR — The bare
Endstatement stops the whole macro immediately: it wipes every variable (including module-level andStatic), closes UserForms, and skips any cleanup you had queued. That is a different thing fromEnd Sub(which just marks where aSubfinishes), fromExit Sub(which returns from one procedure and lets the program continue), and fromStop(which pauses in the debugger). You almost never want the bareEnd. To leave a procedure, useExit Sub.
Sub WhyEndIsDangerous()
Application.ScreenUpdating = False
' ... work ...
If somethingWrong Then End ' stops NOW - ScreenUpdating is left False!
' ... more work ...
Application.ScreenUpdating = True ' this cleanup line never runs after End
End Sub
Four constructs in VBA contain the word end, and confusing them causes real bugs. Only one of them —
the bare End — actually stops your program, and it does so in the most heavy-handed way possible. The
others simply close a block or return from a procedure. Knowing which is which is the difference between
a macro that cleans up after itself and one that leaves Excel in a half-configured state.
What you'll learn
- What the bare
Endstatement actually does — and how much state it destroys - Why
End,End Sub,End If,Exit Sub, andStopare five different things - The real bug: how
Endskips your cleanup and leavesScreenUpdatingor events off - Why
Endwipes module-level andStaticvariables that a normal return would keep - When (if ever)
Endis the right call, and what to use instead - How
Stopdiffers fromEnd— pausing to debug versus terminating
The mental model: End is the plug, not the door
Line up the four look-alikes by how much they stop:
End If ' closes an If block - stops nothing; a structural marker
End Sub ' marks the end of a Sub - the procedure ends here anyway
Exit Sub ' returns from THIS procedure - the program keeps running
End ' terminates the ENTIRE macro - everything stops, nothing cleans up
End Sub and End If are punctuation: they tell VBA where a block finishes. They do not "run." Exit Sub is a door out of one procedure — you leave, the caller continues, your cleanup runs. The bare
End is the plug: it halts the whole call stack at once, as if you had hit the Reset button in the
editor. Everything downstream — the caller, the caller's caller, the cleanup line you wrote two lines
below — is simply abandoned. That single distinction, door versus plug, is the whole page.
What the bare End statement actually destroys
End does far more than "stop the code." When it fires, VBA tears down the entire run-time state of your
project:
- All variables are reset — local, module-level, and
Staticvariables lose their values. - All open UserForms are unloaded, without their
QueryCloseor cleanup events running normally. - The call stack is discarded — no procedure on it gets to finish or run its remaining lines.
On Errorhandlers are cleared, and the VBA project's run-time state resets as if freshly started.
What it does not do is undo anything already done to the workbook or to Application. That is the
crux of the danger. If you turned Application.ScreenUpdating = False at the top and hit End in the
middle, screen updating stays off — because the line that would have turned it back on is one of the many
lines End just abandoned.
The real bug: End skips your cleanup
Most non-trivial macros set some Excel state up front and restore it at the end:
Sub Report()
Application.ScreenUpdating = False
Application.EnableEvents = False
If Not FileExists() Then End ' <-- the trap
' ... build the report ...
Application.EnableEvents = True ' never reached if End fired
Application.ScreenUpdating = True ' never reached if End fired
End Sub
If FileExists returns False, that End stops everything on the spot. EnableEvents and
ScreenUpdating are left False, so the user's Excel now silently ignores worksheet events and does not
repaint — a "frozen Excel" support ticket that looks like a crash but is really just skipped cleanup. The
fix is to return, not terminate: replace End with Exit Sub, and put the restore lines where they
always run (a single exit path, or an error handler). Exit Sub leaves the procedure but lets your
cleanup — and the rest of the program — run.
End wipes Static and module-level variables
There is a subtler consequence worth its own note. A normal return (Exit Sub, or just reaching
End Sub) leaves module-level and Static variables intact — that is the whole
point of them, to persist across calls. The bare End throws them away along with everything else:
' Module level
Dim gRunCount As Long
Sub Tick()
gRunCount = gRunCount + 1 ' meant to accumulate across runs
If gRunCount > 100 Then End ' End resets gRunCount back to 0!
End Sub
If any part of your design relies on state surviving between macro runs — a counter, a cached object, a
loaded configuration — a stray End silently resets it, and the bug shows up much later as "the count
keeps starting over." One more reason the bare End should be rare and deliberate.
Stop is not End: pause to debug, do not terminate
Stop looks related but does the opposite of terminate. It suspends execution and drops you into the
VBA editor at that line, in break mode, with every variable still alive so you can inspect them — exactly
like a breakpoint you wrote into the code:
Sub Investigate()
Dim total As Double
total = ComputeTotal()
Stop ' pause here in the editor; total is still readable
Range("A1").Value = total
End Sub
Use Stop while debugging and remove it before you ship (unlike an F9 breakpoint, Stop lives in the
source, so a forgotten one will halt a user's macro in the editor). End terminates; Stop pauses.
Neither is something you want firing in code your users run — for observing a running macro without
halting it, see VBA Debug.Print.
When is End ever the right call?
Rarely, and always deliberately. The honest use cases are narrow: a catastrophic, unrecoverable condition
in a standalone tool where you would rather stop everything than risk continuing with bad state, or
tearing down a modeless UserForm-driven app where you genuinely want to reset the whole project. Even
then, prefer to reach a single clean exit — restore Application settings, close what you opened — and
then stop. In day-to-day macros, the answer to "how do I stop here?" is Exit Sub (leave this
procedure) or restructuring so the code reaches End Sub on its own. If you are typing the bare End,
pause and make sure you really mean terminate everything, skip all cleanup.
How ExcelMaster helps
The bare End is a small word with an outsized blast radius, and its damage is invisible until a user
reports a "frozen" Excel that is really just ScreenUpdating left off. The mistakes are using End when
you meant Exit Sub, and leaving a Stop in shipped code.
ExcelMaster writes procedures that leave
through a single clean exit: Exit Sub to return, restore lines that always run, and no stray End or
Stop in code your users touch. When a macro needs to bail out early, it does so without leaving Excel
half-configured. You keep the workbook and the code.
Frequently asked questions
What does the End statement do in VBA?
The bare End statement immediately terminates the entire macro. It resets all variables (including
module-level and Static), unloads open UserForms, discards the call stack, and clears On Error
handlers — but it does not undo changes already made to the workbook or to Application, so any
cleanup you had queued is skipped. To leave a procedure without this, use Exit Sub.
What is the difference between End and End Sub?
End Sub simply marks where a Sub procedure finishes — it is a structural marker, and the procedure
would end there anyway. The bare End, written on its own, terminates the whole program on the spot,
wherever it appears. End Sub closes a block; End stops everything.
Should I use End to stop a macro?
Usually no. To leave the current procedure, use Exit Sub, which returns to the caller and lets your
cleanup run. The bare End skips all cleanup and can leave ScreenUpdating off or events disabled,
producing an Excel that looks frozen. Reserve End for rare, deliberate, unrecoverable situations.
What is the difference between End and Stop?
End terminates the macro and clears its state. Stop pauses execution and drops you into the VBA
editor in break mode, with all variables still alive, so you can debug — like a breakpoint written into
the code. Remove Stop before shipping, because unlike an F9 breakpoint it lives in the source and will
halt a user's macro.
Why is ScreenUpdating still off after my macro ran?
Most likely a bare End (or an unhandled error) stopped the macro before the line that sets
Application.ScreenUpdating = True back on. Because End skips remaining code, the restore never ran.
Replace End with Exit Sub and put your restore lines on a single exit path or in an error handler so
they always execute.
Tested in
Tested in: Excel 365 (Windows 11), VBA 7.1 — last verified 2026-09-24.
Related guides: VBA Exit For · VBA GoTo · VBA On Error · VBA Debug.Print · VBA Sub
