INDEX MATCH in Excel — Complete Guide to the Most Powerful Lookup Formula

INDEX MATCH is the professional Excel standard for lookups — more flexible than VLOOKUP, faster on large datasets, and capable of two-way lookups, left lookups, and multiple criteria that VLOOKUP simply cannot do. This guide covers everything from your first formula to advanced array-based multi-criteria matching, with a live formula builder so you can generate the exact syntax for your data.

Dr Waqas Rafique Dr Waqas Rafique · Founder & CTO · PhD, Statistical Machine Learning
· About

TL;DR

INDEX MATCH pairs two functions: MATCH finds the row number of your lookup value, and INDEX uses that row number to return a value from any column. The core formula is =INDEX(ReturnRange, MATCH(LookupValue, LookupRange, 0)). Use it instead of VLOOKUP whenever your lookup column is not the leftmost column, your table structure might change, or you need to match on multiple criteria.

Contents

  1. Why INDEX-MATCH?
  2. The INDEX function explained
  3. The MATCH function explained
  4. Interactive formula builder
  5. VLOOKUP vs INDEX-MATCH diagram
  6. Step 1 — Your first INDEX-MATCH
  7. Step 2 — Looking left
  8. Step 3 — Two-way lookup
  9. Step 4 — Multiple criteria
  10. Step 5 — Error handling with IFERROR
  11. Step 6 — Performance
  12. Step 7 — When to use XLOOKUP instead
  13. Full comparison table
  14. Common mistakes
  15. FAQ

Why INDEX-MATCH?

INDEX-MATCH is not a single Excel function — it is two functions used together. INDEX returns the value at a specific position within a range. MATCH finds the position of a value within a range. Nested together, they replicate everything VLOOKUP does and add capabilities that VLOOKUP will never have.

VLOOKUP has one core limitation that frustrates analysts every day: it can only look to the right. Your lookup column must be the leftmost column of the range, and you specify the return column as a number (1, 2, 3…). If you insert a new column into the middle of your table, every VLOOKUP counting past that column suddenly returns the wrong data — silently, with no error.

INDEX-MATCH solves both problems. The lookup range and return range are specified independently, so they can be in any order — the return range can be to the left, to the right, or in a completely different part of the spreadsheet. And because you reference actual ranges rather than counting column positions, inserting or deleting columns never breaks anything.

You absolutely need INDEX-MATCH over VLOOKUP when:

Market context: INDEX-MATCH has been the professional Excel standard for 20 years. XLOOKUP (Excel 365 and Excel 2021 only) is the modern successor and is simpler for basic cases — but INDEX-MATCH works in every version of Excel from 2003 onwards and remains essential knowledge for any analyst working in a mixed-version environment.

The INDEX Function Explained

The INDEX function returns the value at a specified row (and optionally column) within a range.

=INDEX(array, row_num, [col_num])
ArgumentRequired?What it means
arrayYesThe range you want to return a value from. Can be a single column, single row, or a multi-column block.
row_numYesWhich row to return. 1 = the first row of the array.
col_numNoWhich column to return. Omit if array is a single column. 1 = the first column of the array.
=INDEX(A1:A10, 3)

Returns the 3rd value in column A.

=INDEX(A1:C10, 3, 2)

Returns the value from row 3, column 2 of the range A1:C10 — cell B3.

💡 Pro Tip: When used on its own with a fixed row number, INDEX is just a positional lookup. Its real power unlocks when you replace that fixed number with a MATCH formula that calculates the position dynamically.

The MATCH Function Explained

MATCH searches a single row or column for a value and returns the position number where it was found — not the value itself.

=MATCH(lookup_value, lookup_array, [match_type])
ArgumentWhat it means
lookup_valueThe value you are searching for. Can be text, number, date, or a cell reference.
lookup_arrayA single row or column to search in. Must be one-dimensional.
match_type0 = exact match (use this 95% of the time). 1 = largest value ≤ lookup value (ascending sort required). -1 = smallest value ≥ lookup value (descending sort required).

If "London" is in cell A7 of a list in A1:A20:

=MATCH("London", A1:A20, 0)

Returns 7 — London is the 7th item in the array.

⚠️ Warning: MATCH returns a number, not the value. If you enter MATCH on its own in a cell you will see a number like 7. This is correct — that number is exactly what INDEX needs as its row_num argument.

Interactive Formula Builder

Fill in your actual range references and the formula updates live. Switch between single-lookup and two-way lookup mode with the toggle.

