「プログレスバー」のクラス

Excelのユーザーフォームにはプログレスバー(処理中の進行状況を「帯」の長さで視覚的に見せるもの)コントロールがありません。そこで似たものを作りました。
「プログレスバー」って?「クラス」って? まず、「プログレスバー」は、比較的時間が掛かる処理の進行状況を「帯」の長さで視覚的に表示させるコントロールとか画面ツールのことです。
次に、「クラス」は、ここでの意味としてはその中の細かい記述を理解せずに利用できるように「カプセル化」して、外部からはメソッドやプロパティで制御できるようにしたものです。
これを前提として、以下のサンプルを理解していってください。
まず、「ライセンス」の話をしておきます。
実は旧Visual Basicには「Microsoft ProgressBar Control」というものが搭載されていましたから、このような用途にはこれが一番適しているのです。 この「Microsoft ProgressBar Control」を見つけて使っている方は、ここで何でこのような「代替コントロール」のようなものを紹介しているのだろうと疑問に思うかもしれません。 ですが、「Microsoft ProgressBar Control」は、Microsoft Officeには搭載されておらず、当然、Microsoft Officeからはインストールされません。 開発言語であるVisual Basic (VBAではありません)に搭載されているコントロールですから、そのVisual Basicがインストールされていない環境で使ってしまうのは「ライセンス違反」なのです。
また、ここで「Microsoft ProgressBar Control」を使ったマクロを作る方はVisual Basicがインストールされている環境で何の問題もないと考えているかも知れませんが、 作成したマクロを搭載するワークブックを他のPCで動かそうとした時に、そのPCにVisual Basicがインストールされていなければ動かないわけです。 この時、たまたま、他のソフトのランタイムとして「Microsoft ProgressBar Control」だけがインストールされている場合がありますが、インタプリタ動作のExcelVBAではランタイムライセンスはあり得ないので、ライセンスに抵触するということを覚えておいて下さい。 仕事上で、自社で使うものや、客先に納品するようなものでは、特にライセンスに抵触するような問題があると、それは作成者個人の問題を超えてしまうので、なおさら注意が必要です。
そこで、ここで紹介する「プログレスバー」なのです。「プログレスバー」というもの自体はコントロールにしては比較的構造が簡単なので、「Microsoft ProgressBar Control」がなくても標準のコントロールを組み合わせて使うことで同様な機能が得られるものです。 ここではそれを例として紹介しています。

では、サンプルを見てみましょう。
処理を開始すると、フォーム上に「プログレスバー」のようなものが延びていきます。
プログレスバー
(この画像をクリックすると、ダウンロードができます。)
ダウンロードした圧縮ファイルには、利用するクラスモジュール、フォームと、このページのサンプルのExcelワークブックが入っています。
単に処理中の表現を行なうだけでなく、Escキーによる中断機能も持たせてあります。
Escキーを押した時の中断動作
このような処置を行なうのは、「すぐには終わらない処理」で「後どのくらいで終わるのか」などを視覚的に表示させるためです。 ですが、いくつか前提条件があります。
第一に、コード上での「繰り返し処理」であることが前提です。1行の「FileCopy」で大きいファイルだから時間が掛かり、 これの動作を「プログレスバー」で表示させようとしても、1行の記述でしかないものは表現のしようがありません。
もうひとつは、全体の件数が最初に把握できる処理であることです。 「プログレスバー」の帯の長さは「現在件数」と「全体件数」から算出されますから、「全体件数」が事前に捉えられない処理には利用できません。

次に、利用する場合の現状の処理記述の変更箇所です。
処理の組み込みは、「clsProgressBar1」「frmProgressBar1」をVBEのプロジェクトエクスプローラ上でインポートします。
プロジェクトエクスプローラ
これがインポートした状態です。
サンプルは何も処理することがないので、最大1000件の処理として、1件に10ミリ秒ずつウエイトさせていますが、このサンプルを参考にクラス側との連携を追加して下さい。

サンプルコードを見る前に全体構造を説明しておきます。
全体の処理構造
「プログレスバー」を組み込みたい処理が、元々1つのプロシージャで動いていたとした場合、この図のように「起動処理」と「メイン処理」に分割する必要があります。 中断機能などを動作させるために、「プログレスバー」はモーダルのユーザーフォームを利用していますから、元々の記述に「プログレスバー」Showメソッドを書いたら、それ以降の記述は動作しません。 このため、「メイン処理」のプロシージャ名を一旦「プログレスバー」に引き渡してやって、「プログレスバー」が「メイン処理」を呼び出す構造になっています。
これを前提に以下のサンプルコードを見て下さい。

では、サンプルコードです。
下記のコードは全体の「起動処理」と、「プログレスバー」が表示されている間に動作する「メイン処理」部分です。
「メイン処理」からクラス(「プログレスバー」のフォーム)を呼び出すのではなく、「プログレスバー」は「起動処理」からクラスが呼び出され、呼び出された「プログレスバー」からこの「メイン処理」が呼び出されるイメージになります。(サンプルの標準モジュール)

'***************************************************************************************************
'   プログレスバーをコントロールするクラス(テスト用標準Module)      Module1(Module)
'
'   作成者:井上治  URL:https://www.ne.jp/asahi/excel/inoue/ [Excelでお仕事!]
'***************************************************************************************************
'変更日付 Rev  変更履歴内容------------------------------------------------------------------------>
'03/08/19(1.00)新規作成
'19/11/02(1.10)64ビット版Excelの対応(API関連)
'19/12/29(1.11)処理記述整理(標準化準拠)
'***************************************************************************************************
Option Explicit
Option Private Module
'===================================================================================================
Public Const g_cnsTitle As String = "プログレスバーのサンプル"
' ■スリープ(これは本サンプル用に必要なだけです)
#If VBA7 Then
Private Declare PtrSafe Sub Sleep Lib "KERNEL32.dll" _
    (ByVal dwMilliseconds As Long)
#Else
Private Declare Sub Sleep Lib "KERNEL32.dll" _
    (ByVal dwMilliseconds As Long)
#End If
Public g_objProgress As clsProgressBar1

