Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
学ぶ ユーザーフォーム入門 | ユーザーインタラクション
ビジネス自動化のためのExcel VBA

ユーザーフォーム入門

メニューを表示するにはスワイプしてください

Note
注意

UserFormはExcel for Macでは機能が制限されているか、利用できない場合があります。Mac版のVBA IDEは多くのバージョンでUserFormのデザインを完全にサポートしておらず、このような予期しない動作が発生する原因となります。

MsgBoxやInputBoxは、簡単なはい/いいえの質問や1行の回答には対応できますが、顧客情報の追加には複数の項目が必要です。たとえば、会社名、担当者、都市、ステータスなどです。これらをまとめて入力するためにUserFormを使用します。UserFormは、独自のラベル、テキストボックス、ドロップダウン、ボタンを備えた小さなカスタムウィンドウで、VBE内で作成し、コードで完全に制御します。

フォームの作成

VBEで、Project Explorer内のプロジェクトを右クリックし、挿入 → UserForm を選択します。空白のデザイン画面が表示され、コントロールをドラッグできるツールボックスが浮かび上がります。

図 5.3

ラベル、テキストボックス、コンボボックス、ボタン

フォームにコントロールをドラッグすると、それぞれに TextBox1CommandButton1 のようなデフォルト名が付きますが、コントロールが6つや7つになると意味が分かりにくくなります。このセクションで最も重要な習慣は、プロパティウィンドウで確認できる通り、コントロールを追加した直後に必ず名前を変更することです。型を識別する短いプレフィックス(txt には TextBoxcbo には ComboBoxcmd には CommandButtonopt には OptionButtonchk には CheckBoxlst には 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
各行の詳細解説
expand arrow
  • tbl = ThisWorkbook.Worksheets("Customers").ListObjects("tblCustomers") でフォームからワークブック内のテーブルまでアクセス可能。UserForm も他のコードと同様に ListObjects を利用できる。
  • tbl.ListRows.Add はテーブル内に新しい行を追加し、手動で最終セルの後ろに書き込む必要がない。
  • txtCompanyName.ValuecboCity.Value などは、ユーザーがそのコントロールに入力または選択した値を取得する。.Value はほぼすべてのコントロールタイプで共通のため、TextBox や ComboBox でも同じパターンが利用可能。
  • 顧客ID生成の行は演習用の簡易的なプレースホルダー。本来はIDの重複や欠番をチェックする必要があるが、この行では対応していない。
  • 最後の Unload Me は、行の書き込み後にフォームを閉じる。早く閉じてしまうと、txtCompanyName.Value などの値が取得できなくなるため、必ず書き込み後に実行する。
Note
注意

フォームの「Company Name」ラベルは、テーブルのCustomer列に対する分かりやすいキャプションにすぎません。コードは、ラベルの表示内容に関係なく、txtCompanyName.Valueをその列に書き込みます。VBAにとって重要なのはTextBoxの名前であり、画面上のキャプションではありません。

Note
注意

Customer IDはフォーム上にありません。これはコードによって自動生成されるためです("C0" & (tbl.ListRows.Count + 100))。この仕組みは、実際のシステムが新しいレコードに自動で番号を付与し、ユーザーが一意のIDを手動で入力する必要がないことを反映しています。

課題

  1. 新しいUserFormを挿入し、名前をfrmAddCustomerに設定。3つのTextBox(txtCompanyNametxtContacttxtEmail)と2つのComboBox(cboCity、cboStatus)を、それぞれ対応するLabelとともに追加。
  2. 2つのCommandButton(cmdSavecmdCancel)を追加し、UserForm_InitializeおよびcmdCancel_Clickプロシージャを指示通りに記述。
  3. cmdSave_Clickを指示通りに記述し、ワークブック内の他の場所に一時的なボタンを追加して、frmAddCustomer.Showのコードでフォームが開くことをテスト。
  4. 架空の6人目の顧客情報をフォームに入力し、Saveをクリック。tblCustomersに新しい行が入力内容で追加されていることを確認。
ヒント
expand arrow

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. 完全な保存のテスト

  • すべてのフィールドを入力し、両方のドロップダウンから値を選択してから保存をクリック — コンボボックスが空欄だと空セルが書き込まれる。
  • その後 tblCustomersC00x 形式のIDを持つ新しい行が追加されているか確認。
解答例
expand arrow
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 に新しい行が追加される。

フォームのテスト
すべて明確でしたか?

どのように改善できますか?

フィードバックありがとうございます!

セクション 5.  2

AIに質問する

expand

AIに質問する

ChatGPT

何でも質問するか、提案された質問の1つを試してチャットを始めてください

ユーザーフォーム入門

Note
注意

UserFormはExcel for Macでは機能が制限されているか、利用できない場合があります。Mac版のVBA IDEは多くのバージョンでUserFormのデザインを完全にサポートしておらず、このような予期しない動作が発生する原因となります。

MsgBoxやInputBoxは、簡単なはい/いいえの質問や1行の回答には対応できますが、顧客情報の追加には複数の項目が必要です。たとえば、会社名、担当者、都市、ステータスなどです。これらをまとめて入力するためにUserFormを使用します。UserFormは、独自のラベル、テキストボックス、ドロップダウン、ボタンを備えた小さなカスタムウィンドウで、VBE内で作成し、コードで完全に制御します。

フォームの作成

VBEで、Project Explorer内のプロジェクトを右クリックし、挿入 → UserForm を選択します。空白のデザイン画面が表示され、コントロールをドラッグできるツールボックスが浮かび上がります。

図 5.3

ラベル、テキストボックス、コンボボックス、ボタン

フォームにコントロールをドラッグすると、それぞれに TextBox1CommandButton1 のようなデフォルト名が付きますが、コントロールが6つや7つになると意味が分かりにくくなります。このセクションで最も重要な習慣は、プロパティウィンドウで確認できる通り、コントロールを追加した直後に必ず名前を変更することです。型を識別する短いプレフィックス(txt には TextBoxcbo には ComboBoxcmd には CommandButtonopt には OptionButtonchk には CheckBoxlst には 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
各行の詳細解説
expand arrow
  • tbl = ThisWorkbook.Worksheets("Customers").ListObjects("tblCustomers") でフォームからワークブック内のテーブルまでアクセス可能。UserForm も他のコードと同様に ListObjects を利用できる。
  • tbl.ListRows.Add はテーブル内に新しい行を追加し、手動で最終セルの後ろに書き込む必要がない。
  • txtCompanyName.ValuecboCity.Value などは、ユーザーがそのコントロールに入力または選択した値を取得する。.Value はほぼすべてのコントロールタイプで共通のため、TextBox や ComboBox でも同じパターンが利用可能。
  • 顧客ID生成の行は演習用の簡易的なプレースホルダー。本来はIDの重複や欠番をチェックする必要があるが、この行では対応していない。
  • 最後の Unload Me は、行の書き込み後にフォームを閉じる。早く閉じてしまうと、txtCompanyName.Value などの値が取得できなくなるため、必ず書き込み後に実行する。
Note
注意

フォームの「Company Name」ラベルは、テーブルのCustomer列に対する分かりやすいキャプションにすぎません。コードは、ラベルの表示内容に関係なく、txtCompanyName.Valueをその列に書き込みます。VBAにとって重要なのはTextBoxの名前であり、画面上のキャプションではありません。

Note
注意

Customer IDはフォーム上にありません。これはコードによって自動生成されるためです("C0" & (tbl.ListRows.Count + 100))。この仕組みは、実際のシステムが新しいレコードに自動で番号を付与し、ユーザーが一意のIDを手動で入力する必要がないことを反映しています。

課題

  1. 新しいUserFormを挿入し、名前をfrmAddCustomerに設定。3つのTextBox(txtCompanyNametxtContacttxtEmail)と2つのComboBox(cboCity、cboStatus)を、それぞれ対応するLabelとともに追加。
  2. 2つのCommandButton(cmdSavecmdCancel)を追加し、UserForm_InitializeおよびcmdCancel_Clickプロシージャを指示通りに記述。
  3. cmdSave_Clickを指示通りに記述し、ワークブック内の他の場所に一時的なボタンを追加して、frmAddCustomer.Showのコードでフォームが開くことをテスト。
  4. 架空の6人目の顧客情報をフォームに入力し、Saveをクリック。tblCustomersに新しい行が入力内容で追加されていることを確認。
ヒント
expand arrow

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. 完全な保存のテスト

  • すべてのフィールドを入力し、両方のドロップダウンから値を選択してから保存をクリック — コンボボックスが空欄だと空セルが書き込まれる。
  • その後 tblCustomersC00x 形式のIDを持つ新しい行が追加されているか確認。
解答例
expand arrow
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 に新しい行が追加される。

フォームのテスト
すべて明確でしたか?

どのように改善できますか?

フィードバックありがとうございます!

セクション 5.  2
some-alt