🚀The world's best VBA AI has evolved. ExcelMaster is now an autonomous Agent.Read more →
Back to Blog

Excel VBA の ComboBox — ドロップダウンを埋め、選択を読み、ListIndex = -1 の落とし穴

|

Excel VBA の ComboBox — ドロップダウンを埋め、選択を読み、ListIndex = -1 の落とし穴

TL;DR — ComboBox はドロップダウンです。項目を一つ選ぶか、(既定では)自分で入力します。 ComboBox1.List = Range("A2:A50").Value で埋めます。二つの問いに同時に答えます — .ListIndex による どの項目か(0 始まり、テキストがリストにないときは -1)と、.Value による どんなテキストか です。 落とし穴:.Value <> "" はボックスが空でないことを示すだけで、ユーザーが本物の項目を選んだことは示しません。 リストからの正しい選択が必要なら .ListIndex >= 0 を調べるか、.Style = fmStyleDropDownList で入力を禁じます。

' ComboBox の選択を読む - 必ずリストから選ばせる
Private Sub cmdOK_Click()
    If ComboBox1.ListIndex = -1 Then
        MsgBox "Please choose an item from the list."
        Exit Sub
    End If
    MsgBox "You chose " & ComboBox1.Value       ' リストに裏付けられた本物の選択
End Sub

ComboBox は UserForm 上のコントロールで、ほかのどのコントロールとも同じ規則に従いま す。選択はボックスそのものからではなく、プロパティを通して読む のです。ListBox との違いは、ComboBox が一行を表示し、入力も受け付けられることです — まさにそこに、おもしろいバグが潜んでい ます。

この記事で学べること

  • ComboBox が一行に畳まれた ListBox である理由、そしてほぼ同じように読めること
  • .List = Range.Value で一気に埋める、あるいは計算した項目には .AddItem を使う
  • 答える二つの問い:どの行か(.ListIndex)と どんなテキストか(.Value)
  • .Style プロパティ — fmStyleDropDownCombo は入力を許し、fmStyleDropDownList は許さない
  • 最大の落とし穴:.Value <> "" は正しい選択ではない。.ListIndex >= 0 を調べる
  • ComboBox が正しいコントロールになるのはいつで、ListBox のほうが合うのはいつか

考え方の軸:入力もできる、一行の ListBox

ComboBox は、ドロップ矢印の付いた一行に畳んだ ListBox です。埋め方は同じ、読み方も 同じ二つのプロパティ — ですが自由入力も受け付けられるので、常に二つの問いに同時に答えます。

ComboBox1.ListIndex   ' どの行が選ばれているか(0 始まり、-1 = テキストがリストにない)
ComboBox1.Value       ' ボックスにあるテキストの中身(リストの項目、または入力された文字列)

この二つを分けて持てば、コントロールは腑に落ちます。.Value は ボックスが言っている中身 です。.ListIndex は それがリストから来たかどうか です。ユーザーがドロップダウンから選べば、両者は一致します。ユーザーが新しい ものを入力すると、.Value は入力されたテキストを保ち、.ListIndex は -1 になります — テキストがリストの項 目ではないという合図です。

ComboBox を埋める

埋め方は ListBox とまったく同じです。列全体を一度に代入する、これが速い道です。

Private Sub UserForm_Initialize()
    ComboBox1.List = Sheet1.Range("A2:A50").Value   ' 一列から一度で埋める
End Sub

Range.Value は 2 次元配列で .List はそれを受け取るので、一行でドロップダウンを読み込めます (VBA Range を参照)。.AddItem は一つずつ組み立てる項目のときだけ使います。

Dim i As Long
For i = 1 To 12
    ComboBox1.AddItem "Month " & i     ' 計算した項目を一つずつ追加する
Next i

埋め直す前に空にするには ComboBox1.Clear を呼びます。最初から既定値を表示させたいなら、埋めたあとに .ListIndex = 0 にするか、既知の項目を .Value に代入します。

Style:ユーザーが入力してよいかを決める

これは、人が見落とすプロパティです。ComboBox には、その性格全体を左右する .Style があります。

ComboBox1.Style = fmStyleDropDownCombo   ' 既定:リストから選ぶ、または自分で入力する
ComboBox1.Style = fmStyleDropDownList    ' ロック:ユーザーはリストの項目しか選べない

fmStyleDropDownCombo が既定で — ユーザーは何でも入力できます。fmStyleDropDownList は ComboBox を厳格な 選択器に変えます。入力は一致する項目へジャンプするだけで、最終的な値は常にあなたの用意したものです。フォームが 自由入力を受け付けてはいけないなら、.Style を設定しましょう — あとから検証で追い払おうとしてはいけません。

最大の落とし穴:空でないボックスは正しい選択ではない

不正なデータを通してしまうバグがこれです。既定のスタイルでは、ユーザーはリストにない値を入力できます。ボックス が空でないことしか確かめないコードは、打ち間違いも平気で受け入れてしまいます。

