「カテゴリごとに別々の価格テーブルを用意したら、VLOOKUPをIF関数で5重に囲むはめになった」「列を1つ追加するたびに、数十個の数式を手直しして消耗している」――そんな経験はありませんか?
実はその悩み、INDEX・MATCH・CHOOSEの組み合わせで一気に解消できます。この3つを組み合わせると、参照する表そのものや取得する列を"式の中で動的に切り替える"ことができ、テーブルの追加や列の並び替えに強い、メンテナンスフリーな式が完成します。
この記事を読むと、次の2つができるようになります。
- 条件に応じて参照先テーブルを丸ごと切り替える式が書ける
- 取得したい列をドロップダウンで選ぶ縦横ダブルMATCH式が書ける
まず押さえる:INDEXの「配列引数」は固定しなくていい
INDEX関数の構文を確認しましょう。
=INDEX(配列, 行番号, [列番号])
多くの人は「配列」の部分に $A$1:$C$10 のような固定範囲を入れます。しかしこの引数には、別の関数が返す配列(計算結果)をそのまま渡せます。これが今回のテクニックの核心です。CHOOSE関数を使うと「条件次第で別の範囲を返す」という仕組みが作れるため、INDEXに渡す配列を動的に切り替えられます。
STEP 1:CHOOSEで参照テーブルを丸ごと切り替える
CHOOSE関数のおさらい
=CHOOSE(インデックス番号, 値1, 値2, 値3, ...)
インデックス番号が1なら値1、2なら値2を返します。「値」の部分にはテキストや数値だけでなく、セル範囲(配列)も置けるところがポイントです。
具体例:カテゴリで価格テーブルを切り替える
以下のようなシートを想定してください。
【食品テーブル】 【電化製品テーブル】 A列:商品名 B列:価格 D列:商品名 E列:価格 りんご 150 テレビ 50000 バナナ 80 冷蔵庫 80000 みかん 120 洗濯機 70000 いちご 200 電子レンジ 15000 【入力・出力エリア】 G列:カテゴリ H列:商品名 I列:価格(数式) 1(=食品) バナナ ?(ここを求める) 2(=電化製品) 冷蔵庫 ?(ここを求める)
I2セルに入力する数式はこちらです。
=INDEX(CHOOSE(G2, $A$2:$B$5, $D$2:$E$5),
MATCH(H2, CHOOSE(G2, $A$2:$A$5, $D$2:$D$5), 0),
2)
各パーツの動き:
| パーツ | G2=1のとき | G2=2のとき |
|---|---|---|
CHOOSE(G2, $A$2:$B$5, $D$2:$E$5) |
食品テーブル全体を返す | 電化製品テーブル全体を返す |
MATCH(H2, CHOOSE(G2, $A$2:$A$5, $D$2:$D$5), 0) |
食品の商品名列から行番号を取得 | 電化製品の商品名列から行番号を取得 |
INDEX(..., 行番号, 2) |
該当テーブルの2列目(価格)を返す | 同左 |
VLOOKUPで同じことをしようとすると =IF(G2=1, VLOOKUP(...食品テーブル...), VLOOKUP(...電化製品テーブル...)) と分岐を書く必要がありますが、このやり方ならテーブルが分かれたままで、かつ式は1本で済みます。
STEP 2:取得列もドロップダウンで動的に指定する
次は「どの列の値を取得するか」もセルで切り替えるパターンです。列ヘッダー名をMATCHで拾う「縦横ダブルMATCH」と呼ばれる構成です。
シートのイメージ
【商品マスタ】 A列:商品コード | B列:定価 | C列:仕入値 | D列:在庫数 A001 | 1000 | 600 | 50 A002 | 2500 | 1400 | 30 【検索エリア】 G2: 検索する商品コード(例: A002) H2: 取得したい列名(ドロップダウン)(例: 仕入値) I2: 結果(数式)
I2セルに入力する数式:
=INDEX($A$2:$D$100,
MATCH(G2, $A$2:$A$100, 0),
MATCH(H2, $A$1:$D$1, 0))
- 行方向のMATCH:商品コードで何行目かを特定
- 列方向のMATCH:列ヘッダー名("定価" "仕入値" など)で何列目かを特定
これにより、列の追加・並び替えをしても数式を一切修正する必要がなくなります。H2のドロップダウンで取得項目を切り替えるだけで、欲しい値がすぐ取得できるレポートが完成します。
補足:CHOOSEでVLOOKUPの"右から左に返せない"問題を解決する
VLOOKUPは「検索列は必ず一番左」という制約があります。CHOOSEを使うと、列順を自由に並べた仮想テーブルを即席で作ることができます。
=VLOOKUP(検索値, CHOOSE({1,2}, $C$2:$C$100, $A$2:$A$100), 2, 0)
CHOOSE({1,2}, C列, A列) は「C列を1列目、A列を2列目」とする仮想の2列テーブルを生成します。これでC列を検索キーにしてA列の値を返す逆引きが実現します。
ただし、Excel 365・2021以降やXLOOKUPが使える環境ではINDEX+MATCHで十分対応できます。このCHOOSEトリックは、古いブックを保守するときや仕組みを深く理解したいときに役立つテクニックとして頭に入れておきましょう。
注意点とトラブルシューティング
#VALUE! エラーが出るとき
CHOOSEに渡す複数の範囲で列数が一致していないと発生しやすいです。食品テーブルはA〜B列(2列)、電化製品テーブルはD〜E列(2列)のように、必ず列数を揃えてください。行数は異なっても動作します。
古いExcelでCtrl+Shift+Enterが必要な場合
Excel 2019以前では、CHOOSEが配列を返す式をCtrl+Shift+Enterで確定する必要があります。Excel 365・2021以降では通常のEnterでOKです。
式が長くなったら「名前の定義」を活用する
数式タブの「名前の定義」でテーブル範囲に名前をつけると、式が格段に読みやすくなります。
// 名前定義: 食品テーブル → $A$2:$B$5
// 名前定義: 電化製品テーブル → $D$2:$E$5
=INDEX(CHOOSE(G2, 食品テーブル, 電化製品テーブル),
MATCH(H2, CHOOSE(G2, 食品商品名, 電化製品商品名), 0), 2)
実務パターンまとめ
| パターン | 式のイメージ | ユースケース |
|---|---|---|
| テーブルを条件で切り替え | INDEX(CHOOSE(条件, 表A, 表B), MATCH(...), 列番号) |
部署別・カテゴリ別の別テーブル参照 |
| 取得列をドロップダウン指定 | INDEX(表, MATCH(行キー,...), MATCH(列名,ヘッダー行,0)) |
動的レポートの列切り替え |
| VLOOKUPの逆引き | VLOOKUP(値, CHOOSE({1,2}, 右列, 左列), 2, 0) |
レガシーブックの補修 |
まとめ
- INDEXの配列引数はCHOOSEで動的に切り替えられる。複数テーブルをIF分岐なしに1式で参照できる
- 行・列ともにMATCHで特定することで、列追加・並び替えに強いメンテナンスフリーな式になる
- CHOOSEの逆引きトリックは古いブックや学習目的として有用
最初は式が長く感じるかもしれませんが、「INDEXに渡す配列そのものを式で生成する」という発想を一度つかめば、応用の幅は大きく広がります。まずは手元の小さなテーブルで試してみてください!