'***************************************************************************************************
'   ■■■ 公開プロシージャ ■■■
'***************************************************************************************************
'* 処理名 :SYORI_START
'* 機能  :起動処理 ※本サンプルではこの処理がシートのボタンから起動されます。
'---------------------------------------------------------------------------------------------------
'* 返り値 :(なし)
'* 引数  :(なし)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2003年08月19日
'* 作成者 :井上 治
'* 更新日 :2019年12月29日
'* 更新者 :井上 治
'* 機能説明:
'* 注意事項:
'***************************************************************************************************
Public Sub SYORI_START()
    '-----------------------------------------------------------------------------------------------
    ' クラス[clsProgressBar1]のインスタンスを生成
    Set g_objProgress = New clsProgressBar1
    With g_objProgress
        ' プログレスバー表示で実際の実行をするマクロ名を登録
        .Macro = "SYORI1"  ' バッチメイン処理(Proc名)
        ' プログレスバーのCaption(タイトル)の登録
        .Caption = g_cnsTitle
        ' プログレスバーの閉じる[×]ボタンを表示するかのスイッチ設定
        .ShowBox = False    ' Trueにすると表示されます。
        ' Escキーでの中断機能の使用有無のスイッチ設定
        .EscStop = True     ' Falseにすると一切止まらなくなります。
        ' プログレスバーフォームを起動(「SYORI1」はフォームから起動される)
        .Show
    End With
    ' クラス[clsProgressBar1]のインスタンスを破棄
    Set g_objProgress = Nothing
End Sub

'***************************************************************************************************
'* 処理名 :SYORI1
'* 機能  :処理実行中(プログレスバー)を表示する実際の処理
'---------------------------------------------------------------------------------------------------
'* 返り値 :(なし)
'* 引数  :(なし)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2003年08月19日
'* 作成者 :井上 治
'* 更新日 :2019年12月29日
'* 更新者 :井上 治
'* 機能説明:
'* 注意事項:
'***************************************************************************************************
Public Sub SYORI1()
    '-----------------------------------------------------------------------------------------------
    ' クラス[clsProgressBar1]に対する処理
    With g_objProgress
        ' 最大件数のセット(普通は定数ではないですね)
        .Max = 1000
        ' 繰り返し(限度判定はこの方法とは限らない)
        Do While .Value <= .Max
            ' 中断判定
            If .Tag = 9 Then Exit Do
            ' 処理件数を加算
            .Value = .Value + 1
            '-----------------------------------------------
            ' ■■■ここで実際の1件分の処理を行なう■■■
            Sleep 10    ' これはサンプルなのでちょっと時間を消費
            '-----------------------------------------------
        Loop
        ' 終了(フォームを閉じる)
        .Hide
    End With
End Sub

'----------------------------------------<< End of Source >>----------------------------------------
クラス化させているので、実際のメイン処理上では「最大件数」と「現在件数」など必要なプロパティを渡していけば「プログレスバー」の処理はクラス側で行なわれます。

ですから、既に作成されている処理にこの「プログレスバー」を組み込む場合は「起動処理」「メイン処理」を切り分ける必要があります。
「起動処理」(このサンプルでは「SYORI_START)の方はほとんどこの記述のままの形で利用できると思います。「メイン処理」の繰り返し処理の前後に大きな「前処理」「後処理」がある場合は、この「起動処理」側に記述しても構えません。
また、処理に必要なパラメータを入力フォームなどで受け取るような場合は、その部分を「起動処理」側で行なって、一旦モジュール変数を使って「メイン処理」に引き渡すようにして下さい。

「メイン処理」(このサンプルでは「SYORI1)の方は「最大件数」と「現在件数」などを「プログレスバー」に通知する必要があり、また、後ろで説明する「中断機能」を利用する場合は、中断可能なポイントの単位で「.Tag」プロパティを判定して値が「9」だったら中途終了として下さい。
複数のファイルを順次扱うような処理の場合は、次のファイルを開く前あたりが適切なポイントと考えると良いでしょう。

「クラス」、「フォーム」のコードはこのようになっています。
「クラス処理」などと言うと、何か難しく考えてしまうかも知れませんが、難しいのは作る方です。このように作成済みのクラスを利用するのには「カプセル化」したクラスの内部を理解する必要はなく、提供されているプロパティやメソッドを操作する部分だけを理解すれば良いはずです。
念のため、その「クラス」側のコードはこのようになっています。

'***************************************************************************************************
'   プログレスバーをコントロールするクラス                      clsProgressBar1(Class)
'
'   作成者:井上治  URL:https://www.ne.jp/asahi/excel/inoue/ [Excelでお仕事!]
'***************************************************************************************************
'変更日付 Rev  変更履歴内容------------------------------------------------------------------------>
'03/08/19(1.00)新規作成
'19/12/29(1.11)処理記述整理(標準化準拠)
'***************************************************************************************************
Option Explicit
'===================================================================================================
' クラス側で保持する変数(隠蔽)
Private g_lngWidth As Long                                          ' Width
Private g_lngNow As Long                                            ' 現在件数
Private g_lngMax As Long                                            ' 最大件数
Private g_strCaption As String                                      ' プログレスバーのタイトル
Private g_strMacro As String                                        ' 起動させるプロシージャ名
Private g_lngTag As Long                                            ' 中断指示
Private g_blnSwShow As Boolean                                      ' 閉じる[×]ボタン表示スイッチ
Private g_blnSwStop As Boolean                                      ' 中断機能の使用有無スイッチ

'***************************************************************************************************
' ■■■ メソッド ■■■
'***************************************************************************************************
'* 処理名 :Show
'* 機能  :Showメソッド
'---------------------------------------------------------------------------------------------------
'* 返り値 :(なし)
'* 引数  :(なし)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2003年08月19日
'* 作成者 :井上 治
'* 更新日 :2019年12月29日
'* 更新者 :井上 治
'* 機能説明:
'* 注意事項:
'***************************************************************************************************
Friend Sub Show()
    '-----------------------------------------------------------------------------------------------
    g_lngWidth = 0
    g_lngTag = 0
    With frmProgressBar1
        .Height = 54
        ' 制御情報は一旦ラベルに持たせておく
        .LBL_Macro.Visible = g_blnSwShow        ' 閉じる[×]ボタン表示
        .LBL_Macro.WordWrap = g_blnSwStop       ' 中断機能の使用有無
        .LBL_Macro.Caption = g_strMacro         ' プロシージャ名
        .Caption = g_strCaption                 ' フォームタイトル
        .Show                                   ' プログレスバーフォームの表示
    End With
    g_lngTag = 9
    Unload frmProgressBar1
