ユーザーフォームを作る

フォームは、結構敷居が高く、入力画面もシートで作る方が簡単ですが、VBA のユーザーフォームも慣れてくると簡単に使えるようになります。ただ、ちょっと文化が異なるようで、「プロパティ」で設定する方式が、ややこしいですね。

ツール・マクロから、Visual Basic Editorを開き、挿入メニューのユーザーフォームを実行します。

ツールボックスから選択して、フォームにオブジェクトを貼り付けます。
ここでは、ラベル・テキストボックス・コマンドボタン・リストボックスについて説明します。

ラベルは、固定の文字列を表示させるもの・テキストボックスは文字列を入力するもの、コマンドボタンはマクロを登録して実行させるもので、シートに直接表示させるMsgbox Inputbox ボタンに相当するものです。使い方はほぼ同じですが、それぞれ内容はプロパティで設定します。

それぞれのツールを選択すると、プロパティ一覧が表示されます。表示されない場合は、右クリックでプロパティを実行すると、以後プロパティウインドウが表示されます。

BackColor は背景色、ForeColorは文字色です。これらは、選択すると一覧が現れ、選択できます。

Fontは、文字の設定です。ここで、サイズや種類を選べます。

Captionは、表示される文字列です。直接書き込むか、VBAで
UserForm1.Label1.Caption="表示したい文字"で設定できます。

ちなみに、UserForm1.Caption は、フォームのタイトルです。

プロパティの一覧は、オブジェクトによって異なりますが、英語を理解すれば内容は想像付きます。

テキストボックスの場合は、Captionではなく、textになります。
Cells(1,1)=Userform1.Textbox1.Text のように、セルに値を持ってこられます。


シートにフォームを表示させるには、マクロが必要です。
UserForm1.Show を、マクロに登録して実行します。これは、標準のモジュールシートに登録します。

フォームを消すには、
UserForm1.Hide  ですが、この場合はフォームが非表示になるだけで、フォームの内容は保持されます。
×ボタンで消すのと同じものは、 Unload UserForm1です。
Xボタンで消されると困る場合は、フォーム上のボタンにフォーム終了のマクロを登録して、×ボタンを無効にします。
これには、別途マクロの登録が必要です。

マクロの登録
フォームのマクロは、フォームごとにプライベートマクロが作られるので、ここに登録します。

先の、×ボタンを無効にするマクロは
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
If CloseMode = vbFormControlMenu Then Cancel = True
End Sub
です。

その他、それぞれのオブジェクトをクリックしたりするイベントごとのマクロが自動で作られています。この中に、モジュールシートに登録したマクロを呼び出す記述が可能です。

Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
If CloseMode = vbFormControlMenu Then  ’フォームの×ボタンをクリックしたときのイベントを登録します
 ThisWorkbook.Save
 Application.Quit
End If
End Sub

リストボックスは、複数行の文字列を表示させるものですが、ワークシート上の範囲を表示させることも可能です。
複数列の表データを表示させ、この中の項目を選択する例を紹介します。

サンプルは、一つのシートにまとめてありますが、G1:I18のリストをフォームのリストボックスに表示させ、ここで選択したものをシートのA4、B4、B5に表示するようにしています。

Listbox1のプロパティを表示させ、ここで設定して行きます。

先ず、複数列のリストを表示するために、BoundColumnとColumunCountに、ここで必要な3列の3を入れます。

ColumunHeadは、項目行を表示するかの指定です。Trueを選びます。

列幅を指定するために、50pt;70pt;150pt を入れます。単位の関係で50が49.95に変わりますが、気にする必要はありません。プロパティの下の方にwidthの数値があるので、合計がこれより少なくします。

次に、RowSourceを設定します。
これは、マクロで後から指定しても構いません。
項目行を除くデータの範囲をSheet1!G2:I18として入れておきました。


 
必要なマクロを設定します。

標準のモジュールシートに、フォームを表示させるマクロを設定します。
ここで、RowSourceを指定しても良いです。
その場合の例として、入れてありますが、一般的には条件によってリストの中身が異なるので、プロパティで設定する必要は無いと思います。


UserForm1のプライベートモジュールに下のようなコードを入れます。
ここでは、ボタンを選択確定に使うので、フォームの×ボタンを無効にするマクロは外しました。

listbox1がクリックされたときのマクロは、クリックした位置を取得し、この値を他でも使うこととし、Dimで定義したgy変数に取り込みます。

