Article

Excelで2段階連動ドロップダウンを作る|2解法と子残り対処

この記事で分かること

Excel 連動ドロップダウンの 2 解法 (INDIRECT + 名前定義 / FILTER 関数) と、親変更時の子残りバグ対処マクロを解説します。

Excel のドロップダウンリストは、親セルの選択値に応じて子セルの選択肢を絞り込めます。「都道府県を選ぶと市区町村だけが選べる」というやつです。作り方は INDIRECT 関数 + 名前定義 (全バージョン対応) と FILTER 関数 (Excel 2024 / Microsoft 365 / Excel 2021) の 2 通りで、互換性とメンテ性で選び分けます。

あわせて、親選択を変えたときに子の値が残るバグの対処マクロもまとめます。Excel 2024 / Microsoft 365 で縦持ちマスターを使えるなら h2-3 の FILTER 解法が運用しやすいです。Excel 2019 以前で動かす必要がある場合や、横持ちデータが既にある場合は h2-2 の INDIRECT 解法を選んでください。

INDIRECT を使った多段階ドロップダウンの作り方は他サイトでも紹介されています。本記事では Excel 2024 で使える FILTER 関数版と、親を変更したときに子の値が残る問題への対処までまとめます。

完成イメージ (動きで見る)

都道府県のドロップダウンを選ぶと、市区町村のドロップダウンの選択肢が連動して変わる動きです。さらに親を変更すると、Worksheet_Change マクロで子の値が自動でクリアされます。

連動ドロップダウンの完成動作 (都道府県を選ぶと市区町村が変わる)

3 段階版 (大カテゴリ → 中カテゴリ → 小カテゴリ) への拡張も同じ仕組みで作れます (h2-5 で解説)。

解法選択ガイド

  • Excel 2024 / Microsoft 365 + 縦持ちマスター → h2-3 の FILTER 解法 (運用が楽)
  • Excel 2019 以前 / 横持ちデータが既にある → h2-2 の INDIRECT 解法 (全バージョン対応)
  • 親変更で子の値が残るバグ → h2-4 の Worksheet_Change マクロで対処

解法 1: INDIRECT + 名前定義 (全バージョン対応の定番)

横持ちデータ (列ごとに親の値をヘッダーにし、配下に子の選択肢を並べたもの) と INDIRECT 関数を組み合わせる定番手法です。Excel 2016 以降の全バージョンで動きます。

手順 1: 横持ちデータと名前定義

列ごとにヘッダー (親の値) + 配下に子の選択肢を並べたデータを準備します。

  1. データ範囲 (ヘッダー含む) を選択 (下のスクリーンショットでは横持ちデータ A8:C11 を選択した状態)
  2. [数式] タブ → [選択範囲から作成] をクリック
  3. 「上端行」にチェック → [OK]
横持ちデータ範囲 A8:C11 を選択した Excel 画面 (この状態で「選択範囲から作成」を実行)

これで各列のヘッダーが名前として登録され、配下の選択肢がその名前の参照範囲になります。詳細は Microsoft Support の 数式内の名前 ページを参照してください。

罠 1: ヘッダーに使えない文字は _ に勝手に置換される

「選択範囲から作成」は、ヘッダーに名前定義の規則違反文字があると、エラーを出さずに自動で _ に置換して登録します。

入力ヘッダー登録される名前INDIRECT で読めるか
東京都東京都 (そのまま)OK
東 京 都 (半角スペース)東_京_都NG (親値「東 京 都」と一致しない)
東 京 (全角スペース)東_京NG
東京-都 (ハイフン)東京_都NG
23区 (数字始まり)_23区 (先頭 _ 追加)NG

ヘッダーは「半角英数字 + ひらがな・カタカナ・漢字・アンダースコアのみ」を使ってください。

名前マネージャーで「東 京 都」が「東_京_都」に自動置換されている画面

手順 2: 親と子のドロップダウンを設定

親セル (例: A4) に都道府県のドロップダウン、子セル (例: B4) に市区町村のドロップダウンを設定します。