End Sub

'***************************************************************************************************
'* 処理名 :Hide
'* 機能  :Hideメソッド
'---------------------------------------------------------------------------------------------------
'* 返り値 :(なし)
'* 引数  :(なし)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2003年08月19日
'* 作成者 :井上 治
'* 更新日 :2019年12月29日
'* 更新者 :井上 治
'* 機能説明:
'* 注意事項:
'***************************************************************************************************
Friend Sub Hide()
    '-----------------------------------------------------------------------------------------------
    frmProgressBar1.Hide
    DoEvents
End Sub

'***************************************************************************************************
' ■■■ プロパティ ■■■
'***************************************************************************************************
' 最大件数の取得、設定
'---------------------------------------------------------------------------------------------------
Friend Property Get Max() As Long
    Max = g_lngMax
End Property
Friend Property Let Max(ByVal lngNewMax As Long)
    g_lngMax = lngNewMax
End Property

'===================================================================================================
' 現在件数の取得、設定
'---------------------------------------------------------------------------------------------------
Friend Property Get Value() As Long
    Value = g_lngNow
End Property
Friend Property Let Value(ByVal lngNewValue As Long)
    Dim lngWidth As Long                                            ' 幅
    g_lngNow = lngNewValue
    If g_lngNow >= g_lngMax Then
        frmProgressBar1.Fm_ProgressBar.Width = 200
        frmProgressBar1.Hide
        Exit Property
    End If
    ' Widthの計算
    lngWidth = Int(g_lngNow * 200& / g_lngMax)
    If lngWidth = g_lngWidth Then Exit Property
    ' プログレスバーの長さを変更
    frmProgressBar1.Fm_ProgressBar.Width = lngWidth
    DoEvents
    g_lngWidth = lngWidth
    g_lngTag = frmProgressBar1.Tag
End Property

'===================================================================================================
' プログレスバーから起動させるプロシージャ名の取得、設定
'---------------------------------------------------------------------------------------------------
Friend Property Get Macro() As String
    Macro = g_strMacro
End Property
Friend Property Let Macro(ByVal strNewMacro As String)
    g_strMacro = strNewMacro
End Property

'===================================================================================================
' プログレスバーのタイトルの取得、設定
'---------------------------------------------------------------------------------------------------
Friend Property Get Caption() As String
    Caption = g_strCaption
End Property
Friend Property Let Caption(ByVal strNewCaption As String)
    g_strCaption = strNewCaption
End Property

'===================================================================================================
' 閉じる[×]ボタン表示スイッチの取得、設定
'---------------------------------------------------------------------------------------------------
Friend Property Get ShowBox() As Boolean
    ShowBox = g_blnSwShow
End Property
Friend Property Let ShowBox(ByVal blnSwShow As Boolean)
    g_blnSwShow = blnSwShow
End Property

'===================================================================================================
' 中断機能の使用有無スイッチの取得、設定
'---------------------------------------------------------------------------------------------------
Friend Property Get EscStop() As Boolean
    ShowBox = g_blnSwStop
End Property
Friend Property Let EscStop(ByVal blnSwStop As Boolean)
    g_blnSwStop = blnSwStop
End Property

'===================================================================================================
' 中断指示の取得(Tag=9が中断指示)
'---------------------------------------------------------------------------------------------------
Friend Property Get Tag() As Long
    Tag = g_lngTag
End Property

'----------------------------------------<< End of Source >>----------------------------------------
このクラスモジュールは、利用者のプログラムでフォームの表示や「バー」の長さを計算することなく「プログレスバー」が利用できるように「プロパティ」や「メソッド」を提供する役割を持っています。 ここではそれぞれの「プロパティ」や「メソッド」の機能と名前を理解しておいて下さい。

以下が、ユーザーフォーム(frmProgressBar1)のコードです。
フォームの[×]ボタンを非表示にするためにAPIを使っています。

'***************************************************************************************************
'   プログレスバーを表示するフォーム本体                        frmProgressBar1(UserForm)
'
'   作成者:井上治  URL:https://www.ne.jp/asahi/excel/inoue/ [Excelでお仕事!]
'***************************************************************************************************
'変更日付 Rev  変更履歴内容------------------------------------------------------------------------>
'03/08/19(1.00)新規作成
'19/11/02(1.10)64ビット版Excelの対応(API関連)
'19/12/29(1.11)処理記述整理(標準化準拠)
'***************************************************************************************************
Option Explicit
'===================================================================================================
Private Const GWL_STYLE = (-16)
Private Const WS_SYSMENU = &H80000
' 64ビット対応
#If VBA7 Then
    #If Win64 Then
        ' ウィンドウに関する情報を返す
        Private Declare PtrSafe Function GetWindowLongPtr Lib "USER32.dll" _
            Alias "GetWindowLongPtrA" _
            (ByVal hWnd As LongPtr, _
             ByVal nIndex As Long) As LongPtr
        ' ウィンドウの属性を変更
        Private Declare PtrSafe Function SetWindowLongPtr Lib "USER32.dll" _
            Alias "SetWindowLongPtrA" _
            (ByVal hWnd As LongPtr, _
             ByVal nIndex As Long, _
             ByVal dwNewLong As LongPtr) As LongPtr
    #Else
        ' ウィンドウに関する情報を返す
        Private Declare PtrSafe Function GetWindowLongPtr Lib "USER32.dll" _
            Alias "GetWindowLongA" _
            (ByVal hWnd As LongPtr, _
             ByVal nIndex As Long) As LongPtr
        ' ウィンドウの属性を変更
        Private Declare Function SetWindowLongPtr Lib "USER32.dll" _
            Alias "SetWindowLongA" _
            (ByVal hWnd As LongPtr, _
             ByVal nIndex As Long, _
             ByVal dwNewLong As LongPtr) As LongPtr
    #End If
' Activeなウィンドウのハンドルを取得
Private Declare PtrSafe Function GetActiveWindow Lib "USER32.dll" _
    () As LongPtr