INDEX-MATCH Formula Builder
Enter your ranges to generate the exact formula for your spreadsheet.

VLOOKUP vs INDEX-MATCH: Side-by-Side Diagram

The diagram below shows why VLOOKUP fails when the return column is to the left of the lookup column, and how INDEX-MATCH handles it natively.

VLOOKUP — FAILS LOOKING LEFT A: Name B: Dept C: ID (lookup) Alice Engineering EMP-001 cannot look left =VLOOKUP(ID, A:C, -1, 0) returns #VALUE! INDEX-MATCH — ANY DIRECTION A: Name (return) B: Dept C: ID (lookup) Alice Engineering EMP-001 MATCH: row = 1 INDEX returns "Alice" =INDEX(A:A, MATCH(EMP-001, C:C, 0)) = "Alice"

Step 1.Your First INDEX-MATCH

Scenario: you have a customer table with CustomerID in column D, Name in column E, Email in column F, and Revenue in column G. In cell A2 you have a CustomerID and you want the Email. VLOOKUP would require CustomerID to be the first column — here it is column D, which is fine for VLOOKUP if the return column is to the right. But what if the structure changes? INDEX-MATCH handles it robustly regardless.

D: CustomerIDE: NameF: EmailG: Revenue
CUST-001Alice Martinalice@example.com£4,200
CUST-002Bob Chenbob@example.com£1,850
CUST-003Carol Whitecarol@example.com£7,300
=INDEX($F$2:$F$1000, MATCH(A2, $D$2:$D$1000, 0))

Step by step:

  1. MATCH(A2, $D$2:$D$1000, 0) — searches column D for the value in A2 (e.g. "CUST-002") and returns its position within the range. If CUST-002 is the 2nd item in the range, MATCH returns 2.
  2. INDEX($F$2:$F$1000, 2) — returns the 2nd value from column F, which is "bob@example.com".
  3. Because both ranges start at row 2, the position offset is always consistent.

Why the $ signs matter: $F$2:$F$1000 is an absolute reference — it does not change when you drag the formula down. A2 without $ is a relative reference: it becomes A3, A4… as you drag down, so each row looks up its own customer ID. This is exactly the right behaviour.

💡 Pro Tip: Lock both the column and row of your lookup and return ranges with $. Leave only the lookup value cell (A2) unlocked so it advances as you copy the formula down.

Step 2.Looking Left — The Key Advantage

VLOOKUP cannot look left. If your lookup column is column C and you want to return a value from column A (to the left), VLOOKUP returns an error. INDEX-MATCH handles this trivially because the two ranges are independent.

A: NameB: DepartmentC: Employee IDD: Salary
Alice MartinEngineeringEMP-001£72,000
Bob ChenMarketingEMP-002£58,000
Carol WhiteFinanceEMP-003£65,000

You have EMP-002 in cell F2 and want the Name from column A (to the left of the lookup column C):

=INDEX($A$2:$A$1000, MATCH(F2, $C$2:$C$1000, 0))

The return range ($A$2:$A$1000) is entirely to the left of the lookup range ($C$2:$C$1000). This works identically whether the return column is left, right, or non-adjacent. You can use the same MATCH to return values from multiple columns by writing separate INDEX formulas each with a different return range.

⚠️ Warning: Do not attempt =VLOOKUP(F2, A:C, -1, 0) to look left — this returns #VALUE!. INDEX-MATCH is the correct tool for left lookups.

This is the single most common reason professionals switch from VLOOKUP to INDEX-MATCH. Once your data has the lookup column anywhere other than the leftmost position — which happens frequently with real-world data from databases or exported reports — you need INDEX-MATCH.

Step 3.Two-Way INDEX-MATCH (Row AND Column Lookup)

A two-way lookup finds a value at the intersection of a specific row and column. The classic use case is a price matrix: products on rows, customer tiers on columns.

BronzeSilverGoldPlatinum
Widget A£10.00£9.00£7.50£6.00
Widget B£18.00£16.00£13.00£10.50
Widget C£24.00£21.50£18.00£14.00

Row headers (product names) in A2:A4, column headers (tiers) in B1:E1, price data in B2:E4. Product name in H2, tier in H3:

=INDEX($B$2:$E$4, MATCH(H2, $A$2:$A$4, 0), MATCH(H3, $B$1:$E$1, 0))

Breakdown:

