【VBA】セル入力時にオートコンプリート(自動補完)を実装する方法(コピペOK)

【VBA】セル入力時にオートコンプリート(自動補完)を実装する方法の解説用アイキャッチ画像 VBA

この記事でわかること

  • VBAでセルに文字を入力するだけで候補リストから自動補完できる
  • Worksheet_Changeイベントで前方一致・部分一致の候補表示を実装できる
  • マスタシートと連動して候補リストを動的に管理できる

どんな場面で使う?

  • 商品名や取引先名など、候補が多い項目をセルに入力する作業を効率化したいとき
  • 入力規則のドロップダウンでは候補が多すぎて選びにくいとき
  • マスタシートの候補リストと連動して、新しい候補が自動反映される仕組みを作りたいとき
  • 入力ミス(タイプミス・表記ゆれ)を防いでデータの品質を上げたいとき

完成イメージ(Before / After)

Before(手入力で商品名や取引先名を入力):

操作 問題点
商品名を毎回フル入力 入力ミスが発生する
過去データをCtrl+Fで探す 時間がかかる
入力規則のリストが長すぎる スクロールが大変

After(数文字入力で候補が自動表示):

操作 結果
A列に「り」と入力 「りんご」「りんごジュース」が候補として表示される
候補を選択 セルに正確な値がセットされる
VBAでセル入力時にオートコンプリートを実装するBefore After
手入力から、数文字入力で候補を選べる状態へ変えます。

自分も以前、200件以上ある商品名を毎回手入力していた。入力規則のドロップダウンリストも試したが、候補が多すぎてスクロールがしんどかった。オートコンプリートをVBAで実装してからは、2〜3文字打つだけで候補が絞り込まれるようになった。入力ミスも激減して、正直もっと早く知りたかった。この記事で、同じように入力作業に時間を取られている人がラクになればうれしい。

入力規則のドロップダウンは候補が少ないうちは便利だが、100件を超えると探すのが大変。オートコンプリートなら数文字で候補を絞り込める。

なお、入力規則の基本的な設定方法は 入力規則(ドロップダウンリスト)をVBAで一括設定する方法 を参照。セルの値が変わったときの自動実行の仕組みは セルの値が変わったら自動で処理を実行する方法 で詳しく解説している。

実行前の準備

バックアップを取る

Worksheet_Changeイベントはセルの値を自動で書き換える。 既存データがあるシートで試す場合は、必ずファイルをコピーしてバックアップを取ること。

シート構成を確認する

  • 入力シート — A列に入力する(オートコンプリート対象列)
  • 「マスタ」シート(実務版で使用) — A列に候補リスト(商品名、取引先名など)

基本版はコード内に候補リストを直接書くので、マスタシートは不要。

手順(コピペ → 動作確認まで約5分)

シートモジュールを開く(標準モジュールではない)

ここが最大のポイント。 Worksheet_Changeはシートモジュールに書く。

  1. VBEの左ツリーでオートコンプリートを設定したいシート名(例: Sheet1)をダブルクリック
  2. 右側にコードウィンドウが開く → ここにコードを貼り付ける

間違いやすいポイント:

  • 「挿入」→「標準モジュール」は使わない
  • 左のツリーでシート名をダブルクリックする