' メニューバーを再描画
Private Declare PtrSafe Function DrawMenuBar Lib "USER32.dll" _
    (ByVal hWnd As LongPtr) As LongPtr
#Else
' ウィンドウに関する情報を返す
Private Declare Function GetWindowLong Lib "USER32.dll" _
    Alias "GetWindowLongA" _
    (ByVal hWnd As Long, ByVal nIndex As Long) As Long
' ウィンドウの属性を変更
Private Declare Function SetWindowLong Lib "USER32.dll" _
    Alias "SetWindowLongA" _
    (ByVal hWnd As Long, ByVal nIndex As Long, _
     ByVal dwNewLong As Long) As Long
' Activeなウィンドウのハンドルを取得
Private Declare Function GetActiveWindow Lib "USER32.dll" _
    () As Long
' メニューバーを再描画
Private Declare Function DrawMenuBar Lib "USER32.dll" _
    (ByVal hWnd As Long) As Long
#End If

'***************************************************************************************************
'   ■■■ フォームイベント ■■■
'***************************************************************************************************
'* 処理名 :CMD_CANCEL_Click
'* 機能  :キャンセル(隠しボタン)のイベント(Escキーで本イベントが発生する)
'---------------------------------------------------------------------------------------------------
'* 返り値 :(なし)
'* 引数  :(なし)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2003年08月19日
'* 作成者 :井上 治
'* 更新日 :2019年12月29日
'* 更新者 :井上 治
'* 機能説明:
'* 注意事項:
'***************************************************************************************************
Private Sub CMD_CANCEL_Click()
    '-----------------------------------------------------------------------------------------------
    ' 中断機能の使用有無はラベルのWordWrapプロパティを使う
    If LBL_Macro.WordWrap = True Then
        If MsgBox("キャンセルキーが押されました。" & _
            "ここで中断して終了しますか?", _
            vbInformation + vbYesNo, g_cnsTitle) = vbYes Then
            Me.Tag = 9
        End If
    End If
End Sub

'***************************************************************************************************
'* 処理名 :UserForm_Activate
'* 機能  :フォームの表示初期化
'---------------------------------------------------------------------------------------------------
'* 返り値 :(なし)
'* 引数  :(なし)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2003年08月19日
'* 作成者 :井上 治
'* 更新日 :2019年12月29日
'* 更新者 :井上 治
'* 機能説明:
'* 注意事項:
'***************************************************************************************************
Private Sub UserForm_Activate()
    '-----------------------------------------------------------------------------------------------
#If VBA7 Then
    Dim hWnd As LongPtr
    Dim Wnd_STYLE As LongPtr
#Else
    Dim hWnd As Long
    Dim Wnd_STYLE As Long
#End If
    ' 閉じる[×]ボタンの有効/無効はラベルのVisibleプロパティを使う
    If LBL_Macro.Visible <> True Then
        ' 閉じる[×]ボタンを無効にする
        hWnd = GetActiveWindow()
#If VBA7 Then
        Wnd_STYLE = GetWindowLongPtr(hWnd, GWL_STYLE)
        Wnd_STYLE = Wnd_STYLE And (Not WS_SYSMENU)
        SetWindowLongPtr hWnd, GWL_STYLE, Wnd_STYLE
#Else
        Wnd_STYLE = GetWindowLong(hWnd, GWL_STYLE)
        Wnd_STYLE = Wnd_STYLE And (Not WS_SYSMENU)
        SetWindowLong hWnd, GWL_STYLE, Wnd_STYLE
#End If
        DrawMenuBar hWnd
    End If
    Me.Tag = 0
    Fm_ProgressBar.Width = 0.01
    ' 実際の処理の起動
    Application.Run Macro:=LBL_Macro.Caption
End Sub

'***************************************************************************************************
'* 処理名 :UserForm_QueryClose
'* 機能  :Closeイベント
'---------------------------------------------------------------------------------------------------
'* 返り値 :(なし)
'* 引数  :(既定)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2003年08月19日
'* 作成者 :井上 治
'* 更新日 :2019年12月29日
'* 更新者 :井上 治
'* 機能説明:
'* 注意事項:
'***************************************************************************************************
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
    '-----------------------------------------------------------------------------------------------
    ' 閉じる[×]ボタンは許可しない(表示されない場合は動作しない)
    If CloseMode = vbFormControlMenu Then
        ' Escキーと同様処理とする
        Call CMD_CANCEL_Click
        Cancel = True
    End If
End Sub

'----------------------------------------<< End of Source >>----------------------------------------
このユーザーフォーム自体を利用者プログラムの記述で操作することはないので、この内部のコードは意識しなくても構いません。

ダウンロードはこちら。

←ProgressBar1.zip
      (33KB)

ご希望が多かったので、「モードレス」でやってみました。

一見、組み込みやすそうに見えますが...   作成が済んでいる時間が掛かる一括系処理に「プログレスバー」を組み込もうと考えた時、「モードレス」のユーザーフォームならループの開始直前にユーザーフォームのShowメソッドを書き込んで、 ループ中で「バー」の長さを変えていけば良い、と考える方が多いのだと思います。
それ自体は間違いではないのですが、一括系処理に「モードレス」のユーザーフォームを使うことには別の問題があります。 つまり、「モードレス」ですから、ユーザーフォームが常にアクティブであるとは限らなくなってしまいます。 ユーザーフォームがアクティブなら、Escキーでの割り込み処理はユーザーフォームの上だけに記述しておけば済みますが、 「モードレス」ではそうはいかなくなるのです。
「モードレス」のユーザーフォームではどうでしょう。
結果は、特にEscキーの中断処置記述をあちこちのプロシージャに書かなければならないので、あまりお勧めはできませんが、このようになりました。
※なお、「モードレス」のユーザーフォームは、Excel2000以降の対応となります。
モードレスフォームでの「プログレスバー」
見かけは、ガイドメッセージ表示を加えたため若干違いますが、これは「モーダル版」でも可能なことで、特に機能的に違うわけではありませんが、 「モードレス」のユーザーフォームである以上、表示中にワークシート側の選択ができてしまいます。 本来、「プログレスバー」を必要とする一括系の処理を行なっている最中に、手操作でのウィンドウの切り替えをわざわざ受け入れる必然性は考えにくいですから、 単に、記述上で既存のコードに組み込みやすいからといって「モードレス」を選択するというのは間違いでしょう。

