XLOOKUP in Excel: Every Argument, With Worked Examples

10 min read

To use XLOOKUP, type =XLOOKUP(what to find, where to look, what to return): for example =XLOOKUP(H2,A2:A11,D2:D11) finds the SKU in H2 in column A and returns its price from column D. It matches exactly unless you tell it otherwise, returns #N/A when nothing matches (or your own message, if you add a fourth argument), and works in Microsoft 365, Excel 2021 and Excel 2024, but not in Excel 2016 or 2019.

That covers most days. The other three arguments are where XLOOKUP earns its place: discount tiers, partial names, the latest price in a log, several columns from one formula. This guide walks through each one on a single example business, Harlow Hardware, a fictional hardware store with ten products, a discount table, a supplier cost log and one contractor order. Every formula below is in the workbook, with a Practice sheet to try it and a Solution sheet to check yourself.

Download the practice workbook (.xlsx)

The XLOOKUP formula in one picture

Harlow's product list sits in A1:E11: SKU, item, category, unit price and stock on hand. The counter staff type a SKU in H2 and want the price in I2.

XLOOKUP anatomy on Harlow Hardware's product list: =XLOOKUP(H2,A2:A11,D2:D11) finds HH-1003 in the SKU column A and returns $89.00 from the Unit price column D
Three arguments: what to find (H2), where to look (A2:A11) and what to bring back (D2:D11).

Read the formula left to right as a sentence: "find H2 in A2:A11 and give me the matching item from D2:D11." With HH-1003 in H2, XLOOKUP walks down column A, stops at row 4, and returns the value from row 4 of column D: $89.00, the cordless drill.

Two rules make this work. First, the lookup range and the return range must be the same height. Column A runs from row 2 to row 11, so the return range must too; if one is A2:A11 and the other D2:D10, Excel returns #VALUE! (Exceljet's reference covers this and other edge cases). Second, the return range can be anywhere. It can sit to the left of the lookup column, on another sheet, or be several columns wide. That's the big change from VLOOKUP, which counts columns to the right of the first one. The full side-by-side is in our XLOOKUP vs VLOOKUP comparison.

Want a SKU from an item name instead? Swap the ranges: =XLOOKUP("Paint roller kit",B2:B11,A2:A11) returns HH-1007, even though the SKU column is to the left.

Every XLOOKUP argument, and when you need it

Here is the full syntax from Microsoft's XLOOKUP reference, with the defaults Excel uses when you leave an argument out:

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

ArgumentWhat it doesDefaultUse it when
lookup_valueThe value to findRequiredAlways. Usually a cell reference
lookup_arrayThe single row or column to searchRequiredAlways
return_arrayThe range to return from, same height (or width) as lookup_arrayRequiredAlways. Make it wider to return several columns
if_not_foundWhat to show when there's no match#N/AA friendly message, a 0 or a blank
match_mode0 exact, -1 exact or next smaller, 1 exact or next larger, 2 wildcard0Tiers, bands, partial names
search_mode1 first to last, -1 last to first, 2 or -2 binary search on sorted data1The latest entry in a log

To skip an optional argument, leave a gap between the commas. =XLOOKUP(H6,A15:A18,B15:B18,,-1) leaves if_not_found empty and sets match_mode to -1.

if_not_found: say what went wrong

If someone types HH-1050, which doesn't exist, the plain formula returns #N/A. Add a fourth argument and it returns your text instead: =XLOOKUP(H3,A2:A11,D2:D11,"Check SKU"). Use words that tell the reader what to do. "Check SKU" is better than "Error", and much better than a 0, which can quietly flow into a total as if the item were free.

match_mode: what happens between the values

Harlow gives contractors a discount by order size: 5% from $250, 8% from $500 and 10% from $1,000. The tiers sit in A15:B18, listed by their lower edge (0, 250, 500, 1,000). A contractor's order comes to $609.49. There's no row for exactly 609.49, so the exact-match default returns #N/A. match_mode tells XLOOKUP which way to go instead.