コードを貼り付けて動作確認する

  1. 下の「コード(基本版)」をコピーして貼り付ける
  2. Excelの画面に戻る(Alt + F11
  3. A列に「り」と入力してEnterを押す → セルの値が「りんご」に変わればOK
Worksheet_Changeを使ったVBAオートコンプリートの処理フロー
基本版は、入力文字を受け取って候補を検索し、該当値をセルへ戻します。

コード(基本版)– 完全前方一致で候補セット

まずはこれだけで動く。A列にテキストを入力すると、候補リストから前方一致する最初の値を自動でセルにセットする。

★ 貼り付け先はシートモジュール(標準モジュールではない)


Private Sub Worksheet_Change(ByVal Target As Range)
    '--- セル入力時にオートコンプリート(基本版) ---
    Dim candidates As Variant
    Dim i As Long
    Dim inputVal As String

    ' A列以外は無視
    If Target.Column <> 1 Then Exit Sub
    ' 複数セル同時変更は無視
    If Target.Count > 1 Then Exit Sub
    ' 空欄は無視
    If Target.Value = "" Then Exit Sub

    ' 候補リスト(ここを書き換える)
    candidates = Array("りんご", "りんごジュース", "みかん", _
                       "バナナ", "ぶどう", "メロン", "もも")

    inputVal = CStr(Target.Value)

    ' 前方一致で候補を検索
    Application.EnableEvents = False
    For i = LBound(candidates) To UBound(candidates)
        If Left(candidates(i), Len(inputVal)) = inputVal Then
            Target.Value = candidates(i)
            Exit For
        End If
    Next i
    Application.EnableEvents = True
End Sub

書き換えポイント:

項目 変更箇所
対象列 Target.Column <> 1 B列なら <> 2、C列なら <> 3
候補リスト Array("りんご", ...) 自分のマスタデータに書き換え
マスタシートとコンボボックスを連動したVBAオートコンプリート実務版の構成
実務版では、候補をマスタシートで管理して入力欄に表示します。

コード(実務版)– 部分一致+コンボボックス表示+マスタシート連動+複数列対応

自分はこの実務版を使ってから、商品名や取引先名の入力が格段に速くなった。マスタシートに候補を追加するだけで自動的にオートコンプリートに反映されるのが便利。

シートモジュールに貼り付ける部分:


Private Sub Worksheet_Change(ByVal Target As Range)
    '--- セル入力時にオートコンプリート(実務版) ---
    Dim wsMaster As Worksheet
    Dim lastRowMaster As Long
    Dim inputVal As String
    Dim candidates() As String
    Dim candidateCount As Long
    Dim i As Long
    Dim masterCol As Long
    Dim cellVal As String

    ' ここが追加:複数列対応(A列=マスタA列、C列=マスタB列)
    Select Case Target.Column
        Case 1: masterCol = 1    ' A列入力 → マスタA列(商品名)
        Case 3: masterCol = 2    ' C列入力 → マスタB列(取引先名)
        Case Else: Exit Sub      ' それ以外は無視
    End Select

    ' 複数セル同時変更は無視
    If Target.Count > 1 Then Exit Sub
    ' 空欄は無視
    If Target.Value = "" Then Exit Sub

    inputVal = CStr(Target.Value)

    ' ここが追加:マスタシートから候補を取得
    On Error Resume Next
    Set wsMaster = ThisWorkbook.Sheets("マスタ")
    On Error GoTo 0
    If wsMaster Is Nothing Then Exit Sub

    lastRowMaster = wsMaster.Cells(wsMaster.Rows.Count, masterCol).End(xlUp).Row
    If lastRowMaster < 2 Then Exit Sub

    ' ここが追加:部分一致で候補を収集
    candidateCount = 0
    ReDim candidates(1 To lastRowMaster)

    For i = 2 To lastRowMaster
        cellVal = CStr(wsMaster.Cells(i, masterCol).Value)
        If InStr(1, cellVal, inputVal, vbTextCompare) > 0 Then
            candidateCount = candidateCount + 1
            candidates(candidateCount) = cellVal
        End If
    Next i

    If candidateCount = 0 Then Exit Sub

    Application.EnableEvents = False

    ' ここが追加:候補が1件なら即セット、複数ならコンボボックス表示
    If candidateCount = 1 Then
        Target.Value = candidates(1)
    Else
        ' コンボボックスで候補を表示
        ShowCandidateCombo Target, candidates, candidateCount
    End If

    Application.EnableEvents = True
End Sub

Private Sub ShowCandidateCombo(ByVal Target As Range, _
                                ByRef candidates() As String, _
                                ByVal cnt As Long)
    '--- ここが追加:アクティブXコンボボックスで候補表示 ---
    Dim cb As OLEObject
    Dim cbName As String
    cbName = "cmbAutoComplete"

    ' 既存のコンボボックスがあれば削除
    On Error Resume Next
    Me.OLEObjects(cbName).Delete
    On Error GoTo 0

    ' コンボボックスを作成(セルの位置に合わせる)
    Set cb = Me.OLEObjects.Add( _
        ClassType:="Forms.ComboBox.1", _
        Left:=Target.Left, _
        Top:=Target.Top + Target.Height, _
        Width:=Target.Width + 50, _
        Height:=20)
    cb.Name = cbName

    ' 候補を追加
    Dim cmb As MSForms.ComboBox
    Set cmb = cb.Object
    cmb.Clear
    Dim j As Long
    For j = 1 To cnt
        cmb.AddItem candidates(j)
    Next j

    cmb.ListRows = WorksheetFunction.Min(cnt, 8)
    cb.Activate
    cmb.DropDown
End Sub

標準モジュールに貼り付ける部分(コンボボックス選択時の処理):


Sub AutoComplete_ComboSelect()
    '--- コンボボックスの値をセルにセットして削除する ---
    Dim ws As Worksheet
    Dim cb As OLEObject
    Dim cmb As MSForms.ComboBox

    Set ws = ActiveSheet
    On Error Resume Next
    Set cb = ws.OLEObjects("cmbAutoComplete")
    On Error GoTo 0
    If cb Is Nothing Then Exit Sub

    Set cmb = cb.Object
    If cmb.Value <> "" Then
        Application.EnableEvents = False
        ActiveCell.Value = cmb.Value
        Application.EnableEvents = True
    End If

    cb.Delete
End Sub

自分はこの実務版を商品名入力に使っている。マスタシートに新商品を追加するだけで候補に反映されるので、メンテナンスがラクになった。

書き換えポイント:

項目 変更箇所
対象列とマスタ列の対応 Case 1: masterCol = 1 D列入力→マスタC列なら Case 4: masterCol = 3
マスタシート名 "マスタ" "商品マスタ"
部分一致→前方一致に変更 InStr(1, cellVal, inputVal, ...) Left(cellVal, Len(inputVal)) = inputVal
コンボボックスの幅 Width:=Target.Width + 50 候補が長い場合は数値を大きくする

入力規則との組み合わせは 入力規則のリストを別のセルの値に連動させる方法 を参照。

よくある落とし穴6選

# 症状 原因 対策
1 コードを貼り付けたのに何も起きない 標準モジュールに貼り付けている。Worksheet_Changeはシートモジュール専用 VBEの左ツリーで対象シート(例: Sheet1)をダブルクリックして、そこに貼り付ける
2 Excelがフリーズする(無限ループ) Application.EnableEvents = False を書き忘れている。Worksheet_Change内でセルの値を変更すると、自身が再度発火して無限ループになる コードの先頭で EnableEvents = False、末尾で True に戻す。自分もこれで初めてExcelがフリーズして焦った
3 他のマクロのイベントが動かなくなった EnableEvents = False のままエラーで処理が中断した VBEのイミディエイトウィンドウ(Ctrl+G)で Application.EnableEvents = True と入力して Enter
4 大文字・小文字が区別されて候補が見つからない 基本版は Left() での比較なので大文字小文字を区別する 実務版の InStr(1, ..., vbTextCompare) を使えば大文字小文字を無視して検索できる
5 コンボボックスが残ったまま消えない コンボボックスの選択処理(AutoComplete_ComboSelect)を標準モジュールに貼り忘れている、またはEscキーで閉じた場合 残ったコンボボックスは手動で右クリック→削除するか、VBEのイミディエイトウィンドウで ActiveSheet.OLEObjects("cmbAutoComplete").Delete を実行
6 マスタシートに候補を追加したのに反映されない マスタシートの列番号が masterCol と一致していない。または最終行の取得で空行が含まれている マスタシートのA列に空行がないか確認。列番号の対応を Select Case で再確認する

VBAのオートコンプリートが動かないときの対処法

「コードを貼り付けたのにセル入力しても何も起きない」場合、コードを標準モジュールに貼り付けていることが原因だ。Worksheet_Changeイベントはシートモジュール専用なので、VBEの左ツリーで対象シート(例: Sheet1)をダブルクリックして、そこに貼り付けよう。

VBAのオートコンプリートでExcelがフリーズするときの対処法

「セルに入力した瞬間にExcelが固まる」場合、Application.EnableEvents = Falseを書き忘れていて無限ループが発生していることが原因だ。Worksheet_Change内でセルの値を変更すると自身が再発火する。コードの先頭でEnableEvents = False、末尾でTrueに戻す処理を必ず入れよう。

実務で候補リストを安全に運用する考え方

オートコンプリートは入力が速くなる一方で、候補リストの管理が雑だと、古い候補が残ったり、表記ゆれが増えたりします。特に同じ部署でブックを配布して使う場合、各自のPC設定やExcelの表示環境が少しずつ違うため、外部ファイルのパスに依存した作りにすると動かない原因になります。候補マスタはできるだけ同じブック内の専用シートに置き、更新担当者、入力ルール、削除してよい候補の基準を決めておくと運用しやすくなります。

また、Worksheet_Change や KeyUp などのイベントで候補を更新する場合は、対象範囲を広げすぎないことが大切です。シート全体を監視すると、関係ないセルを編集しただけでも処理が走り、動作が重くなったり、貼り付け時に意図しない候補更新が起きたりします。実務では、入力列だけに範囲を絞り、空白、重複、前後のスペースを除外してから候補に使うほうが安定します。

確認項目起きやすい問題対策
候補マスタ古い候補や重複が残る定期的に重複・空白・表記ゆれを確認する
対象範囲関係ない編集でも処理が走る入力対象列だけに限定する
外部参照PCごとのパス差で動かない同じブック内のマスタを基本にする
貼り付け操作大量貼り付けでイベントが連続実行される複数セル変更時は処理を抜ける

複数セル貼り付け時に処理を止める例

Private Sub Worksheet_Change(ByVal Target As Range)
    If Target.CountLarge > 1 Then Exit Sub
    If Intersect(Target, Me.Range("B:B")) Is Nothing Then Exit Sub

    'ここに候補更新や入力チェックの処理を書く
End Sub

このように最初に対象外の操作を抜けるだけでも、マクロの安定感はかなり変わります。入力補助のマクロは便利さが目立ちますが、実務では「候補を誰が直すか」「どの列だけ反応するか」「一括貼り付けをどう扱うか」まで決めておくと、配布後の問い合わせを減らせます。

FAQ

Q1. Excel標準のオートコンプリート(入力候補)とどう違う?

Excel標準のオートコンプリートは同じ列の既存データから候補を出すだけで、カスタマイズできない。VBA版なら候補リストをマスタシートで管理でき、部分一致や複数列対応も可能。

Q2. 入力規則(ドロップダウンリスト)とどちらがよい?

候補が30件以下なら入力規則のドロップダウンで十分。50件以上ならオートコンプリートのほうが快適。入力規則の設定方法は 入力規則(ドロップダウンリスト)をVBAで一括設定する方法 を参照。

Q3. UserFormで候補一覧を表示する方法はある?

ある。コンボボックスの代わりにUserFormのリストボックスを使えば、候補のプレビューや複数列表示もできる。UserFormの作り方は ユーザーフォームで本格的な入力画面を作る方法 を参照。自分は商品名+単価を並べて表示するのにUserForm版を使っている。

Q4. 数値入力でもオートコンプリートは使える?

使える。ただし、数値の場合は CStr(Target.Value) で文字列に変換してから比較する必要がある。商品コード(数字)で商品名を引きたい場合は、マスタシートのA列にコード、B列に商品名を入れ、Cells(i, 2).Value で商品名を取得する方法が実用的。

Q5. 保護されたシートでもオートコンプリートは動く?

シート保護が有効な場合、VBAからのセル書き込みがブロックされる。UserInterfaceOnly:=True で保護すれば、VBAからの操作は許可される。保護の詳細は 特定シートだけ保護・解除する方法 を参照。

まとめ

この記事では、VBAでセル入力時にオートコンプリート(自動補完)を実装する方法を解説した。

  • 基本版 — Worksheet_Changeイベントで候補リストから前方一致の値を自動セット
  • 実務版 — 部分一致検索+コンボボックス候補表示+マスタシート連動+複数列対応

候補が多いデータの入力作業が格段に速くなり、入力ミスも減る。

関連記事:

次にやりたくなること

  • ユーザーフォームで本格的な入力画面を作る方法 — オートコンプリートに加えて、入力フォーム全体をUserFormで構築したい場合に
  • 入力規則のリストを別のセルの値に連動させる方法 — カテゴリ選択に応じて候補リストを切り替えたい場合に
  • セルの入力値をVBAでチェック・制限する方法 — オートコンプリート後にさらに入力値のバリデーション(数値チェック・日付チェック等)を追加したい場合に
  • セルの値が変わったら自動で処理を実行する方法 — オートコンプリート以外のWorksheet_Change活用パターンを知りたい場合に

コメント

タイトルとURLをコピーしました