古庄 潤(ふるしょう じゅん)

本業はエンジニア。ICに様々な機械をつなぎ,電流やら電圧を測定する。もちろん,これらの測定器もVBAでコントロールし,取り込んだデータもマクロで処理する。人呼んで,マクロの鬼軍曹!。

診断(4)
マクロ実行中のメッセージを出したい

「先生,何やってるんですか? 診療の時間ですよ」
「おぉ,もうそんな時間か。カーナビにワンセグのチューナーを取り付けておったのじゃよ」
「ナスビにワンタン?」
「これじゃ」
「なんだテレビじゃないですかぁ」
「デジタル放送じゃぞ!」
「ふ~ん」
「それだけかい!」
「はいはい。さ,お仕事しましょ」

今月の相談
「マクロの処理時間が長いので,その間『実行中』の表示をしたいと思います。しかし,処理を始める前にメッセージボックスを表示すると,肝心の処理が実行されません。どうにかならないでしょうか?」

「ふむふむ,これははまりがちな問題じゃな」
「先生,それは処方できないという意味ですか?」
「うむ,完治は難しいかもしれん。じゃが,対処療法ならある」
「それはどういうことですか?」

 相談者がお悩みのように,メッセージボックスを表示すると,ユーザーがボタンをクリックしてメッセージボックスが消えるまで,次のステートメントは実行されません。というか,次を実行されてはメッセージボックスを出す意味がありません。これは仕様です。

 しかし,何らかの表示をしながら,バックグラウンドでマクロを実行したい状況はあります。リスト1のように,ウィンドウ一番下のステータスバーに文字列を表示することはできますが,ステータスバーは目立たないので,ユーザーが気づかない可能性が高いです。


Sub stb1()
  Application.StatusBar = "ここがステータスバー"
End Sub
リスト1●ステータスバーに文字列を表示するプロシジャ

 やはり,もっと目立つようにメッセージを表示したい,そして,マクロが終了したらそのメッセージを消したい──そういうケースもあるでしょう。このような場合,ちょっとしたテクニックを使えば,希望に近いものを作ることができます。例えば,ワークシートのセルを使ってプログレスバー(進ちょく状況を表示するバー)を描画するという手もあります。ここでは,ユーザーフォームを使って,擬似的なメッセージボックスを表示するテクニックを紹介しましょう。

 なお,ユーザーフォームを使う場合でも,それを表示するステートメントの次のステートメントは,ユーザーフォームが非表示(UnloadまたはHide)になるまで実行されません。例えば,リスト2のマクロは,ユーザーフォームが表示されている間は,(1)のステートメントは実行されず,メッセージボックスは表示されません。ユーザーフォームを閉じると,メッセージボックスが表示されます。


Sub test1()
  UserForm1.Show
  MsgBox "完了"  '--------(1)
End Sub
リスト2●ユーザーフォームのテスト

 したがって,ここまではユーザーフォームもメッセージボックスも同じです。つまり,ユーザーフォームを表示するステートメントと,実際に処理を実行するステートメントを同じプロシジャに記述したのでは,希望の動作はしないということです。

 しかし,ユーザーフォームにはイベントプロシジャがあります。今回使用するのは,Activateイベントです。このイベントは,ユーザーフォームがアクティブになると発生します。そしてUserForm_Activateプロシジャが記述されていると,それを実行します。

 このUserForm_Activateプロシジャの中に,処理のステートメントを記述すれば,まるでユーザーフォームのバックグラウンドで処理が実行されているかのように見えます。「じゃあ,これで問題解決?」というと,そう簡単ではありません。

 UserForm_Activateプロシジャの実行中は,ユーザーフォーム自体は表示されても,ユーザーフォーム上に配置したコントロールが表示されません。つまり,「マクロ実行中」といったラベルをユーザーフォーム上に配置しても無意味なのです。では,どのようにしてメッセージをユーザーに伝えるのか? 唯一表示されるのが,ユーザーフォームのCaptionです。これを利用して,ユーザーにメッセージを伝えます。

 では,順を追って説明しましょう。

(1)ユーザーフォームを作成する
 まず,ユーザーフォームを作成します。VBEのメニューから[挿入]-[ユーザーフォーム]の順にクリックするとユーザーフォームが作成されます(図1)。

図1●ユーザーフォームの作成
図1●ユーザーフォームの作成
[画像のクリックで拡大表示]