Number line of Harlow Hardware discount tiers at $0, $250, $500 and $1,000; an order of $609.49 gets 8% with match_mode -1, 10% with match_mode 1 and #N/A with the default 0
Tiers listed by their starting value need -1. The wrong direction gives away 2 points of margin.
  • -1 (exact or next smaller): =XLOOKUP(H6,A15:A18,B15:B18,,-1) returns 8%, because 500 is the largest tier at or below 609.49. That's correct.
  • 1 (exact or next larger): the same formula with ,,1) returns 10%, from the 1,000 tier. That's wrong here; 1 is for tables listed by their upper limit, such as "up to 5 kg".
  • 2 (wildcard): turns on * (any characters), ? (one character) and ~ (treat the next character literally). =XLOOKUP("*"&H8&"*",B2:B11,D2:D11,"No match",2) with "gloves" in H8 returns $9.99 for "Work gloves L". Without the 2, the asterisks are treated as text and you get #N/A. Microsoft's wildcard guide lists the three characters.

Unlike VLOOKUP's approximate match, XLOOKUP's -1 and 1 don't need the tier table sorted. Keep it sorted anyway, so a person can read it.

Newer option: Microsoft 365 has added a fourth match_mode, 3, which matches a regular expression (a text pattern such as "starts with HH- then four digits"). Microsoft announced it on its Insider blog; the main XLOOKUP reference page still lists only 0 to 2, and Excel 2021 and 2024 don't have it. Don't use it in a file people open in other versions.

search_mode: which match wins

XLOOKUP returns the first match it finds. That's fine for a product list where each SKU appears once. It's a problem in a log, where the same SKU appears every time a supplier invoice comes in. Harlow's cost history in A21:C29 has three rows for the exterior paint, HH-1006, in date order.

Harlow Hardware supplier cost log with three HH-1006 rows: the default search returns the July cost of $21.10, search_mode -1 returns the latest, $22.40 from September
Same SKU, same log: the search direction decides whether you get the oldest or the newest cost.

=XLOOKUP(H10,B22:B29,C22:C29) returns $21.10, the July cost, because it reads from the top. =XLOOKUP(H9,B22:B29,C22:C29,,0,-1) reads from the bottom and returns $22.40, the September cost. If you price from the latest cost, the first version understates it by $1.30 a gallon. Reverse search only gives "latest" if the log is in date order, oldest at the top, which is how most exports arrive.

The binary modes, 2 and -2, are for very large lists sorted ascending or descending. They're faster, but Microsoft warns that unsorted data gives invalid results, with no error to tell you. For a list of a few thousand rows, leave search_mode at 1 or -1.

Return several columns with one XLOOKUP

Make the return range wider and XLOOKUP returns the whole slice of the row. =XLOOKUP(H5,A2:A11,B2:E11) in I5, with HH-1006 in H5, fills I5:L5 with the item, category, price and stock: Exterior paint 1 gal, Paint, $34.95, 18.

One XLOOKUP returning B2:E11 for HH-1006 spills Exterior paint 1 gal, Paint, $34.95 and 18 across I5:L5; when J5 already holds a note, the formula shows #SPILL!
The result spills into the cells to the right. Anything already in those cells blocks it.

Excel calls this spilling. It needs the cells the answer will fill to be empty; if J5 holds a note, I5 shows #SPILL!. Select the error cell and Excel outlines the range it wanted, and its #SPILL! guide shows how to jump to the cell in the way. You only type the formula in I5; the other cells show the spilled values and can't be edited on their own. Microsoft's page on dynamic arrays and spilling covers the rules.

Worked example: pricing a contractor order

Here's how the pieces fit on a real task. A contractor's order lands as five SKUs and quantities in A33:B37. Harlow needs a price per line, a subtotal and the discount.

In C33, look up the unit price with the ranges locked by dollar signs, then copy it down to C37:

=XLOOKUP(A33,$A$2:$A$11,$D$2:$D$11)

=B33*C33 in D33 for the line total

Without the dollar signs, copying down shifts the ranges to A3:A12, then A4:A13, and the lookups start missing the top of the list. This is the most common reason a column of lookups works in the first row and fails lower down.

SKUItemQtyUnit priceLine total
HH-1003Cordless drill2$89.00$178.00
HH-1006Exterior paint 1 gal8$34.95$279.60
HH-1007Paint roller kit4$14.25$57.00
HH-1004Wood screws (100)6$7.49$44.94
HH-1010Work gloves L5$9.99$49.95
Subtotal$609.49
Discount8% tier−$48.76
Order total$560.73