この値が-1のときは、どこもクリックしていない状態なので、Label1のキャプションにメッセージを置き、そうでないときにこれを書換え、gy位置の1列目のデータをTextbox1に表示します。ここは、本当はラベルで良いです。

このTextbox1の中身が変化したときに、シートの3つのセルをクリアします。

そして、コマンドボタンがクリックされたときに、リストのデータを3つのセルに反映させています。フォームを使う目的は、このようなリストボックスが必要な場合です。単純な表示や入力は、MsgboxやInputboxの方が手軽に使えます。このサンプルで、リストを表示させ、そこから選んだものを入力に使うというフォームが理解できると思います。

リストボックスにデータを並べるには、additemを使う方法もあります。この場合は、ListBoxの項目行にデータを表示することは出来ないと考えた方が良いです。そのかわり、シートにデータを並べなくとも、直接指定できます。
With Form1.ListBox1
.Clear Listboxをクリア
.AddItem .List(gyo, 0) = data1 gyoは、0から始まるListbox内の行位置、0は1列目:data1はそこに表示させるもの
.List(gyo, 1) = data2 同じく、2列目にdata2を表示
.List(gyo, 2) = data3 同じく、3列目にdata3を追加
End With   gyoを変えて追加するには、 .AddItemから

複数列の表データを表示させ、この中の項目を選択する例を紹介します。

サンプルは、一つのシートにまとめてありますが、G1:I18のリストをフォームのリストボックスに表示させ、ここで選択したものをシートのA4、B4、B5に表示するようにしています。

Listbox1のプロパティを表示させ、ここで設定して行きます。

先ず、複数列のリストを表示するために、BoundColumnとColumunCountに、ここで必要な3列の3を入れます。

ColumunHeadは、項目行を表示するかの指定です。Trueを選びます。

列幅を指定するために、50pt;70pt;150pt を入れます。単位の関係で50が49.95に変わりますが、気にする必要はありません。プロパティの下の方にwidthの数値があるので、合計がこれより少なくします。

次に、RowSourceを設定します。
これは、マクロで後から指定しても構いません。
項目行を除くデータの範囲をSheet1!G2:I18として入れておきました。


 
必要なマクロを設定します。

標準のモジュールシートに、フォームを表示させるマクロを設定します。
ここで、RowSourceを指定しても良いです。
その場合の例として、入れてありますが、一般的には条件によってリストの中身が異なるので、プロパティで設定する必要は無いと思います。


UserForm1のプライベートモジュールに下のようなコードを入れます。
ここでは、ボタンを選択確定に使うので、フォームの×ボタンを無効にするマクロは外しました。

listbox1がクリックされたときのマクロは、クリックした位置を取得し、この値を他でも使うこととし、Dimで定義したgy変数に取り込みます。

この値が-1のときは、どこもクリックしていない状態なので、Label1のキャプションにメッセージを置き、そうでないときにこれを書換え、gy位置の1列目のデータをTextbox1に表示します。ここは、本当はラベルで良いです。

このTextbox1の中身が変化したときに、シートの3つのセルをクリアします。

そして、コマンドボタンがクリックされたときに、リストのデータを3つのセルに反映させています。フォームを使う目的は、このようなリストボックスが必要な場合です。単純な表示や入力は、MsgboxやInputboxの方が手軽に使えます。このサンプルで、リストを表示させ、そこから選んだものを入力に使うというフォームが理解できると思います。

フォームを閉じると、エクセルが終了

Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
If CloseMode = vbFormControlMenu Then  ’フォームの×ボタンをクリックしたときのイベントを登録します
 ThisWorkbook.Save
 Application.Quit
End If
End Sub
 

フォーム以外は見せない

Application.WindowState = xlMinimized  ’ワークシートは、最小化してしまう
UserForm.Show vbModeless        ’フォームは、表示する

または、まったくワークブックを隠してしまうには

 Application.Visible = False  これを使うときは、どこかで Application.Visible = True を実行しないと、永久に見えない・・

カーソルの移動・移動後文字列の最後にカーソルを移動する

UserForm1.TextBox5.SetFocus
UserForm1.TextBox5.SelStart = Len(UserForm1.TextBox5.Text)

フォームのコントロールの番号を変数で指定する

menuF.Controls("TextBox" & nb + 8).Value =""   のように記述します。
Contrors(”コントロール名”&変数).プロパティ名