長い時間を要する処理をしている間は、マウスカーソルを[砂時計]にしたり、進行の程度(現在どこまで進んでいるのかや、あとどれくらいかかるのか)を表示すると、ユーザに親切です。

そんな進行表示の方法を、三種類紹介します。

1.ステータスバー その1

Excelにはそんな表示をするためのStatusBarというおApplication.StatusBar プロパティがあります。

Application.StatusBar プロパティの仕様は、VBAのヘルプをみてください。

Option Explicit

Dim oldstatusbar As Variant

Public abortFlag As Boolean

Public Sub setStatusBar(msg As Variant)

    'ステータスバー表示

    With Application

        oldstatusbar = .DisplayStatusBar

        .DisplayStatusBar = True

        .StatusBar = msg

    End With

End Sub

Public Sub msgStatusBar(msg As Variant)

    With Application

        .StatusBar = msg

    End With

End Sub

Public Sub resetStatusBar()

    'ステータスバー復帰

    With Application

        .StatusBar = False

        .DisplayStatusBar = oldstatusbar

    End With

End Sub

進行表示のテストプログラムです。

Public Sub progressbar11()

    'StatusBarで進行表示その1

    Dim idx As Long

    Const idxmax As Long = 20

    Dim tm As Variant

    'Excelウィンドウの左下にあるステータスバーを初期化する

    Call setStatusBar("しばらくお待ちください‥")

    For idx = 0 To idxmax

        'ステータスバーにメッセージを表示する

        Call msgStatusBar("しばらくお待ちください‥" & idx & "/" & idxmax)

        '**********

        ' 本来の繰り返し処理がここに入る

        '**********

        '**********

        ' 本来の繰り返し処理の代わり

        tm = Timer() 'システムのタイマー

        Do Until Timer() - tm > 1

            DoEvents '1 秒経過するまで待つ

        Loop

        '**********

    Next idx

    'ステータスバーをリセットする

    Call resetStatusBar

End Sub

以下、使用例です。  

どうですか?とても簡単に使えますよね。動作の負荷もあまりかからないし、手軽に使えて便利です。 その反面、なんだか物足りなさも感じます。

2.ステータスバー その2

今度は、同じステータスバーですが、少しグラフィカルっぼくしてみます。

Public Function initStrBar(barLength As Long) As Variant

    initStrBar = String(barLength, "□")

End Function

Public Function setStrBar(crntValue As Long, maxValue As Long, barLength As Long) As Variant

    setStrBar = String(CInt(barLength * crntValue / maxValue), "■") _

                & String(barLength - CInt(barLength * crntValue / maxValue), "□")

End Function

Public Sub progressbar12()

    'StatusBarで進行表示 その2

    Dim idx As Long

    Const idxmax As Long = 20

    Dim tm As Variant

    Const prgrsmax As Long = 30

    'Excelウィンドウの左下にあるステータスバーを初期化する

    Call setStatusBar(initStrBar(prgrsmax))

    For idx = 0 To idxmax

        'ステータスバーにバーを表示する

        Call msgStatusBar(setStrBar(idx, idxmax, prgrsmax))

        '**********

        ' 本来の繰り返し処理がここに入る

        '**********

        '**********

        ' 本来の繰り返し処理の代わり

        tm = Timer() 'システムのタイマー

        Do Until Timer() - tm > 1

            DoEvents '1 秒経過するまで待つ

        Loop

        '**********

    Next idx

    'ステータスバーをリセットする

    Call resetStatusBar

End Sub

実行結果は次のとおり。

少しはグラフィカルになったでしようか?

まだまだですかね??

3. フォームを使ったプログレスバー

では自前のプログレスバーです。

以下のように、まず、ユーザフォームを挿入します。

lblBackをlblFrontのうしろに、図のように配置します。ここではコントロールの大きさは橙でかまいません。

ユーザフォームのプログラムです。

Option Explicit

Public widthmax As Long

Private Sub cmdAbort_Click()

    abortFlag = True

End Sub

Private Sub UserForm_Initialize()

    With txtMsg

        .BackColor = &H8000000F

        .BorderStyle = fmBorderStyleSingle

        .BorderColor = &H8000000F

        .Text = ""

    End With

    With txtProgressbar

        .BackColor = &H8000000F

        .BorderStyle = fmBorderStyleSingle

        .BorderColor = &H8000000F

        .Text = ""

    End With

    With lblBack

        .BackColor = &H8000000F

        widthmax = .Width - 2 * 1

    End With

    With lblFront 'サイズを調節します

        .Left = lblBack.Left + 1

        .Top = lblBack.Top + 2

        .Height = lblBack.Height - 2 * 2

        .Width = 0

        .BackColor = &H8000&

        .Caption = ""

        .TextAlign = fmTextAlignCenter

    End With

End Sub

Private Sub UserForm_Terminate()

    abortFlag = True

End Sub

次に進行表示のプログラム。

Public Sub progressbar21()

    'ユーザフォームで進行表示

    Dim idx As Long

    Const idxmax As Long = 20

    Dim tm As Variant

    Dim wdmax As Long

    With frmProgress

        'フォームを初期化後表示する

        wdmax = .widthmax 'フォームからラベルの表示幅を取得

        .txtMsg.Text = "しばらくお待ちください‥"

        'フォームを表示

        ' → modelessなので表示したまま他の(show 以下の)処理を実行可能

        '   ただし、Modalで表示しているフォームから、さらにmodelessで

        '   フォームを表示することはできない

        .Show vbModeless

        abortFlag = False '中止フラグを初期化

        For idx = 0 To idxmax

            If abortFlag Then

                '中止ボタンが押されたら、中止

                Exit For

            End If

            'プログレスバーを表示

            With .lblFront

                .Width = wdmax * idx / idxmax

            End With

            With .txtProgressbar

                .Text = idx & "/" & idxmax

            End With

            '**********

            ' 本来の繰り返し処理がここに入る

            '**********

            '**********

            ' 本来の繰り返し処理の代わり

            tm = Timer() 'システムのタイマー

            Do Until Timer() - tm > 1

                DoEvents '1 秒経過するまで待つ

            Loop

            '**********

        Next idx

    End With

    'フォームを削除する

    Unload frmProgress

    Set frmProgress = Nothing

End Sub

実行結果は右図のとおりです。