親 A4 の入力規則:

東京都,神奈川県,大阪府

子 B4 の入力規則「元の値」:

=INDIRECT($A4)

列を絶対参照 $A4 にするのがポイントです。これで A4 の値 (= 名前定義のキー) を参照する範囲が、子のドロップダウン候補になります。

INDIRECT 解法で親 (都道府県) を選ぶと子 (市区町村) のドロップダウンが連動

罠 2: 親値と名前定義は完全一致が必須

INDIRECT 関数は名前を文字列で受け取るので、親値の表記が名前定義と完全に一致している必要があります。Excel 2024 build 19929 で実機確認した判定マトリクスです。

親値判定備考
東京都OK完全一致
東京都 (末尾半角スペース)通るINDIRECT が末尾スペースを無視。可読性のため推奨しない
東京都  (末尾全角スペース)通る同上
東京都 (先頭スペース)NGエラー
東京 都 (途中スペース)NGエラー
Tokyo (別名)NG登録されていない名前

「選択範囲から作成」で _ 置換が起きた場合、親側の選択肢も置換後の名前 (例: 東_京_都) で揃える必要があります。

手順 3: 動作の注意点

  • 親 A4 が空のまま子 B4 の入力規則を設定しようとすると「リストの元の値が間違っています」エラーが出ます。先に親に有効値を入れてから子を設定してください
  • 親値が名前定義に存在しないと、子のドロップダウンを開いた瞬間にエラーになります
  • 名前定義は標準ではブック全体 (Workbook スコープ) で有効です

INDIRECT 関数の詳しい動作原理は post 1902 INDIRECT 関数を理解しよう を参照してください。INDIRECT の公式ドキュメントは Microsoft Support にあります。

動的拡張 (行追加で増えるリスト) と組み合わせたい場合は post 14661 動的に更新されるドロップダウン を参照してください。

解法 2: FILTER 関数版 (Excel 2024 / Microsoft 365 / Excel 2021)

縦持ちマスターと FILTER 関数を組み合わせる現代的な解法です。データを縦持ちで運用できるので、市区町村の追加・削除がしやすく、3 段階以上に拡張しやすいのが利点です。

手順 1: 縦持ちマスターをテーブル化

都道府県と市区町村を 2 列で並べた縦持ちマスターを準備し、Ctrl + T でテーブル化してテーブル名を マスター にします。

縦持ちマスターと FILTER のスピル + 入力規則の # 参照

手順 2: 親候補と子候補をスピルで作る

別のシート (またはマスターの右側) に親候補と子候補をスピルで展開します。

親候補 (例: D8 セル):

=SORT(UNIQUE(マスター[都道府県]))

子候補 (例: E8 セル、A4 = 親セルに依存):

=SORT(UNIQUE(FILTER(マスター[市区町村], マスター[都道府県]=$A$4)))

UNIQUE で重複を除外し、SORT で並び替えています。FILTER の詳細は Microsoft Support の FILTER 関数 ページを参照してください。

手順 3: 入力規則にスピル参照を渡す

親 A4 の入力規則「元の値」:

=$D$8#

子 B4 の入力規則「元の値」:

=$E$8#

末尾の # がスピル範囲演算子で、スピルの長さに合わせて自動で範囲が伸び縮みします。マスターに新しい都道府県や市区町村を追加すると、ドロップダウンの選択肢にも自動で反映されます。

罠 3: 親が空のときは #CALC! エラーになる

親 A4 が空のとき、FILTER のスピルは #CALC! エラーになります。IFERROR でラップすると安全です。

=IFERROR(SORT(UNIQUE(FILTER(マスター[市区町村], マスター[都道府県]=$A$4))),"")

FILTER 関数は Microsoft 365 / Excel 2024 / Excel 2021 でのみ使えます。Excel 2019 以前は #NAME? になるので、その場合は h2-2 の INDIRECT 解法を選んでください。

親選択を変えると子の値が残るバグの回避 (Worksheet_Change マクロ)

