親愛なる貴方のために・・・え?誰?
一つのブックで、ユーザーフォームを使った複数の異なる作業を行うとき、フォームのデザインに迷います。作業によって項目が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 ]などと、最初に表示するページを指定すると良いです。
図:[ 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メソッド ]を実行します。
図:4つのユーザーフォームをモニターの指定位置に同時に表示する
- ★
4つの異なるユーザーフォームを同時に表示する
- ※[ UserForm1 ]を追加し[ CommandButton1 ]を配置、以下コードを記述する
- ※[ UserForm2 ]を追加し[ CommandButton1 ]を配置、以下を記述する
- ※[ UserForm3 ]を追加し[ CommandButton1 ]を配置、以下を記述する
- ※[ UserForm4 ]を追加し[ CommandButton1 ]を配置、以下を記述する
この一連のコードでは、フォームが次々と次のフォームを開いていきます。全てのフォームはモードレスで開かれますが、仮にモーダル状態で[
Showメソッド ]を実行すると、[ UserForm4
]から降順にしかフォーカスを受け取れないので、自由に閉じることは出来なくなります。
各フォームにはタイトルバーが付きますので、実際にはフォームを複数表示するより、1つのフォーム上で[
MultiPageコントロール ]や[ TabStripコントロール ]で使い分けた方が、スッキリしますね。
|