それでも強引に作ってみましたので紹介してみます。
当然、上記の「モーダル版」と違って、プロシージャを分割することをせずに「プログレスバー」を実現することになります。 最初のコードは、その「プログレスバー」を組み込むモジュール(Module1)のサンプルです。

'***************************************************************************************************
'   プログレスバーをコントロールするクラス(テスト用標準Module)      Module1(Module)
'
'   作成者:井上治  URL:https://www.ne.jp/asahi/excel/inoue/ [Excelでお仕事!]
'***************************************************************************************************
'変更日付 Rev  変更履歴内容------------------------------------------------------------------------>
'03/08/19(1.00)新規作成
'19/11/02(1.10)64ビット版Excelの対応(API関連)
'19/12/29(1.11)処理記述整理(標準化準拠)
'***************************************************************************************************
Option Explicit
Option Private Module
'===================================================================================================
Private Const g_cnsTitle As String = "プログレスバーのサンプル"
#If VBA7 Then
' ■スリープ(これは本サンプル用に必要なだけです)
Private Declare PtrSafe Sub Sleep Lib "KERNEL32.dll" _
    (ByVal dwMilliseconds As Long)
#Else
' ■スリープ(これは本サンプル用に必要なだけです)
Private Declare Sub Sleep Lib "KERNEL32.dll" _
    (ByVal dwMilliseconds As Long)
#End If

'***************************************************************************************************
'   ■■■ 公開プロシージャ ■■■
'***************************************************************************************************
'* 処理名 :SYORI_START
'* 機能  :起動処理 ※本サンプルではこの処理がシートのボタンから起動されます。
'---------------------------------------------------------------------------------------------------
'* 返り値 :(なし)
'* 引数  :(なし)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2003年08月19日
'* 作成者 :井上 治
'* 更新日 :2019年12月29日
'* 更新者 :井上 治
'* 機能説明:
'* 注意事項:
'***************************************************************************************************
Public Sub MAIN_SYORI()
    '-----------------------------------------------------------------------------------------------
    Dim lngCNT_MAX As Long                                          ' 最大件数
    Dim lngCNT_NOW As Long                                          ' 現在件数
    ' クラス[clsProgressBar2]のインスタンスを生成
    Set g_objProgress2 = New clsProgressBar2
    '===============================================================================================
    '  ■初期処理
    '-----------------------------------------------------------------------------------------------
    ' プログレスバーのCaption(タイトル)の登録
    g_objProgress2.Caption = g_cnsTitle
    ' プログレスバーの閉じる[×]ボタンを表示するかのスイッチ設定
    ' ※記述しない場合は「False(初期値)」で動作します。
    g_objProgress2.ShowBox = False    ' Trueにすると表示されます。
    ' Escキーでの中断機能の使用有無のスイッチ設定
    ' ※記述しない場合は「True(初期値)」で動作します。
    g_objProgress2.EscStop = True     ' Falseにすると一切止まらなくなります。
    ' 最大件数のセット(普通は定数ではないですね)
    lngCNT_MAX = 1000
    ' Maxプロパティに最大件数をセット
    ' ※Showの後で変更しても構いません
    g_objProgress2.Max = lngCNT_MAX
    ' プログレスバーフォームを起動(Modeless)
    g_objProgress2.Show
    On Error GoTo ERR_STOP
    '===============================================================================================
    '  ■メイン処理
    '-----------------------------------------------------------------------------------------------
    ' 繰り返し(限度判定はこの方法とは限らない)
    Do While lngCNT_NOW <= lngCNT_MAX
        ' 中断判定
        If g_objProgress2.Tag = 9 Then Exit Do
        DoEvents
        ' 処理件数を加算
        lngCNT_NOW = lngCNT_NOW + 1
        ' 処理件数をValueプロパティにセット
        g_objProgress2.Value = lngCNT_NOW
        g_objProgress2.StatusBar = lngCNT_NOW & " / " & lngCNT_MAX
        '-----------------------------------------------------------------------
        ' ■■■ここで実際の1件分の処理を行なう■■■
        Sleep 10    ' これはサンプルなのでちょっと時間を消費
        '-----------------------------------------------------------------------
    Loop
    '===============================================================================================
    '  ■終了処理
    '-----------------------------------------------------------------------------------------------
    ' 終了(フォームを閉じる)
    g_objProgress2.Hide
    ' クラス[clsProgressBar2]のインスタンスを破棄
    Set g_objProgress2 = Nothing
    Exit Sub

'===================================================================================================
' 中断処理
ERR_STOP:
    ' ユーザー割り込みかを判定
    If Err.Number = 18 Then
        ' 終了しない場合は戻る(クラス側で確認処理)
        If g_objProgress2.EscKey() <> True Then Resume
    Else
        ' その他のエラーはメッセージ処置などを行なう
        MsgBox Err.Description, vbCritical, g_cnsTitle
    End If
    ' クラス[clsProgressBar2]のインスタンスを破棄
    Set g_objProgress2 = Nothing
End Sub

'----------------------------------------<< End of Source >>----------------------------------------
このように、「初期処理」の最後で「プログレスバー」を表示(Showメソッド)させていますが、実際のループ処理は、その後に記述されています。 初心者の方だと、モーダルなユーザーフォームでもこのような記述を書いて「うまくいかない」を聞いてくることがよくあります。
でも、この方法ではユーザー操作によるウィンドウ切り替えができてしまい、表示されたユーザーフォームを無視してExcelウィンドウ(ワークシート)をアクティブに戻したりできます。 Excelウィンドウ(ワークシート)がアクティブになると、ユーザーフォームは裏に隠れてしまい、そこでEscキーが押されると、ユーザーフォームではなく、このメイン処理記述の方でエラー処理が発生します。 プロシージャが複数に分かれていれば、その各プロシージャに対応記述を追加しなければならないわけです。

「クラス」、「フォーム」のコードはこのようになっています。
次がクラスモジュール(clsProgressBar2)の記述ですが、「プログレスバー」の各プロパティを参照・操作する場合、その時点のクラスモジュール側のコードでもEscキーによる割り込みが起きるので以下のようなコードになっています。

