Excel VBA 逆引き集 | プログレスバー

Excel VBA
スポンサーリンク

ねらい:プログレスバーで「今どれくらい進んだか」を直感表示

長い処理では、ただ待つより「進捗が目で見える」方が安心です。プログレスバーは、進捗率をバーの長さで表す仕組み。初心者でも貼ってすぐ使えるように「最短テンプレ」「ユーザーフォーム型」「セル表示型」「キャンセル対応」「残り時間表示」まで、使い方を丁寧に解説します。

  • メリット: 視覚的に分かる/不安や誤操作を減らす/遅延の把握が容易
  • 重要ポイント(深掘り):
    • UI応答を保つ: DoEvents を挟み、Excelが固まらないようにする
    • 更新間隔の工夫: 毎回更新は遅い。100件ごとなど「間引き更新」
    • 描画負荷の制御: Application.ScreenUpdating は基本OFF、表示更新時だけONに戻す

ステータスバー版(最短・邪魔にならない)

一番簡単。画面下のステータスバーに進捗率と件数を出します。

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:複数マクロでステータスバー競合
    • 対策: 終了時に必ずクリア。進捗表示は一元管理。

スターター手順(最短導入)

  1. まずはステータスバー版を貼って進捗%を出す。
  2. ユーザーフォーム版を追加し、Frame+Labelでバーを伸ばす。
  3. ETAキャンセルボタンを加えて、ユーザー体験を向上。
  4. セルバーで「進捗記録が残る」スタイルを必要に応じて使い分け。

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