VLOOKUP XLOOKUP

A self-study lesson you can turn around and teach.

🏑 Australian Field Hockey 🗣️ Language Learning
§ Intro

How this deck works

Driving it

Click (or / Space) — build the current slide one step at a time, then move on
— undo one step, then one slide
E — edit any text in place (Ctrl+S saves a copy)
Rail (left) — jump between the 7 sections

The colour key — memorise this

Amber — the value we're looking up / the lookup array
Green — the return array (what we bring back)
Blue — the result cell / a spill anchor
Try it now — click anywhere to light up a cell ▸
One click = one build step. That's the whole trick.
§ Intro

Prerequisite knowledge

✔ VLOOKUP

=VLOOKUP(value, table, col_index, FALSE)

This lesson assumes basic VLOOKUP — find a value, bring something back. XLOOKUP keeps that mental move and removes the traps around it.

✔ Named ranges & tables

Players[Goals]  beats  F2:F200

This deck writes lookups against named table columns like the one above. You'll need to know how to use Excel tables and the Name Manager for this part — if that's unfamiliar, pause here, look it up, and come back.

§ Intro

Meet your two datasets

One skill, two worlds. If you can make a formula work in both, you actually understand it — that's transfer, and transfer is what lets you teach it.

🏑 tblPlayers — Australian field hockey roster

7 players · 6 fields — plus state, match and award tables we'll meet later.

🗣️ tblVocab — a personal phrasebook in three scripts

5 words · Arabic, Russian & Chinese columns, with a mastery score per word.

§ Why move on from VLOOKUP

VLOOKUP anatomy — a quick refresher

=VLOOKUP("HR-107", Players, 6, FALSE)
the ID we're hunting for the whole table — and it must start at the lookup column count the columns by hand: 1… 2… 3… 4… 5… 6 — every single time FALSE = exact match — forget it, and Excel quietly guesses landed: Talia's goal count
result →
§ Why move on from VLOOKUP

The five pains of VLOOKUP

You've probably hit every one of these. None of them are your fault — they're baked into the function.

Can't look left

The lookup column must be column 1 of the table. Need an ID from a name? Rearrange your data or give up.

→ XLOOKUP fixes this

Breaks on insert

Insert one column and your hard-counted index goes stale: 6 → ? — silently pointing at the wrong field.

→ XLOOKUP fixes this

Guesses by default

Omit FALSE and you get approximate matching — near-misses that look like real answers.

→ XLOOKUP fixes this

Fails ugly

No match means #N/A — unless you wrap the whole thing in an IFERROR bandage.

→ XLOOKUP fixes this

One cell at a time

One formula returns one value from one column. Need three fields? Write three formulas.

→ XLOOKUP fixes this
§ XLOOKUP core

XLOOKUP, one argument at a time

=XLOOKUP(lookup_value, lookup_array, return_array, [if_not_found], [match_mode], [search_mode])
required — the value required — where to look required — what to bring back optional — friendly text instead of #N/A optional — how to match (exact by default) optional — which direction to search
Only three things are required: the value · where to look · what to bring back.
grey boxes = safe to omit
§ XLOOKUP core

Head-to-head: same task, fewer traps

The task: Talia Rourke's goal count, from her ID.

old=VLOOKUP("HR-107", A2:F8, 6, FALSE)  → 41
new=XLOOKUP("HR-107", Players[PlayerID], Players[Goals])  → 41
the hand-counted 6 is gone — you point at the column by name the FALSE ritual is gone — exact match is the default
No counting. No match-type gotcha. Same answer, and the formula says what it means.
§ XLOOKUP core

The sentence you'll teach

Every XLOOKUP — no matter how fancy — is these three plain-English chunks:

the value
lookup_value
where to look
lookup_array
what to bring back
return_array
Say it out loud when you teach: "find this, in here, bring back that."
§ XLOOKUP core

Named ranges read like English

Both formulas below give the same answer. One of them you can read over the phone.

raw=XLOOKUP("Indi Fraser", B2:B8, F2:F8)
named=XLOOKUP("Indi Fraser", Players[Player], Players[Goals])
same result — but only one of these survives a column insert and explains itself Indi Fraser → 31 goals
result →
§ Exact match mastery — hockey

Worked example: ID → name

=XLOOKUP("HR-107", Players[PlayerID], Players[Player])
the value — the ID we're hunting for where to look — the whole PlayerID column lights up what to bring back — the Player column match found on row 7 → the name comes back
result →
§ Exact match mastery — hockey

Now reverse it — look left

=XLOOKUP("Talia Rourke", Players[Player], Players[PlayerID])
this time we start from the name …searching column B… …and bring back column A — one column to the left the ID comes back, no data rearranging, no helper column
result →
VLOOKUP literally cannot do this.
§ Exact match mastery — hockey

Fail gracefully: if_not_found