💡 Pro Tip: Use named ranges to make two-way lookups self-documenting. Name B2:E4 as "PriceTable", A2:A4 as "Products", B1:E1 as "Tiers". The formula becomes =INDEX(PriceTable, MATCH(H2, Products, 0), MATCH(H3, Tiers, 0)).

Critical setup rule: the data table must not include the row or column headers. The data table (B2:E4) starts one row below and one column to the right of the header ranges. Both MATCH functions return positions within their respective 1-dimensional ranges, and INDEX uses those positions within the data body.

Step 4.INDEX-MATCH with Multiple Criteria

VLOOKUP can only match on one column. INDEX-MATCH with multiple criteria is one of the most powerful Excel techniques available. The technique uses array multiplication of Boolean conditions — when all conditions are met, the product is 1; when any condition fails, the product is 0.

Two-criteria example

Salesperson in column A, Product in column B, Revenue in column C. You want the revenue where Salesperson = E2 AND Product = F2:

=INDEX($C$2:$C$1000, MATCH(1, ($A$2:$A$1000=E2)*($B$2:$B$1000=F2), 0))
⚠️ Excel 2019 and earlier: Press Ctrl + Shift + Enter instead of Enter. Excel wraps it in curly braces {=INDEX(...)} to confirm it is an array formula. In Excel 365 and 2021, press Enter normally.

How it works: ($A$2:$A$1000=E2) produces an array of TRUE/FALSE for each row where Salesperson matches. ($B$2:$B$1000=F2) does the same for Product. Multiplying them gives 1 only where both are TRUE. MATCH(1, ..., 0) finds the first row where the product is 1.

Three-criteria extension

=INDEX($D$2:$D$1000, MATCH(1, ($A$2:$A$1000=E2)*($B$2:$B$1000=F2)*($C$2:$C$1000=G2), 0))

Add another multiplication term for each additional criterion. For very large datasets (100k+ rows), consider adding a concatenated helper column instead to avoid performance degradation.

💡 Pro Tip: On Excel 365, you can use =XLOOKUP or =FILTER for multiple-criteria lookups with simpler syntax. INDEX-MATCH multiple criteria is the go-to for Excel 2016/2019 compatibility.

Step 5.IFERROR Wrapping and Error Handling

When MATCH cannot find the lookup value it returns #N/A, which propagates to INDEX. Wrap the formula with IFERROR to handle this gracefully:

=IFERROR(INDEX($F$2:$F$1000, MATCH(A2, $D$2:$D$1000, 0)), "Not Found")

Common fallback values: "Not Found" for text columns, 0 for numeric columns (careful — this can be confused with a real zero), "" to return a blank cell.

💡 Pro Tip: Use IFNA instead of IFERROR if you only want to catch #N/A and still see other errors like #REF!: =IFNA(INDEX(..., MATCH(...)), "Not Found"). This helps surface genuine formula errors rather than silently hiding them.

Common causes of #N/A: lookup value genuinely not in the range; extra spaces in the data (use TRIM); number stored as text vs actual number; match type set to 1 on unsorted data.

Step 6.Performance — Why INDEX-MATCH is Faster

On small datasets the difference is negligible. On large datasets, the gap is real. VLOOKUP loads the entire table_array into memory and scans from left to right on every recalculation. MATCH with match_type 0 operates on a single column and stops immediately when the match is found.

Dataset sizeVLOOKUPINDEX-MATCH exact (0)INDEX-MATCH sorted (1)
10,000 rows~0.03s~0.02s<0.01s
100,000 rows~0.25s~0.12s~0.01s
500,000 rows~1.2s~0.4s~0.02s

The most dramatic gain comes from match_type 1 (binary search) on a sorted lookup column. Binary search is O(log n) versus O(n) for a linear scan — 500K rows becomes almost instantaneous.

=INDEX($F$2:$F$1000, MATCH(A2, $D$2:$D$1000, 1))
⚠️ Warning: Only use match_type 1 if the lookup column is sorted ascending and will stay sorted. On unsorted data it returns wrong results with no error. Default to match_type 0 for safety.

Step 7.When to Use XLOOKUP Instead

XLOOKUP (Excel 365 and Excel 2021+) is the modern successor with cleaner syntax for common cases:

=XLOOKUP(A2, $D$2:$D$1000, $F$2:$F$1000, "Not Found")

XLOOKUP advantages: simpler syntax, built-in not-found parameter (no IFERROR wrapper needed), can return multiple columns natively, can search from last to first with search_mode -1.