'***************************************************************************************************
'   プログレスバーをコントロールするクラス                      clsProgressBar2(Class)
'
'   作成者:井上治  URL:https://www.ne.jp/asahi/excel/inoue/ [Excelでお仕事!]
'***************************************************************************************************
'変更日付 Rev  変更履歴内容------------------------------------------------------------------------>
'03/08/19(1.00)新規作成
'19/12/29(1.11)処理記述整理(標準化準拠)
'***************************************************************************************************
Option Explicit
'===================================================================================================
' クラス側で保持する変数(隠蔽)
Private g_lngWidth As Long                                          ' Width
Private g_lngNow As Long                                            ' 現在件数
Private g_lngMax As Long                                            ' 最大件数
Private g_strCaption As String                                      ' プログレスバーのタイトル
Private g_strMessage As String                                      ' Window内上部のメッセージ
Private g_strStatusBar As String                                    ' ステータスバー
Private g_lngTag As Long                                            ' 中断指示
Private g_blnSwShow As Boolean                                      ' 閉じる[×]ボタン表示スイッチ
Private g_blnSwStop As Boolean                                      ' 中断機能の使用有無スイッチ
Private g_lngEnableCancelKey As Long                                ' Escキー動作の保管

'***************************************************************************************************
' ■■■ イベント ■■■
'***************************************************************************************************
'* 処理名 :Class_Initialize
'* 機能  :クラス初期化
'---------------------------------------------------------------------------------------------------
'* 返り値 :(なし)
'* 引数  :(なし)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2003年08月19日
'* 作成者 :井上 治
'* 更新日 :2019年12月29日
'* 更新者 :井上 治
'* 機能説明:
'* 注意事項:
'***************************************************************************************************
Private Sub Class_Initialize()
    '-----------------------------------------------------------------------------------------------
#If VBA6 Or VBA7 Then
    ' デフォルト値のセット
    g_blnSwShow = False                         ' 閉じる[×]ボタン表示
    g_blnSwStop = True                          ' 中断機能の使用有無
    g_strMessage = "処理中です。しばらくお待ち下さい...."
    g_strStatusBar = ""
    ' Escキー動作を保管
    g_lngEnableCancelKey = Application.EnableCancelKey
#Else
    ' Excel97以前ではModeLessユーザーフォームは利用不可
    MsgBox "この処理はExcel2000以降で動作します。", vbExclamation
    End
#End If
End Sub

'***************************************************************************************************
'* 処理名 :Class_Terminate
'* 機能  :クラス終了
'---------------------------------------------------------------------------------------------------
'* 返り値 :(なし)
'* 引数  :(なし)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2003年08月19日
'* 作成者 :井上 治
'* 更新日 :2019年12月29日
'* 更新者 :井上 治
'* 機能説明:
'* 注意事項:
'***************************************************************************************************
Private Sub Class_Terminate()
    '-----------------------------------------------------------------------------------------------
    Unload frmProgressBar2
    ' Escキー動作を復帰
    Application.EnableCancelKey = g_lngEnableCancelKey
End Sub

'***************************************************************************************************
' ■■■ メソッド ■■■
'***************************************************************************************************
'* 処理名 :Show
'* 機能  :Showメソッド
'---------------------------------------------------------------------------------------------------
'* 返り値 :(なし)
'* 引数  :(なし)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2003年08月19日
'* 作成者 :井上 治
'* 更新日 :2019年12月29日
'* 更新者 :井上 治
'* 機能説明:
'* 注意事項:
'***************************************************************************************************
Friend Sub Show()
    '-----------------------------------------------------------------------------------------------
    g_lngWidth = 0
    g_lngTag = 0
    With frmProgressBar2
        .Height = 81
        ' 制御情報は一旦ラベルに持たせておく
        .LBL_Macro.Visible = g_blnSwShow        ' 閉じる[×]ボタン表示
        .LBL_Macro.WordWrap = g_blnSwStop       ' 中断機能の使用有無
        If g_blnSwStop = True Then
            ' 中断キーを使用する場合
            Application.EnableCancelKey = xlErrorHandler
        Else
            ' 中断キーを使用しない場合
            Application.EnableCancelKey = xlDisabled
        End If
        .Caption = g_strCaption                 ' フォームタイトル
        .LBL_Message = g_strMessage             ' フォーム画面メッセージ
        .LBL_StatusBar = g_strStatusBar         ' フォームステータス表示
        .Show vbModeless                        ' プログレスバーの表示(モードレス)
        DoEvents
    End With
End Sub

'***************************************************************************************************
'* 処理名 :Hide
'* 機能  :Hideメソッド
'---------------------------------------------------------------------------------------------------
'* 返り値 :(なし)
'* 引数  :(なし)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2003年08月19日
'* 作成者 :井上 治
'* 更新日 :2019年12月29日
'* 更新者 :井上 治
'* 機能説明:
'* 注意事項:
'***************************************************************************************************
Friend Sub Hide()
    '-----------------------------------------------------------------------------------------------
    frmProgressBar2.Hide
    DoEvents
End Sub

'***************************************************************************************************
'* 処理名 :EscKey
'* 機能  :Escキー押下メソッド(フォームがアクティブでない場合の対応)
'---------------------------------------------------------------------------------------------------
'* 返り値 :終了判定(Boolean)
'* 引数  :(なし)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2003年08月19日
'* 作成者 :井上 治
'* 更新日 :2019年12月29日
'* 更新者 :井上 治
'* 機能説明:
'* 注意事項:
'***************************************************************************************************
Friend Function EscKey() As Boolean
    '-----------------------------------------------------------------------------------------------
    If MsgBox("キャンセルキーが押されました。" & _
        "ここで中断して終了しますか?", _
        vbInformation + vbYesNo, Me.Caption) = vbYes Then
        frmProgressBar2.Tag = 9
        g_lngTag = 9
        EscKey = True                   ' 終了する(True)
    Else
        EscKey = False                  ' 終了しない(False)
    End If
End Function

'***************************************************************************************************
' ■■■ プロパティ ■■■
'***************************************************************************************************
' 最大件数の取得、設定
'---------------------------------------------------------------------------------------------------
Friend Property Get Max() As Long
    Max = g_lngMax
End Property
Friend Property Let Max(ByVal lngNewMax As Long)
    g_lngMax = lngNewMax