連動ドロップダウンを作ったあと、こんな現象に気づくことがあります。

  1. 親 A4 で「東京都」を選択
  2. 子 B4 で「世田谷区」を選択
  3. 親 A4 を「神奈川県」に変更
  4. → 子 B4 に「世田谷区」が残ったまま (神奈川県には世田谷区はない)
親 (東京都) と子 (世田谷区) を選んだ状態
親を神奈川県に変更しても、子に世田谷区が残ったまま

これは Excel の入力規則の仕様です。入力規則は「現在の入力時点」しか検証しないので、親変更時に子の値を再検証する機能はありません。Excel 2024 build 19929 で確認したところ、親を変更しても子セルの Validation の式 (=INDIRECT($A4)) はそのまま維持されますが、現在値の再チェックは行われません。

解決: シートに Worksheet_Change マクロを追加する

親列を監視して、変更があったら子セルを自動でクリアするマクロを追加します。シートタブを右クリック → [コードの表示] → 開いたコードウィンドウに次のコードを貼り付けてください。

Private Sub Worksheet_Change(ByVal Target As Range)
    Dim changed As Range
    Set changed = Intersect(Target, Me.Range("A2:A100"))
    If changed Is Nothing Then Exit Sub

    On Error GoTo CleanUp
    Application.EnableEvents = False
    changed.Offset(0, 1).ClearContents

CleanUp:
    Application.EnableEvents = True
End Sub
マクロを追加した後、親を変更すると子が自動でクリアされる

コードの解説

  • Intersect(Target, Me.Range("A2:A100")) で、変更されたセルと監視範囲 (A2 〜 A100) の交差を取得します
  • 監視範囲外の変更なら Exit Sub で何もせず終了
  • changed.Offset(0, 1).ClearContents で監視範囲の右隣 (B 列の対応セル) だけをクリアします
  • On Error GoTo CleanUp で例外時も EnableEvents = True に確実に戻します
  • マクロ内の ClearContents が再度 Worksheet_Change を呼ばないよう、Application.EnableEvents = False で抑制します

マクロ運用上の注意

  • このマクロを使うにはファイルを マクロ有効ブック (.xlsm) として保存する必要があります
  • ダウンロードした .xlsm を開くと「保護ビュー」が表示されます。発信元を確認のうえ「マクロを有効にする」をクリックしてください
  • ファイルプロパティで「ブロック解除」が必要なケースもあります (プロパティ → 全般 → ブロック解除)
  • Delete キーや右クリック → クリアによる一括削除では、環境によってマクロが拾わないことがあります。確実に消したい場合は子セルも手動で消すか、セル単位で操作してください
  • VBA を使いたくない場合は、子残りを許容して必要に応じて手動で消す運用も選べます (本記事末尾の配布ブックの「マクロなし版」シート参照)

3 段階以上に拡張する

「都道府県 → 市区町村 → 町丁目」のように 3 段階の連動ドロップダウンも作れます。INDIRECT 版と FILTER 版で考え方が違います。

INDIRECT 版: 名前を _ で連結する

親値と中カテゴリ値を _ で連結した名前を作り、それを参照します。

名前定義の例:

  • 名前 東京都 の参照範囲 = 「新宿区, 世田谷区, 港区」
  • 名前 東京都_新宿区 の参照範囲 = 「歌舞伎町, 西新宿」
  • 名前 東京都_世田谷区 の参照範囲 = 「三軒茶屋, 下北沢」

孫セル (C5) の入力規則「元の値」:

=INDIRECT($A5 & "_" & $B5)

組み合わせが多いと名前定義の数が爆発的に増えるので、規模が大きくなったら FILTER 版を検討してください。

FILTER 版: 第 2 引数に * 演算子で AND 条件を加える

FILTER の include 引数に AND 条件を渡すには、* 演算子を使って要素ごとに掛け算します。

孫セル (C5) のスピル元 (例: G20):

