VBAのMsgBox・InputBox・UserFormを使い分ける完全ガイド|引数・戻り値・イベント処理まで

  • 確認・通知のダイアログを表示したい
  • ユーザーから1つの値を受け取りたい
  • 複数の入力項目をまとめて受け取りたい

この記事を読めば、目的に応じてMsgBox・InputBox・UserFormを適切に使い分けられるようになります。

VBAでユーザーとやり取りする手段は、大きく分けてこの3つです。それぞれ役割が異なるので、まずは全体像から整理します。

本記事の内容
  • 3つの手段の使い分け基準
  • MsgBoxの引数・戻り値
  • InputBoxの2種類と違い
  • UserFormの作成とイベント処理
  • 入力値の検証と呼び出し元への受け渡し

MsgBox・InputBox・UserFormは何が違うのか

3つの手段は、「受け取れる情報の量」で役割が分かれています。

用途適した手段理由
確認・通知のみ(入力不要)MsgBoxボタンとアイコンを表示する専用の関数で、文字列や数値の入力は受け付けない
1つの値を受け取りたいInputBox / Application.InputBox単一の入力欄のみを持つ、シンプルな入力用の関数
複数項目・独自レイアウトが必要UserFormTextBox・ListBox・ComboBoxなど複数のコントロールを自由に配置できる

MsgBoxとInputBoxはどちらも1行のコードで呼び出せる組み込み関数です。一方UserFormは、フォームをあらかじめ設計しておく必要がある分、表現の自由度が高くなります。

MsgBoxで確認・通知を表示する

基本構文と最小コード

最も単純な形は、メッセージを1つ渡すだけです。

VB
MsgBox "処理が完了しました。"

MsgBox関数の正式な構文は次のとおりです。

VB
MsgBox(prompt, buttons, title)

promptはメッセージ本文、buttonsはボタン・アイコンの種類、titleはタイトルバーの文字列です。buttonsとtitleは省略できます。

ボタンの種類とアイコンを指定する

buttons引数には、ボタンの構成とアイコンの種類を、定数を+(プラス)で組み合わせて指定します。

分類定数内容
ボタン構成vbOKOnlyOKのみ(既定値)
vbOKCancelOK・キャンセル
vbAbortRetryIgnore中止・再試行・無視
vbYesNoCancelはい・いいえ・キャンセル
vbYesNoはい・いいえ
vbRetryCancel再試行・キャンセル
アイコンvbCriticalエラーアイコン(赤い×)
vbQuestion確認アイコン(?)
vbExclamation警告アイコン(!)
vbInformation情報アイコン(i)

ボタン構成とアイコンを組み合わせる例です。

VB
MsgBox "この内容で確定しますか?", vbYesNo + vbQuestion, "確認"

戻り値で処理を分岐する

MsgBoxは、押されたボタンに応じた戻り値を返します。戻り値を変数で受け取れば、その後の処理を分岐できます。

VB
Dim result As VbMsgBoxResult
result = MsgBox("この内容で確定しますか?", vbYesNo + vbQuestion, "確認")

If result = vbYes Then
    MsgBox "処理を実行します。"
Else
    MsgBox "処理をキャンセルしました。"
End If

戻り値の判定に使う定数は、vbOK・vbCancel・vbAbort・vbRetry・vbIgnore・vbYes・vbNoの7種類です。押されたボタンに対応する定数と比較します。

メッセージを改行する

改行を入れたい場合は、改行を表す定数vbCrLfを文字列と連結します。

VB
MsgBox "入力内容を確認してください。" & vbCrLf & "問題なければOKを押してください。"

» Microsoft 公式ドキュメント: MsgBox 関数

InputBoxで1つの値を受け取る

VBAで値を1つ受け取る手段には、組み込みのInputBox関数Application.InputBoxメソッドの2種類があります。名前は似ていますが、戻り値の型と使いどころが異なります。

VBA組み込みのInputBox関数

組み込みのInputBox関数は、常に文字列(String型)を返します。

VB
Dim inputValue As String
inputValue = InputBox("名前を入力してください。", "入力", "山田太郎")

If inputValue = "" Then
    MsgBox "入力がキャンセルされました。"
Else
    MsgBox inputValue & "さん、こんにちは。"
End If

第1引数がメッセージ、第2引数がタイトル、第3引数が入力欄の初期値です。3つとも文字列で指定します。

Application.InputBoxで型を指定する