End Property

'===================================================================================================
' 現在件数の取得、設定
'---------------------------------------------------------------------------------------------------
Friend Property Get Value() As Long
    Value = g_lngNow
End Property
Friend Property Let Value(ByVal lngNewValue As Long)
    Dim lngWidth As Long, lngTag As Long

    On Error GoTo Value_Error
    g_lngNow = lngNewValue
    If g_lngNow >= g_lngMax Then
        frmProgressBar2.Fm_ProgressBar.Width = 200
        frmProgressBar2.Hide
        Exit Property
    End If
    ' Widthの計算
    lngWidth = Int(g_lngNow * 200& / g_lngMax)
    ' 長さに変動がなければ終了
    If lngWidth = g_lngWidth Then Exit Property

    ' プログレスバーの長さを変更
    frmProgressBar2.Fm_ProgressBar.Width = lngWidth
    DoEvents
    g_lngWidth = lngWidth
    lngTag = Val(frmProgressBar2.Tag)
    If lngTag = 9 Then g_lngTag = lngTag
    Exit Property

'===================================================================================================
' エラー処理(中断キーの対応)
Value_Error:
    If Err.Number = 18 Then
        Call EscKey
    Else
        MsgBox Err.Description, vbCritical, g_strCaption
        frmProgressBar2.Tag = 9
        g_lngTag = 9
        DoEvents
    End If
End Property

'===================================================================================================
' プログレスバーのタイトルの取得、設定
'---------------------------------------------------------------------------------------------------
Friend Property Get Caption() As String
    Caption = g_strCaption
End Property
Friend Property Let Caption(ByVal strNewCaption As String)
    g_strCaption = strNewCaption
End Property

'===================================================================================================
' プログレスバーの画面メッセージの取得、設定
'---------------------------------------------------------------------------------------------------
Friend Property Get Message() As String
    Message = g_strMessage
End Property
Friend Property Let Message(ByVal strNewMessage As String)
    g_strMessage = strNewMessage
    If g_blnShowProgressBar2 = True Then
        frmProgressBar2.LBL_Message.Caption = g_strMessage
        DoEvents
    End If
End Property

'===================================================================================================
' プログレスバーのステータス表示の取得、設定
'---------------------------------------------------------------------------------------------------
Friend Property Get StatusBar() As String
    StatusBar = g_strStatusBar
End Property
Friend Property Let StatusBar(ByVal strNewStatusBar As String)
    g_strStatusBar = strNewStatusBar
    If g_blnShowProgressBar2 = True Then
        frmProgressBar2.LBL_StatusBar.Caption = g_strStatusBar
        DoEvents
    End If
End Property

'===================================================================================================
' 閉じる[×]ボタン表示スイッチの取得、設定
'---------------------------------------------------------------------------------------------------
Friend Property Get ShowBox() As Boolean
    ShowBox = g_blnSwShow
End Property
Friend Property Let ShowBox(ByVal blnSwShow As Boolean)
    g_blnSwShow = blnSwShow
End Property

'===================================================================================================
' 中断機能の使用有無スイッチの取得、設定
'---------------------------------------------------------------------------------------------------
Friend Property Get EscStop() As Boolean
    ShowBox = g_blnSwStop
End Property
Friend Property Let EscStop(ByVal blnSwStop As Boolean)
    g_blnSwStop = blnSwStop
End Property

'===================================================================================================
' 中断指示の取得(Tag=9が中断指示)
'---------------------------------------------------------------------------------------------------
Friend Property Get Tag() As Long
    On Error Resume Next
    Tag = g_lngTag
    If Err.Number = 18 Then Call EscKey
End Property

'----------------------------------------<< End of Source >>----------------------------------------
このように、クラス側でもループ中に呼び出されるプロパティ記述にはEscキーでの割り込みが発生することがあるので対応が必要になります。 これらは、ユーザーフォームが常にアクティブなら必要がないのです。

この「モードレス版」と「モーダル版」の組み込み方の違いはもう一つあって、ユーザーフォーム側とクラス側の変数のやりとりをモジュール変数を使って行なっているため、 標準モジュール(modProgressBar2)の組み込みも必要です。

'***************************************************************************************************
'   プログレスバー(frmProgressBar2)をコントロールする(共通変数)
'
'   作成者:井上治  URL:https://www.ne.jp/asahi/excel/inoue/ [Excelでお仕事!]
'***************************************************************************************************
'変更日付 Rev  変更履歴内容------------------------------------------------------------------------>
'03/08/19(1.00)新規作成
'19/12/29(1.11)処理記述整理(標準化準拠)
'***************************************************************************************************
Option Explicit
Option Private Module
'===================================================================================================
' クラス(clsProgressBar2)のインスタンス
Public g_objProgress2 As clsProgressBar2
' ProgressBarの表示有無スイッチ
Public g_blnShowProgressBar2 As Boolean

'----------------------------------------<< End of Source >>----------------------------------------

以下が、ユーザーフォーム(frmProgressBar2)のコードです。
フォームの[×]ボタンを非表示にするためにAPIを使っています。

'***************************************************************************************************
'   プログレスバーを表示するフォーム本体                        frmProgressBar2(UserForm)
'
'   作成者:井上治  URL:https://www.ne.jp/asahi/excel/inoue/ [Excelでお仕事!]
'***************************************************************************************************
'変更日付 Rev  変更履歴内容------------------------------------------------------------------------>
'03/08/19(1.00)新規作成
'19/11/02(1.10)64ビット版Excelの対応(API関連)
'19/12/29(1.11)処理記述整理(標準化準拠)
'***************************************************************************************************
Option Explicit
'===================================================================================================
Private Const GWL_STYLE = (-16)
Private Const WS_SYSMENU = &H80000
' 64ビット対応
#If VBA7 Then
    #If Win64 Then
        ' ウィンドウに関する情報を返す
        Private Declare PtrSafe Function GetWindowLongPtr Lib "USER32.dll" _
            Alias "GetWindowLongPtrA" _
            (ByVal hWnd As LongPtr, _
             ByVal nIndex As Long) As LongPtr
        ' ウィンドウの属性を変更
        Private Declare PtrSafe Function SetWindowLongPtr Lib "USER32.dll" _
            Alias "SetWindowLongPtrA" _
            (ByVal hWnd As LongPtr, _
             ByVal nIndex As Long, _
             ByVal dwNewLong As LongPtr) As LongPtr
    #Else
        ' ウィンドウに関する情報を返す
        Private Declare PtrSafe Function GetWindowLongPtr Lib "USER32.dll" _
            Alias "GetWindowLongA" _
            (ByVal hWnd As LongPtr, _
             ByVal nIndex As Long) As LongPtr
        ' ウィンドウの属性を変更
        Private Declare Function SetWindowLongPtr Lib "USER32.dll" _
            Alias "SetWindowLongA" _
            (ByVal hWnd As LongPtr, _
             ByVal nIndex As Long, _
             ByVal dwNewLong As LongPtr) As LongPtr
    #End If
