この記事でできること
1000行のデータ処理マクロを実行した。画面が固まったまま動かない。あと何分かかるのかわからない。
「フリーズしたのか、それとも処理中なのか」——判断がつかない。2分待って、3分待って、不安になってExcelを強制終了してしまった。再度開いたら、処理が中途半端に終わっていてデータがおかしくなっていた。
この記事のVBAを使えば、マクロ実行中にステータスバーへ「350 / 1000 件処理中… 経過: 00:01:23」と進捗が表示されます。動いていることが一目でわかる。あとどれくらいかも見える。不安で途中終了させてしまう事故がゼロになります。
- 対象:マクロの処理中に不安を感じたことがある人。VBAを知らなくてOK
- 所要時間:コピペ → 実行まで約5分
—
完成イメージ(Before / After)
Before(進捗表示なし)

| A | B | |
|---|---|---|
| 1 | 状態 | 表示 |
| 2 | 画面固まる | (何も表示されない) |
| 3 | 応答なし | フリーズ?処理中? |
| 4 | 不安で強制終了 | データが壊れた |
After(進捗表示あり)

| A | B | |
|---|---|---|
| 1 | 状態 | ステータスバー表示 |
| 2 | 処理中 | 350 / 1000 件処理中… |
| 3 | 処理中 | 700 / 1000 件処理中… |
| 4 | 完了 | 処理完了(1000件) |
進捗が見えるから安心して待てる。強制終了の事故がゼロに。
あの時「150 / 500 件処理中…」とステータスバーに表示されていれば、安心して待てたはずだ。実際にStatusBarを1行追加しただけで、大量ファイル統合(複数Excelファイルを1つに統合)の処理中も「ちゃんと動いてる」と分かるようになった。
この記事では、マクロ実行中に進捗を表示する方法を最小版と実務版の2パターンで紹介する。まずは最小版をコピペして、ステータスバーの手軽さを体験してほしい。
ステータスバーに進捗を出すだけで、マクロ実行中の「動いてるのか分からない」不安がなくなる。
—
どんな場面で使う?
- 大量ファイルの処理中に「今何件目か」を表示して安心感を出したい
- マクロ実行中に画面が固まったように見えて同僚から「フリーズした?」と聞かれる
- 長時間処理のマクロを同僚に渡すとき、進捗が分からないと不安がられる
- 処理完了までの見込み時間を表示して、待ち時間のストレスを減らしたい
—
実行前の準備
バックアップを取る
マクロ実行前に、Excelファイルのコピーを別フォルダに保存しておく。進捗表示の追加自体はデータを壊す操作ではないが、大量データを処理するマクロに組み込む以上、バックアップは習慣にしておく。
Excelをマクロ有効ブック(.xlsm)で保存する
拡張子が .xlsx のままだとマクロは保存できない。
- 「ファイル」→「名前を付けて保存」
- ファイルの種類を「Excelマクロ有効ブック (*.xlsm)」に変更
- 保存
—
手順(コピペ → 実行まで約5分)
VBE(コードを書く画面)を開く
- Excelで
Alt + F11を押す - VBE(Visual Basic Editor)が開く
標準モジュールを挿入する
- VBEのメニュー →「挿入」→「標準モジュール」
- 白い画面(コードウィンドウ)が表示される
コードを貼り付けて実行する
- コードウィンドウに、下のコードをそのままコピペする
Alt + F8→ マクロ名を選んで「実行」
—
コード(最小版)– ステータスバーに処理件数を表示
'============================================================
' ■ ステータスバーに処理件数を表示(最小版)
' → ループ処理の進捗をステータスバーで確認できる
' → 処理完了後にステータスバーをリセットする
'============================================================
Sub ShowProgressMinimal()
'--- ★書き換えポイント ---
Dim wsName As String
wsName = "Sheet1" '← 処理対象のシート名
Dim startRow As Long
startRow = 2 '← データの開始行(1行目がヘッダーなら2)
Dim dataCol As String
dataCol = "A" '← データが入っている列
'--- ★ここまで ---
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets(wsName)
'--- 最終行を取得
Dim lastRow As Long
lastRow = ws.Cells(ws.Rows.Count, dataCol).End(xlUp).Row
Dim totalCount As Long
totalCount = lastRow - startRow + 1
'--- ループ処理(ここに実際の処理を書く)
Dim i As Long
For i = startRow To lastRow
'=== ここに1行ごとの処理を書く ===
'(例)セルの値を読み取って何かする
' Dim val As String
' val = ws.Cells(i, dataCol).Value
'=================================
'--- ステータスバーに進捗を表示
Application.StatusBar = (i - startRow + 1) & " / " & totalCount & " 件処理中..."
Next i
'--- 処理完了:ステータスバーをリセット
Application.StatusBar = False
MsgBox totalCount & " 件の処理が完了しました。", vbInformation
End Sub
書き換えポイント
| 変数 | 説明 | 初期値 |
|---|---|---|
wsName |
処理対象のシート名 | "Sheet1" |
startRow |
データの開始行 | 2(1行目ヘッダー想定) |
dataCol |
データが入っている列 | "A" |
コードの流れ
- シートと最終行の取得: 処理対象のシートとデータの最終行を特定する
- ループ処理: 各行に対して処理を実行する
- StatusBar更新: ループの中で「○件 / ○件 処理中…」とステータスバーに表示する
- リセット: 処理完了後に
Application.StatusBar = Falseでステータスバーを元に戻す
テスト方法: A列に適当なデータを100行ほど入れて実行する。ステータスバー(Excel下部)に件数が表示されれば成功。フォルダ内のファイル一覧を取得する処理(フォルダ内ファイル一覧を自動取得)と組み合わせて、ファイル処理の進捗を表示することもできる。
—
コード(実務版)– 高速化+応答維持+経過時間表示
実務では1000行を超えるデータを処理することが珍しくない。最小版のまま大量データを流すと、処理は遅いし画面はチカチカするし、タスクバーに「応答なし」が出る。
以前、DoEventsを入れずに1000行の生産データを処理したら、タスクバーに「応答なし」と表示されて上司に「パソコン壊れた?」と聞かれた。DoEventsを1行追加するだけで応答なし表示が消えて、ステータスバーの進捗もスムーズに更新されるようになった。
最小版で「ステータスバーに文字が出る」ことを確認できたら、実務版で高速化と経過時間表示を追加しよう。大量データを扱う場面で、この進捗表示があるだけで安心感がまるで違う。
実務版では以下の3つを追加する:
- ScreenUpdating=False: 画面更新を止めて処理速度を2〜5倍に高速化
- DoEvents: OSに制御を返して「応答なし」表示を防ぎ、StatusBarの表示も更新する
- 経過時間表示: Timer関数で処理開始からの経過時間を「hh:mm:ss」形式で表示
複数シート処理(複数シートを一括処理する方法)のように対象が多い場合は、この実務版を使うことを推奨する。
'============================================================
' ■ 進捗表示+高速化+応答維持(実務版)
' → ScreenUpdating=False で高速化
' → DoEvents で「応答なし」防止+StatusBar更新
' → Timer で経過時間を表示
' → エラー時も ScreenUpdating=True に復帰する
'============================================================
Sub ShowProgressAdvanced()
'--- ★書き換えポイント ---
Dim wsName As String
wsName = "Sheet1" '← 処理対象のシート名
Dim startRow As Long
startRow = 2 '← データの開始行
Dim dataCol As String
dataCol = "A" '← データが入っている列
Dim updateInterval As Long
updateInterval = 10 '← 何件ごとにステータスバーを更新するか
'--- ★ここまで ---
'--- 画面更新を停止(高速化)
Application.ScreenUpdating = False
'--- エラー時にScreenUpdating=Trueに復帰するためのエラー処理
On Error GoTo ErrHandler
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets(wsName)
'--- 最終行を取得
Dim lastRow As Long
lastRow = ws.Cells(ws.Rows.Count, dataCol).End(xlUp).Row
Dim totalCount As Long
totalCount = lastRow - startRow + 1
'--- 開始時刻を記録
Dim startTime As Double
startTime = Timer
'--- ループ処理
Dim i As Long
For i = startRow To lastRow
'=== ここに1行ごとの処理を書く ===
'(例)セルの値を読み取って何かする
' Dim val As String
' val = ws.Cells(i, dataCol).Value
'=================================
'--- N件ごとにステータスバーを更新(毎回更新すると遅くなる)
If (i - startRow + 1) Mod updateInterval = 0 Or i = lastRow Then
'--- 経過時間を計算
Dim elapsed As Double
elapsed = Timer - startTime
'--- 経過時間を hh:mm:ss 形式に変換
Dim elapsedStr As String
elapsedStr = Format(elapsed / 86400, "hh:nn:ss")
'--- ステータスバーに進捗+経過時間を表示
Application.StatusBar = _
(i - startRow + 1) & " / " & totalCount & " 件処理中... " & _
"経過: " & elapsedStr
'--- OSに制御を返す(応答なし防止+StatusBar更新)
DoEvents
End If
Next i
'--- 処理完了:経過時間を含む完了メッセージ
Dim totalElapsed As String
totalElapsed = Format((Timer - startTime) / 86400, "hh:nn:ss")
Application.StatusBar = "処理完了(" & totalCount & "件 / 経過: " & totalElapsed & ")"
'--- 画面更新を再開
Application.ScreenUpdating = True
MsgBox totalCount & " 件の処理が完了しました。" & vbCrLf & _
"経過時間: " & totalElapsed, vbInformation
'--- 3秒後にステータスバーをリセット(完了メッセージを少し残す)
Application.StatusBar = False
Exit Sub
ErrHandler:
'--- エラー時もScreenUpdatingを必ず復帰させる
Application.ScreenUpdating = True
Application.StatusBar = False
MsgBox "エラーが発生しました。" & vbCrLf & _
"エラー番号: " & Err.Number & vbCrLf & _
"内容: " & Err.Description, vbCritical
End Sub
書き換えポイント
| 変数 | 説明 | 初期値 |
|---|---|---|
wsName |
処理対象のシート名 | "Sheet1" |
startRow |
データの開始行 | 2 |
dataCol |
データが入っている列 | "A" |
updateInterval |
何件ごとにステータスバーを更新するか | 10 |
コードの流れ
- ScreenUpdating=False: 画面更新を停止して高速化する
- On Error GoTo ErrHandler: エラー発生時に必ず ScreenUpdating=True に復帰するための安全策(エラー処理の詳細は VBAのエラー処理入門 を参照)
- 最終行の取得: データの範囲を自動検出する
- Timer で開始時刻を記録: 処理時間の計測を開始する
- N件ごとにStatusBar更新: 毎ループではなく
updateInterval件ごとに更新(パフォーマンス維持) - DoEvents: OSに制御を返し、「応答なし」を防ぎつつStatusBarの表示を更新する
- 完了処理: 経過時間を含む完了メッセージをMsgBoxで表示し、StatusBarをリセットする
- エラーハンドラ: エラー時もScreenUpdating=TrueとStatusBar=Falseを実行して安全に復帰する
ScreenUpdating=False にした処理は、必ずエラー処理で True に戻す仕組みを入れておく。これを忘れると画面が真っ白になる。詳しくは VBAのエラー処理入門 を参照。
—
よくある落とし穴5選
1. 処理完了後もステータスバーにメッセージが残ったまま
原因: Application.StatusBar = False を書き忘れている。
対策: ループの後に必ず Application.StatusBar = False を入れる。エラーハンドラの中にも入れておく(実務版コード参照)。
2. ScreenUpdating=False のまま止まって画面が真っ白に
原因: エラーで処理が中断し、ScreenUpdating = True に戻る前にマクロが終了した。
自分もこれをやった。ScreenUpdating=Falseにしたら処理が3倍速くなって喜んでいたが、途中でエラーが出て止まった時にTrueに戻し忘れてExcelの画面が真っ白になった。セルをクリックしても何も表示されない。VBEを開いてイミディエイトウィンドウに Application.ScreenUpdating = True と入力して実行したらようやく復帰した。それ以来、On Error GoTo でScreenUpdatingの復帰を必ず書くようにしている。
対策: 実務版コードのように On Error GoTo ErrHandler で、エラー時も ScreenUpdating = True に戻す処理を入れる。
3. StatusBarの表示が更新されない
原因: ScreenUpdating = False の状態では、StatusBarの表示更新も止まることがある。
対策: StatusBarを更新した直後に DoEvents を呼ぶ。実務版コードではN件ごとにDoEventsを呼んでいる。
4. DoEventsを入れたら処理が遅くなった
自分も最初はループの中で毎回DoEventsを呼んでいた。1000行の処理が30秒から2分に増えて「高速化どころか遅くなった」と焦った。updateIntervalで間引くだけで元の速度に戻った。
原因: ループの中で毎回 DoEvents を呼んでいる。DoEvents は OS に制御を返す処理で、毎回呼ぶとオーバーヘッドが大きい。
対策: updateInterval(初期値10)件ごとに1回だけ呼ぶ。1000件のデータなら100回の DoEvents で済む。データ量が多い場合は updateInterval を50〜100に増やす。
5. Timer の値がマイナスになる
原因: Timer は午前0時からの経過秒数を返す。日付をまたぐ処理では0時にリセットされ、Timer - startTime がマイナスになる。
対策: 日付をまたぐ可能性がある処理では、Timer の代わりに Now を使う。通常の業務時間内の処理であれば Timer で問題ない。
VBAのステータスバーに進捗が表示されないときの対処法
「StatusBarに値を設定したのに何も表示されない」という場合、原因は Application.DisplayStatusBar = False になっていることだ。コードの先頭に Application.DisplayStatusBar = True を追加し、処理完了後に Application.StatusBar = False でリセットすれば正しく表示される。
VBAで進捗表示を入れたら処理が遅くなったときの対処法
「進捗表示を追加したら処理速度が半分になった」という場合、原因はループの全回にStatusBar更新を入れていることだ。1万回のループなら100回に1回(If i Mod 100 = 0 Then)だけ更新するようにすれば、速度をほぼ維持しつつ進捗表示ができる。
—
FAQ
Q1: ステータスバーはどこに表示される?
Excelウィンドウの一番下にある細い帯がステータスバー。通常は「準備完了」や選択範囲の合計値が表示されている場所。Application.StatusBar に文字列を代入すると、ここに任意のテキストが表示される。
Q2: UserForm のプログレスバーとどちらがいい?
手軽さならStatusBar。見た目のインパクトならUserFormのプログレスバー。StatusBarはコード1行で表示できるので、既存のマクロに進捗表示を追加するならStatusBarが圧倒的に楽。UserFormは見栄えは良いが、フォーム作成+表示制御のコードが必要で手間がかかる。
Q3: ボタンクリックで進捗付きマクロを実行したい
ボタン設置(マクロをボタン1つで実行する方法)と組み合わせれば、ワンクリックで進捗表示付きの処理が走る。ボタンの OnAction に進捗表示付きマクロ名を指定するだけ。
Q4: ScreenUpdating=False にしなくても進捗は表示される?
される。最小版コードは ScreenUpdating を操作していないが、ステータスバーは更新される。ただし画面が毎行更新されるため処理が遅く、画面がチカチカする。大量データ(100行以上)を処理するなら、実務版の ScreenUpdating=False を推奨する。
Q5: 経過時間ではなく残り時間を表示したい
現在の処理速度から概算できる:
Dim progress As Double
progress = (i - startRow + 1) / totalCount
Dim remaining As Double
remaining = elapsed / progress - elapsed
Application.StatusBar = "残り約 " & Format(remaining / 86400, "hh:nn:ss")
ただし処理速度が一定でないと誤差が大きくなるため、あくまで目安として表示する。
—
まとめ
Application.StatusBar = "テキスト"でステータスバーに進捗を表示できる- 処理完了後は
Application.StatusBar = Falseで必ずリセットする ScreenUpdating = Falseで処理を高速化し、DoEventsでStatusBarの更新と「応答なし」防止を両立する- エラー時に
ScreenUpdating = Trueに戻す処理を必ず入れる(On Error GoTo) - 進捗表示があるだけで、大量データ処理の「動いてるのか分からない」不安がなくなる
関連記事
- 複数Excelファイルを1つに統合 — 大量ファイル統合で進捗表示が活きる場面
- 複数シートを一括処理する方法 — シート数が多い処理にも進捗表示を組み込める
- VBAのエラー処理入門 — ScreenUpdating復帰に必須のエラー処理を学ぶ
—
次にやりたくなること
- 複数Excelファイルを1つに統合する方法: 大量ファイルを統合する処理に進捗表示を組み込めば、何ファイル目まで完了したか一目で分かる
- エラー処理で止まらないマクロを作る方法: ScreenUpdating復帰とStatusBarリセットを安全に行うためのエラー処理を学ぶ
- マクロをボタン1つで実行する方法: 進捗表示付きマクロをボタンに割り当てれば、ワンクリックで安心して大量処理を実行できる
—
進捗表示があるだけで、マクロ実行中の不安がゼロになる。まずは最小版でStatusBarの手軽さを体験してみてほしい。
—


コメント