(2)UserFormのCaptionプロパティを変更
 プロパティウィンドウで,ユーザーフォームのキャプションを変更します(図2)。

図2●ユーザーフォームのキャプションを変更する
図2●ユーザーフォームのキャプションを変更する
[画像のクリックで拡大表示]

(3)UserForm_Activateプロシジャを作成
 [コードの表示]ボタンをクリックすると,ユーザーフォームのモジュールが表示されます。「オブジェクトボックス」で,「UserForm」を選ぶとUserForm_Clickプロシジャが自動的に作成されますが,これは削除してください。次に「イベントボックス」で「Activate」をクリックすると,UserForm_Activateプロシジャが作成されます(図3)。

図3●UserForm_Activateプロシジャを作成する
図3●UserForm_Activateプロシジャを作成する
[画像のクリックで拡大表示]

(4)処理のステートメントを記述
 UserForm_Activateプロシジャに,処理のステートメントを記述します。例えば,リスト3のように記述すると,ユーザーフォームが表示されると同時に「MAKE_DATA」プロシジャが実行されます。


Private Sub UserForm_Activate()
  Call MAKE_DATA
End Sub
リスト3●UserForm_Activateプロシジャの例

(5)ユーザーフォームを非表示にするステートメントを記述
 実行したい処理のステートメントの後に,ユーザーフォームを非表示にするステートメントを記述します(リスト4)。これにより,「MAKE_DATA」プロシジャが実行された後,すぐにユーザーフォームは非表示になります。


Private Sub UserForm_Activate()
  Call MAKE_DATA
  Unload Me
End Sub
リスト4●UserForm_Activateプロシジャの例その2

(6)標準モジュールを作成
 VBEのメニューから[挿入]-[ユーザーフォーム]の順にクリックして標準モジュールを作成します。

(7)標準モジュールにユーザーフォームを表示するプロシジャを記述
 リスト5のShowメソッドのオプションは,ユーザーフォーム表示中にExcelの操作を認めるかどうかの選択です。このオプションを省略,またはvbModalにした場合は,ユーザーフォームを表示中にExcelの操作はできません。vbModelesにした場合は,ユーザーフォームを表示中であってもExcelの操作が可能です。


Sub UF1SHOW()
  UserForm1.Show vbModal
End Sub
リスト5●ユーザーフォームを表示するプロシジャ

(8)ワークシートにマクロを実行するボタンを配置
 最後にワークシート上にボタンを配置し,ユーザーフォームを表示するマクロを登録します(図4)。

図4●ボタンを配置し,マクロを登録する
図4●ボタンを配置し,マクロを登録する

 図5の「マクロの登録」ウィンドウで,登録するマクロを選び,[OK]ボタンをクリックして完了です。

図5●マクロの登録ウィンドウ
図5●マクロの登録ウィンドウ

「どうじゃな? こうすれば,マクロ実行中はユーザーフォームが表示され,マクロ終了と同時に消えるじゃろ?」
「はい,先生,すばらしい出来です。でも,マクロを実行して終ったことが確認できません」
「どういうことじゃ?」
「マクロを実行する前と終った後が同じ画面の場合,もしかしたらマクロを実行していないのかもって思っちゃうんです」
「ほー,では,こんなのはどうかな?」

図6●マクロ実行後にメッセージを表示
図6●マクロ実行後にメッセージを表示
[画像のクリックで拡大表示]

「これなら,マクロ実行中に席を離れて戻ってきたときでも,マクロを実行して終ったことがはっきりわかりますね」
「そうじゃろ」
「先生,このマクロはどうなってるんですか?」

 ユーザーフォームにラベルを一つ配置し,処理をするマクロを実行後にラベルのCaptionプロパティの値を変更します(1)。その代わりに,ユーザーフォームを非表示にするステートメントを削除しました(リスト6)。


Private Sub UserForm_Activate()
  Call MAKE_DATA
  Me.Label1.Caption = "マクロの実行が完了しました"  '-----(1)
End Sub
リスト6●「完了」を表示するマクロ

「実は,処理するマクロ(MAKE_DATA)が終了するまで,ラベルは表示されないから,プロパティ設定で,初めからキャプションを『マクロの実行が完了しました』にしておいても結果は同じなんじゃがね」
「え~! じゃあ,(1)のステートメントは無意味じゃないですか」
「……」
「先生?」
「次の方,ど~ぞ~」