ねらい:プログレスバーで「今どれくらい進んだか」を直感表示
長い処理では、ただ待つより「進捗が目で見える」方が安心です。プログレスバーは、進捗率をバーの長さで表す仕組み。初心者でも貼ってすぐ使えるように「最短テンプレ」「ユーザーフォーム型」「セル表示型」「キャンセル対応」「残り時間表示」まで、使い方を丁寧に解説します。
- メリット: 視覚的に分かる/不安や誤操作を減らす/遅延の把握が容易
- 重要ポイント(深掘り):
- UI応答を保つ:
DoEventsを挟み、Excelが固まらないようにする - 更新間隔の工夫: 毎回更新は遅い。100件ごとなど「間引き更新」
- 描画負荷の制御:
Application.ScreenUpdatingは基本OFF、表示更新時だけONに戻す
- UI応答を保つ:
ステータスバー版(最短・邪魔にならない)
一番簡単。画面下のステータスバーに進捗率と件数を出します。
Sub Progress_StatusBar()
Dim total As Long: total = 50000
Dim i As Long
Application.StatusBar = "開始..."
Application.ScreenUpdating = False
For i = 1 To total
' --- 本処理(例) ---
Dim s As String: s = "テスト" & i
' ---------------------
If i Mod 100 = 0 Then ' 100件ごとに更新
Dim pct As Double: pct = i / total
Application.StatusBar = "進捗 " & Format(pct, "0%") & " (" & i & "/" & total & ")"
DoEvents
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のように間隔を置くと高速。総件数に合わせて調整。 - 後片付け: 終了後は必ず
StatusBar=Falseに戻す(他のマクロと競合防止)。
- 間引き更新:
ユーザーフォーム版(見た目重視の本格プログレスバー)
フォームにバー(Frame/Label)を載せて、伸びるバーで進捗を表示します。
準備(デザイン)
- UserForm1 を作成
- FrameProgress(バーの枠、Width例: 300)
- LabelBar(バー本体、初期 Width = 0、BackColor を緑など)
- LabelText(テキスト表示、「0%」など)
コード(標準モジュール)
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 = UserForm1.FrameProgress.Width
Application.ScreenUpdating = False
For i = 1 To total
' --- 本処理(例) ---
Dim s As String: s = "テスト" & i
' ---------------------
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操作可。長処理でのストレス軽減。
- バー幅はピクセル:
Frame.Width * 進捗率が基本。LabelBarは枠内で伸縮。 - 更新負荷:
i Mod 150などでほどよいなめらかさに。
残り時間(ETA)付き表示で体感を良くする
ステータスバーやフォームのテキストに「残り約XX秒」を足します。
Sub Progress_UserForm_WithETA()
Dim total As Long: total = 40000
Dim t0 As Double: t0 = Timer
Dim i As Long
UserForm1.LabelBar.Width = 0
UserForm1.LabelText.Caption = "0%"
UserForm1.Show vbModeless
Dim maxWidth As Single: maxWidth = UserForm1.FrameProgress.Width
For i = 1 To total
' --- 本処理 ---
' ...
If i Mod 200 = 0 Then
Dim pct As Double: pct = i / total
Dim elapsed As Double: elapsed = Timer - t0
Dim eta As Double: If pct > 0 Then eta = elapsed * (1 / pct - 1)
UserForm1.LabelBar.Width = maxWidth * pct
UserForm1.LabelText.Caption = _
Format(pct, "0%") & " 経過 " & Format(elapsed, "0.0") & "s 残り約 " & Format(eta, "0.0") & "s"
DoEvents
End If
Next
UserForm1.LabelBar.Width = maxWidth
UserForm1.LabelText.Caption = "100% 完了"
Unload UserForm1
MsgBox "処理完了!"
End Sub
VB- 重要ポイント(深掘り):
- 序盤のブレ: 初期は推定が不安定。中盤以降の値が目安として有効。
- UI表現: %+経過秒+残り秒で「待つ安心感」が大きく向上。
キャンセルボタン付き(ユーザーが中断可能)
長処理では「やっぱり止めたい」を受け入れる設計が親切です。
準備(UserForm1)
- CommandButtonCancel(Caption: キャンセル)
- 標準モジュールにフラグを追加
' 標準モジュール先頭
Public gCancel As Boolean
' UserForm1 モジュール
Private Sub CommandButtonCancel_Click()
gCancel = True
End Sub
' 実行本体
Sub Progress_UserForm_Cancellable()
gCancel = False
Dim total As Long: total = 60000
Dim i As Long
UserForm1.LabelBar.Width = 0
UserForm1.LabelText.Caption = "0%"
UserForm1.Show vbModeless
Dim maxWidth As Single: maxWidth = UserForm1.FrameProgress.Width
Application.ScreenUpdating = False
For i = 1 To total
' キャンセル判定
If gCancel Then
UserForm1.LabelText.Caption = "キャンセルされました"
Application.ScreenUpdating = True
Unload UserForm1
MsgBox "処理を中断しました。"
Exit Sub
End If
' --- 本処理 ---
' ...
If i Mod 200 = 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% 完了"
Unload UserForm1
MsgBox "処理完了!"
End Sub
VB- 重要ポイント(深掘り):
- フラグで中断:
gCancelをチェックして即Exit。途中で安全に抜ける。 - 後片付け: 画面更新・フォームUnload・メッセージ通知を忘れない。
- フラグで中断:
セル(シート)での簡易バー表示(画面に記録を残したい時)
セル幅を使ってバーを再現。ログや報告用に便利。
Sub Progress_CellBar()
Dim ws As Worksheet: Set ws = Worksheets("Log")
ws.Range("A1:B1").Value = Array("進捗バー", "進捗率")
ws.Range("A2").ClearContents: ws.Range("B2").NumberFormat = "0.0%"
Dim total As Long: total = 20000
Dim i As Long
Dim maxLen As Long: maxLen = 50 ' バーの文字長(□の数)
For i = 1 To total
' --- 本処理 ---
' ...
If i Mod 200 = 0 Then
Dim pct As Double: pct = i / total
Dim filled As Long: filled = CLng(maxLen * pct)
ws.Range("A2").Value = String$(filled, "■") & String$(maxLen - filled, "□")
ws.Range("B2").Value = pct
DoEvents
End If
Next
ws.Range("A2").Value = String$(maxLen, "■")
ws.Range("B2").Value = 1
MsgBox "処理完了!"
End Sub
VB- 重要ポイント(深掘り):
- 視覚記録: 進捗がシートに残るため、後から振り返りやすい。
- 文字ベース: フォントによって見え方が変わるので、全角/半角の見栄えを調整。
例題で練習(貼って試せる)
- 例1: ステータスバー版(Progress_StatusBar)を実行して、%表示の更新を体験。
- 例2: ユーザーフォーム版(Progress_UserForm)でバーが伸びていく様子を確認。
- 例3: ETA付き(Progress_UserForm_WithETA)で残り秒数の見積りを見る。
- 例4: キャンセル対応(Progress_UserForm_Cancellable)で途中中断を試す。
- 例5: セルバー(Progress_CellBar)でシートに記録が残る進捗を作る。
実務の落とし穴と対策(ここが肝)
- 落とし穴1:毎ループ更新で極端に遅くなる
- 対策: 更新は一定ステップのみ(100〜500件ごと)。文字列連結や描画を最小化。
- 落とし穴2:総件数が分からないと%が出せない
- 対策: 事前に最終行などで総件数を計算。分からない場合は「処理件数のみ」表示に切替。
- 落とし穴3:画面が固まる
- 対策:
DoEventsを適度に挿入。長処理中はScreenUpdating=False。
- 対策:
- 落とし穴4:フォームが背後に隠れて見えない
- 対策: フォーム表示直後に
UserForm1.Repaint、非モーダル表示を徹底。
- 対策: フォーム表示直後に
- 落とし穴5:複数マクロでステータスバー競合
- 対策: 終了時に必ずクリア。進捗表示は一元管理。
スターター手順(最短導入)
- まずはステータスバー版を貼って進捗%を出す。
- ユーザーフォーム版を追加し、Frame+Labelでバーを伸ばす。
- ETAやキャンセルボタンを加えて、ユーザー体験を向上。
- セルバーで「進捗記録が残る」スタイルを必要に応じて使い分け。
