TL;DR —
Application.Waitはマクロを壁時計の瞬間まで一時停止するのであって、秒数のあいだ止めるのではありません。だからApplication.Wait 5はほとんど何もしません —5はすでに過去にある時刻のシリアル値だからです。欲しいのは「いま+5 秒」であり、その分解能は秒単位だけです。
Sub PauseFiveSeconds()
' 現在時刻に 5 秒足した瞬間に起きる
Application.Wait Now + TimeValue("0:00:05")
MsgBox "Five seconds later."
End Sub
マクロを「一時停止」させたいとき、人が最初に手を伸ばすのが Application.Wait であり、そして最初に間違えるのもこれです。名前が仕組みを隠しているからです。これは時間の長さをセットするキッチンタイマーではありません — 瞬間をセットする目覚まし時計です。本記事はこの 1 つの考えを軸にしています。目覚まし時計のモデルが、あらゆるクセを説明するからです。引数のこと、秒単位という下限、そしてアラームがセットされている間はExcel が完全に固まって他に何もできないこと。
この記事で学べること
- 考え方の軸 —
Application.Waitは目覚まし時計(瞬間)であって、ストップウォッチ(時間の長さ)ではない - 誰もがつまずくたった一つのルール — 引数は時間の長さではなく絶対時刻である
- なぜ秒単位でしか刻めないのか、そして 1 秒未満の停止には何を使うか
- 待っている間、なぜExcel が固まるのか — 再描画なし、クリックなし、ステータスバーの更新なし
Application.Waitが正しいのはいつか、そして Sleep や DoEvents ループこそが本当に欲しかった道具なのはいつか、についての正直な結論
考え方の軸:目覚まし時計であって、ストップウォッチではない
目覚まし時計に「8 時間後に鳴れ」とは言いません。「7 時に鳴れ」と言います。Application.Wait もまったく同じです。起きるべき時点を渡すと、システムクロックがその時点に達するまでブロックします。時間の長さをカウントダウンするのではありません。
このたった一つの事実が、ナンバーワンのバグの源です。引数が瞬間であるため、欲しい秒数をそのまま書くことはできません — いま、プラス欲しい秒数、と書かねばならず、その「欲しい秒数」は TimeValue で組み立てます。
Application.Wait Now + TimeValue("0:00:05") ' いま + 5 秒に起きる -> 約 5 秒待つ
Application.Wait Now + TimeValue("0:01:30") ' いま + 1 分 30 秒に起きる
Application.Wait "14:30:00" ' 今日の午後 2 時 30 分に起きる(文字どおりの瞬間)
Now は現在の日付と時刻、TimeValue("0:00:05") は 5 秒という時間の長さを時刻値で表したもの。両者を足すと、いまから 5 秒後の瞬間になります。それが Application.Wait の求めるものです。
誰もがつまずくルール:引数は絶対時刻である
人を検索エンジンへ走らせる失敗がこれです。「Wait はマクロを一時停止する」と読んで、こう書きます。
Application.Wait 5 ' 誤り - 5 秒は待たない
VBA にとって 5 は「5 秒」ではありません。シリアル値の 5、つまり日付/時刻です。1900 年のエポックから 5 日後の深夜 0 時 — 何十年も過去の瞬間です。Application.Wait はクロックを見て、その瞬間はとうに過ぎていると分かり、実質すぐに戻ります。マクロはエラーになりません。ただ待たないだけです。この「止まりもしなければ、文句も言わない」という静けさが、まさに混乱の元です。
もっと分かりにくい形の同じ罠:Application.Wait Now + 5 は5 日待ちます。日付に足した 5 は 5 秒ではなく 5 日を意味するからです。時間の長さは必ず TimeValue(または TimeSerial)で包みましょう。
Application.Wait Now + 5 ' 5 日待つ - まず意図しない結果
Application.Wait Now + TimeValue("0:00:05") ' 5 秒待つ - 正しい
Application.Wait Now + TimeSerial(0, 0, 5) ' 同じこと。数値から組み立てる
このページから一行だけ覚えるなら、Now + TimeValue(...) にしてください。
刻めるのは秒単位だけ — もっと細かくは Sleep を
TimeValue は 1 秒未満を表現できません。Application.Wait が取れる最小の停止は1 秒で、TimeValue("0:00:00.25") などというものはありません。4 分の 1 秒の停止 — ポーリングループを間引く、リクエストの間隔を空ける、アニメーションを一押しする — を頼んでも、Application.Wait にはできません。
これが、二つの待機ツールを分けるきれいな境界線です。秒単位で、Declare も不要なら Application.Wait。1 秒未満、ミリ秒精度なら Sleep という Windows API です。Application.Wait がミリ秒を取ってくれたら、と思い始めたら、あなたはもうそれを卒業しています — Sleep に切り替えましょう。
誰もが忘れる部分:Excel を完全に固める
Application.Wait がブロックしている間、Excel は他に何もしていません。これは Excel のたった一本のスレッドの上で走り、メッセージを処理するためにそのスレッドを手放しません。だから待っている間は次のようになります。
- 画面は再描画されない、
- いま設定したステータスバーのメッセージは現れない、
- クリックとキー入力は処理されないまま溜まっていく、
- そして待ちが十分に長ければ、Windows はウィンドウに**「応答なし」**を焼き付ける。
これこそ、人が Application.Wait を使う最も一般的な理由に対して、それを間違った道具に変えてしまう罠です。目的が「カウントダウンを見せる」「進捗をユーザーに見せる」「キャンセルを押させる」のいずれかなら、Application.Wait は積極的にあなたの邪魔をします — 生かしておきたかったまさにそのインターフェイスを固めてしまうのです。
応答的な停止は、まったく別の構成です。DoEvents で制御を譲る短いループで、時間が過ぎる間も Excel が息をつき続けます。
' Excel を生かしたまま中断もできる停止 - Application.Wait ではない
Dim finishAt As Double
finishAt = Timer + 5 ' Timer = 深夜 0 時からの秒数
Do While Timer < finishAt
DoEvents ' Excel に再描画とクリック処理をさせる
If gCancel Then Exit Do
Loop
何を使っているかに注目してください。経過秒数を測る Timer と、ウィンドウを生かし続ける DoEvents です。Application.Wait はそのどちらも与えてくれません。
正直な結論:Application.Wait が本当に正しいとき
Application.Wait がその居場所を得るのは、ちょうど一つの状況です。整数秒の停止が必要で、その間 Excel が固まっていても本当に構わないとき。教科書的な例は、外部フィードが追いつくのを少し待つ場面です — DDE/RTD リクエスト、Web クエリ、あるいは QueryTable の更新を撃ったばかりで、結果を読む前にデータが着地するのを 2、3 秒待ちたい。単純で、API 宣言も要らず、CPU を手放す(スピンしない)ので、短く、対話を伴わない、整数秒の停止なら申し分ない用途です。
それ以外はすべて、本当に欲しいものを名指ししましょう。
- 1 秒未満の停止(ループを間引く、呼び出しの間隔を空ける)—
Sleep。Application.Waitは 1 秒より下へ行けないからです。 - Excel が応答的でなければならない停止(進捗、キャンセル、目に見えるカウントダウン)—
DoEventsループ。Application.Waitはウィンドウを固めるからです。 - 何かを後で、スケジュールに従って実行する(5 分ごと、午前 9 時に)—
Application.OnTime。そもそも待機ではありません。
固まった Excel は Application.Wait の正しい挙動であって、バグではありません。バグは、固まった Excel が望みでないときにそれを使うことです。
ExcelMaster の活用
Application.Wait、Sleep、DoEvents ループ、OnTime のどれを選ぶかは、1 秒未満の精度が要るか、Excel が応答的であり続けねばならないか、遅延が一度きりかスケジュールか、に左右される判断です。間違えれば、生かしておくつもりだった Excel を固めるか、Application.Wait 5 と書いて何も止まらない理由に首をひねるか、どちらかです。
ExcelMaster は、その判断をあなたの代わりに下します。欲しいものを言うだけ — 「クエリの更新のために 2、3 秒止めて」あるいは「待ちたい、でもキャンセルはさせて」 — で、正しい構成を選びます。単純な整数秒の停止には Application.Wait Now + TimeValue(...)、1 秒未満の間引きには Sleep の宣言、ウィンドウが応答的であり続けねばならないときはガード付きの DoEvents ループ。シリアル値ひとつ分のズレもなく、生きたマクロが欲しかったのに固まったマクロ、ということもありません。
よくある質問
VBA でマクロを 5 秒待たせるには?
Application.Wait Now + TimeValue("0:00:05") を使います。Application.Wait の引数は時間の長さではなく起きるべき瞬間なので、5 秒分の TimeValue を Now(現在時刻)に足します。Application.Wait 5 と書いても効きません — VBA は 5 を過去の日付/時刻シリアル値として読むため、マクロはまったく止まりません。
Application.Wait 5 でマクロが止まらないのはなぜですか?
5 が時刻のシリアル値(おおよそ 1900 年の 5 日目の深夜 0 時)として解釈され、それがすでに過去だからです。Application.Wait は渡された瞬間にクロックが達するまでブロックしますが、その瞬間はとうに過ぎているので、すぐに戻ります。Now + TimeValue("0:00:05") のように未来の瞬間を渡す必要があります。
Application.Wait は 1 秒未満で止められますか?
いいえ。TimeValue が 1 秒未満を表現できないため、Application.Wait は秒単位でしか刻めません。1 秒未満の停止 — たとえば 250 ミリ秒 — には、代わりにミリ秒を取る Windows の Sleep API(Sleep 250)を使います。
Application.Wait の最中に Excel が固まったり「応答なし」と出たりするのはなぜですか?
Application.Wait が Excel のたった一本のスレッドをブロックし、待っている間メッセージを処理させないため、画面は再描画できず、クリックも処理されないからです。Excel が生きていなければならない停止 — 進捗を見せる、キャンセルを許す — には、Application.Wait ではなく DoEvents を呼ぶ短いループを使いましょう。
Application.Wait と Sleep の違いは何ですか?
Application.Wait は Excel に組み込まれ、宣言が不要で、壁時計の瞬間まで待ち、秒単位で刻みます。Sleep は自分で宣言しなければならない Windows API 呼び出しで、ミリ秒数だけ待ち(1 秒未満の精度)、64 ビット Excel では PtrSafe 属性が必要です。単純な整数秒の停止には Application.Wait を、もっと細かい精度が要るときは Sleep を使いましょう。どちらも待っている間は Excel を固めます。
検証環境
検証環境: Excel 365 (Windows 11), VBA 7.1 — 最終確認 2026-08-19。
関連ガイド: VBA Sleep · VBA Timer · VBA DoEvents · VBA StatusBar · VBA ScreenUpdating