Stick with INDEX-MATCH when:

VLOOKUP vs INDEX-MATCH vs XLOOKUP: Full Comparison

FeatureVLOOKUPINDEX-MATCHXLOOKUP
Excel 2016/2019 supportYesYesNo
Look left (return col before lookup col)NoYesYes
Two-way (row + column) lookupNoYesNested only
Multiple criteriaNoYes (array)No (use FILTER)
Built-in not-found handlingNeeds IFERRORNeeds IFERROR4th argument
Return multiple columnsNoSeparate formulasYes (native)
Binary search on sorted dataYes (type 1)Yes (match_type 1)Yes (search_mode 2)
Safe when columns insertedNo (index breaks)YesYes
Search from last to firstNoNoYes (search_mode -1)
Wildcard supportYesYes (match_type 0)Yes (match_mode 2)

📥 Free INDEX-MATCH Excel Template

Upload your data to DataHub Pro and get automated lookups, cross-table joins, and data validation — no formula work required.

Get your free DataHub Pro account →

Common Mistakes

1. Forgetting to lock ranges with $ signs

When you drag a formula down, unlocked ranges shift by one row per cell. D2:D1000 becomes D3:D1001 in the next row — your lookup range is now off by one and the formula returns wrong values silently. Always use $D$2:$D$1000 for lookup and return ranges. Only leave the lookup value cell (A2) without $ so it advances with each row.

2. Using match_type 1 instead of 0 on unsorted data

This is the most dangerous mistake because it produces wrong results with no error. Match type 1 uses binary search and assumes ascending sort order. On unsorted data it returns the last value that is less than or equal to the lookup value — which could be any row. Default to 0 for exact match in all cases unless you have explicitly sorted and will keep sorted.

3. Lookup range and return range different sizes

If your lookup range is $D$2:$D$100 but your return range is $F$2:$F$200, MATCH might return position 85, but INDEX looks up position 85 within $F$2:$F$200 — a completely different row than intended. Both ranges must start at the same row and span the same number of rows.

4. Not using Ctrl+Shift+Enter for array formulas in Excel 2019

The multiple-criteria formula is an array formula in Excel 2019 and earlier. Pressing Enter alone causes MATCH to see only the first cell value rather than the full array, returning a wrong row. Confirm with Ctrl+Shift+Enter and check for curly braces {=...} in the formula bar.

Stop writing lookups by hand

DataHub Pro joins, filters, and cross-references your data automatically. Connect your Excel files, Google Sheets, or database and get clean joined tables in seconds.

Try DataHub Pro free →

Frequently asked questions