Look up an ID that doesn't exist — HR-999 — and watch the fourth argument earn its keep.

=XLOOKUP("HR-999", Players[PlayerID], Players[Player], "Not on roster")
no HR-999 anywhere → the raw error surfaces add one argument → a clean, human answer. No IFERROR wrapper needed.
result →
Teach it as a habit: any XLOOKUP a colleague will see gets an if_not_found.
§ Spill — the mini-arc

First, a new law of physics: the dynamic array

The old world

One formula lives in one cell and returns one value. Want seven names? Write seven formulas.

The new world

One formula can return a whole block — and Excel spills the answers into the empty cells next door. Automatically.

B2=Players[Player]
One formula, typed once, in one cell ▸ click
…and seven answers cascade out. That's a spill.
§ Spill — the mini-arc

Anatomy of a spill — four words to own

1 Anchor cell

Solid blue border — the only cell that really contains the formula. Edit happens here, and only here.

2 Spilled cells

Dashed halo, greyed formula in the bar. They display values but can't be edited directly — they belong to the anchor.

3 Spill range

The whole block, anchor + spilled cells, treated as one unit.

4 The # operator

=B2# means "the entire spilled range that starts at B2" — however big it happens to be today.

§ Spill — the mini-arc

When spill breaks: #SPILL!

The #1 spill confusion, fully unpacked: something is sitting in the way of where the answers need to go.

B2=Players[Player]
A stray note is parked in the spill path…
The formula needs B2:B8 — but B5 is occupied → #SPILL!
Clear the blocker → the answers flow in. That's the whole fix.
§ Spill payoffs + language

The payoff: three answers from one formula

=XLOOKUP("HR-107", Players[PlayerID], Players[[Position]:[Goals]])
find Talia's row, as usual… …but return three columns at once: Position through Goals one anchor + two spilled cells — remember pain ⑤? Gone.
spills →
§ Spill payoffs + language

Context switch: the phrasebook

Same skill, new world. tblVocab holds five words with translations in three scripts — plus pinyin, a category, and a mastery score out of 100.

Three script columns — Arabic reads right-to-left, Chinese uses hanzi, Russian uses Cyrillic. XLOOKUP doesn't care: text is text.
Watch the Mastery column — it comes back for approximate matching.
§ Spill payoffs + language

One word, three scripts, one formula

=XLOOKUP("Hello", Vocab[English], Vocab[[Arabic]:[Chinese]])
find "Hello" in the English column… …return the whole Arabic-to-Chinese stretch — three columns three writing systems spill out of one formula
spills →
§ Spill payoffs + language

It works in any direction — even across scripts

=XLOOKUP("水", Vocab[Chinese], Vocab[English])
start from the Chinese column, three columns to the right… …and look left all the way back to English 水 → Water. Direction is simply not a thing you think about anymore.
result →
§ match_mode & search_mode

Wildcards: match_mode 2

Everything so far needed the exact text. Meet match_mode — XLOOKUP's fifth argument, which sets how strictly the value has to match. Mode 2 switches on wildcards: you only remember the word starts with "hel…"? Good enough.

=XLOOKUP("hel*", Vocab[English], Vocab[Chinese], , 2)
hel* = "starts with hel" → matches Hello (note the skipped if_not_found slot: two commas) partial text in, exact answer out
result →
* any characters · ? one character · ~ escapes a literal * or ?
Why two commas in a row? Arguments live in fixed positions: slot 4 is if_not_found, which we're skipping — its comma stays behind so the 2 lands in slot 5, match_mode. This comma-counting shows up again over the next few slides.
§ match_mode & search_mode

match_mode — how to match

You just used mode 2 — here's the whole menu. One question decides which you need: what should count as a match when the exact value isn't in the list? Leave the argument out for exact; reach for the others when "close" is the point.

0
Exact matchDEFAULT
#N/A (or if_not_found) when missing — what you want 95% of the time
-1
Exact, or next smaller
banded lookups: grades, tiers, tax brackets, CEFR levels
1
Exact, or next larger
ceilings and minimum thresholds: "the first band above this"
2
Wildcard * ? ~
partial text — the "hel*" trick from the last slide
§ match_mode & search_mode

Approximate match, done right

Score → band, in both worlds. A band table lists the minimum score for each band, so your exact score is usually not in it — and an exact match would fail. match_mode -1 says what VLOOKUP's fragile TRUE only implied: exact, or the next smaller value — which lands you in the band you're inside.

=XLOOKUP(78, Levels[MinScore], Levels[Level], , -1)

Mastery 78 isn't in the table → slide down to 70.

=XLOOKUP(41, Tiers[MinGoals], Tiers[Award], , -1)

Talia's 41 goals → next smaller band is 40.

⚠ One rule survives from the old world: band tables must be sorted ascending.
§ match_mode & search_mode

search_mode — where to start looking