The discount rate in C39 is =XLOOKUP(D38,$A$15:$A$18,$B$15:$B$18,,-1), the tier lookup from earlier pointed at the subtotal. Check the arithmetic: $609.49 × 8% = $48.76 after rounding, and $609.49 − $48.76 = $560.73. If the contractor adds another $390.51 of stock, the subtotal reaches $1,000 and the same formula moves them to 10% without anyone editing it.

XLOOKUP errors and how to fix each one

Most broken lookups come down to a handful of causes. Work down this table in order; the first two cover most cases.

What you seeLikely causeFix
#N/A for a value you can see in the listA hidden space: "HH-1004 " pasted from an export isn't "HH-1004"Wrap the value in TRIM: =XLOOKUP(TRIM(H11),A2:A11,D2:D11), or clean the column once
#N/A for numeric codesText vs number: 40112 typed as a number, stored as text in the list (or the reverse)Convert the column to numbers, or match the type in the formula: TEXT(H2,"0") or VALUE(H2)
#N/A for a partial nameWildcards without match_mode 2Add ,,2 or ,"No match",2 at the end
#N/A for an amount between tiersExact match on a banded tableUse match_mode -1 (tiers by lower edge) or 1 (by upper limit)
#VALUE!lookup_array and return_array are different sizesMake both cover the same rows, such as A2:A11 and D2:D11
#SPILL!Cells the result needs aren't emptyClear the cells to the right (or below)
#NAME?Typo in the function name, or a version without XLOOKUPCheck spelling; see versions below
A wrong value, no errorBinary search on unsorted data, wrong match_mode direction, ranges that moved when copied, or duplicates where you wanted the latestUse search_mode 1 or -1, check the tier direction, add $ signs, use -1 for logs

If you'd rather show a blank than an error on a printed report, use if_not_found with "". Avoid wrapping XLOOKUP in IFERROR: it also hides the #VALUE! and #SPILL! errors that point at a real problem.

Which Excel versions have XLOOKUP

XLOOKUP is in Excel for Microsoft 365 (Windows, Mac and the mobile apps), Excel 2021 and Excel 2024. Microsoft's reference says plainly that it is not available in Excel 2016 and Excel 2019, even though those versions can open a file that contains it. In those versions the formula can't calculate and shows #NAME?, Excel's error for a name it doesn't recognise; often you'll also see an _xlfn. prefix in front of the function name.

So before you send a workbook to a client, a bookkeeper or a supplier, ask what they open it in. If anyone is on Excel 2019 or older, use INDEX and MATCH for that file; our XLOOKUP vs INDEX MATCH guide covers the trade-offs and the formulas that work everywhere. Google Sheets has its own XLOOKUP with the same six arguments, so a file shared through Sheets will usually keep working.

One more variation comes up often: looking up on two or three conditions at once, such as style, size and colour. That needs a slightly different pattern, covered step by step in XLOOKUP with multiple criteria.

When the lookup is only step one

For Harlow, XLOOKUP is how a sales export, a price list and a supplier log get joined so someone can answer a question: which products sell at the thinnest margin, what's running low, what changed since last month. If you're rebuilding that join every month from a QuickBooks or Shopify export, the lookups are the part most likely to break, usually because a column moved or a code arrived with a trailing space.

Parity can do that step from the files themselves. Upload the exports (CSV or Excel), or connect QuickBooks Online or Shopify directly, and it builds a dashboard with the headline numbers, charts, what explains them, and a table of what needs attention, such as items below their reorder level. Every number is checked against queries on the full dataset before you see it, and you can export the result to Excel if you want to keep working on it. For the stock side specifically, our inventory dashboard guide shows what to put on the page.

Skip the monthly lookup rebuild

Upload your sales and stock exports and get a checked dashboard without stitching the files together with XLOOKUP first. Build a report from your data free

If you remember one thing, make it the three-part sentence: find this, in here, and bring back that. Everything else is a dial on top of it, and each dial is a small number at the end of the same XLOOKUP formula.

Want to see what Parity builds from your data?

Build a report