What is the difference between INDEX MATCH and VLOOKUP?
VLOOKUP searches the leftmost column of a table and returns a value from a column to the right — it cannot look left. INDEX MATCH combines two functions: MATCH finds the position of your lookup value in any row or column, and INDEX returns the value at that position from any separate range. This means INDEX MATCH can return values from columns to the left of the lookup column, handles table structure changes without breaking, is faster on large datasets because MATCH stops at the first hit, and works with two-dimensional lookups. VLOOKUP is simpler to write for basic cases, but INDEX MATCH is the professional standard for any lookup that goes beyond the simplest single-column right-lookup.
How do I use INDEX MATCH with multiple criteria?
Use an array formula that multiplies Boolean arrays together: =INDEX(ReturnRange, MATCH(1, (Criteria1Range=Value1)*(Criteria2Range=Value2), 0)). In Excel 2019 and earlier, confirm with Ctrl+Shift+Enter instead of just Enter — Excel wraps it in curly braces {=...} to indicate an array formula. In Excel 365 and Excel 2021, just press Enter normally as these versions support dynamic arrays natively. You can extend to three or more criteria by multiplying additional Boolean arrays: *(Criteria3Range=Value3). The 1 in the MATCH function is the target — the multiplication of the Boolean arrays produces 1 only when ALL conditions are met simultaneously, so MATCH finds the first row where every criterion is satisfied.
Why does INDEX MATCH return a wrong value?
The most common causes are: (1) Match type set to 1 instead of 0 — match type 1 does an approximate match and requires sorted data; if your data is unsorted, it will return the wrong row. Always use 0 for exact match unless you specifically need approximate matching. (2) The lookup range and return range have different sizes — if your lookup range is A2:A100 but your return range is B2:B200, INDEX will offset incorrectly. Both ranges must start at the same row and span the same number of rows. (3) Missing $ signs — if you drag the formula down and the ranges shift, the formula returns values from the wrong rows. Lock ranges with $ on both the column and row references for ranges that should not move.
How do I do a two-way lookup with INDEX MATCH?
A two-way lookup uses INDEX with two MATCH functions — one for the row and one for the column: =INDEX(DataTable, MATCH(RowLookupValue, RowHeaders, 0), MATCH(ColLookupValue, ColHeaders, 0)). DataTable is the data body (not including the row or column headers). RowHeaders is the single column of row labels. ColHeaders is the single row of column labels. The first MATCH finds which row the row lookup value appears in, and the second MATCH finds which column the column lookup value appears in. INDEX then returns the cell at that intersection. This is particularly useful for price matrices, scheduling grids, and any cross-tabulated reference table.
Is INDEX MATCH faster than VLOOKUP?
Yes, meaningfully so on large datasets. VLOOKUP scans the entire table_array from left to right on every recalculation, even after it has found its match. MATCH with match_type 0 (exact) also scans linearly, but it operates on a single column rather than loading the entire table into memory. The practical difference becomes noticeable above ~50,000 rows. In benchmarks on 500,000-row datasets, INDEX-MATCH calculates in approximately 0.4 seconds versus approximately 1.2 seconds for VLOOKUP — roughly 3x faster. If your lookup column is sorted, using match_type 1 (binary search) instead of 0 reduces lookup time to O(log n) rather than O(n), making it dramatically faster still — though this requires the data to be in ascending sort order.
How do I use INDEX MATCH across multiple sheets?
Reference the other sheet in each range argument. For example, to look up a value from Sheet2: =INDEX(Sheet2!$B$2:$B$1000, MATCH(A2, Sheet2!$A$2:$A$1000, 0)). The sheet name is prefixed with an exclamation mark before the cell reference. If the sheet name contains spaces, wrap it in single quotes: =INDEX('Sales Data'!$B$2:$B$1000, MATCH(A2, 'Sales Data'!$A$2:$A$1000, 0)). You can also reference a closed workbook by including the file name in square brackets before the sheet name, though Excel will prompt you to update links when the source file is closed.
What is the MATCH function return value?
MATCH returns a number — specifically, the relative position of the lookup value within the lookup array. If your lookup array is A2:A100 and your value is found in cell A7, MATCH returns 6 (the 6th item in the array, since A2 is position 1). It does not return the cell reference or the value itself — just the position number. This is why INDEX and MATCH work together so naturally: MATCH produces the row number that INDEX needs to retrieve the actual value. If the lookup value is not found, MATCH returns #N/A. You can test for this with IFERROR or IFNA.
Can INDEX MATCH return multiple values?
Standard INDEX MATCH returns a single value — the first match found. To return all matching values, use a different approach. In Excel 365, use FILTER: =FILTER(ReturnRange, LookupRange=LookupValue) — this returns all matching rows as a dynamic spill array, no array formula entry required. In older Excel versions, you need an array formula with SMALL and IF entered with Ctrl+Shift+Enter and dragged down. If you are on Excel 365, FILTER is far simpler and should be preferred for returning multiple results.
How do I use INDEX MATCH with wildcard characters?
Use match_type 0 (exact match) and include the wildcard in your lookup value. The asterisk (*) matches any sequence of characters; the question mark (?) matches any single character. To find the first customer whose name starts with "Smith": =INDEX(B2:B100, MATCH("Smith*", A2:A100, 0)). You can also reference a cell and concatenate: =INDEX(B2:B100, MATCH(D2&"*", A2:A100, 0)) where D2 contains the partial value. Wildcards only work with match_type 0. For case-sensitive wildcard matching you need to combine with EXACT inside an array formula.
Should I use INDEX MATCH or XLOOKUP?
If you are on Excel 365 or Excel 2021 and your file will only ever be opened in those versions, XLOOKUP is generally simpler: =XLOOKUP(lookup_value, lookup_array, return_array, "Not Found") handles left lookups, has a built-in not-found parameter, and can return entire rows or columns natively. Use INDEX MATCH when you need compatibility with Excel 2016 or 2019; when you need a two-way row-and-column lookup (INDEX-MATCH-MATCH is more explicit than nested XLOOKUP); when working in a shared file where some users have older Excel; or when you need binary search performance on large sorted datasets. Both are professional-grade solutions — the choice is primarily about compatibility and team context.

Further reading