ユーザーフォーム入門
メニューを表示するにはスワイプしてください
UserFormはExcel for Macでは機能が制限されているか、利用できない場合があります。Mac版のVBA IDEは多くのバージョンでUserFormのデザインを完全にサポートしておらず、このような予期しない動作が発生する原因となります。
MsgBoxやInputBoxは、簡単なはい/いいえの質問や1行の回答には対応できますが、顧客情報の追加には複数の項目が必要です。たとえば、会社名、担当者、都市、ステータスなどです。これらをまとめて入力するためにUserFormを使用します。UserFormは、独自のラベル、テキストボックス、ドロップダウン、ボタンを備えた小さなカスタムウィンドウで、VBE内で作成し、コードで完全に制御します。
フォームの作成
VBEで、Project Explorer内のプロジェクトを右クリックし、挿入 → UserForm を選択します。空白のデザイン画面が表示され、コントロールをドラッグできるツールボックスが浮かび上がります。
ラベル、テキストボックス、コンボボックス、ボタン
フォームにコントロールをドラッグすると、それぞれに TextBox1 や CommandButton1 のようなデフォルト名が付きますが、コントロールが6つや7つになると意味が分かりにくくなります。このセクションで最も重要な習慣は、プロパティウィンドウで確認できる通り、コントロールを追加した直後に必ず名前を変更することです。型を識別する短いプレフィックス(txt には TextBox、cbo には ComboBox、cmd には CommandButton、opt には OptionButton、chk には CheckBox、lst には ListBox)と、説明的な名前を組み合わせてください。たとえば、txtCompanyName であれば、3週間後にコードを見ても明確に意味が分かりますが、TextBox1 では分かりません。
ラベルは単なる非対話型のテキストキャプション(「Company Name:」など)で、ユーザーは見ることはできますが、入力やクリックはできません。テキストボックスは自由形式のテキストを入力する場所です。コンボボックスは選択肢のドロップダウンを表示し、cboCity や cboStatus のように、City や Status を既知のリストに制限するために使います。これにより、同じ内容でも "chicago"、"Chicago,IL"、"CHI" のように異なる表記で複数のレコードに入力されることを防げます。
フォーム背後のコード記述
デザイン画面上の任意のコントロールをダブルクリックすると、そのコードに直接ジャンプ可能。VBAは自動的に ControlName_EventName というイベントプロシージャを作成し、その中にコードを記述すると、特定のコントロールでそのイベントが発生した際に実行される。ボタンのデフォルトイベントは Click:
Private Sub UserForm_Initialize()
' runs once, automatically, when the form is first shown
cboCity.AddItem "Chicago"
cboCity.AddItem "Boston"
cboCity.AddItem "Austin"
cboCity.AddItem "Seattle"
cboCity.AddItem "Denver"
cboStatus.AddItem "Active"
cboStatus.AddItem "Inactive"
cboStatus.AddItem "Prospect"
End Sub
Private Sub cmdCancel_Click()
Unload Me
End Sub
UserForm_Initialize はフォームの読み込み時、ユーザーが何も見ていない段階で自動的に発生する特別なイベントプロシージャ。これにより、ComboBox の選択肢を .AddItem で動的に追加でき、プロパティウィンドウで手動入力する必要がなくなる。選択肢が変更されたり、ワークシートから取得する場合にも有効。Unload Me 内の cmdCancel_Click はフォーム全体を閉じる処理。Me は常に現在実行中のフォームを指すため、フォーム名を変更してもこの記述はそのまま利用可能。
実践例:新規顧客の保存
以下は保存ボタンの背後にあるプロシージャ。新しい行を tblCustomers に書き込む処理:
Private Sub cmdSave_Click()
Dim tbl As ListObject
Dim newRow As ListRow
Set tbl = ThisWorkbook.Worksheets("Customers").ListObjects("tblCustomers")
Set newRow = tbl.ListRows.Add
newRow.Range(1, 1).Value = "C" & Format(tbl.ListRows.Count + 1, "000")
newRow.Range(1, 2).Value = txtCompanyName.Value
newRow.Range(1, 3).Value = txtContact.Value
newRow.Range(1, 4).Value = txtEmail.Value
newRow.Range(1, 5).Value = cboCity.Value
newRow.Range(1, 6).Value = cboStatus.Value
MsgBox txtCompanyName.Value & " was added successfully."
Unload Me
End Sub
tbl = ThisWorkbook.Worksheets("Customers").ListObjects("tblCustomers")でフォームからワークブック内のテーブルまでアクセス可能。UserForm も他のコードと同様に ListObjects を利用できる。tbl.ListRows.Addはテーブル内に新しい行を追加し、手動で最終セルの後ろに書き込む必要がない。txtCompanyName.ValueやcboCity.Valueなどは、ユーザーがそのコントロールに入力または選択した値を取得する。.Valueはほぼすべてのコントロールタイプで共通のため、TextBox や ComboBox でも同じパターンが利用可能。- 顧客ID生成の行は演習用の簡易的なプレースホルダー。本来はIDの重複や欠番をチェックする必要があるが、この行では対応していない。
- 最後の Unload Me は、行の書き込み後にフォームを閉じる。早く閉じてしまうと、
txtCompanyName.Valueなどの値が取得できなくなるため、必ず書き込み後に実行する。
フォームの「Company Name」ラベルは、テーブルのCustomer列に対する分かりやすいキャプションにすぎません。コードは、ラベルの表示内容に関係なく、txtCompanyName.Valueをその列に書き込みます。VBAにとって重要なのはTextBoxの名前であり、画面上のキャプションではありません。
Customer IDはフォーム上にありません。これはコードによって自動生成されるためです("C0" & (tbl.ListRows.Count + 100))。この仕組みは、実際のシステムが新しいレコードに自動で番号を付与し、ユーザーが一意のIDを手動で入力する必要がないことを反映しています。
課題
- 新しいUserFormを挿入し、名前を
frmAddCustomerに設定。3つのTextBox(txtCompanyName、txtContact、txtEmail)と2つのComboBox(cboCity、cboStatus)を、それぞれ対応するLabelとともに追加。 - 2つのCommandButton(
cmdSaveとcmdCancel)を追加し、UserForm_InitializeおよびcmdCancel_Clickプロシージャを指示通りに記述。 cmdSave_Clickを指示通りに記述し、ワークブック内の他の場所に一時的なボタンを追加して、frmAddCustomer.Showのコードでフォームが開くことをテスト。- 架空の6人目の顧客情報をフォームに入力し、Saveをクリック。tblCustomersに新しい行が入力内容で追加されていることを確認。
1. フォームの作成
- VBEで 挿入 → UserForm を選択し、プロパティウィンドウの
(Name)フィールドでfrmAddCustomerに名前を変更(タイトルバーのテキストのみを変更する Caption フィールドではありません)。 - 会社名、連絡先、メールアドレスごとにラベルとテキストボックスのペアを1つずつ、都市とステータスにはラベルとコンボボックスのペアを1つずつドラッグ。
- 各コントロールは追加後すぐに名前を変更 — 本章で強調された習慣。ラベルはコードで参照しないためコード向きの名前は不要ですが、テキストボックス/コンボボックス/ボタンはすべて必要。
2. UserForm_Initialize と cmdCancel_Click
- フォームの空白部分(コントロール以外)をダブルクリックすると
UserForm_Initializeへ —cmdCancelをダブルクリックするとcmdCancel_Clickへ直接移動。 - 両プロシージャは本章でそのまま提示されたもの — 変更せずに入力。
3. 一時的なボタンでのテスト
- このボタンはフォーム上に配置する必要はなく、開発 → 挿入 → ボタン(フォームコントロール) で任意のワークシートに配置、またはワークシートボタンを追加せずVBEから1行の
Subを実行してもよい。 - フォームを表示するコードは
frmAddCustomer.Showのみ。
4. 完全な保存のテスト
- すべてのフィールドを入力し、両方のドロップダウンから値を選択してから保存をクリック — コンボボックスが空欄だと空セルが書き込まれる。
- その後
tblCustomersにC00x形式のIDを持つ新しい行が追加されているか確認。
Private Sub UserForm_Initialize()
' runs once, automatically, when the form is first shown
cboCity.AddItem "Chicago"
cboCity.AddItem "Boston"
cboCity.AddItem "Austin"
cboCity.AddItem "Seattle"
cboCity.AddItem "Denver"
cboStatus.AddItem "Active"
cboStatus.AddItem "Inactive"
cboStatus.AddItem "Prospect"
End Sub
Private Sub cmdCancel_Click()
Unload Me
End Sub
Private Sub cmdSave_Click()
Dim tbl As ListObject
Dim newRow As ListRow
Set tbl = ThisWorkbook.Worksheets("Customers").ListObjects("tblCustomers")
Set newRow = tbl.ListRows.Add
newRow.Range(1, 1).Value = "C0" & (tbl.ListRows.Count + 100)
newRow.Range(1, 2).Value = txtCompanyName.Value
newRow.Range(1, 3).Value = txtContact.Value
newRow.Range(1, 4).Value = txtEmail.Value
newRow.Range(1, 5).Value = cboCity.Value
newRow.Range(1, 6).Value = cboStatus.Value
MsgBox txtCompanyName.Value & " was added successfully."
Unload Me
End Sub
テスト方法:通常のモジュール(UserFormのコードではない)から次を実行:
Sub ShowAddCustomerForm()
frmAddCustomer.Show
End Sub
ShowAddCustomerForm 内にカーソルを置いてF5を押すとフォームが開き、入力して保存をクリックすると tblCustomers に新しい行が追加される。
フィードバックありがとうございます!
AIに質問する
AIに質問する
何でも質問するか、提案された質問の1つを試してチャットを始めてください
ユーザーフォーム入門
UserFormはExcel for Macでは機能が制限されているか、利用できない場合があります。Mac版のVBA IDEは多くのバージョンでUserFormのデザインを完全にサポートしておらず、このような予期しない動作が発生する原因となります。
MsgBoxやInputBoxは、簡単なはい/いいえの質問や1行の回答には対応できますが、顧客情報の追加には複数の項目が必要です。たとえば、会社名、担当者、都市、ステータスなどです。これらをまとめて入力するためにUserFormを使用します。UserFormは、独自のラベル、テキストボックス、ドロップダウン、ボタンを備えた小さなカスタムウィンドウで、VBE内で作成し、コードで完全に制御します。
フォームの作成
VBEで、Project Explorer内のプロジェクトを右クリックし、挿入 → UserForm を選択します。空白のデザイン画面が表示され、コントロールをドラッグできるツールボックスが浮かび上がります。
ラベル、テキストボックス、コンボボックス、ボタン
フォームにコントロールをドラッグすると、それぞれに TextBox1 や CommandButton1 のようなデフォルト名が付きますが、コントロールが6つや7つになると意味が分かりにくくなります。このセクションで最も重要な習慣は、プロパティウィンドウで確認できる通り、コントロールを追加した直後に必ず名前を変更することです。型を識別する短いプレフィックス(txt には TextBox、cbo には ComboBox、cmd には CommandButton、opt には OptionButton、chk には CheckBox、lst には ListBox)と、説明的な名前を組み合わせてください。たとえば、txtCompanyName であれば、3週間後にコードを見ても明確に意味が分かりますが、TextBox1 では分かりません。
ラベルは単なる非対話型のテキストキャプション(「Company Name:」など)で、ユーザーは見ることはできますが、入力やクリックはできません。テキストボックスは自由形式のテキストを入力する場所です。コンボボックスは選択肢のドロップダウンを表示し、cboCity や cboStatus のように、City や Status を既知のリストに制限するために使います。これにより、同じ内容でも "chicago"、"Chicago,IL"、"CHI" のように異なる表記で複数のレコードに入力されることを防げます。
フォーム背後のコード記述
デザイン画面上の任意のコントロールをダブルクリックすると、そのコードに直接ジャンプ可能。VBAは自動的に ControlName_EventName というイベントプロシージャを作成し、その中にコードを記述すると、特定のコントロールでそのイベントが発生した際に実行される。ボタンのデフォルトイベントは Click:
Private Sub UserForm_Initialize()
' runs once, automatically, when the form is first shown
cboCity.AddItem "Chicago"
cboCity.AddItem "Boston"
cboCity.AddItem "Austin"
cboCity.AddItem "Seattle"
cboCity.AddItem "Denver"
cboStatus.AddItem "Active"
cboStatus.AddItem "Inactive"
cboStatus.AddItem "Prospect"
End Sub
Private Sub cmdCancel_Click()
Unload Me
End Sub
UserForm_Initialize はフォームの読み込み時、ユーザーが何も見ていない段階で自動的に発生する特別なイベントプロシージャ。これにより、ComboBox の選択肢を .AddItem で動的に追加でき、プロパティウィンドウで手動入力する必要がなくなる。選択肢が変更されたり、ワークシートから取得する場合にも有効。Unload Me 内の cmdCancel_Click はフォーム全体を閉じる処理。Me は常に現在実行中のフォームを指すため、フォーム名を変更してもこの記述はそのまま利用可能。
実践例:新規顧客の保存
以下は保存ボタンの背後にあるプロシージャ。新しい行を tblCustomers に書き込む処理:
Private Sub cmdSave_Click()
Dim tbl As ListObject
Dim newRow As ListRow
Set tbl = ThisWorkbook.Worksheets("Customers").ListObjects("tblCustomers")
Set newRow = tbl.ListRows.Add
newRow.Range(1, 1).Value = "C" & Format(tbl.ListRows.Count + 1, "000")
newRow.Range(1, 2).Value = txtCompanyName.Value
newRow.Range(1, 3).Value = txtContact.Value
newRow.Range(1, 4).Value = txtEmail.Value
newRow.Range(1, 5).Value = cboCity.Value
newRow.Range(1, 6).Value = cboStatus.Value
MsgBox txtCompanyName.Value & " was added successfully."
Unload Me
End Sub
tbl = ThisWorkbook.Worksheets("Customers").ListObjects("tblCustomers")でフォームからワークブック内のテーブルまでアクセス可能。UserForm も他のコードと同様に ListObjects を利用できる。tbl.ListRows.Addはテーブル内に新しい行を追加し、手動で最終セルの後ろに書き込む必要がない。txtCompanyName.ValueやcboCity.Valueなどは、ユーザーがそのコントロールに入力または選択した値を取得する。.Valueはほぼすべてのコントロールタイプで共通のため、TextBox や ComboBox でも同じパターンが利用可能。- 顧客ID生成の行は演習用の簡易的なプレースホルダー。本来はIDの重複や欠番をチェックする必要があるが、この行では対応していない。
- 最後の Unload Me は、行の書き込み後にフォームを閉じる。早く閉じてしまうと、
txtCompanyName.Valueなどの値が取得できなくなるため、必ず書き込み後に実行する。
フォームの「Company Name」ラベルは、テーブルのCustomer列に対する分かりやすいキャプションにすぎません。コードは、ラベルの表示内容に関係なく、txtCompanyName.Valueをその列に書き込みます。VBAにとって重要なのはTextBoxの名前であり、画面上のキャプションではありません。
Customer IDはフォーム上にありません。これはコードによって自動生成されるためです("C0" & (tbl.ListRows.Count + 100))。この仕組みは、実際のシステムが新しいレコードに自動で番号を付与し、ユーザーが一意のIDを手動で入力する必要がないことを反映しています。
課題
- 新しいUserFormを挿入し、名前を
frmAddCustomerに設定。3つのTextBox(txtCompanyName、txtContact、txtEmail)と2つのComboBox(cboCity、cboStatus)を、それぞれ対応するLabelとともに追加。 - 2つのCommandButton(
cmdSaveとcmdCancel)を追加し、UserForm_InitializeおよびcmdCancel_Clickプロシージャを指示通りに記述。 cmdSave_Clickを指示通りに記述し、ワークブック内の他の場所に一時的なボタンを追加して、frmAddCustomer.Showのコードでフォームが開くことをテスト。- 架空の6人目の顧客情報をフォームに入力し、Saveをクリック。tblCustomersに新しい行が入力内容で追加されていることを確認。
1. フォームの作成
- VBEで 挿入 → UserForm を選択し、プロパティウィンドウの
(Name)フィールドでfrmAddCustomerに名前を変更(タイトルバーのテキストのみを変更する Caption フィールドではありません)。 - 会社名、連絡先、メールアドレスごとにラベルとテキストボックスのペアを1つずつ、都市とステータスにはラベルとコンボボックスのペアを1つずつドラッグ。
- 各コントロールは追加後すぐに名前を変更 — 本章で強調された習慣。ラベルはコードで参照しないためコード向きの名前は不要ですが、テキストボックス/コンボボックス/ボタンはすべて必要。
2. UserForm_Initialize と cmdCancel_Click
- フォームの空白部分(コントロール以外)をダブルクリックすると
UserForm_Initializeへ —cmdCancelをダブルクリックするとcmdCancel_Clickへ直接移動。 - 両プロシージャは本章でそのまま提示されたもの — 変更せずに入力。
3. 一時的なボタンでのテスト
- このボタンはフォーム上に配置する必要はなく、開発 → 挿入 → ボタン(フォームコントロール) で任意のワークシートに配置、またはワークシートボタンを追加せずVBEから1行の
Subを実行してもよい。 - フォームを表示するコードは
frmAddCustomer.Showのみ。
4. 完全な保存のテスト
- すべてのフィールドを入力し、両方のドロップダウンから値を選択してから保存をクリック — コンボボックスが空欄だと空セルが書き込まれる。
- その後
tblCustomersにC00x形式のIDを持つ新しい行が追加されているか確認。
Private Sub UserForm_Initialize()
' runs once, automatically, when the form is first shown
cboCity.AddItem "Chicago"
cboCity.AddItem "Boston"
cboCity.AddItem "Austin"
cboCity.AddItem "Seattle"
cboCity.AddItem "Denver"
cboStatus.AddItem "Active"
cboStatus.AddItem "Inactive"
cboStatus.AddItem "Prospect"
End Sub
Private Sub cmdCancel_Click()
Unload Me
End Sub
Private Sub cmdSave_Click()
Dim tbl As ListObject
Dim newRow As ListRow
Set tbl = ThisWorkbook.Worksheets("Customers").ListObjects("tblCustomers")
Set newRow = tbl.ListRows.Add
newRow.Range(1, 1).Value = "C0" & (tbl.ListRows.Count + 100)
newRow.Range(1, 2).Value = txtCompanyName.Value
newRow.Range(1, 3).Value = txtContact.Value
newRow.Range(1, 4).Value = txtEmail.Value
newRow.Range(1, 5).Value = cboCity.Value
newRow.Range(1, 6).Value = cboStatus.Value
MsgBox txtCompanyName.Value & " was added successfully."
Unload Me
End Sub
テスト方法:通常のモジュール(UserFormのコードではない)から次を実行:
Sub ShowAddCustomerForm()
frmAddCustomer.Show
End Sub
ShowAddCustomerForm 内にカーソルを置いてF5を押すとフォームが開き、入力して保存をクリックすると tblCustomers に新しい行が追加される。
フィードバックありがとうございます!