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

Excel VBA の StatusBar — UserForm なしでマクロの進捗を見せる(そして永遠に固まって残るメッセージ)

|

Excel VBA の StatusBar — UserForm なしでマクロの進捗を見せる(そして永遠に固まって残るメッセージ)

TL;DRApplication.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 プログレスバーが元を取る場面
  • ScreenUpdatingCleanExit の復元との組み合わせ方

考え方の軸:バーは 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.DisplayStatusBarTrue でなければならない点にも注意してください。 以前のマクロや設定がそれを隠していたら、あなたのテキストは書き込まれても表示されません。

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.StatusBarApplication.ScreenUpdating = False でも更新されます。これは、長い マクロで UserForm のプログレスバーより良い既定である理由の一つです。タイトなループの中でテキストを 描き直すには、なお DoEvents が必要なこともあります。また Application.DisplayStatusBarTrue であることも確かめてください。さもないとバーは隠れ、あなたのテキストは表示されません。

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