The sixth and final argument does a different job: it changes nothing about what counts as a match, only where Excel starts reading the column. That matters exactly when a value appears more than once — XLOOKUP returns the first match it meets, so direction decides which one wins.

1
First → lastDEFAULT
top-down scan; returns the first match it meets
-1
Last → first
the killer feature: "the most recent record" — next slide
2
Binary, ascending
huge sorted data, blazing fast — data must be sorted ascending
-2
Binary, descending
same speed trick for descending-sorted data
§ match_mode & search_mode

"How did we go last time against New Zealand?"

We've played New Zealand twice, so the Opponent column holds two matches. A normal top-down search stops at the March game and never sees June's. Scanning bottom-up with search_mode -1 makes the last matching row win — and in any log that grows downwards, the last row is the most recent.

=XLOOKUP("New Zealand", Matches[Opponent], Matches[Result], , , -1)
default search runs top-down → stops at the first NZ match it finds: March in Perth search_mode -1 scans bottom-up → finds the June match. That's why direction matters.
result →
§ Advanced + wrap

The party trick: nested, two-table lookup

Where is Talia's home base? Her row says NT — but "Darwin" lives in a different table. Chain two XLOOKUPs: the inner answer becomes the outer question.

=XLOOKUP(XLOOKUP("Talia Rourke", Players[Player], Players[State]), States[State], States[HomeBase])
the inner XLOOKUP runs first: Talia → "NT" "NT" becomes the outer lookup_value against the States table two hops, one formula → Darwin
hop 1 · tblPlayers
hop 2 · tblStates
result →
§ Advanced + wrap

It replaces HLOOKUP too

Point the arrays at rows instead of columns and the same three-chunk sentence works sideways. You can retire a second function today.

=XLOOKUP("NT", B1:G1, B2:G2)
lookup_array is a row this time — scan the state codes left-to-right return_array is the row beneath → Darwin. Vertical, horizontal — same function.
result →
One function now covers VLOOKUP, HLOOKUP and LOOKUP. That's three old tools off your belt.
§ Advanced + wrap

The cheat sheet — screenshot this one 📸

=XLOOKUP(lookup_value, lookup_array, return_array, [if_not_found], [match_mode], [search_mode])

the value · where to look · what to bring back — only the first three are required

match_mode

0exact (default)
-1exact or next smaller — bands
1exact or next larger
2wildcard  * ? ~

search_mode

1first → last (default)
-1last → first — most recent
2binary, sorted ascending
-2binary, sorted descending

Remember

  • Looks left, right, up, down — anywhere
  • Exact match by default
  • if_not_found beats IFERROR
  • Multi-column return_array → spill
  • =B2# refers to a whole spill range
  • Band tables sorted ascending
lookup value / array
return array
result / spill anchor
requires Excel 2021+ / Microsoft 365
§ Advanced + wrap

When it goes wrong — the five usual suspects

#SPILL!

Something is parked in the spill path.

Fix: clear the blocking cells — nothing is wrong with the formula.

#N/A

No match found and no fallback provided.

Fix: add an if_not_found — argument 4, plain text.

#VALUE!

lookup_array and return_array are different sizes — 7 rows vs 6, say.

Fix: make both arrays span the same rows (tables do this for free).

Wrong band

Approximate match over a table that isn't sorted ascending returns plausible nonsense.

Fix: sort the band column ascending. Always.

Mode in wrong slot

match_mode is argument 5, search_mode is 6. A misplaced -1 changes meaning silently.

Fix: count your commas — skipped slots stay empty:  , , -1

Golden rule

Every error above is diagnosable with the three-chunk sentence: the value, where to look, what to bring back. Check them in that order.

§ Advanced + wrap

Now teach it

Your six talking points

  1. The sentence: the value · where to look · what to bring back.
  2. It looks anywhere — left, right, up, down. No more column-1 rule.
  3. Exact match by default — the FALSE ritual is gone.
  4. if_not_found replaces the IFERROR wrapper with one friendly argument.
  5. Spill: a multi-column return spills; the anchor owns the formula; #SPILL! just means "something's in the way".
  6. Modes: match_mode -1 for bands (sorted ascending), search_mode -1 for "most recent".

Three challenges — click to reveal each answer

① Hockey · How many caps does Indi Fraser have?
=XLOOKUP("Indi Fraser", Players[Player], Players[Caps]) → 47
② Language · Spill "Thank you" into all three scripts with one formula.
=XLOOKUP("Thank you", Vocab[English], Vocab[[Arabic]:[Chinese]]) → شكرا · Спасибо · 谢谢
③ Two-way · What is Noor Haddad's home base city?
=XLOOKUP(XLOOKUP("Noor Haddad", Players[Player], Players[State]),
  States[State], States[HomeBase]) → Perth

If you can walk someone through these three, you own it.

editing — click any text · Ctrl+S saves a copy · E to exit