Lookup and reference functions
HLOOKUP
Matches all 30 recorded answers
Recorded: 30 workbook cells. How we measure this · See the Rust code
Local names in 40 languages
| Language | Name in Excel |
|---|---|
| Arabic | HLOOKUP |
| Bulgarian | HLOOKUP |
| Czech | VVYHLEDAT |
| Danish | VOPSLAG |
| German | WVERWEIS |
| Greek | HLOOKUP |
| English (Australia) | HLOOKUP |
| English (United Kingdom) | HLOOKUP |
| English (United States) | HLOOKUP |
| Spanish | BUSCARH |
| Estonian | HLOOKUP |
| Finnish | VHAKU |
| French | RECHERCHEH |
| Hebrew | HLOOKUP |
| Croatian | HLOOKUP |
| Hungarian | VKERES |
| Indonesian | HLOOKUP |
| Italian | CERCA.ORIZZ |
| Japanese | HLOOKUP |
| Korean | HLOOKUP |
| Lithuanian | HLOOKUP |
| Latvian | HLOOKUP |
| Norwegian | FINN.KOLONNE |
| Dutch | HORIZ.ZOEKEN |
| Polish | WYSZUKAJ.POZIOMO |
| Portuguese (Brazil) | PROCH |
| Portuguese (Portugal) | PROCH |
| Romanian | HLOOKUP |
| Russian | ГПР |
| Slovak | HLOOKUP |
| Slovenian | HLOOKUP |
| Serbian (Latin) | HLOOKUP |
| Swedish | LETAKOLUMN |
| Thai | HLOOKUP |
| Turkish | YATAYARA işlevi |
| Ukrainian | HLOOKUP |
| Vietnamese | HLOOKUP |
| Chinese (Simplified) | HLOOKUP |
| Chinese (Hong Kong) | HLOOKUP |
| Chinese (Traditional) | HLOOKUP |
Names from Microsoft's support site.
What it does
HLOOKUP(lookup_value, table_array, row_index_num, [range_lookup])
HLOOKUP(lookup_value, table_array, row_index_num, [range_lookup]) searches the top row of
table_array for lookup_value, and returns the value in the same column from the row given by
row_index_num, counting the top row as row 1.
"Searches" means one of two genuinely different algorithms, chosen by range_lookup:
Exact match (range_lookup = FALSE). A linear scan of the top row for a value equal to
lookup_value; the first match wins. Microsoft documents that in this mode wildcards are
honoured in a text lookup_value: ? matches any single character, * any run of characters,
and ~ escapes a literal ? or *. If nothing matches, the result is #N/A.
Approximate match (range_lookup = TRUE, or omitted). The top row is assumed sorted in
ascending order, and the function finds the largest value that is less than or equal to
lookup_value. This is a range lookup in the literal sense — it is how tax bands, grade
boundaries and shipping tiers are expressed. If lookup_value is smaller than every value in
the top row, the result is #N/A.
The assumption in the second mode is not checked, and this is the function's defining hazard. Microsoft documents that the values must be sorted ascending; on unsorted data the function does not error, it simply returns something. What it returns depends on the search strategy the implementation uses, which is why "approximate match on unsorted data" is a bug that survives review — the answer looks like an answer.
Arguments
| Argument | Meaning |
|---|---|
lookup_value | The value sought in the top row. May be a value, a reference, or text — and, on the exact-match lane, wildcard text. |
table_array | The table to search. The top row is the search axis; the returned value comes from a row of the same block. |
row_index_num | Which row of table_array supplies the result, counting the top row as 1. |
range_lookup | Logical. TRUE or omitted selects approximate match; FALSE selects exact match. |
The two positions that are routinely misunderstood:
Try it
Quirks
Result and edge cases
Return kind: whatever the located cell holds — number, text, logical, error, or a blank normalized under the publication rules in the value universe.
Edge cases specific to this function:
- Duplicate keys. On the exact lane the first match wins. On the approximate lane, which of several equal keys is found depends on the search strategy, and the Handbook has not established Excel's choice.
- Mixed types in the search row. Excel's ordering across numbers, text and logicals is a total order, but where the type boundaries fall governs what "largest value less than or equal" means on a mixed row. Not established here.
- Text comparison is case-insensitive in Excel's usual convention, and the collation used for the approximate lane's ordering may be locale-dependent. Not established here.
- Empty cells in the search row — skipped, matched by an empty lookup value, or treated as a zero — is a real question for approximate match over a partially filled table.
Errors
Microsoft's page documents the error surface:
| Condition | Result |
|---|---|
| No match found (either lane) | #N/A |
lookup_value smaller than every value in the top row, approximate lane | #N/A |
row_index_num less than 1 | #VALUE! |
row_index_num greater than the number of rows in table_array | #REF! |
The #VALUE! / #REF! split on row_index_num is worth keeping straight: too small is a bad
argument, too large is a bad reference. That asymmetry is inherited from the C-API era and is
shared with VLOOKUP.
An error value in lookup_value propagates under the universal rule in
coercion and lifting. An error value sitting in the
located cell is simply the result — it is a value like any other.
How to implement
Notes for implementers
- The two lanes are two algorithms and must be tested as two functions. Exact match is a linear scan with wildcard support; approximate match is an ordered search. Sharing one code path between them is where wildcard characters start leaking into the sorted lane, or where the sorted lane's early exit silently truncates an exact scan.
- Do not validate sortedness. Excel does not, and an implementation that errors on unsorted input will reject workbooks that Excel computes. The obligation is to match the observable answer, including on unsorted data — which means the search strategy itself is observable and cannot be freely chosen.
- Wildcard escaping.
~before?or*makes the character literal. A naive glob-to-regex translation that does not honour~will match the wrong cells and never error. - Selective dereference. The reference-aware preparation exists so that a lookup over a
large
table_arrayneed not materialize it. The shared model records this as function-local and not generalized, so an implementation should treat it as a permitted optimization within this function rather than as a pipeline guarantee.
Rust code
Show the CalcFunc source of this function
Quoted from the public repository DnaCalc/DnaCalc, crates calc-func and calc-fml, at commit 9e1884369a67. Comments are the source's own. A kernel shared with other functions appears once, on its module page.
HLOOKUP · 12 lines · calc-func/src/catalogue/lookup.rs on GitHubeager(
HLOOKUP,
"HLOOKUP",
CallableArityShape::range(3, 4),
&[
Parameter::value("lookup_value"),
Parameter::value_or_reference("table_array"),
Parameter::value("row_index_num"),
Parameter::value("range_lookup"),
],
hlookup,
)
hlookup · 7 lines · calc-func/src/catalogue/lookup.rs on GitHubfn hlookup(
arguments: &[CalcValue],
services: &mut EvalServices<'_>,
) -> Result<CalcValue, FunctionFault> {
let site = Site::new(HLOOKUP, services);
Site::finish(table_lookup(&site, arguments, services, false))
}
Kernels shared with other functions
textscatalogue/comparisoncomparecatalogue/comparison/collationweighedcatalogue/comparison/collationmeasured_iteration_extensioncatalogue/comparison/collationtablecatalogue/comparison/sort_keydecode64catalogue/comparison/sort_keyReader::bytecatalogue/comparison/sort_keyReader::varintcatalogue/comparison/sort_keyReader::donecatalogue/comparison/sort_keyin_rangescatalogue/comparison/sort_keybuildcatalogue/comparison/sort_keyhan_basecatalogue/comparison/sort_keyderivecatalogue/comparison/sort_keyshared_jamo_tailscatalogue/comparison/sort_keyordinary_jamo_prefixcatalogue/comparison/sort_keyindependent_jamo_suffixcatalogue/comparison/sort_keyjamo_leading_primarycatalogue/comparison/sort_keyleading_ordercatalogue/comparison/sort_keyBefore::separate_specialcatalogue/comparison/sort_keyGathered::kanacatalogue/comparison/sort_keyGathered::unitcatalogue/comparison/sort_keypartscatalogue/comparison/sort_keydiacritic_ordercatalogue/comparison/sort_keydiacriticscatalogue/comparison/sort_keyeagercatalogue/lookupItem::rankcatalogue/lookupitemcatalogue/lookuplookup_keycatalogue/lookuptext_limitcatalogue/lookupequalcatalogue/lookuperror_rankcatalogue/lookupordercatalogue/lookuppatterncatalogue/lookupmatchescatalogue/lookuphitscatalogue/lookupLine::lencatalogue/lookupLine::scancatalogue/lookupLine::heldcatalogue/lookupreadercatalogue/lookupcell_valuecatalogue/lookuprowscatalogue/lookupcolumnscatalogue/lookuprow_linecatalogue/lookupcolumn_linecatalogue/lookuplinecatalogue/lookupvaluecatalogue/lookupspancatalogue/lookupshapecatalogue/lookupfirst_hitcatalogue/lookupbisectcatalogue/lookupindex_numbercatalogue/lookuptable_lookupcatalogue/lookupindexcatalogue/lookupselectorcatalogue/lookupindexedcatalogue/lookupselectcatalogue/lookuprowcatalogue/lookupcolumncatalogue/lookupposition_ofcatalogue/lookupareascatalogue/lookup
Argument and result plumbing
Parameter::valuecatalogueParameter::value_or_referencecataloguelogicalcoerceoperandcoerce
No implementation has been published with a Handbook test suite for this function.
Version differences
No comparison between specific Excel builds is recorded here yet. This does not establish that all builds behave alike.
Alternatives
Relationships
XLOOKUPis the modern replacement for both. It searches in either direction, defaults to exact match, takes an explicit not-found argument instead of#N/A, and separates the search array from the return array sorow_index_numdisappears entirely. New code should use it; Microsoft retainsHLOOKUPfor workbook compatibility.INDEX+MATCHis the classic decomposition:MATCHfinds the position,INDEXretrieves it. It removes the index-counting fragility and lets the search row sit anywhere in the table rather than being forced to the top.LOOKUP's array form does something similar and is documented by Microsoft as provided chiefly for compatibility with other spreadsheet programs;HLOOKUPis the better-specified choice.MATCHalone carries the same three-way match-type argument and the same sorted-data requirement for its approximate modes, so the hazard described above is shared.
Named variants
No named variants are recorded yet.
Suggest a correction or contribute an implementation · For agents