Lookup and reference functions

HSTACK

Known larger differences on 5 of 28 recorded answers

Of 28 recorded answers (28 workbook cells), 5 do not match: 5 differ in kind or value. How we measure this · See the Rust code

Local names in 40 languages
LanguageName in Excel
ArabicHSTACK
BulgarianHSTACK
CzechSROVNAT.VODOROVNĚ
DanishVSTAK
GermanHSTACK
GreekHSTACK
English (Australia)HSTACK
English (United Kingdom)HSTACK
English (United States)HSTACK
SpanishAPILARH
EstonianHSTACK
FinnishHPINO
FrenchASSEMB.H
HebrewHSTACK
CroatianHSTACK
HungarianVÍZSZ.HALMOZÁS
IndonesianHSTACK
ItalianHSTACK
JapaneseHSTACK
KoreanHSTACK
LithuanianHSTACK
LatvianHSTACK
NorwegianHSTACK
DutchHOR.STAPELEN
PolishSTOS.POZ
Portuguese (Brazil)HSTACK
Portuguese (Portugal)JUNTARH
RomanianHSTACK
RussianГСТОЛБИК
SlovakHSTACK
SlovenianHSTACK
Serbian (Latin)HSTACK
SwedishHSTACK
ThaiHSTACK
TurkishYATAYYIĞ
UkrainianHSTACK
VietnameseHSTACK
Chinese (Simplified)HSTACK
Chinese (Hong Kong)HSTACK
Chinese (Traditional)HSTACK

Names from Microsoft's support site.

What it does

HSTACK(array1, [array2], ...)

HSTACK(array1, [array2], …) places its arguments side by side, left to right in the order given, and returns the combined array.

The result's width is the sum of the arguments' widths. Its height is the height of the tallest argument — and every argument shorter than that is padded at the bottom. Microsoft documents the pad value as #N/A, which is the same convention VSTACK uses and the same default EXPAND uses: synthesized cells announce themselves rather than passing as zeros.

That padding rule is what makes HSTACK a stacking operation rather than a join. It does not align rows by any key; it aligns them by position, starting at row 1. Two lists of different lengths stacked horizontally give you a two-column array whose shorter column trails off into #N/A, which is correct and is very often not what the author meant.

Arguments

ArgumentMeaning
array1The first array or range. Required.
array2, …Further arrays, in left-to-right order. Optional, to the arity ceiling of 255 arguments.

Scalars are admissible: a scalar is a 1×1 array, so HSTACK(A1:A10, "total") produces a two-column result whose second column is one value and nine #N/As.

The misunderstanding to head off: HSTACK takes several arguments, not a multi-area reference. HSTACK((A1:A5,C1:C5)) passes one union-shaped argument, which is a different thing from HSTACK(A1:A5, C1:C5). What the union form does is not established here.

Try it

Input cells (optional)

Example: {"B2": 3, "B3": 4}. A1 holds the formula. Other cells need values before a formula can read them.

Enter a formula, then calculate.

Runs locally in your browser with OneCalc. Its answer may differ from Excel. Use English function names and commas between arguments.

Quirks

Result and edge cases

Return kind: Array, spilled. Spilling is host-side adaptation (the call pipeline).

  • References are resolved first (ValuesOnlyPreAdapter), so the result carries values, not reference structure. HSTACK cannot be used where a reference is required.
  • A single argument returns that argument as an array — the identity case, and a useful way to force a reference into array form.
  • Element kinds are preserved: no coercion is applied to the stacked elements, and errors inside the inputs pass through as values (error_collapse_profile: None).
  • Ragged inputs are the normal case, not an error. Padding is the documented behaviour; there is no strict mode.
  • Whether a whole-column reference is admissible as an argument, and what height it contributes, is not established here — it is the input most likely to interact badly with the "height of the tallest argument" rule.

Errors

Microsoft's page for HSTACK documents #N/A as the pad value, which is a value in the result rather than a failure of the call. The page does not publish a general error table. #VALUE! for an inadmissible argument is the family's conventional code and is recorded here as expected, not verified.

An error value supplied as an argument propagates under the universal rule in coercion and lifting — as distinct from an error sitting inside an argument array, which is stacked like any other value.

A result exceeding the grid's dimensions is a host limit rather than a function semantic; what Excel returns at that limit is not established here.

