2010年11月11日

3.ユーザーフォームは1つしかなかった

 一つのブックで、ユーザーフォームを使った複数の異なる作業を行うとき、フォームのデザインに迷います。 作業によって項目が2〜3個しか無いものもあれば、会計処理や流通伝票などでは、数十個の[ TextBoxコントロール ]を 1画面に配置するときもありますので、1つのマクロブックに複数のユーザーフォームを持たせることはよくあります。
 [ BakuJAN活用例.xls ]は、ユーザーフォームの表示直後、解像度1280×1024以下のモニターであればフルスクリーン状態になっていて、 フォームがデスクトップ全体を覆い隠しています。これは、Excelのユーザーフォームをコンピュータのログイン画面に見立て、 “パスワードを知らない人は、Excelの操作ができないようにする”ためのものです。
 モニターのサイズはユーザーによって異なりますので、ウィンドウのサイズを取得するために[ API関数 ]を使い、 デスクトップウィンドウのハンドルを取得しています。
  •  ★  [ API関数 ]で、モニターの解像度を求める


     ※全画面表示になるため、フォームを閉じる方法を必ず用意して実行してください。

  •  ★  モニター画面の解像度に合わせ、ユーザーフォームのサイズを変更する


     このコードは、ユーザーフォームが表示される前の[ Initializeイベント ]で開始されます。 ユーザーフォームがモニターへ表示されたときには、既にこのプロシージャは終了しています。 [ Initializeイベント ] を使う理由は、[ Activateイベント ]を使った場合はフォームを表示してからコードが実行されるので、 フォームの表示位置の基準とする座標が[ Initializeイベント ]で求める座標と異なってしまうためです。

  •  ★  指定したファイルの有無を調べる

     ★  コントロールに外部画像ファイルを読み込む


     [ Initializeイベント ]では、ユーザーフォームのフルスクリーン設定の他に、[ Dir関数 ]を使って画像ファイルの有無を調べ、 存在する場合はフレームコントロールの[ Pictureプロパティ ]に、[ LoadPictureプロパティ ]で画像を読み込む処理を行っています。
     コントロールの[ Pictureプロパティ ]に予め画像を設定しないことで、必要に応じて画像を読み込ませ、 マクロブックと画像ファイルを切り離して使うことができ、Excelブックが不必要な画像データを持たず、 Excelブックの肥大化とメモリの消費を抑えています。

 ユーザーフォームが表示されると、最初に[ メニュー画面 ]が現れます。複数のマルチページを扱うときは、 デザインモード時に表示しているページが、マクロ実行時の最初の表示ページになってしまうので、[ Initializeイベント ] 中で [ MultiPage1.Value = 0 ]などと、最初に表示するページを指定すると良いです。
