VBAを使えるようになってくると、ユーザーフォームを作りたくなりますよね?
今回は、ユーザーフォームを作るテクニックについて解説します。
もくじ
この記事を書いている私は、10年前からVBAを活用して業務改善を続けてきました。
ユーザーフォームもたくさん作ってきました。
ユーザーフォームには多くのパーツがあります。パーツの数だけテクニックがありますが、「こういう使い方を覚えれば大丈夫」という項目に絞って解説します。
「VBAをある程度使えるけど、ユーザーフォームの経験が少ない方」が対象になります。
また、たまにしかユーザーフォームを使わない方にとっても、忘備録として活用できるようにしました。
サンプルコードも載せておきますが、100%の動作保証が取られるものではありませんので、ご自分のフォームに合わせてカスタマイズして頂ければと思います。
テクニック1-フォームを起動したり閉じたりする
ユーザーフォームを使ったことの無い方は、まずは開き方と閉じ方をしっかりと覚えておきましょう。
この記事では、下の表を作ってユーザーフォームでデータを表示してみます。

ユーザーフォームを作る
次にユーザーフォームを作ります。
オブジェクトブラウザを右クリックし、「挿入」→「ユーザーフォーム」の順に選択します。

ユーザーフォームが作成されるので、閉じるためのボタンも設置します。

OPENメソッドで作ったフォームを開くことが出来ます。
ユーザーフォームの開き方
ユーザーフォームを作るだけでは、フォームを起動することが出来ません。
ワークシートにボタン設けてフォームを起動してみます。

VBEで標準モジュールを作成します。
ユーザーフォームと同様に、「挿入」→「標準モジュール」の順に選択します。

標準モジュールにフォームを起動させるコードを書きます。
Sub OpenForm1()
'ユーザーフォームを起動させる
UserForm1.Show
End Sub
次にボタンを右クリックし、マクロを登録します。

「OpenForm1」プロシージャを選択します。

ボタンをクリックすると、ユーザーフォームが起動することが確認できました。

「CommandButton1」をクリックしても、なにも作動しません。

一旦×ボタンでフォームを閉じます。

ユーザーフォームの閉じ方
ここでは、ユーザーフォーム上のボタンを使って閉じる方法を紹介します。
「CommondButton1」をクリックし、「コードの表示」をクリックします。

エディターが表示され、以下のようにコードが書かれています。
Private Sub CommandButton1_Click()
End Sub
フォームを閉じるための一文を追加し、下のように修正します。
Private Sub CommandButton1_Click()
Unload UserForm1 'UserForm1を閉じる
End Sub
ボタンをクリックすることで、開いていたユーザーフォームを閉じることができます。
ボタンの名前を編集する
左下の「プロパティウインドウ」で、ボタンの名前や表示を設定することもできます。

名前は「オブジェクト名」、表示は「Caption」で編集できます。

オブジェクト名を「閉じる」とすると、
Private Sub 閉じる_Click()
Unload UserForm1 'UserForm1を閉じる
End Sub
のようにプロシージャ名を変えなければいけません。
テクニック2-開いた時にプログラムを作動させる
エディターの上部に選択ボックスがあります。
項目を選択することで、パーツのイベントプロシージャを作ることが出来ます。
「UserForm」を選択します。

隣のボックスは、「Initialize」を選択します。

新しいイベントプロシージャを作成できました。

フォームが起動したと同時に命令を出すことが出来ます。
新しく作ったテキストボックスに文字を表示させてみます。
文字を表示させるためのテキストボックスをユーザーフォームに配置します。

「UserForm_Initialize」プロシージャに、データ表示するコードを書きます。
Private Sub UserForm_Initialize()
'テキストボックスに表示させる
Me.TextBox1.Value = "Hello World"
End Sub
フォームを起動させると、テキストボックスに文字を表示できました。

フォーム起動時には、
- コンボボックスやリストボックスなどに選択データを登録する
- 特定のワークシート内のデータを取得する
といった動作をよく行います。
テクニック3-モーダルとモードレスを使い分ける
「ユーザーフォームを起動させると、ワークシートを操作出来ない」
こういったことが不便に感じたことはありませんか?
「モードレス」を指定すれば、フォームを起動しながらワークシートの編集が可能です。
Sub OpenForm1()
'モードレスでフォームを表示(シート編集可)
UserForm1.Show vbModeless
End Sub
一方、初期設定されている編集できない状態は「モーダル」と呼ばれます。
Sub OpenForm1()
'モーダルでフォームを表示(シート編集不可)
UserForm1.Show vbModal
End Sub
誰かにワークシートの中身を書き換えられたくない場合は、モーダル設定の方が適しています。
モーダルとモードレスは用途によって使い分けましょう。
テクニック4-コンボボックスを使いこなす
コンボボックスは、ワークシートの入力規則と同じように、複数の選択データを格納することが出来ます。
新しいフォームUserForm2を作り、オブジェクトを配置します。

