Excel VBA 逆引き集 | 進捗率表示

Excel VBA
スポンサーリンク

ねらい:進捗率を「見える化」して不安をなくす

長い処理でも「今どれくらい進んでいるか」が分かれば、ユーザーは安心して待てます。ここでは初心者でも扱える進捗表示のテンプレを、重要ポイントを深掘りしながら紹介します。基本は「総件数を数える→現在件数を割る→パーセンテージにして表示」。表示手段はステータスバー、セル表示、ユーザーフォーム(プログレスバー)の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%") で桁数を統一すると読みやすい。

ユーザーフォームでプログレスバー(見た目重視・丁寧)

  1. ユーザーフォーム(例: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が必要なら時間計測を組み込み、期待値の見せ方を調整。

タイトルとURLをコピーしました