VBAで比較的長い処理時間がかかるプログラム実行時にユーザーフォームで「処理中」や「実行中」等のメッセージを表示させながらバックグラウンドでVBAの処理を行わせるサンプルプログラムを覚書。
VBAサンプルプログラム概要
非常に時間のかかる処理を実行させる際にユーザー側にプログラムの処理中であることを明示的に示しておくことは非常に重要です。
処理中であることを示さないとユーザー側に正常に処理が進んでいるのか、ハングアップしているのかわからないためユーザー側が不安になったり、ハングアップしていると誤解して強制終了されたりする場合があります。
処理中のメッセージを表示しながらバックグラウンドで処理を行う際はユーザーフォームを使用します。
ユーザーフォーム(処理中フォーム)の作成と設定
まず最初に「処理中」や「実行中」のメッセージを表示するためのユーザーフォームを作成します。
ユーザーフォームの作成は、VBAエディタの[挿入]メニューから[ユーザーフォーム]を選択します。
挿入されたユーザーフォームには、以下のようにコマンドボタンとラベルを配置します。
ユーザーフォームと配置した各コントロールの設定
ユーザーフォームと配置したコマンドボタンとラベルの設定は以下のとおりです。
フォーム名:UserForm1
UserForm1のCaptionプロパティ:プログラム処理中
ラベル名:Label1
Captionプロパティ:空白
コマンドボタン名:CommandButton1
Captionプロパティ:閉じる
Enableプロパティ:True
プログラムの処理の流れ
プログラムの処理の流れは以下のとおりです。
- 処理中メッセージを表示するユーザーフォームを表示する。 (※1)
- ユーザーフォーム表示後にメインの処理を実行(メイン処理実行中はExcelの操作ができないようにしておく)
- メインの処理の実行が終了したら処理中メッセージを処理が終了したことを示すメッセージに差し替える
- [閉じる]コマンドボタンを押せるようにする
- [閉じる]コマンドボタンを押すとユーザーフォームが消えてExcelの操作ができるようになる
※1.[X]ボタンの非表示はできないため、フォームを表示する際にはユーザーフォームの[X]閉じるボタンを無効化して、クリックされても閉じないようにしておきます。
VBAサンプルプログラム
以下に上記の処理の流れにそってVBAの各サンプルプログラムを記載します。
ユーザーフォームの表示
ユーザーフォームを表示するプログラムは、標準モジュールに記載します。
Sub Show_UserForm()
'処理中フォームの表示(モーダル)
UserForm1.Show vbModal
End Sub
処理中フォームを表示した際(メイン処理の実行中)にユーザーがExcelの操作をできないようにしておくためにモーダルで表示していることに注意してください。
メイン処理
処理中フォームを表示しながらバックグラウンドで動作させるメインのプログラムです。
標準モジュールに記載します。
サンプルプログラムの動作がわかりやすいように単純なループ処理をメインプログラムとして書いています。
実際には実行させたいコードを記載してください。
'処理中フォームを表示している際に実行する
'メイン処理プログラム
Sub main()
Application.ScreenUpdating = False
For i = 0 To 100000
'OSに処理を返す(画面描画を更新)
DoEvents
UserForm1.Label1.Caption = "処理中です..." & i
Next i
End Sub
メイン処理のポイント
メイン処理のループ内に"DoEvents"を入れています。
"DoEvents"は、発生したイベントがOSによって処理されるように制御をOS戻す関数です。
なぜこれが必要かというと、処理中フォームがユーザーによりドラッグ(移動)されたり、処理中フォーム内の文字列に変更があった際に一度OSに制御を戻さないと再描画処理が行われないためです。
イマイチイメージが湧かない場合は一度"DoEvents"をコメントアウトして実行してみるとわかると思います。
処理中フォームのイベントプロシージャに記述するプログラム
処理中フォームの各イベントプロシージャに記載するプログラムを以下に記載します。
処理中フォームが表示された時(Activate)に実行するプログラム
以下のプログラムは、処理中フォームのActivateイベントに記載します。
Private Sub UserForm_Activate()
'マウスポインターを砂時計に変更
Application.Cursor = xlWait
'メインの処理を呼び出す
Call main
'マウスポインターを元に戻す
Application.Cursor = xlDefault
'処理終了のメッセージを表示
UserForm1.Label1.Caption = "処理が終了しました。"
'閉じるボタンを使用可能にする
CommandButton1.Enabled = True
End Sub
処理中フォームの[閉じる]ボタンがクリックされた時に実行するプログラム
処理中フォームに配置したコマンドボタン(CommandButton1)のクリック時イベントに記載します。
'閉じるボタンが押された際の処理
Private Sub CommandButton1_Click()
'フォームをアンロードする
Unload UserForm1
End Sub
処理中フォームの[X]ボタンがクリックされた時に実行するプログラム
ユーザーに処理中フォームを勝手に閉じられないようにフォームの[X]ボタンを無効化しておきます。
非表示にすることはできないので[X]ボタンがクリックされても処理中フォームが閉じないように処理中フォームのQueryCloseイベントに以下のコードを記載します。
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
'フォームの閉じるボタンの無効化
If CloseMode = 0 Then Cancel = True
End Sub
以上で終了です。
サンプルプログラムの実行
サンプルプログラムを実行する際は、Show_UserFormプロシージャを実行します。
Show_UserFormプロシージャを実行すると処理中フォームが表示され「処理中です...」というメッセージとカウントアップが始まります。
カウントが100000に達するとメッセージが「処理が終了しました。」に変わり、[閉じる]ボタンがクリックできるようになります。
[閉じる]ボタンをクリックすると処理中フォームが閉じられます。
コメント