※使用するオブジェクト名は()内に記載しています。
Additemで収納する
コンボボックスには、定数とセルの値の両方を格納することが可能です。
フォームの起動時に商品CDを定数で格納してみます。
Private Sub UserForm_Initialize()
'AddItemで格納(定数)
Me.ComboBox1.AddItem "S01"
Me.ComboBox1.AddItem "S02"
Me.ComboBox1.AddItem "S03"
Me.ComboBox1.AddItem "S04"
Me.ComboBox1.AddItem "S05"
Me.ComboBox1.AddItem "S06"
Me.ComboBox1.AddItem "S07"
End Sub
データの格納はAdditemでシンプルに書けますが、商品CDが多くなると行数が増えます。
商品マスタの増減とともに都度コードを変えなければいけません。
一方、A列のデータを変数を使って格納するコードです。
Private Sub UserForm_Initialize()
'AddItemで格納(変数)
Dim n As Integer
For n = 0 To Sheets("Sheet1").Range("A1").End(xlDown).Row - 2
Me.ComboBox1.AddItem Cells(2 + n, 1).Value
Next n
End Sub
繰り返し(ループ)を使っていますので、商品の増減にも自動で対応できます。
実行すると、いずれもコンボボックスにデータが格納されているのが分かります。

RowSourceで収納する
AddItemはデータを一個ずつ格納する方法ですが、RowSourceを使うと、セルの範囲をそのまま指定できます。
範囲を定数で指定したパターンです。
Private Sub UserForm_Initialize()
'RowSourceで格納("範囲の変更非対応")
Me.ComboBox1.RowSource = Sheets("Sheet1").Range("A2:A8").Address
End Sub
商品マスタが増減した場合はコードの修正が必要です。
A列の最終行を取得し、商品マスタの増減に対応したパターンです。
Private Sub UserForm_Initialize()
'RowSourceで格納("範囲の変更対応")
Me.ComboBox1.RowSource = Sheets("Sheet1").Range(Cells(2, 1),_
Cells(Sheets("Sheet1").Range("A1").End(xlDown).Row, 1)).Address
End Sub
コード自体は長くなりますが、運用上このパターンをオススメします。
コンボボックスからデータを参照する
Excelでワークシートで入力規則とVLOOKUP関数を組み合わせる方法って、とても便利ですよね?
ユーザーフォームのコンボボックスでも、WorksheetFunctionを使って、同じような方法ができます。
Private Sub ComboBox1_Change()
Dim i As Integer
'VLOOKUP関数を使ってテキストボックスにデータを反映
For i = 1 To 4
Me.Controls("TextBox" & i).Value = _
WorksheetFunction.VLookup(Me.ComboBox1.Value, Sheets("Sheet1")._
Range("A1:E8"), i + 1, 0)
Next i
End Sub
商品CDを選択すると、各テキストボックスにデータが反映されます。

テクニック5-リストボックスを使って複数のデータを選択する
リストボックスも複数のデータを収納できますが、更に便利に使えます。
- 列ごとの幅を決める
- 列見出しを表示する
- 項目を複数選択させる
- 左端にチェックボックスを表示させる
といった設定がありますが、下のコードは全てを有効にしています。
Private Sub UserForm_Initialize()
'列数の表示
ListBox1.ColumnCount = 5
'各列の幅
ListBox1.ColumnWidths = "40;40;80;40;40"
'見出し列の表示
ListBox1.ColumnHeads = True
'複数選択
ListBox1.MultiSelect = fmMultiSelectExtended
ListBox1.ListStyle = fmListStyleOption
'範囲の指定
ListBox1.RowSource = Worksheets("Sheet1").Range("A2:E8").Address
End Sub
不要なコードは削除するかコメントするかで無効にできます。
実行すると、左端にチェックボックスが表示されています。

Ctrlキーを押しながら複数データを選択できます。

また、選択した複数データをメッセージボックスで表示するコードです。
Private Sub CommandButton2_Click()
Dim i As Integer
'選択した複数データを表示
For i = 0 To ListBox1.ListCount - 1
If ListBox1.Selected(i) = True Then
MsgBox (ListBox1.List(i, 0) & ":" & ListBox1.List(i, 1))
End If
Next
MsgBox ("おわり")
End Sub
例えば、複数のデータを選択して、帳票をまとめて印刷させるときにはとても便利です。
まとめ
ユーザーフォームについて解説しました。
今回は、項目を絞り他のパーツは省略しましたが、実務に使える本当に大事なところを盛り込んでいます。
ユーザーフォームを使えるようになりたい方は、是非こちらのコードをコピペして自分流にアレンジしてみましょう。
ユーザーフォームで別のパーツを使う時にも、イベントプロシージャとオプションを扱えれば何とかなります。
本日もありがとうございました。