' WRONG - accepts anything the user typed
If ComboBox1.Value <> "" Then ProcessOrder ComboBox1.Value

' RIGHT - insist the choice came from the list
If ComboBox1.ListIndex >= 0 Then
    ProcessOrder ComboBox1.Value
Else
    MsgBox "Please choose an item from the list, not free text."
End If

.Value <> "" が示すのは、ボックスに 何か があることだけです。.ListIndex >= 0 は、ユーザーが実際のリスト 項目を選んだことを示します — テキストが選ばれたのではなく入力されたときは、いつでも .ListIndex が -1 だか らです。規則は単純です。リストからの正しい選択が大事なときは、.Value <> "" ではなく .ListIndex を調べる のです。自由入力がそもそも一切あってはならないなら、より上流のきれいな直し方があります — .Style = fmStyleDropDownList に設定すれば、落とし穴は起こりえません。(ボックスがフォーカスを失ったときに一致しない入 力を拒む .MatchRequired プロパティもありますが、.Style を設定するほうが無骨でも確実な道具です。)

Value と Text、そして変化への反応

ComboBox では、.Value と .Text はたいてい同じ文字列を読みます。あなたが使うのは .Value です。.Text が効くのは、入力が確定する前に 入力中に表示されているもの を気にするときです。ユーザーが選択を変えた瞬間に反 応するには、Change イベントを扱います。

Private Sub ComboBox1_Change()
    ' キー入力のたび、選択のたびに発火する - 軽く保つ
    Label1.Caption = "Current: " & ComboBox1.Value
End Sub

入力できる ComboBox では Change がキー入力のたびに発火するので、そのハンドラーは軽く保ちます — 一文字ごと にデータベース検索を走らせてはいけません。

ComboBox か ListBox か:スペースと選択数で決める

ComboBox と ListBox は埋め方と読み取りのプロパティを共有するので、選択がどう振る舞 うべきかで選びます。答えが 単一の値 で、スペースが限られていて、畳まれたドロップダウンのほうがすっきりする とき — あるいは自由入力を 許したい とき — は ComboBox を使います。選択肢が 一目で見えている べき、ある いはユーザーが 複数 を選ぶかもしれないときは ListBox を使います。複数選択は ListBox だけの機能です。 ComboBox は決して複数の項目を返せません。

ExcelMaster の活用

ここでの静かな失敗は、コードが .ListIndex >= 0 ではなく .Value <> "" を確かめたせいで、ユーザーの入力を何 でも受け入れてしまう ComboBox です — つづりを間違えた製品名が、そのままあなたのデータに流れ込みます。

ExcelMaster には、コントロールを普通の言 葉で伝えられます — 「ユーザーが必ず選ぶ製品コードのドロップダウン、自由入力はなし」 — すると正しい .Style を 設定し、あなたのデータから一覧を埋め、.ListIndex を調べて選択を読むので、本物の選択だけが通ります。ブックと コードはあなたの手元に残ります。

よくある質問

VBA で範囲から ComboBox を埋めるには?

範囲を一文で .List に代入します。ComboBox1.List = Sheet1.Range("A2:A50").Value です。Range.Value は 2 次元配列で .List はそれを受け取るので、これで列全体を一度に読み込めます。.AddItem は一つずつ組み立てる項 目のときだけ使い、すでに行のあるボックスを埋め直す前に .Clear を呼びます。

VBA の ComboBox から選択された値を取得するには?

現在の入力のテキストは .Value で、それが来た 0 始まりの行は .ListIndex で読みます。テキストがリストから選 ばれたのではなく入力されたとき .ListIndex は -1 なので、本物のリスト選択が必要なら、.Value に対して動く 前に .ListIndex >= 0 を調べます。

ComboBox でユーザーが自由入力するのを止めるには?

ComboBox1.Style = fmStyleDropDownList を設定します。これでコントロールはリストの項目だけにロックされます — 入力は一致する項目へジャンプするだけで、最終的な値は常にあなたの用意したものです。既定の fmStyleDropDownCombo は自由入力を許すので、それを保つときは .ListIndex >= 0 での検証が大事になります。

ComboBox で ListIndex = -1 は何を意味しますか?

現在のテキストがリストの項目のどれでもない、という意味です — ボックスが空か、ユーザーが一致しない何かを入力し たかです。ドロップダウンからの正しい選択は常に 0 以上の .ListIndex を返すので、.ListIndex = -1 は入力を 拒むか、もう一度うながすための合図です。

ComboBox と ListBox の違いは何ですか?

ComboBox はドロップダウン付きの一行を表示し、単一の値を返し、自由入力を許せます。 ListBox は複数の行を一度に表示し、複数選択を許せます。コンパクトな単一の選択には ComboBox、選択肢が見えているべき、あるいはユーザーが複数を選ぶときは ListBox を選びましょう。

検証環境

検証環境: Excel 365 (Windows 11)、VBA 7.1 — 最終確認 2026-09-25。

関連ガイド: VBA ListBox · VBA CheckBox · VBA UserForm · VBA Range · VBA InputBox