A direct error stops these array functions; the same error in an array or cell is an element

An error written directly as an argument of these functions is the answer for the whole call. It is not placed in the result: HSTACK(1,#VALUE!) is #VALUE!, not a row holding 1 and an error, and TAKE(#N/A,0) is #N/A. With MAP the LAMBDA does not run at all: MAP(NA(),LAMBDA(xx,IFERROR(xx,3))) is #N/A. The same error inside an array, or in a referenced cell, is an ordinary element: MAP({#N/A},LAMBDA(xx,3)) is 3, and HSTACK(Data!C1,{1;2}) with #N/A in Data!C1 is a 2 by 2 array with #N/A in its first column. TOCOL and TOROW show the difference with ignore 2: TOCOL(#N/A,2) is #N/A, while TOCOL({#N/A},2) drops the error, has nothing left, and is #CALC!. EXPAND is an exception on the cell side: EXPAND(Data!C1,2,2,"pad") is #N/A for the whole call. BYROW and BYCOL check the direct error first too: BYROW(#N/A,#VALUE!) is #N/A, while BYROW({#N/A},2), where 2 is not a LAMBDA, is #VALUE!.

FormulaExcelMathematical value
=HSTACK(1,#VALUE!)
Excel 16.0.20527.20088 Current Channel, Windows 64-bit (NT 10.0.26200), x86-64, AMD Ryzen 7 4800H, en-ZA
Inputs and reference value

Typed formula.

#VALUE!—
=TAKE(#N/A,0)
Excel 16.0.20527.20088 Current Channel, Windows 64-bit (NT 10.0.26200), x86-64, AMD Ryzen 7 4800H, en-ZA
Inputs and reference value

Typed formula.

#N/A—
=MAP(NA(),LAMBDA(xx,IFERROR(xx,3)))
Excel 16.0.20527.20088 Current Channel, Windows 64-bit (NT 10.0.26200), x86-64, AMD Ryzen 7 4800H, en-ZA
Inputs and reference value

Typed formula.

#N/A—
=MAP({#N/A},LAMBDA(xx,3))
Excel 16.0.20527.20088 Current Channel, Windows 64-bit (NT 10.0.26200), x86-64, AMD Ryzen 7 4800H, en-ZA
Inputs and reference value

Typed formula.

3
0x4008000000000000
—
=HSTACK(Data!C1,{1;2})
Excel 16.0.20527.20088 Current Channel, Windows 64-bit (NT 10.0.26200), x86-64, AMD Ryzen 7 4800H, en-ZA
Inputs and reference value

Number supplied through a cell.

Data!C1: #N/A

{#N/A,1;#N/A,2}—
=TOCOL(#N/A,2)
Excel 16.0.20527.20088 Current Channel, Windows 64-bit (NT 10.0.26200), x86-64, AMD Ryzen 7 4800H, en-ZA
Inputs and reference value

Typed formula.

#N/A—
=TOCOL({#N/A},2)
Excel 16.0.20527.20088 Current Channel, Windows 64-bit (NT 10.0.26200), x86-64, AMD Ryzen 7 4800H, en-ZA
Inputs and reference value

Typed formula.

#CALC!—
=EXPAND(Data!C1,2,2,"pad")
Excel 16.0.20527.20088 Current Channel, Windows 64-bit (NT 10.0.26200), x86-64, AMD Ryzen 7 4800H, en-ZA
Inputs and reference value

Number supplied through a cell.

Data!C1: #N/A

#N/A—
=BYROW(#N/A,#VALUE!)
Excel 16.0.20527.20088 Current Channel, Windows 64-bit (NT 10.0.26200), x86-64, AMD Ryzen 7 4800H, en-ZA
Inputs and reference value

Typed formula.

#N/A—
=BYROW({#N/A},2)
Excel 16.0.20527.20088 Current Channel, Windows 64-bit (NT 10.0.26200), x86-64, AMD Ryzen 7 4800H, en-ZA
Inputs and reference value

Typed formula.

#VALUE!—

Inputs, build details and evidence

How to implement

Notes for implementers

  • The pad is per-argument, not per-result. Each argument is padded to the common height independently; there is no single rectangle being filled. Implementations that build the output row-major must know each source's height to decide where padding begins in that row.
  • Width is a sum and can overflow the grid. Validate against the host's column limit before allocating, and decide what the failure looks like — the Handbook has not established Excel's behaviour at the boundary.
  • Preserve element kinds exactly. Stacking is a copy, not a conversion; text, logicals and errors must arrive unchanged. This is the property that lets HSTACK build heterogeneous tables, and the easiest one to lose in an implementation that types its buffers numerically.
  • The identity case matters. HSTACK(x) with a single argument is a legitimate call — the arity minimum is 1 — and it is used deliberately to materialize a reference as an array. It must not be optimized into a pass-through that preserves reference-ness.
  • This function has its own module in the reference implementation rather than sharing the reshape family's, which is a code-organization fact, not a behavioural one.

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.

HSTACK · 12 lines · calc-func/src/catalogue/arrays.rs on GitHub
11 hstack_fn "HSTACK" (1, 254) [R "array1", R "array2"] |s, a, sv| {
    // Fn2: a direct error in any source precedes stacking; reference/array cells remain cells.
    for source in a { scalar_error(source)?; }
    // dc-h9u: a row of functions, as GROUPBY and PIVOTBY take them
    // (`GROUPBY(A2:A9,B2:B9,HSTACK(SUM,MAX))`, Excel 16.0.20527).
    if a.iter().all(|v| v.callable_value().is_some()) {
        return CalcArray::from_rows(vec![a.to_vec()])
            .map(CalcValue::array)
            .ok_or_else(|| s.not_modelled(None));
    }
    run(s, a, sv, k::eval_hstack_prepared)
}
eval_hstack_prepared · 20 lines · calc-func/src/ported/dynamic_array_reshape_family.rs on GitHub
/// HSTACK (hstack.rs): the arguments side by side, each padded with #N/A below to the tallest.
pub fn eval_hstack_prepared(args: &[CalcValue]) -> Result<CalcValue, DynamicArrayReshapeEvalError> {
    let sources: Vec<StackArgSource<'_>> = args.iter().map(StackArgSource::new).collect();
    let rows = sources.iter().map(|source| source.shape().rows).max().unwrap_or(1);
    let cols: usize = sources.iter().map(|source| source.shape().cols).sum();
    let mut cells = Vec::with_capacity(rows * cols);
    for row in 0..rows {
        for source in &sources {
            for col in 0..source.shape().cols {
                cells.push(
                    source
                        .get(row, col)
                        .cloned()
                        .unwrap_or(CalcValue::error(WorksheetErrorCode::NA)),
                );
            }
        }
    }
    build_array(rows, cols, cells)
}

Kernels shared with other functions

Argument and result plumbing

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.

Excel 16.0.20527.20088

Windows 64-bit (NT 10.0.26200), x86-64, AMD Ryzen 7 4800H, en-ZA

=HSTACK(1,#VALUE!) returned #VALUE!. =HSTACK(Data!C1,{1;2}) returned {#N/A,1;#N/A,2}. Inputs were supplied through cells using Value2, formula literals. These are controls from this environment, not a same-input comparison with another build.

Observed formulas and results
  • =HSTACK(1,#VALUE!) → #VALUE! (formula-literal)
  • =HSTACK(Data!C1,{1;2}) → {#N/A,1;#N/A,2} (cell-value2)

Alternatives

Relationships

  • VSTACK stacks vertically: widths are padded instead of heights, and the result's height is the sum. The pair is symmetric, and HSTACK(VSTACK(…), …) compositions are how dynamic-array formulas assemble tables.
  • EXPAND is how you control the padding rather than accept #N/A: expand each piece to the common height with your own pad value first, then stack.
  • CHOOSECOLS is the inverse in spirit — it takes columns out of one array where HSTACK puts columns from several together.
  • TOROW / TOCOL flatten rather than stack, and WRAPROWS / WRAPCOLS reshape a vector into a rectangle; all four answer the neighbouring question of "how do I get this data into that shape".
  • The & operator and TEXTJOIN concatenate values; HSTACK concatenates arrays. The word "concatenate" pulls readers toward the wrong one.
  • INDEX / OFFSET gymnastics were how workbooks assembled multi-source arrays before the stacking functions existed; HSTACK replaces most of that with a call whose intent is legible.

Named variants

No named variants are recorded yet.

Suggest a correction or contribute an implementation · For agents