Application.InputBoxメソッドは、Type引数で戻り値の型を指定できる点が組み込み関数との違いです。特にType:=8を指定すると、セル範囲(Range型)を選択させることができます。

VB
Dim targetRange As Range

On Error Resume Next
Set targetRange = Application.InputBox("集計するセル範囲を選択してください。", "範囲選択", Type:=8)
On Error GoTo 0

If targetRange Is Nothing Then
    MsgBox "範囲が選択されませんでした。"
Else
    MsgBox "選択範囲: " & targetRange.Address
End If

Type引数に指定できる主な値は次のとおりです。複数の型を許可したい場合は、値を合計して指定します(例: 数値と文字列を許可する場合は1+2=3)。

戻り値の型
0数式(文字列として)
1数値
2文字列
4論理値(True / False)
8セル参照(Range)
16エラー値(#N/A など)
64数値の配列

キャンセル時の挙動の違いに注意する

2つの手段は、キャンセル時の戻り値がまったく異なります。これは実装時に混同しやすいポイントです。

  • 組み込みInputBox:キャンセルすると空文字列(””)を返す。「何も入力せずOK」を押した場合も同じく空文字列になるため、この2つを区別できない
  • Application.InputBox:キャンセルするとブール値のFalseを返す。Range型の変数にFalseを代入しようとすると型不一致の実行時エラーになるため、上記コード例のようにOn Error Resume Nextでエラーを無視してから、Is Nothingで判定する必要がある

Application.InputBoxはキャンセル時にFalseを返す仕様のため、戻り値を受け取る変数の型がRangeやString型のままだと、代入時にエラーが発生します。On Error Resume Nextでエラーを一旦回避し、判定後にOn Error GoTo 0で元に戻すのが定石です。

» Microsoft 公式ドキュメント: Application.InputBox メソッド (Excel)

UserFormで複数項目の入力フォームを作る

複数の項目をまとめて受け取りたい場合や、選択肢から選ばせたい場合は、UserFormを使います。

フォームを追加してコントロールを配置する

UserFormの作成手順は次のとおりです。

UserForm作成の手順
  1. VBEを開く(Alt+F11)
  2. 「挿入」メニューから「ユーザーフォーム」を選択する
  3. ツールボックスからTextBox・ListBox・CommandButtonなどをフォーム上にドラッグ&ドロップする
  4. プロパティウィンドウで各コントロールの(Name)を設定する

(Name)プロパティは、コードから参照するときの識別子になります。既定のTextBox1のままでも動作しますが、txtName・lstCity・btnOKのように役割がわかる名前に変更しておくと、後述するイベントプロシージャの見通しがよくなります。

イベントプロシージャの基本形

UserFormの動作は、コントロール名_イベント名という名前のプロシージャに記述します。VBEのコード画面上部にある2つのドロップダウンから、対象のコントロールとイベントを選択すると、プロシージャの雛形が自動生成されます。

ボタンがクリックされたときの処理はClickイベント、フォームが表示される直前の初期化処理はUserForm_Initializeイベントに書きます。

VB
Private Sub UserForm_Initialize()
    Me.lstCity.AddItem "東京"
    Me.lstCity.AddItem "大阪"
    Me.lstCity.AddItem "福岡"
    Me.lstCity.ListIndex = 0
End Sub

Private Sub btnOK_Click()
    Me.Hide
End Sub

ListIndexプロパティに0を指定すると、ListBoxの1番目の項目(東京)が初期状態で選択された状態になります。

Showメソッドでモーダル・モードレスを切り替える

フォームを表示するにはShowメソッドを使います。引数によって、フォームを表示している間に他の操作を受け付けるかどうかが変わります。

VB
UserForm1.Show            ' モーダル(既定): フォームを閉じるまで他の操作を受け付けない
UserForm1.Show vbModeless ' モードレス: 表示したまま他の操作もできる

入力を完了させてから後続の処理に進みたい場合はモーダル、フォームを表示したままシート側の操作もさせたい場合はモードレスを選びます。引数を省略した場合はモーダルになります。

入力値を呼び出し元に渡す

Me.Hideでフォームを非表示にした直後は、フォームのインスタンス自体はまだメモリ上に残っています。そのため、呼び出し元のコードからフォーム上のコントロールの値に直接アクセスできます。

VB
Dim frm As UserForm1
Set frm = New UserForm1

frm.Show

MsgBox frm.txtName.Value & "さんが入力されました。"

Unload frm

フォームモジュールにPublicなプロパティやフラグ変数を用意しておくと、キャンセル状態のようにコントロールの値だけでは表せない情報も呼び出し元に伝えられます。

VB
' フォームモジュール(UserForm1)側
Public Cancelled As Boolean

Private Sub btnCancel_Click()
    Cancelled = True
    Me.Hide
End Sub

フォーム内部の変数を直接公開せず、Property Get / Property Letプロシージャ経由でアクセスさせる書き方もあります。外部から値を書き換えられたくない場合や、取得時に加工処理を挟みたい場合に使います。

VB
' フォームモジュール(UserForm1)側
Private m_UserName As String

Public Property Get UserName() As String
    UserName = m_UserName
End Property

Private Sub btnOK_Click()
    m_UserName = Me.txtName.Value
    Me.Hide
End Sub

フォーム内で入力値を検証する

OKボタンが押された時点で、必須項目が空でないかをチェックし、問題があればフォームを閉じずにメッセージだけ表示するのが基本パターンです。

VB
Private Sub btnOK_Click()
    If Me.txtName.Value = "" Then
        MsgBox "名前を入力してください。", vbExclamation, "入力エラー"
        Exit Sub
    End If

    Me.Hide
End Sub

Exit Subでプロシージャを抜けることで、Me.Hideが実行されずフォームは表示されたままになります。ユーザーは同じフォーム上で入力をやり直せます。

通しサンプル:名前と都市を入力するフォーム

ここまでの内容をまとめて、TextBox(名前)とListBox(都市)を持つフォームの例を示します。

フォームには、txtName(TextBox)・lstCity(ListBox)・btnOK(CommandButton)・btnCancel(CommandButton)の4つのコントロールを配置している前提です。

VB
' UserForm1 側のコード
Public Cancelled As Boolean

Private Sub UserForm_Initialize()
    Me.lstCity.AddItem "東京"
    Me.lstCity.AddItem "大阪"
    Me.lstCity.AddItem "福岡"
    Me.lstCity.ListIndex = 0
    Cancelled = False
End Sub

Private Sub btnOK_Click()
    If Me.txtName.Value = "" Then
        MsgBox "名前を入力してください。", vbExclamation, "入力エラー"
        Exit Sub
    End If
    Me.Hide
End Sub

Private Sub btnCancel_Click()
    Cancelled = True
    Me.Hide
End Sub
VB
' 標準モジュール側のコード
Sub ShowNameForm()
    Dim frm As UserForm1
    Set frm = New UserForm1

    frm.Show

    If frm.Cancelled Then
        MsgBox "入力がキャンセルされました。"
    Else
        MsgBox frm.txtName.Value & "さん(" & frm.lstCity.Value & ")で登録します。"
    End If

    Unload frm
End Sub

標準モジュール側でUnload frmを呼び出し、フォームのインスタンスを確実に破棄しています。frm.Showの直後にフォームの値を読み取ってから、Unloadする順序を守ります。

発展Tips:ListBoxへの複数列追加とフォームの後始末

ListBoxは、ColumnCountプロパティを設定すると、1つの項目に複数列のデータを持たせられます。

VB
With Me.lstItems
    .ColumnCount = 2
    .AddItem "A001"
    .List(.ListCount - 1, 1) = "商品A"
End With

AddItemで1列目(商品コード)を追加したあと、Listプロパティにインデックスと列番号を指定して2列目(商品名)を設定しています。列番号は0始まりです。

複数のフォームを扱うマクロでは、UnloadしないままSetを繰り返すと、使われなくなったフォームのインスタンスがメモリ上に残り続けます。フォームの役目が終わったら、Unloadで確実に破棄することが推奨されます。

Me.Hideはフォームを非表示にするだけで、インスタンスは破棄されません。値の受け渡しが終わったあとは、呼び出し元でUnloadを呼び出してください。

まとめ

確認・通知はMsgBox、1つの値の取得はInputBox、複数項目やレイアウトが必要な場合はUserFormと、受け取りたい情報の量に応じて選べば迷いません。

セルやシートの基本操作については、以下の記事もあわせてご覧ください。

» VBAのRange・Cells・最終行取得を使い分ける実務ガイド

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

普段は主にPython開発をしています。
最近はAI駆動開発にも関わっています。

コメント

コメントする