TL;DR —
Application.StatusBar = "..."は、Excel ウィンドウ左下のバーに自分のテキストを 書き込みます。考えうるいちばん軽い進捗インジケーター — 一行、UserForm なし、ちらつきなし、 しかもScreenUpdating = Falseでも生き残ります。落とし穴はリセットです。書いたものは マクロが終わってもそこに固まって残り、Application.StatusBar = False(空文字列ではなく)で バーを Excel に返すまでそのままです。エラーハンドラーの中で復元し、クラッシュが古いメッセージを ウィンドウに貼り付けたまま残さないようにしましょう。
Sub LongJob()
Application.ScreenUpdating = False
On Error GoTo CleanExit
Dim i As Long, n As Long
n = 10000
For i = 1 To n
' ... i 行目の処理 ...
If i Mod 250 = 0 Then
Application.StatusBar = "Processing " & i & " of " & n & " (" & Int(i / n * 100) & "%)"
End If
Next i
CleanExit:
Application.StatusBar = False ' バーを Excel に返す - "" のまま残さないこと
Application.ScreenUpdating = True
End Sub
マクロが 1、2 秒より長く走るとき、ユーザーがまず抱く疑問は「これはまだ生きているのか」です。 ステータスバーは、その答えを一行の代金で返します。本記事は 1 つの考えを軸にしています — ステータス バーは借り物だ。あなたはそこに書き、そして必ず返さなければならない。 Excel は自分から取り返さない ので、プロフェッショナルな進捗インジケーターと「Processing 73%...」を焼き付けたまま固まった ウィンドウとの違いは、たった一行のリセットに尽きます。
この記事で学べること
- 考え方の軸 — ステータスバーは Excel のもの。あなたは借りて、必ず返す
- 書いて戻すパターン、そして
= Falseが= ""に勝る理由 - 「あとどれくらい」に答える進捗パーセントの定石
- テキストがタイトなループで更新されない理由 — そして DoEvents がはまる場所
- 一行で足りる場面と、本格的な UserForm プログレスバーが元を取る場面
- ScreenUpdating と CleanExit の復元との組み合わせ方
考え方の軸:バーは Excel のもの
既定では、ウィンドウ左下の帯は Excel が管理するものです。「準備完了」や「計算中」、あるいは選択した
セルの合計を表示します。Application.StatusBar に文字列を代入すると、あなたはその領域を引き取り —
Excel はそこに自前のメッセージを流すのをやめ、代わりにあなたのものを表示します。その瞬間から、バーは
あなたが返すまであなたのものです。
返すのは一行、Application.StatusBar = False です。これは単にテキストを消すのではなく — 制御を
Excel に返すので、バーは「準備完了」などの表示を再開します。これが誰もがつまずく唯一の事実なので、
はっきり述べておく価値があります。
Application.StatusBar = "Working..." ' これでバーはあなたのもの
Application.StatusBar = False ' Excel に返す。ふたたび Excel が管理する
なぜ空文字列ではなく False なのか
終わったときの本能は、メッセージを消すこと、Application.StatusBar = "" です。きれいに見えて、
そして間違いです。空文字列も依然としてあなたのメッセージ — 空っぽのメッセージ — です。Excel は
あなたに譲り続けるので、バーは空のまま座り込み、二度と「準備完了」や選択範囲の合計へ戻りません。
これは古いテキストを残すのと同じバグで、ただ症状が目に見える固まったメッセージではなく、妙に静かな
ステータスバーなので気づきにくいだけです。
Application.StatusBar = False だけが「もう終わった、返す」と告げる唯一の代入です。反射にして
しまいましょう。ステータスバーをオンにする行には、CleanExit ハンドラーの中に対になる = False
がある — ちょうど ScreenUpdating = True がそうであるように。
進捗パーセントの定石
人が「VBA プログレスバー」を検索する理由は、ほとんどいつもこれです。ユーザーが動いているのを見る 必要があるほど長く走るループ。ステータスバーは、追加の UI なしにそれをこなします。
Dim i As Long, n As Long
n = UBound(data)
For i = 1 To n
' ... 処理 ...
If i Mod 100 = 0 Then
Application.StatusBar = "Row " & i & " of " & n & " - " & Format(i / n, "0%")
End If
Next i
2 つの点がこれを正しく感じさせます。第一に、毎回ではなく一定間隔で更新すること(i Mod 100 = 0)
— ステータスバーを 10,000 回書くこと自体が遅く、それほど速く飛んでいく数字をユーザーは読めません。
第二に、ただのスピナーではなく総数に対する進捗を見せること(i of n、パーセント)で、ユーザーが
あとどれくらいかを見積もれるようにします。それが「何かが起きている」と「あなたは 3 分の 2 まで来て
いる」との違いです。
テキストが更新されない理由 — そして DoEvents がはまる場所
ここが人をフォーラムへ送り込む罠です。ループの中で Application.StatusBar を設定したのに、テキストが
画面上でまったく変わらない — コードは明らかに再代入しているのに、最初の値を表示したまま固まる。
ステータスバーも他のすべてと同じで、Excel がメッセージキューを処理する間を得たときにしか描き直され
ません。タイトな VBA ループはその間を決して譲らないので、描画は起きません。
直し方は DoEvents — 制御を少しの間 Excel に返し、バーが実際に描き直される ようにします。
If i Mod 100 = 0 Then
Application.StatusBar = "Row " & i & " of " & n
DoEvents ' Excel にバーを描き直させる
End If
更新と同じ間隔で使い、毎回は使わないこと — DoEvents にはそれ自身のコストと
再入のリスクがあります。そしてここは、ScreenUpdating = False の下で
ステータスバーが UserForm よりも良く振る舞う唯一の場所だと注意してください。ステータスバーは画面
更新を切っていてもきちんと更新されますが、UserForm のプログレスバーには明示的な .Repaint が
必要です。
一行で足りる場面 — そして足りない場面
大多数のマクロにとって、Application.StatusBar が正しい進捗インジケーターで、UserForm に手を伸ばす
のは過剰設計です。一行で済み、フォーカスを奪わず、ちらつかず、ScreenUpdating = False と共存します。
既定ではこれを選びましょう。
UserForm のプログレスバーが余分なコードの元を取るのは、ステータスバーに出せないものが具体的に必要な
ときだけです。グラフィカルに満ちていくバー、キャンセルボタン、複数行の内訳、あるいはユーザーが
見逃せないダイアログでのブランディング。それらが本当に必要なこともありますが — 例外であり、そして
ステータスバーが丸ごと回避しているフォーカス・再描画・モーダルの頭痛がついてきます。それから、バーが
そもそも見えるには Application.DisplayStatusBar が True でなければならない点にも注意してください。
以前のマクロや設定がそれを隠していたら、あなたのテキストは書き込まれても表示されません。
ExcelMaster の活用
良い進捗インジケーターは、書くのに一行、リセットに一行、そこに一定間隔で更新する判断、バーが描き直す
必要のあるところにだけ DoEvents を足す判断、そしてクラッシュが古いメッセージをウィンドウに貼り
付けたまま残さないようエラーハンドラーの中で = False で戻す判断が加わります。リセットを忘れれば、
「Processing 47%...」と永遠に言い続けるブックを出荷することになります。
ExcelMaster は、これを配線して
くれます。「5 万行にわたって走る間、進捗を見せて」と頼めば、ほどよい間隔でステータスバーにパーセントを
書き、実際に動くよう DoEvents と組み合わせ、ScreenUpdating と同じ CleanExit の復元の中で
Application.StatusBar = False を使ってバーをリセットします — だから、行儀よく、自分で後始末をする
進捗インジケーターが手に入ります。
よくある質問
Excel VBA でプログレスバーを表示するには?
いちばん軽い方法は Application.StatusBar = "..." で、ウィンドウ左下のバーにテキストを書き込みます
— UserForm は不要です。ループの中で一定間隔で更新し(たとえば If i Mod 100 = 0 Then)、進捗を
「row i of n」やパーセントで見せ、終わったら Application.StatusBar = False でリセットします。
グラフィカルな UserForm のプログレスバーが余分なコードに見合うのは、満ちていくバーやキャンセル
ボタンが必要なときだけです。
VBA で Application.StatusBar をリセットするには?
Application.StatusBar = False を設定します。これでバーの制御が Excel に返り、ふたたび「準備完了」
や自前のメッセージを表示します。Application.StatusBar = "" は使わないでください — 空文字列も
依然としてあなたのメッセージなので、Excel は譲り続け、バーは通常の挙動に戻らず空のままになります。
マクロの実行中にステータスバーのテキストが更新されないのはなぜですか?
タイトな VBA ループが Excel にメッセージキューを処理させないため、バーが描き直されないからです。
テキストを設定した直後に(更新と同じ間隔で)DoEvents を足し、Excel に描き
直す間を与えましょう。UserForm のプログレスバーとは違い、ステータスバーは ScreenUpdating = False
でも正しく更新されます。
ScreenUpdating を切っていてもステータスバーは動きますか?
はい。Application.StatusBar は Application.ScreenUpdating = False でも更新されます。これは、長い
マクロで UserForm のプログレスバーより良い既定である理由の一つです。タイトなループの中でテキストを
描き直すには、なお DoEvents が必要なこともあります。また Application.DisplayStatusBar が True
であることも確かめてください。さもないとバーは隠れ、あなたのテキストは表示されません。
StatusBar と UserForm のプログレスバー、どちらを使うべき?
ほとんどすべてに Application.StatusBar を使いましょう。一行で、ちらつかず、フォーカスを奪わず、
ScreenUpdating = False を生き延びます。UserForm のプログレスバーを作るのは、グラフィカルに満ちて
いくバー、キャンセルボタン、あるいは一行のバーでは見せられない複数行のステータスが具体的に必要な
ときだけにしましょう。
検証環境
検証環境: Excel 365 (Windows 11), VBA 7.1 — 最終確認 2026-08-18。
関連ガイド: VBA DoEvents · VBA DisplayAlerts · VBA ScreenUpdating · VBA On Error · VBA MsgBox