' Activeなウィンドウのハンドルを取得
Private Declare PtrSafe Function GetActiveWindow Lib "USER32.dll" _
    () As LongPtr
' メニューバーを再描画
Private Declare PtrSafe Function DrawMenuBar Lib "USER32.dll" _
    (ByVal hWnd As LongPtr) As LongPtr
#Else
' ウィンドウに関する情報を返す
Private Declare Function GetWindowLong Lib "USER32.dll" _
    Alias "GetWindowLongA" _
    (ByVal hWnd As Long, ByVal nIndex As Long) As Long
' ウィンドウの属性を変更
Private Declare Function SetWindowLong Lib "USER32.dll" _
    Alias "SetWindowLongA" _
    (ByVal hWnd As Long, ByVal nIndex As Long, _
     ByVal dwNewLong As Long) As Long
' Activeなウィンドウのハンドルを取得
Private Declare Function GetActiveWindow Lib "USER32.dll" _
    () As Long
' メニューバーを再描画
Private Declare Function DrawMenuBar Lib "USER32.dll" _
    (ByVal hWnd As Long) As Long
#End If

'***************************************************************************************************
'   ■■■ フォームイベント ■■■
'***************************************************************************************************
'* 処理名 :CMD_CANCEL_Click
'* 機能  :キャンセル(隠しボタン)のイベント(Escキーで本イベントが発生する)
'---------------------------------------------------------------------------------------------------
'* 返り値 :(なし)
'* 引数  :(なし)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2003年08月19日
'* 作成者 :井上 治
'* 更新日 :2019年12月29日
'* 更新者 :井上 治
'* 機能説明:
'* 注意事項:
'***************************************************************************************************
Private Sub CMD_CANCEL_Click()
    '-----------------------------------------------------------------------------------------------
    ' 中断機能の使用有無はラベルのWordWrapプロパティを使う
    If LBL_Macro.WordWrap = True Then
        If MsgBox("キャンセルキーが押されました。" & _
            "ここで中断して終了しますか?", _
            vbInformation + vbYesNo, Me.Caption) = vbYes Then
            Me.Tag = 9
        End If
    End If
End Sub

'***************************************************************************************************
'* 処理名 :UserForm_Activate
'* 機能  :フォームの表示初期化
'---------------------------------------------------------------------------------------------------
'* 返り値 :(なし)
'* 引数  :(なし)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2003年08月19日
'* 作成者 :井上 治
'* 更新日 :2019年12月29日
'* 更新者 :井上 治
'* 機能説明:
'* 注意事項:
'***************************************************************************************************
Private Sub UserForm_Activate()
    '-----------------------------------------------------------------------------------------------
#If VBA7 Then
    Dim hWnd As LongPtr
    Dim Wnd_STYLE As LongPtr
#Else
    Dim hWnd As Long
    Dim Wnd_STYLE As Long
#End If
    ' 閉じる[×]ボタンの有効/無効はラベルのVisibleプロパティを使う
    If LBL_Macro.Visible <> True Then
        ' 閉じる[×]ボタンを無効にする
        hWnd = GetActiveWindow()
#If VBA7 Then
        Wnd_STYLE = GetWindowLongPtr(hWnd, GWL_STYLE)
        Wnd_STYLE = Wnd_STYLE And (Not WS_SYSMENU)
        SetWindowLongPtr hWnd, GWL_STYLE, Wnd_STYLE
#Else
        Wnd_STYLE = GetWindowLong(hWnd, GWL_STYLE)
        Wnd_STYLE = Wnd_STYLE And (Not WS_SYSMENU)
        SetWindowLong hWnd, GWL_STYLE, Wnd_STYLE
#End If
        DrawMenuBar hWnd
    End If
    Me.Tag = 0
    Fm_ProgressBar.Width = 0.01
    g_blnShowProgressBar2 = True
End Sub

'***************************************************************************************************
'* 処理名 :UserForm_Deactivate
'* 機能  :フォーム不活性化
'---------------------------------------------------------------------------------------------------
'* 返り値 :(なし)
'* 引数  :(なし)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2003年08月19日
'* 作成者 :井上 治
'* 更新日 :2019年12月29日
'* 更新者 :井上 治
'* 機能説明:
'* 注意事項:
'***************************************************************************************************
Private Sub UserForm_Deactivate()
    '-----------------------------------------------------------------------------------------------
    g_blnShowProgressBar2 = False
End Sub

'***************************************************************************************************
'* 処理名 :UserForm_QueryClose
'* 機能  :Closeイベント
'---------------------------------------------------------------------------------------------------
'* 返り値 :(なし)
'* 引数  :(既定)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2003年08月19日
'* 作成者 :井上 治
'* 更新日 :2019年12月29日
'* 更新者 :井上 治
'* 機能説明:
'* 注意事項:
'***************************************************************************************************
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
    '-----------------------------------------------------------------------------------------------
    ' 閉じる[×]ボタンは許可しない(表示されない場合は動作しない)
    If CloseMode = vbFormControlMenu Then
        ' Escキーと同様処理とする
        Call CMD_CANCEL_Click
        Cancel = True
    End If
End Sub

'----------------------------------------<< End of Source >>----------------------------------------
このユーザーフォーム自体を利用者プログラムの記述で操作することはないので、この内部のコードは意識しなくても構いません。 「モーダル版」とコード内容はほとんど変わらないと思います。

ダウンロードはこちら。

←ProgressBar2.zip
      (43KB)