=SORT(UNIQUE(FILTER(マスター[町丁目], (マスター[都道府県]=$A$5)*(マスター[市区町村]=$B$5))))

入力規則「元の値」は =$G$20# のようにスピル参照で渡します。

配布ブックを開いたときの注意

本記事末尾の配布ブック「3段階拡張」シートでは、INDIRECT 名前合成版を A5・B5・C5 にFILTER の * 演算子 AND 版を A15・B15・C15 に分けて併置しています。FILTER 版のスピル元 G20 は $A$15 / $B$15 を参照する形になっているので、本文の式 (A5/B5 基準) を配布ブックで試すときは、入力セル番地を読み替えてください。

3 段階拡張で都道府県 → 市区町村 → 町丁目が連動

罠 4: AND 関数を使うと #CALC! エラーになる

同じ意味で AND(マスター[都道府県]=$A$5, マスター[市区町村]=$B$5) と書いてしまうと #CALC! エラーになります。

× =FILTER(マスター[町丁目], AND(マスター[都道府県]=$A$5, マスター[市区町村]=$B$5))
   → #CALC! (ERROR.TYPE=14)

○ =FILTER(マスター[町丁目], (マスター[都道府県]=$A$5)*(マスター[市区町村]=$B$5))
   → 正常スピル

理由: AND 関数は配列を畳み込んで単一の TRUE / FALSE を返すため、要素ごとの AND としては機能しません。* 演算子は配列の要素ごとに TRUE × TRUE = 1 / TRUE × FALSE = 0 を計算するので、include 引数として正しく動きます。

互換性と運用コストの比較表

解法対応バージョンデータ構造拡張性メンテ
INDIRECT + 名前定義Excel 2016 以降の全バージョン横持ち (列ごと)名前を追加中 (名前管理が必要)
FILTER 関数Microsoft 365 / Excel 2024 / Excel 2021縦持ち (列で並べる)引数追加 (* で AND)楽 (テーブルに追加するだけ)

選び方の目安:

  • Excel 2019 以前で動かす必要がある → INDIRECT 一択 (FILTER は使えない)
  • Excel 2021 以降 + 縦持ちマスターを既に持っている → FILTER がおすすめ
  • 横持ちデータが既にある → INDIRECT が手早い

親変更時の子残り対処は、両解法とも同じ Worksheet_Change マクロで OK です (h2-4)。

うまく動かないとき + まとめ

まとめ

  • 2 解法のおすすめ: Excel 2021 以降なら FILTER (h2-3)、それ以前なら INDIRECT (h2-2)
  • 子残りバグは Worksheet_Change マクロ で一発解決 (h2-4)。Delete キーでの一括削除では拾わないことがある点だけ注意
  • 3 段階以上に広げるなら、INDIRECT は名前を _ で連結、FILTER は * 演算子で AND 条件 (h2-5)。AND 関数を使うと #CALC! になる点に注意

配布ブック (xlsm)

シート構成:

  • マスター: 縦持ちマスター (都道府県 / 市区町村 / 町丁目、テーブル名「マスター」)
  • INDIRECT解法: マクロあり完成版 (Worksheet_Change で子残り対処)
  • FILTER解法: マクロあり完成版 (スピル参照 + 改良マクロ)
  • マクロなし版: VBA を使わずに INDIRECT / FILTER 両方を併置 (子残りは手動でクリア)
  • 3段階拡張: INDIRECT 名前合成 + FILTER の * 演算子
  • 罠デモ: CreateNames 自動 _ 置換、親値表記ゆれ判定、Worksheet_Change なしでの子残り再現

ダウンロードしたファイルを開くと「保護ビュー」が表示されます。発信元を確認のうえ、必要に応じて「マクロを有効にする」をクリックしてください。プロパティで「ブロック解除」が必要なケースもあります。

Next Read

このあと読む記事

今の内容に近い記事から、次の1本と補助記事を続けて見つけられるようにしています。

Keep Exploring

このテーマをさらに探す

同じテーマの入口記事と更新記事を、一覧の形でまとめています。

コメント