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

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

診断(10)
シートごとに異なるフォームを表示する

「先生,肩でもお揉みしましょうか?」
「どうしたんじゃ?」
「それともお茶にしますか?」
「うへっ,ますます気持ち悪い。プライベートで何か良いことがあったのかな」
「うふふ,正解!」
「やっぱり。で,恋のお相手は誰じゃ」
「藪医院の院長先生」
「なに!? やつは,わしより年上じゃぞ」
「それが何か?」
「それが何かって,ゲール君。年齢を気にしないのなら…」
「今夜はデート,急がなきゃ。次の方ど~ぞ~」

今月の相談
「ワークシートのタブをクリックしたら,そのシート専用のメニューやユーザーフォームを表示したいのです。シートごとに異なるフォームを表示するといったことはできるのでしょうか?」

「先生,今回はちょっと変わった相談ですね」
「うむ,これぞイベントドリブンの醍醐味というやつじゃな」
「じゃあ,実現できるんですね」
「もちろん。ワークシートにはWorksheet_Activateイベントがある。これは,ワークシートがアクティブになったときに発生するイベントじゃ。このイベントによって,Worksheet_Activateプロシジャが実行される。このプロシジャの中にメニューやフォームを表示するコードを書けばOKじゃ」
「なるほど。でも,先生,アクティブになったシートはどうやって区別するんですか? ただフォームを表示するのではなくて,そのシート専用のフォームを表示するんですよ」
「ゲール君,その心配は無用じゃ。Worksheet_Activateプロシジャを書くところは,そのシート専用のモジュールなんじゃ。例えば,シート名「Sheet1」のワークシート・モジュールにあるWorksheet_Activateプロシジャは,「Sheet1」がアクティブになったときにだけ実行される。他のシートがアクティブになっても,このプロシジャは実行されない」
「標準モジュールに書いたらどうなるんですか?」
「実行されない」
「それだけ?」
「それだけじゃ」
「いわゆる,仕様というやつですね?」
「うむ,シートのイベントで実行されるイベントプロシジャは,そのシート専用のモジュールに書く。それがルールじゃ」
「そのシート・モジュールはどこにあるんですか?」
「うむ,説明しよう」

 では,VBE(Visual Basic Editor)を開いてください。「プロジェクトエクスプローラ」のリストウィンドウにあるシート名をクリックし,続いて左上の[コードの表示]ボタンをクリックすると,そのシート専用のモジュールが表示されます(図1)。

図1●ワークシート・モジュールを表示する手順 その1
図1●ワークシート・モジュールを表示する手順 その1
[画像のクリックで拡大表示]

 ワークシート・モジュールを表示する方法は,ほかにもあります。「プロジェクトエクスプローラ」のリストウィンドウにあるシート名をダブルクリックしてもOKです。または,「プロジェクトエクスプローラ」のリストウィンドウにあるシート名をクリックして,メニュー[表示]→[コード]の順にクリックするという方法もあります(図2)。

図2●ワークシート・モジュールを表示する手順 その2
図2●ワークシート・モジュールを表示する手順 その2
[画像のクリックで拡大表示]

「先生,いろいろなやり方があるんですね」
「直感で結果にたどり着けるように,複数のアプローチが用意されておる。まぁ,最後にはダブルクリックに落ち着くがな」
「直感でたどり着く?」
「そうじゃ。たまにしか利用しない機能は,その存在を知っていても,手順までは忘れてしまうことが多い。しかし,Windowsアプリケーションのメニューは共通している部分が多いので,『ここにあるんじゃないか』とか『こうやったら出るんじゃないか』と試してみると,結構当たるもんなんじゃ」
「そういえば,[コピー]とか[ペースト]のアイコンは,どのアプリケーションでも同じですもんね」
「いちいちマニュアルや参考書を見なくても,直感的に操作できる。それがGUI(Graphical User Interface)の魅力の一つじゃ」
「なるほど。では,構成とコードの解説をお願いします」

 サンプルを作ってみましょう。まず,ワークシートを3枚用意します。それぞれ,シート名を「テレビ」「冷蔵庫」「洗濯機」としてください。

 次に,VBEを開き,メニュー[挿入]→[ユーザーフォーム]の順にクリックして,ユーザーフォームを作ります。これを繰り返して三つのユーザーフォームを作ります。それぞれ,UserForm1がSheet1,UserForm2がSheet2,UserForm3がSheet3のフォームになります。

 オブジェクトウィンドウのSheet1(テレビ)をダブルクリックしてシートモジュールを開き,リスト1のコードを記述します。


Private Sub Worksheet_Activate()
  UserForm1.Show vbModeless

  UserForm2.Hide
  UserForm3.Hide
End Sub
リスト1●「テレビ」シート・モジュールのWorksheet_Activateプロシジャ

 処理は,単純明解です。UserForm1をモーダレスで表示した後,UserForm2とUserForm3を非表示にします。

 同様の手順で,Sheet2(冷蔵庫)とSheet3(洗濯機)のシート・モジュールを開き,リスト2リスト3のコードをそれぞれ記述します。内容は,見ておわかりののように,シートごとに対応するユーザーフォームだけを表示します。


Private Sub Worksheet_Activate()
  UserForm2.Show vbModeless

  UserForm1.Hide
  UserForm3.Hide
End Sub
リスト2●「冷蔵庫」シート・モジュールのWorksheet_Activateプロシジャ


Private Sub Worksheet_Activate()
  UserForm3.Show vbModeless

  UserForm1.Hide
  UserForm2.Hide
End Sub
リスト3●「洗濯機」シート・モジュールのWorksheet_Activateプロシジャ

「先生,それぞれのプロシジャに,ほかのシートのユーザーフォームを非表示にするコードがありますが,これらは必要なんですか?」
「うむ,それがないと三つのユーザーフォームが全部表示されて,画面がユーザーフォームだらけになるんじゃ。利用するユーザーが,不要なフォームをいちいち消すのでは不便このうえない。したがって,他のシートのフォームは消してしまうんじゃ」
「言われてみれば,なるほどそうですね」
「大したことではない。実際に使ってみればすぐにわかることじゃ」
「Hideメソッドで,ユーザーフォームを消すんですね?」
「いや,正確には背後に隠す。つまり,見えなくするだけなんじゃ」
「ユーザーフォームはあるけど,見えないだけ?」
「ユーザーフォームを見えなくするメソッドには,UnloadメソッドとHideメソッドがある。Hideメソッドは画面から消して見えなくするだけで,Unloadメソッドは,指定されたユーザーフォームのインスタンスを抹消し,メモリーを解放する」
「実際に使った場合,二つのメソッドはどう違うんですか?」
「その違いは,一度ユーザーフォームを消して,再度表示したときに明らかになる」
「Unloadメソッドは?」
「Unloadメソッドで消して,Showメソッドで表示すると,ユーザーフォームはイニシャライズして表示される」
「初期状態に戻るということですね?」
「そうじゃ」
「では,Hideメソッドは?」
「Hideメソッドで消して,Showメソッドで表示すると,ユーザーフォームはHideメソッドで消す前の状態で表示される」
「なるほど」
「イニシャライズするか,前の状態を保持するかは,アプリケーションやユーザーの好みによる。好きなほうを選べばよい」
「はい! では,早速ブックを開いて,さっき作ったマクロを確認してみましょう。おや? フォームが表示されませんよ」