ExcelVBAでFormにプログレスバー（進行表示）と簡易ログを表示する

# ExcelVBAでFormにプログレスバー（進行表示）と簡易ログを表示する
Excel等のVBAでマクロを実行中に進行を表示したい場合があります。
標準のプログレスバーは、64bit版で不具合があったりと、イマイチです。
左下のステータスバーに表示する方法が簡単ですが、フィルターを使用したりすると　表示が上書きされてしまって見にくい場合があります。
フォームを利用する事で　いろいろと試せるので　そちらを使うことにしました。

進行表示をバー表示するだけではなく、
手順とかの簡易ログ的なものも同時に表示できます。（イミディエイトウィンドウの様に）
こうする事で　進行を見ながら、簡易デバッグにも利用できます。
やっぱり、文字やメッセージも表示できると便利ですよね。
また、複数のファイルを作成するようなマクロの場合にも　どんなファイルを作成したのか？も表示できます。


## フォームを作成する
まず、フォームを作成します。
フォームの名称は変えなくてもOKですが、変えておいた方が　他のマクロに利用するときにも便利だと思います。
![20230311_103820_ScreenShot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017925/476f8cd1-71a5-b5f3-9b29-747c5c67d676.png)
![20230311_103827_ScreenShot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017925/a598e5d1-9181-bea6-ddbf-4695d7c122bf.png)
ラベルとテキストボックスを配置します。
（進捗バーのみの場合は　ラベルのみでOKです。）

次に　ラベルの名前やプロパティー設定を変更します。
ラベルの　width　300　となるように注意してください。
![20230311_103847_ScreenShot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017925/10dada72-a9d9-f756-7da5-fe12ba41c2dd.png)

次に、テキストボックスの名前やプロパティー設定を変更します。
![20230311_103901_ScreenShot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017925/5e088255-9bc4-2831-328a-9e78550325d4.png)


## 標準モジュールに表示用の関数を作成する

下記のコードをコピペしてください。
```diff_vba
'宣言セクションで　パブリックな変数（グローバル変数）（どのモジュールからでも変数を参照できるようにしておく）を宣言しておく。
Public PBar_count As Long '他のモジュールでも共有する変数の宣言
Public PBar_str_all As String


Sub PBar_Form(PBar_input As Variant)
    'プログレスバーをユーザーフォームで表示。下記の準備と宣言が必要。
    'フォーム名PBarForm1　／　ラベル名PBarLabel.　ラベルWidth=300　ラベルBackColorを適当に着色　／　テキストボックス名PBarBox　フォントサイズは6程度
    '◆宣言セクション
    'Public PBar_count As Long '他のモジュールでも共有する変数の宣言(宣言セクションで宣言する必要がある)
    'Public PBar_str_all As String
    '◆Main関数の最初
    'PBarForm1.Show vbModeless 'プログレスバーのフォーム表示
    'PBar_count = 100
    '◆Main関数の最後
    'Unload PBarForm1 'プログレスバーを消す
    '
    '◆使用例
    'Call PBar_Form('あ１２３いうえお')
    'Call PBar_Form(Str(i))
    'Call PBar_Form(i)
    Dim maxWidth As Integer
    Dim i As Integer
    Dim j_str As String
    maxWidth = 300 'フォームのラベルをwidth300で作成しておく
    j_str = "進捗をBar表示しています。。。進捗％ではなく、繰り返し表示です。。。" '進捗バー（ラベル）にメッセージを表示したらおもしろいかな。。。と。不要なら消す。
    PBarForm1.PBarLabel.Caption = j_str & vbCrLf & PBar_input 'ラベルに最新のログを追記する表示です。
    PBarForm1.PBarLabel.Width = maxWidth * (PBar_count / 100) '進捗バーの巾を変えて進捗表示にしています。
    PBar_str_all = PBar_str_all & vbCrLf & PBar_input 'テキストボックス内に表示する簡易ログの文字列を生成
    PBarForm1.PBarBox.Text = PBar_str_all 'テキストボックスに　簡易ログを表示。
    DoEvents '再作画
    If PBar_count < 100 Then
        PBar_count = PBar_count + 1
    Else
        PBar_count = 1
    End If
End Sub
```

## 試してみる
上記のコードを試してみます。
```
Sub PBar_test()
    PBarForm1.Show vbModeless 'プログレスバーのフォーム表示
    PPbar_count = 100

    For i = 1 To 250
        DoEvents '再作画
        '1ミリ秒待機する処理
        Application.Wait [Now() + "0:00:00.1"]
        Call PBar_Form("１２３")
    Next i

        MsgBox "終了！"
    Unload PBarForm1 'プログレスバーを消す
End Sub

```

