TL;DR —
Application.Waitpauses your macro until a wall-clock moment, not for a number of seconds. That is whyApplication.Wait 5does almost nothing —5is a time-of-day serial that is already in the past. You want "now plus five seconds," and its resolution is whole seconds only:
Sub PauseFiveSeconds()
' wake up at the current time PLUS five seconds
Application.Wait Now + TimeValue("0:00:05")
MsgBox "Five seconds later."
End Sub
Application.Wait is the tool people reach for first when they want a macro to "pause," and it is the
one they get wrong first, because its name hides how it works. It is not an egg-timer you set to a
duration — it is an alarm clock you set to a moment. This guide is built on that one idea, because
the alarm-clock model explains every quirk: the argument, the whole-second floor, and the fact that
while the alarm is set, Excel is frozen solid and cannot do anything else.
What you'll learn
- The mental model —
Application.Waitis an alarm clock (a moment), not a stopwatch (a duration) - The one rule that trips everyone — the argument is an absolute time, not a length of time
- Why it only resolves to whole seconds, and what to use for sub-second pauses
- Why it freezes Excel — no repaint, no clicks, no status-bar updates — while it waits
- The honest verdict on when
Application.Waitis right, and when Sleep or a DoEvents loop is the tool you actually wanted
The mental model: an alarm clock, not a stopwatch
You do not tell an alarm clock "ring in eight hours." You tell it "ring at 7:00." Application.Wait
works exactly the same way: you give it a point in time to wake up at, and it blocks until the
system clock reaches that point. It does not count down a duration.
That single fact is the source of the number-one bug. Because the argument is a moment, you cannot
write the number of seconds you want — you have to write now, plus the seconds you want, and you
build "the seconds you want" with TimeValue:
Application.Wait Now + TimeValue("0:00:05") ' wake at now + 5 seconds -> waits ~5s
Application.Wait Now + TimeValue("0:01:30") ' wake at now + 1 min 30s
Application.Wait "14:30:00" ' wake at 2:30 PM today (a literal moment)
Now is the current date and time; TimeValue("0:00:05") is the duration five seconds expressed as
a time value; adding them gives the moment five seconds from now. That is what Application.Wait
needs.
The rule that trips everyone: the argument is an absolute time
Here is the failure that sends people to search engines. They read "Wait pauses the macro" and write:
Application.Wait 5 ' WRONG - does NOT wait 5 seconds
To VBA, 5 is not "five seconds." It is the serial number 5, which is a date/time: five days
after the 1900 epoch, at midnight — a moment that is decades in the past. Application.Wait looks at
the clock, sees that moment has long since passed, and returns essentially immediately. The macro does
not error; it just does not wait. That silent "it didn't pause and it didn't complain" is exactly why
it is so confusing.
The same trap in a subtler form: Application.Wait Now + 5 waits five days, because 5 added to a
date means five days, not five seconds. Always wrap the duration in TimeValue (or TimeSerial):
Application.Wait Now + 5 ' waits 5 DAYS - almost never what you meant
Application.Wait Now + TimeValue("0:00:05") ' waits 5 seconds - correct
Application.Wait Now + TimeSerial(0, 0, 5) ' same thing, built from numbers
If you remember one line from this page, make it Now + TimeValue(...).
Whole seconds only — for anything finer, use Sleep
TimeValue cannot express fractions of a second. The finest pause Application.Wait can take is one
second; there is no TimeValue("0:00:00.25"). If you ask for a quarter-second pause — to throttle a
polling loop, to space out requests, to nudge an animation — Application.Wait cannot do it.
That is the clean dividing line between the two waiting tools. Whole seconds, no Declare needed:
Application.Wait. Sub-second, millisecond precision: the Sleep Windows API. If
you find yourself wishing Application.Wait took milliseconds, you have already outgrown it — switch
to Sleep.
The part everyone forgets: it freezes Excel completely
While Application.Wait is blocking, Excel is doing nothing else. It runs on Excel's single
thread, and it does not release that thread to pump messages. So during the wait:
- the screen does not repaint,
- a status-bar message you just set does not appear,
- clicks and keystrokes pile up unhandled,
- and if the wait is long enough, Windows stamps "Not Responding" on the window.
This is the trap that turns Application.Wait into the wrong tool for the most common reason people
use it. If your goal is "show a countdown," "let the user watch progress," or "let them press Cancel,"
Application.Wait actively defeats you — it freezes the very interface you were trying to keep alive.
A responsive pause is a different construction entirely: a short loop that yields with
DoEvents so Excel keeps breathing while time passes.
' A pause that keeps Excel alive and cancellable - NOT Application.Wait
Dim finishAt As Double
finishAt = Timer + 5 ' Timer = seconds since midnight
Do While Timer < finishAt
DoEvents ' let Excel repaint and handle clicks
If gCancel Then Exit Do
Loop
Note what that uses: Timer to measure the elapsed seconds and DoEvents to keep
the window alive. Application.Wait gives you neither.
The honest verdict: when Application.Wait is actually right
Application.Wait earns its place in exactly one situation: you need a pause of a whole number of
seconds, and you genuinely do not care that Excel is frozen during it. The textbook case is giving an
external feed a moment to catch up — you have just fired a DDE/RTD request, a web query, or a
QueryTable refresh, and you want to wait a couple of seconds for the data to land before you read the
result. It is simple, it needs no API declaration, and it releases the CPU (it does not spin), so a
short, non-interactive, whole-second pause is a fine use.
For everything else, name what you actually want:
- Sub-second pause (throttle a loop, space out calls) —
Sleep, becauseApplication.Waitcannot go below one second. - A pause where Excel must stay responsive (progress, cancel, a visible countdown) — a
DoEventsloop, becauseApplication.Waitfreezes the window. - Run something later on a schedule (every 5 minutes, at 9 AM) —
Application.OnTime, not a wait at all.
A frozen Excel is the correct behaviour for Application.Wait, not a bug. The bug is using it when a
frozen Excel is not what you wanted.
How ExcelMaster helps
Choosing between Application.Wait, Sleep, a DoEvents loop, and OnTime is a judgment call that
depends on whether you need sub-second timing, whether Excel must stay responsive, and whether the
delay is a one-off or a schedule. Get it wrong and you either freeze Excel when you meant to keep it
alive, or you write Application.Wait 5 and wonder why nothing pauses.
ExcelMaster makes that call for you.
Describe what you want — "pause a couple of seconds for the query to refresh," or "wait, but let me
cancel" — and it picks the right construct: Application.Wait Now + TimeValue(...) for a simple
whole-second pause, a Sleep declaration for sub-second throttling, or a guarded DoEvents loop when
the window has to stay responsive. No off-by-a-serial-number, no frozen macro where you wanted a live
one.
Frequently asked questions
How do I make a macro wait 5 seconds in VBA?
Use Application.Wait Now + TimeValue("0:00:05"). The argument to Application.Wait is a moment to
wake up at, not a duration, so you add the five-second TimeValue to Now (the current time).
Writing Application.Wait 5 does not work — VBA reads 5 as a date/time serial in the past, so the
macro does not pause at all.
Why does Application.Wait 5 not pause my macro?
Because 5 is interpreted as a time-of-day serial number (roughly midnight on the fifth day of 1900),
which is already in the past. Application.Wait blocks until the clock reaches the moment you gave it,
and that moment has long passed, so it returns immediately. You must pass a future moment, such as
Now + TimeValue("0:00:05").
Can Application.Wait pause for less than a second?
No. Application.Wait resolves only to whole seconds, because TimeValue cannot express fractions of
a second. For a sub-second pause — 250 milliseconds, for example — use the Windows Sleep API
(Sleep 250) instead, which takes milliseconds.
Why does Excel freeze or say "Not Responding" during Application.Wait?
Because Application.Wait blocks Excel's single thread and does not let it process messages while it
waits, so the screen cannot repaint and clicks are not handled. For a pause where Excel must stay
alive — to show progress or allow Cancel — use a short loop that calls DoEvents instead of
Application.Wait.
What is the difference between Application.Wait and Sleep?
Application.Wait is built into Excel, needs no declaration, waits until a wall-clock moment, and
resolves to whole seconds. Sleep is a Windows API call you must declare, waits for a number of
milliseconds (sub-second precision), and needs the PtrSafe attribute on 64-bit Excel. Use
Application.Wait for simple whole-second pauses and Sleep when you need finer timing. Both freeze
Excel while they wait.
Tested in
Tested in: Excel 365 (Windows 11), VBA 7.1 — last verified 2026-08-19.
Related guides: VBA Sleep · VBA Timer · VBA DoEvents · VBA StatusBar · VBA ScreenUpdating
