動作確認: Excel 365 v2509 · Excel 2021 · Excel 2019 · 最終確認 2026-06-06
要点(TL;DR) — UserForm は、一度デザインしてイベントコードで動かす独自のダイアログです。コントロールを置き、各ボタンが何をするかを書き、表示する。全体は3つの部品でできています。
' 1. フォームモジュール内 — OK クリック時に走るコード:
Private Sub btnOK_Click()
If txtName.Value = "" Then
MsgBox "名前は必須です。", vbExclamation
Exit Sub
End If
Me.Hide ' 非表示にする。ただし呼び出し側が値を読めるよう保持する
End Sub
' 2. フォームモジュール内 — キャンセルは閉じるだけ:
Private Sub btnCancel_Click()
Me.Tag = "cancel"
Me.Hide
End Sub
' 3. 標準モジュール内 — 表示して、入力された内容を読む:
Sub AddRecord()
With frmEntry
.Show ' フォームが非表示になるまでここで止まる
If .Tag = "cancel" Then Unload frmEntry: Exit Sub
Cells(Rows.Count, 1).End(xlUp).Offset(1).Value = .txtName.Value
End With
Unload frmEntry ' 読み終えてから破棄する
End Sub
「ユーザーが入力したのに、なぜテキストボックスが空なのか?」——そう思ったことがあるなら、それが Hide と Unload のルールで、この記事の核心です。
考え方:あなたはハンドルを離し、フォームが運転する
MsgBox と InputBox は同期的です——1行が走り、値が返り、次の行が走る。UserForm はこのリズムを崩します。.Show を呼ぶと、あなたのコードはハンドルをフォームに渡して一時停止します。次に何が起きるかは、マクロの次の行ではなく、ユーザーがどのコントロールをクリックするかで決まり、各コントロールがそれぞれの小さなコードのかたまりを実行します。
初心者なら誰もが抱く疑問——「UserForm1.Show のあと、私のコードはどこへ行った?」——への答えは明快です。待っているのです。 本当の処理は、btnOK_Click のようなコントロールのイベントプロシージャへ移りました。UserForm は3つのものを貼り合わせたものです。
- デザイン — 上に置くコントロール(TextBox、ComboBox、CommandButton)。デザイン時に一度だけ設定する。
- イベントコード — フォームのモジュール内の
Private Subプロシージャ。ユーザーの操作1つにつき1つ。 - 呼び出し — 標準モジュールからの
frmEntry.Show。
「つつくとコードを実行するオブジェクト」——「値を返す関数」ではなく——として見えた瞬間、UserForm は怖くなくなります。
3ステップで作る
- VBA エディタ(Alt+F11)で 挿入 ▸ ユーザーフォーム。プロパティで
(オブジェクト名)をfrmEntryに設定——フォームやコントロールに今のうちに名前を付ければ、あとでTextBox1、TextBox2の混乱を避けられます。 - ツールボックスから配置:TextBox を2つ(
txtName、txtQty)、ComboBox を1つ(cboDept)、CommandButton を2つ(btnOK、btnCancel)。横にラベルを添えます。 - ボタンをダブルクリック——エディタがその
_Clickイベントへ直接連れていきます。そこに動作が住んでいます。
たった一つのルール:Me.Hide は値を残し、Unload Me は消す
このルールが、フォームが入力ツールとして機能するかどうかを決めます。
Unload Meはフォームをメモリから取り除き、すべてのコントロールを空にリセットします。Unload のあとにtxtName.Valueを読むと""——データは消えています。Me.Hideはフォームを見えなくしますが、メモリ上に生かしたまま、値はそのままです。実行は.Showの次の行に戻り、呼び出し側はまだfrmEntry.txtName.Valueを読めます。
ですから、データを返すフォームの型はこうです——OK で Me.Hide を呼び、呼び出し側がコントロールを読み、そのあとで呼び出し側が Unload する。btnOK_Click の中で Unload Me するのが、*「フォームが入力内容を失う」*の最も多い原因です。
Private Sub btnOK_Click()
' まず検証、それから非表示(ここで Unload しない)
If Not IsNumeric(txtQty.Value) Then
MsgBox "数量は数値で入力してください。", vbExclamation
txtQty.SetFocus
Exit Sub
End If
Me.Hide
End Sub
フォームの初期化は UserForm_Initialize で
ユーザーが見る前にフォームに必要なもの——ドロップダウンの選択肢、既定値、今日の日付——は、呼び出し側のマクロではなく UserForm_Initialize イベントに書きます。こうするとフォームは自己完結し、誰が表示しても毎回正しく開きます。
Private Sub UserForm_Initialize()
cboDept.List = Array("営業", "経理", "業務") ' ドロップダウンを埋める
txtQty.Value = "1" ' 妥当な既定値
txtName.SetFocus ' カーソルはここから
End Sub
モーダルかモードレスか — 意図して選ぶ
.Show は既定でモーダル(vbModal)です。ユーザーはシートに触れる前にフォームを片付けねばならず、呼び出し側のコードは待ちます。データ入力にはこれが望ましい挙動です。.Show vbModeless は、ユーザーが作業しながら開いておく浮動パレットのときだけ使い、その場合は呼び出し側のマクロが待たずに先へ進むことを覚えておきましょう。
frmEntry.Show ' モーダル — 呼び出し側は一時停止(通常はこちら)
frmTools.Show vbModeless ' モードレス — 呼び出し側は続行、フォームは浮く
配線しすぎない
陥りやすい罠が、「リアルタイム」検証のために各コントロールへ _Change イベントを撒くことです。絶えず発火し、互いを呼び合い、デバッグをモグラ叩きに変えます。検証は btnOK_Click で一度だけ行い、それから非表示に。 各イベントプロシージャは短く、目的を1つに保ちましょう。
そして、UserForm がそもそも不向きな場面も見極めてください。10個以上の項目を並べて1画面に収まらないなら、それは MultiPage に分ける合図——あるいは、データは本当はユーザーが直接打ち込む素の Excel テーブルに属する、と認める合図です。UserForm が報われるのは、実質的な検証を伴うおよそ3〜8項目のとき。それ未満なら InputBox の連続のほうが軽く、それを超えるならワークシートのほうがフォームに勝ることが多いのです。
よくある UserForm の間違い(と直し方)
| 症状 | 原因 | 直し方 |
|---|---|---|
| 入力したのにテキストボックスが空 | btnOK_Click の Unload Me が値を消した |
Me.Hide を使い、呼び出し側が読んでから Unload |
| ドロップダウンが空 | フォームではなく呼び出し側マクロで埋めた | UserForm_Initialize で埋める |
| フォーム名で「オブジェクトが必要です」 | 読み込み前にコントロールを参照した | 先にフォームを表示、またはフォーム変数経由で読む |
.Show の後のコードが早すぎる |
誤って vbModeless で表示した |
入力には素の .Show(モーダル)を使う |
| OK とキャンセルが区別できない | キャンセル時にフラグを立てていない | 非表示の前に Me.Tag = "cancel"(または公開 Boolean)を立てる |
| 赤い ✕ が OK のように振る舞う | QueryClose を処理していない |
UserForm_QueryClose で ✕ をキャンセル扱いに |
「3つたずねるだけ」にしては配線が多すぎる
UserForm は本格的なデータ入力の正しい道具です——けれど、コントロール、Initialize、Hide と Unload の駆け引き、検証と、1行を保存する前に配線が山ほどあります。目的がただ*「名前・数量・部署を集めて、1行として追加する」*だけなら、ExcelMaster Agent に自然な日本語で説明するだけで、入力のやり取りと書き込みまで作ってくれます——保守するフォームモジュールはありません。無料で試す →
関連ガイド
- VBA MsgBox — はい/いいえ・ボタン・カッコのルール
- VBA InputBox — 2つの InputBox と使い分け
- VBA Range — セルの参照・読み取り・書き込み
- VBA For ループ — 実務で使える8例
よくある質問(FAQ)
VBA の UserForm とは何ですか?
UserForm は、VBA エディタでデザインし、イベントコードで制御する独自のダイアログです。コントロール(テキストボックス、コンボボックス、ボタン)を載せ、ユーザーの操作1つごとにプロシージャを書き、.Show で表示します。MsgBox や InputBox を超えて、VBA が複数の入力を一度に集める手段です。
Excel VBA で UserForm を作るには?
Alt+F11 を押し、挿入 ▸ ユーザーフォーム。ツールボックスからコントロールをドラッグし、プロパティウィンドウで名前を付け、ボタンをダブルクリックして _Click イベントを書きます。標準モジュールから frmName.Show で表示します。
ユーザーが入力したのに UserForm のテキストボックスが空なのはなぜ?
OK ボタンの中で Unload Me を呼んだからです。これはフォームを破棄し、すべてのコントロールを空にします。OK イベントでは代わりに Me.Hide を使ってください。フォーム(とその値)をメモリに残すので、呼び出し側のコードが frmName.txtName.Value を読め、そのあと Unload できます。
Unload Me と Me.Hide の違いは?
Me.Hide はフォームを見えなくしますが読み込んだままにするので、値はまだ読めます。Unload Me はフォームをメモリから取り除き、すべてのコントロールをリセットします。閉じたあとに入力を読む必要があるなら Hide、本当に終わりなら Unload です。
UserForm の ComboBox を埋めるには?
表示前に準備できるよう、UserForm_Initialize イベントで埋めます:cboDept.List = Array("営業", "経理", "業務")。あるいは cboDept.RowSource = "Sheet1!A1:A10" でセル範囲に紐づけます。
フォームはモーダルとモードレスのどちらにすべき?
データ入力にはモーダル(既定の .Show)を使います——ユーザーは他の操作の前にフォームを終える必要があり、コードは結果を待ちます。.Show vbModeless は、シートで作業しながら開いておくツールバー型の浮動フォームのときだけ使います。