ちなみに、最後の
　Unload PBarForm1 'プログレスバーを消す
を、コメントアウトして
```
'Unload PBarForm1 'プログレスバーを消す
```
の様にすると　デバッグ時に便利です。


## 各部分の説明
最初に宣言セクションで　Public　で変数を宣言しています。
こうする事で　他のモジュールから呼び出しても進行バーや簡易ログの中身が継承されるので便利でした。
```
Public PBar_count As Long '他のモジュールでも共有する変数の宣言
Public PBar_str_all As String
```

Sub PBar_Form(PBar_input As Variant)
とする事で　Long型やString型とか気にしなくても表示できるようになります。

DoEvents '再作画
これを入れないと　再作画されないので、進捗バーが動かないです。
ただ、テキストボックスにユーザが入力できてしまいます。
簡易ログ的な利用なら問題ないでしょう。
テキストボックスにする事で　まとまって、コピペする事も可能になります。

## 使い方
下記の様に使う事ができます。
中に入れる変数は　文字型でも数値型でもどちらでも大丈夫でした。
    Call PBar_Form('あ１２３いうえお')
    Call PBar_Form(Str(i))
    Call PBar_Form(i)


## 最後に
私は　日曜プログラマーです。
色々なコマンドや設定を　覚えていて、がりがりとプログラムをかけるわけでもない為、
注釈をいっぱい入れています。
後で　見直したときに、何やっていた？と分かり易いようにです。
なので、こんなに注釈の多いプログラムは　汚いと、怒られる方もおられるでしょう。
ご容赦ください。

また、
部品として繰り返し利用するような関数には、利用方法等も記載するようにしておくと
後々、忘れてしまってから再利用するときにも便利です。
毎日ＶＢＡを触るような方には、不要な注釈ですので　消していただいてもＯＫです。



## 全体のコード
最後に、一式コピペするだけにまとめたコードを添付しておきます。

```
'宣言セクションで　パブリックな変数（グローバル変数）（どのモジュールからでも変数を参照できるようにしておく）を宣言しておく。
Public PBar_count As Long '他のモジュールでも共有する変数の宣言
Public PBar_str_all As String


Sub PBar_Form(PBar_input As Variant)
    'プログレスバーをユーザーフォームで表示。下記の準備と宣言が必要。
    'フォーム名PBarForm1　／　ラベル名PBarLabel.　ラベルWidth=300　ラベルBackColorを適当に着色　／　テキストボックス名PBarBox　フォントサイズは6程度
    '◆宣言セクション
    'Public PBar_count As Long '他のモジュールでも共有する変数の宣言(宣言セクションで宣言する必要がある)
    'Public PBar_str_all As String
    '◆Main関数の最初
    'PBarForm1.Show vbModeless 'プログレスバーのフォーム表示
    'PBar_count = 100
    '◆Main関数の最後
    'Unload PBarForm1 'プログレスバーを消す
    '
    '◆使用例
    'Call PBar_Form('あ１２３いうえお')
    'Call PBar_Form(Str(i))
    'Call PBar_Form(i)
    Dim maxWidth As Integer
    Dim i As Integer
    Dim j_str As String
    maxWidth = 300 'フォームのラベルをwidth300で作成しておく
    j_str = "進捗をBar表示しています。。。進捗％ではなく、繰り返し表示です。。。" '進捗バー（ラベル）にメッセージを表示したらおもしろいかな。。。と。不要なら消す。
    PBarForm1.PBarLabel.Caption = j_str & vbCrLf & PBar_input 'ラベルに最新のログを追記する表示です。
    PBarForm1.PBarLabel.Width = maxWidth * (PBar_count / 100) '進捗バーの巾を変えて進捗表示にしています。
    PBar_str_all = PBar_str_all & vbCrLf & PBar_input 'テキストボックス内に表示する簡易ログの文字列を生成
    PBarForm1.PBarBox.Text = PBar_str_all 'テキストボックスに　簡易ログを表示。
    DoEvents '再作画
    If PBar_count < 100 Then
        PBar_count = PBar_count + 1
    Else
        PBar_count = 1
    End If
End Sub

Sub PBar_test()
    PBarForm1.Show vbModeless 'プログレスバーのフォーム表示
    PPbar_count = 100

    For i = 1 To 100
        DoEvents '再作画
        '1ミリ秒待機する処理
        Application.Wait [Now() + "0:00:00.1"]
        Call PBar_Form("１２３")
    Next i

        MsgBox "終了！"
    Unload PBarForm1 'プログレスバーを消す
End Sub

```