ねらい:進捗率を「見える化」して不安をなくす
長い処理でも「今どれくらい進んでいるか」が分かれば、ユーザーは安心して待てます。ここでは初心者でも扱える進捗表示のテンプレを、重要ポイントを深掘りしながら紹介します。基本は「総件数を数える→現在件数を割る→パーセンテージにして表示」。表示手段はステータスバー、セル表示、ユーザーフォーム(プログレスバー)の3段構えが鉄板です。
- 目的: 進捗率(%)と残り時間感覚を伝え、操作ミスや不安を減らす
- 基本式: 進捗率 = 現在件数 / 総件数 × 100
- 重要ポイント(深掘り):
- DoEventsでUI応答を保つ: 長処理でも画面が固まらない
- 更新間隔を調整: 毎回更新は重い。一定ステップで更新する
- ScreenUpdatingの使い分け: 計算中はOFF、進捗描画時のみONに戻す方法も有効
ステータスバーで進捗率表示(最も簡単・邪魔にならない)
Sub Progress_StatusBar()
Dim total As Long, i As Long
total = 50000
Application.StatusBar = "準備中..."
Application.ScreenUpdating = False
For i = 1 To total
' --- 本処理(例:文字作成) ---
Dim s As String
s = "テスト" & i
' ------------------------------
' 100件ごとに進捗表示を更新(軽量化)
If i Mod 100 = 0 Then
Dim pct As Double: pct = i / total
Application.StatusBar = "進捗 " & Format(pct, "0%") & " (" & i & "/" & total & ")"
DoEvents ' 画面・UI応答を確保
End If
Next
Application.ScreenUpdating = True
Application.StatusBar = "完了! 100%"
' 数秒後にステータスバーをクリア
Application.OnTime Now + TimeValue("00:00:05"), "ClearStatusBar"
End Sub
Sub ClearStatusBar()
Application.StatusBar = False
End Sub
VB- 重要ポイント(深掘り):
- 更新間隔:
i Mod 100のように間引き更新すると高速。総件数に応じて間隔を調整。 - DoEvents: ユーザーがキャンセルしたり、Excelが「応答なし」にならないための必須呼び出し。
- ScreenUpdating: 描画負荷を下げるため処理中はOFF、最後にONへ戻す。
- 更新間隔:
セルに進捗を表示(ログや記録と相性が良い)
Sub Progress_Cell()
Dim ws As Worksheet: Set ws = Worksheets("Log")
ws.Range("A1").Value = "進捗"
ws.Range("B1").Value = "件数"
Dim total As Long: total = 20000
Dim i As Long
Application.ScreenUpdating = False
For i = 1 To total
' --- 本処理 ---
' ...(省略)
If i Mod 200 = 0 Then
Dim pct As Double: pct = i / total
ws.Range("A2").Value = Format(pct, "0.0%")
ws.Range("B2").Value = i & " / " & total
DoEvents
End If
Next
Application.ScreenUpdating = True
ws.Range("A2").Value = "100.0%"
ws.Range("B2").Value = total & " / " & total
MsgBox "処理完了!"
End Sub
VB- 重要ポイント(深掘り):
- 見える場所: 進捗セルは固定位置(例:Log!A2/B2)にして、ユーザーがすぐ見られるように。
- 書式の統一:
Format(pct, "0.0%")で桁数を統一すると読みやすい。
ユーザーフォームでプログレスバー(見た目重視・丁寧)
- ユーザーフォーム(例:UserForm1)に Label を2つ置く
- LabelBar(幅を伸ばすバー)
- LabelText(%表示テキスト)
- UserFormの幅を例: 300px程度に設定
' 標準モジュール
Sub Progress_UserForm()
Dim total As Long: total = 30000
Dim i As Long
' 初期表示
UserForm1.LabelBar.Width = 0
UserForm1.LabelText.Caption = "0%"
UserForm1.Show vbModeless ' 非モーダルで操作継続可能
Dim maxWidth As Single: maxWidth = 250 ' バー最大幅(フォームに合わせて調整)
Application.ScreenUpdating = False
For i = 1 To total
' --- 本処理 ---
' ...(省略)
If i Mod 150 = 0 Then
Dim pct As Double: pct = i / total
UserForm1.LabelBar.Width = maxWidth * pct
UserForm1.LabelText.Caption = Format(pct, "0%") & " (" & i & "/" & total & ")"
DoEvents
End If
Next
Application.ScreenUpdating = True
UserForm1.LabelBar.Width = maxWidth
UserForm1.LabelText.Caption = "100% (" & total & "/" & total & ")"
MsgBox "処理完了!"
Unload UserForm1
End Sub
VB- 重要ポイント(深掘り):
- vbModeless: 完了までExcel操作も可能。長処理でも不安が減る。
- バー幅更新: ピクセルの伸縮で「進捗の見える化」。%表示と件数を併記すると具体的。
- 負荷管理: 更新間隔(
i Mod 150)を調整して滑らかさと速度のバランスを取る。
推定残り時間の表示(体感をさらに良くする)
Sub Progress_WithETA()
Dim total As Long: total = 40000
Dim i As Long, t0 As Double: t0 = Timer
Application.StatusBar = "開始..."
For i = 1 To total
' --- 本処理 ---
' ...(省略)
If i Mod 200 = 0 Then
Dim elapsed As Double: elapsed = Timer - t0
Dim pct As Double: pct = i / total
Dim eta As Double
If pct > 0 Then eta = elapsed * (1 / pct - 1) ' 残り秒数の推定
Application.StatusBar = "進捗 " & Format(pct, "0%") & _
" | 経過 " & Format(elapsed, "0.0") & "s" & _
" | 残り約 " & Format(eta, "0.0") & "s"
DoEvents
End If
Next
Application.StatusBar = "完了!"
Application.OnTime Now + TimeValue("00:00:05"), "ClearStatusBar"
End Sub
VB- 重要ポイント(深掘り):
- ETA(Estimated Time of Arrival): 完了予測で「あと何秒?」の不安を解消。
- 初期バラつき: 序盤は推定がぶれやすい。中盤以降の値が安定。
例題で練習(貼って試せる)
- 例1(手軽): ステータスバー表示(Progress_StatusBar)で進捗%を体感。
- 例2(記録): セル表示(Progress_Cell)で進捗と件数をシートに残す。
- 例3(見た目重視): ユーザーフォーム(Progress_UserForm)でバーと%を表示。
- 例4(残り時間): ETA表示(Progress_WithETA)で時間見積もり付きの進捗を確認。
実務の落とし穴と対策(ここが肝)
- 落とし穴1:毎ループ更新で極端に遅くなる
- 対策: 更新間隔を設ける(例:100件ごと)。文字列連結・描画を減らす。
- 落とし穴2:総件数が分からないと%が出せない
- 対策: 事前に総件数を算出(最終行取得など)。不明なら「完了件数のみ」表示。
- 落とし穴3:画面が固まる
- 対策: DoEventsを適度に入れる。ScreenUpdatingはOFFで計算負荷を抑える。
- 落とし穴4:ETAが外れる
- 対策: 処理の重さが行ごとに異なると誤差が出る。ガイド程度に扱う。
- 落とし穴5:複数マクロが同時にステータスバーを使う
- 対策: 終了時に必ずクリア(Application.StatusBar=False)。競合を避ける。
スターター手順(最短導入)
- 手順1: ステータスバー版を貼って、更新間隔を「総件数に対して適度」に設定。
- 手順2: セル表示でログ残しが必要なら Progress_Cell を導入。
- 手順3: UIをリッチにしたいなら UserForm のプログレスバーを追加。
- 手順4: ETAが必要なら時間計測を組み込み、期待値の見せ方を調整。
