INDEXは、範囲の中から「何行目・何列目」を指定して値を取り出す関数です。
単体では地味ですが、MATCH と組み合わせることで、VLOOKUP の弱点をすべて回避した検索が組めます。この INDEX+MATCH は長年スプレッドシートの定番テクニックとして使われてきました。
書式
=INDEX(範囲, [行番号], [列番号])
| 引数 | 内容 |
|---|---|
| 範囲 | 取り出す対象の範囲 |
| 行番号 | 範囲の上から何番目か |
| 列番号 | 範囲の左から何番目か。範囲が1列なら省略可 |
行番号・列番号はシート全体ではなく、指定した範囲の中での位置です。ここを間違えやすいので注意してください。
基本の使い方
| A | B | C | |
|---|---|---|---|
| 1 | 商品コード | 商品名 | 価格 |
| 2 | A-101 | ボールペン | 150 |
| 3 | A-102 | ノート | 320 |
| 4 | B-201 | ハサミ | 480 |
=INDEX(A1:C4, 3, 2) → ノート
範囲 A1:C4 の中で、上から3番目・左から2番目 = B3セルの「ノート」が返ります。
範囲を1列だけにすれば、列番号は省略できます。
=INDEX(B1:B4, 3) → ノート
行番号を0にすると列全体が返る
行番号に 0 を指定すると、その列の全体が配列として返ります。
=INDEX(A1:C4, 0, 2) → 商品名 / ボールペン / ノート / ハサミ
列番号を 0 にすれば行全体です。この挙動は他の関数に範囲を渡すときに使います。
INDEX + MATCH ── 定番の検索パターン
INDEXの本領はここです。行番号を MATCH で求めると、検索関数になります。
「B-201」の商品名を取り出す例:
=INDEX(B2:B4, MATCH("B-201", A2:A4, 0))
分解するとこうなります。
MATCH("B-201", A2:A4, 0)→ A列の上から3番目にある、なので3INDEX(B2:B4, 3)→ B列の3番目 =ハサミ
MATCHで位置を求め、INDEXでその位置の値を取る。 これだけです。
VLOOKUPより優れている点
左方向にも検索できます。 VLOOKUPは範囲の左端列しか検索できませんが、INDEX+MATCHは検索する列と取り出す列が独立しているため、位置関係を問いません。
=INDEX(A2:A4, MATCH("ハサミ", B2:B4, 0)) → B-201
列を挿入しても壊れません。 列番号を数字で書いていないためです。
処理が軽いという利点もあります。VLOOKUPは指定した範囲全体を読みますが、INDEX+MATCHは検索列と結果列の2列しか見ません。行数が数万規模になると体感で差が出ます。
XLOOKUPがあるなら
XLOOKUP は INDEX+MATCH と同じことを、1つの関数で書けます。
=XLOOKUP("B-201", A2:A4, B2:B4)
読みやすさでは明らかにXLOOKUPが上です。新しく書くならXLOOKUPで構いません。
INDEX+MATCHを覚えておく価値があるのは、次の場合です。
- 古いExcelとファイルを共有する(XLOOKUPが動かない)
- 既存ファイルの数式を読む・直す必要がある
- 行と列の両方をMATCHで求める二次元検索をしたい
二次元の検索
行も列も動的に決めたい場合、MATCHを2つ使います。
=INDEX($B$2:$D$10, MATCH($F$1, $A$2:$A$10, 0), MATCH($F$2, $B$1:$D$1, 0))
F1に行の項目、F2に列の項目を入れると、その交差点の値が返ります。クロス集計表からのピンポイント抽出はこの形が定番です。
エラーの対処
#REF! が出る
指定した行番号・列番号が範囲の外を指しています。範囲が3行なのに行番号4を指定した、というケースです。MATCHの結果と範囲の開始行がずれていることも多いので、MATCH 単体の結果を別セルで確かめると原因が早く分かります。
#N/A が出る
INDEXではなく、中の MATCH が失敗しています。検索キーが見つかっていません。
結果が1つずれる
範囲の開始行のずれが原因です。MATCH を A1:A4(見出し行を含む)で取り、INDEX を B2:B4(見出しなし)で指定すると1行ずれます。両方を同じ行から始めるのが鉄則です。
位置で取り出すという発想
INDEXは、他の検索関数とは考え方が根本的に違います。VLOOKUPやXLOOKUPが「この値を探して、対応する値を返す」という動きをするのに対し、INDEXは「この範囲の、上から何番目、左から何番目の値を返す」という動きをします。探す機能を持っていません。位置を指定して取り出すだけの関数です。
この違いを理解すると、なぜINDEXが単独ではあまり使われず、MATCHとの組み合わせで語られるのかが分かります。MATCHが「この値は上から何番目か」を返す関数なので、その答えをINDEXの位置指定に渡せば、検索と取り出しが完成します。二つの関数で役割を分担しているわけです。
役割が分かれていることには利点があります。検索する列と返す列を完全に独立して指定できるため、左方向の検索が自然にできます。VLOOKUPが構造的にできなかったことが、INDEXとMATCHでは制約なしにできます。また、返す範囲を後から広げても列番号を数え直す必要がありません。列の挿入で壊れる事故が起きない、という点でも堅牢です。
一方で、数式が長くなり、初見では何をしているか読み取りにくいという欠点があります。自分だけが触るファイルなら問題ありませんが、他人に引き継ぐ場合は、コメント行や補助列で意図を残しておくと親切です。
行番号と列番号の指定で気をつけること
INDEXに渡す番号は、シート全体の行番号ではなく、指定した範囲の中での順番です。範囲を二行目から百行目までにした場合、一と指定すれば二行目が返ります。シートの行番号と混同すると、常に一行ずれた値が返ることになります。
この一行ずれは、見出し行を範囲に含めるかどうかで起きやすくなります。見出しを含めた範囲にすると、データの一行目は範囲の中では二番目になります。MATCHと組み合わせる場合、両方の範囲の開始行を必ず揃えてください。片方が見出しを含み、もう片方が含まないと、結果が一行ずれます。この種のずれは、目で見て気づきにくく、数字としてはもっともらしい値が返るため、発見が遅れます。
範囲が一列だけの場合は、列番号を省略できます。行番号だけを指定すれば、その位置の値が返ります。逆に一行だけの範囲なら、列番号だけの指定でも動きます。二次元の範囲に対しては、行番号と列番号の両方が必要です。
範囲の外を指定するとエラーになります。範囲が五行しかないのに六を指定すれば、参照が無効という意味のエラーが返ります。MATCHが見つからなかった場合、MATCH側がエラーを返すので、INDEXまで到達しません。エラーが出たときは、まずMATCHの部分だけを取り出して単独で実行し、正しい番号が返っているかを確かめてください。
範囲として返す使い方
INDEXは値を返すだけでなく、範囲そのものを返すこともできます。行番号にゼロを指定すると、その列全体が範囲として返ります。列番号にゼロを指定すれば、その行全体が返ります。
この性質を使うと、合計する範囲を動的に決められます。たとえば、月ごとの列が並んだ表があり、指定した月の列だけを合計したい場合、MATCHで月の位置を求め、INDEXで列全体を取り出し、それをSUMに渡します。列を追加しても数式を直す必要がありません。
もうひとつの使い方が、範囲の一部を切り出すことです。開始位置と終了位置をそれぞれINDEXで指定し、コロンでつなぐと、その間の範囲になります。データが増えても自動で追従する集計を作るときに使われます。同じことはOFFSETでもできますが、OFFSETは揮発性関数なので、再計算のたびにシート全体が走ります。行数の多いファイルでは、INDEXを使うほうが軽く済みます。
範囲を返すという性質は最初はぴんと来ませんが、覚えておくと選択肢が広がります。特に、集計対象が状況によって変わる表を作るときに効いてきます。
二次元の表から値を取り出す
行と列の両方で条件を指定して、交差する位置の値を取り出したい場面はよくあります。商品と月が並んだ表から、特定の商品の特定の月の数値を取り出す、といった用途です。
この場合、MATCHを二回使います。一回目で商品名が上から何番目かを求め、二回目で月が左から何番目かを求めます。その二つの番号をINDEXに渡せば、交差する位置の値が返ります。
書き方は長くなりますが、構造は単純です。INDEXの中に、行の位置を求めるMATCHと、列の位置を求めるMATCHが入っているだけです。範囲の指定さえ間違えなければ、確実に動きます。
注意点は、三つの範囲の関係です。INDEXに渡す表の範囲、行を探すMATCHの範囲、列を探すMATCHの範囲。この三つが正しく対応している必要があります。表の範囲が二行目から始まるなら、行を探すMATCHの範囲も二行目から始めてください。開始位置がずれると、結果もずれます。
この二次元検索は、ピボットテーブルで作った集計表から値を引っ張ってくるときにもよく使われます。集計表の形が変わっても、見出しで探しているので壊れにくいという利点があります。
INDEXを使う判断の基準
INDEXは単体でも使えますが、実務で選ぶ場面は限られます。判断の基準を整理しておきます。
行番号と列番号が既に分かっている場合。 計算で位置を出せるなら、INDEX単体で足ります。
検索が必要な場合は、MATCHと組み合わせてください。 値から位置を求め、その位置を取り出す流れになります。
XLOOKUPが使える環境なら、そちらを先に検討してください。 同じことがより短く書けます。INDEX+MATCHが必要になるのは、XLOOKUPが使えない環境か、複雑な参照を組む場合です。
範囲全体を返す使い方もあります。 行番号か列番号に0を指定すると、その行または列がまるごと返ります。SUMなどと組み合わせるときに使います。
動的な範囲指定にも使えます。 INDEXを範囲の端に置くと、参照範囲そのものを可変にできます。ただし、可読性が落ちるため、他の人が触る表では避けてください。
迷ったら、まずXLOOKUPかFILTERで書けないかを考えてください。 短く書けるほうが、後で読むときに楽です。
よくある質問
Q. XLOOKUPが使えるなら、INDEXとMATCHは不要ですか
新規に作るならXLOOKUPで足ります。ただし、古い環境で開くファイルや、既存のファイルにはINDEXとMATCHが大量に残っています。読めることは必要です。
Q. 結果が一行ずれます
INDEXの範囲とMATCHの範囲で、開始行が違っています。両方を揃えてください。
Q. 参照が無効というエラーが出ます
指定した番号が範囲の外です。範囲の行数と、渡している番号を確かめてください。
Q. 見つからないときに空欄にしたいのですが
全体をIFERRORで包みます。ただし、本当は見つかるはずなのに見つかっていない場合まで隠れるので、動作確認が終わってから包んでください。
Q. 複数の条件で検索できますか
MATCHの検索値と検索範囲をそれぞれ連結する書き方があります。ただし読みにくいので、元データに結合列を作るほうが保守しやすくなります。
Q. 別のシートを参照できますか
できます。範囲の指定にシート名を付けるだけです。
Q. 数式が長くて読めません
数式バーの中で改行できます。INDEXの部分とMATCHの部分を行で分けると、構造が見えやすくなります。
Q. 該当が複数あるとどうなりますか
MATCHが最初に見つけた位置を返すため、一番上の一件だけが対象になります。全件を取り出したい場合はFILTERを使ってください。
まとめ
- 書式は
=INDEX(範囲, 行番号, 列番号) - 位置はシートではなく指定範囲の中での番号
INDEX(結果列, MATCH(キー, 検索列, 0))が検索の定番形- 左方向の検索・列挿入への耐性・処理の軽さが利点
- 新規に書くなら XLOOKUP のほうが読みやすい