ExcelVBAマクロ
図:[ UserForm ]は1つで、[ MultiPageコントロール ]により処理毎の画面に切り替える

 ユーザーの使用環境、ここではモニター画面の解像度でしたが、ユーザーフォームの実行中(表示中)に、 その大きさをダイナミック(動的)に変更したり、ユーザーのモニター解像度に合わせて、 フォームのサイズや表示位置を変更できると便利ですね。 VBAマクロの実行中は、[ メニュー画面 ]にある [ フルスクリーン解除(設定) ]ボタンを押すことによって、 ユーザーフォームのサイズを任意の値まで拡大/縮小させています。
 また、ユーザーフォームの上には、[ MultiPageコントロール ]が乗っているため、ユーザーフォームの拡大/縮小に併せて、 [ MultiPageコントロール ]の表示位置も調整し、画面の中央にくるようにしています。(※モニター解像度1280×1024の場合)。 フォームの表示位置は、モニター画面に対してフォーム全体の中心位置にしているため、実際には上部の座標がタイトルバーの分だけ、下にずれて表示されます。
  •  ★  VBAマクロの実行中に、ユーザーフォームのサイズを動的に変更する



     表示状態は、コマンドボタン[ Btn_WinSET ]の[ Captionプロパティ ]の値を[ If〜Then〜Else ステートメント ] で判断し処理を分岐しています。現在の表示状態を変更するコマンドボタンですから、[ Captionプロパティ ]「〜解除」の時は フルスクリーン状態ですし、「〜設定」の時はフルスクリーンではありません。

 このプロシージャは、パスワードを入力しないとログインできないようにするためのもので、フォームに配置されるコントロールは、 パスワードを入力するための[ TextBoxコントロール ]ただ一つです。ユーサーインターフェースとして利用されるのは、 このコントロール一つだけなので、ユーザーフォームを必要以上、ここでは全画面フルスクリーン化する必要はありません。 では、なぜわざわざフルスクリーン化したのでしょうか。
 それは、ユーザーフォームの背面に「見せたくないもの」があった場合、ユーザーフォームがモニターサイズよりも小さかったり、 マウスで移動できてしまうと、フォームの後ろに隠れているデスクトップアイコンなど、情報が丸見えになってしまうからです。 デスクトップアイコンを隠すだけでも、何か専門のアプリケーションのような雰囲気を作ることが出来ますね。 念を入れるなら、アシスタントの表示も停止しておきましょう。
 また、ユーザーフォームのタイトルバーが表示されていると、マウス操作のドラッグなどで、 モニター上の表示位置を変更することが出来てしまいますので、ユーザーフォームをモニターサイズよりも大きくし( + 50ポイント)、 フォームの外枠を上にはみ出させて、マウスカーソルがタイトルバーへ届かないようにしています。
 ユーザーフォームには、[ QueryCloseイベント ]を使った以下のプロシージャが記述してあり、タイトルバーにある[ ×(閉じる) ] ボタンを無効にしてあります。 [ QueryCloseイベント ]は、ユーザーフォームが閉じられる直前に発生するイベントです。
  •  ★  タイトルバーの[ X(閉じる) ]ボタンを無効にする



    [ Blink ]は、操作すべきボタンを指し示すため、[ CommandButtonコントロール ]の背景色を点滅させるプロシージャ名で、後の章で説明してあります。

 このように1つのユーザーフォームでも、サイズや位置のプロパティを指定することで、複数のユーザーフォームがあるかのように見せる事が出来ます。 しかしながら、1つのフォームだけで運用するとなると、異なった処理系のコードが、1つのユーザーフォームのコード内に記述されるため、 メンテナンス上も好ましくありません。本来は異なる処理系毎にフォームを用意しましょう。
 [ BakuJAN活用例.xls ]では、1つのユーザーフォームに全ての処理系をまとめてありますが、次の番外のように、処理系に応じたフォームをそれぞれ作成し、 コードの記述場所も変えたほうが良いでしょう。

番外3.


 ユーザーフォームの表示位置を自由に扱えるようになると、複数のユーザーフォームを使ったマルチウィンドウのマクロソフトも、 楽にレイアウトすることができます。医療系ソフトでは、電子カルテと投薬のオーダー、検査項目の指示などのフォームを見間違いや憶え間違いが無いよう、 異なるオーダーフォームを1画面に表示するのが一般的ですね。オーダーによって画面が変移するということは、ユーザー(人間)の記憶に頼った ヒューマンエラーの原因になるわけです。
 ExcelのVBAマクロで使うユーザーフォームズオブジェクト[ UserForm* ]は、引数に値を指定しないと、モーダル状態が既定値となります。 複数のユーザーフォームを同時に表示しても、それぞれのフォームを自由に行き来することが出来ません。 マルチウィンドウで操作するフォームは、引数に[ vbModeless ]を設定して、[ Showメソッド ]を実行します。
ExcelVBAマクロ
図:4つのユーザーフォームをモニターの指定位置に同時に表示する

  •  ★  4つの異なるユーザーフォームを同時に表示する



    ※[ UserForm1 ]を追加し[ CommandButton1 ]を配置、以下を記述する
    ※[ UserForm2 ]を追加し[ CommandButton1 ]を配置、以下を記述する
    ※[ UserForm3 ]を追加し[ CommandButton1 ]を配置、以下を記述する
    ※[ UserForm4 ]を追加し[ CommandButton1 ]を配置、以下を記述する
     この一連のコードでは、フォームが次々と次のフォームを開いていきます。 全てのフォームはモードレスで開かれますが、仮にモーダル状態で[ Showメソッド ]を実行すると、 [ UserForm4 ]から降順にしかフォーカスを受け取れないので、自由に閉じることは出来なくなります。
     各フォームにはタイトルバーが付きますので、実際にはフォームを複数表示するより、 1つのフォーム上で[ MultiPageコントロール ]や[ TabStripコントロール ]で使い分けた方が、スッキリしますね。
posted by くきお at 11:11| Comment(0) | ExcelVBAマクロ | このブログの読者になる | 更新情報をチェックする