EXPAND(array, rows, [columns], [pad_with]) returns an array of the requested dimensions whose
top-left region is array and whose remaining cells are all pad_with.
The operation is one-directional: it grows, it never shrinks. The original elements keep their
positions relative to the top-left corner, and every new cell — to the right, below, and in the
bottom-right corner block — receives the same pad value. Microsoft documents the default
pad_with as #N/A, which is a deliberate choice rather than a convenience: #N/A is the
value model's "not available" marker, so an unpadded EXPAND produces a result whose synthetic
cells announce themselves rather than masquerading as zeros or blanks.
EXPAND is the growing complement of TAKE/DROP and the shape-fixing tool for the whole
dynamic-array family: when two arrays must be conformable — for HSTACK alignment, for an
elementwise operation, for a fixed-size output block — EXPAND is how you make them so
explicitly instead of relying on broadcasting.
Arguments
Argument
Meaning
array
The array or range to pad. Required.
rows
The number of rows the result should have. Required.
columns
The number of columns the result should have. Optional; omitted keeps the array's current column count.
pad_with
The value to fill new cells with. Optional; Microsoft documents the default as #N/A.
Two positions are commonly misread.
rows and columns are target dimensions, not increments.EXPAND(a, 3) means "make it
three rows tall", not "add three rows". This is the opposite convention from DROP and TAKE,
whose counts are increments, and the inconsistency is the most reliable source of error when
the two are used in the same formula.
Omitting columns is not the same as passing the current width in one respect: it is
shorter and it tracks a changing input, but the documented effect is the same — the column axis
is left as it is. Passing an explicit width smaller than the current width is an error, not a
truncation.
Try it
Quirks
Result and edge cases
Return kind: Array, of exactly the requested dimensions. The result spills; spilling is
host-side adaptation (the call pipeline).
rows or columns equal to the current extent is a no-op on that axis.
pad_with may be any scalar: a number, text, a logical, or an error value. Passing ""
is the common way to get visually blank padding, and it produces empty text, not the Empty
kind — the value universe keeps those distinct, and
downstream ISBLANK will disagree with your eyes.
Whether pad_with may be an array is not established here. If it can, the padding
semantics are no longer "one value everywhere".
Element errors inside an array in array pass through unchanged; nothing collapses
(error_collapse_profile: None). An error written directly, or held in a single referenced
cell, is the answer for the whole call: EXPAND(Data!C1,2,2,"pad") with #N/A in Data!C1 is
#N/A (FN-HSTACK-001).
Errors
Microsoft's page documents that EXPAND returns #VALUE! when rows or columns is smaller
than the array's current row or column count. That is the characteristic error of this function
and it follows from its one-directional design: there is no shrinking mode to fall back on.
The documented default pad_with of #N/A means an ordinary successful EXPAND routinely
contains error values without being an error. That distinction matters downstream: an
aggregate scanning the padded result will meet #N/A and, under the propagation rule in
coercion and lifting, surface it. Supplying an explicit
pad_with — 0, "" — is usually what a formula that feeds an aggregate actually wants.
An error value supplied as rows or columns propagates by the same universal rule.
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!.
Formula
Excel
Mathematical 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-ZAInputs 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-ZAInputs 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-ZAInputs 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-ZAInputs 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-ZAInputs 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-ZAInputs 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-ZAInputs 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-ZAInputs 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-ZAInputs 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-ZAInputs and reference value
The pad region is an L, not a rectangle. Growing both axes creates three new regions
(right, below, bottom-right). Implementations that fill row-major over the whole output and
copy the original in afterwards get this right by construction; implementations that fill
"the new rows" and "the new columns" separately double-fill or miss the corner.
Validate before allocating. The documented #VALUE! condition — a target smaller than the
current extent — must be checked before any output buffer is sized, or a shrink request
becomes a truncation bug.
pad_with must be copied as a value of any kind, including error values, without
coercion. An implementation that types the fill as a number cannot express the documented
default.
Large targets are a resource question.EXPAND is the easiest function in the family to
ask for an enormous result from, since the size is an argument rather than derived from the
input. Whatever ceiling the host imposes is the host's, not this function's, and the Handbook
has not established what Excel does at that ceiling.
The module is shared with the rest of the dynamic-array reshapers.
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.
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
=EXPAND(Data!C1,2,2,"pad") returned #N/A. Inputs were supplied through cells using Value2. These are controls from this environment, not a same-input comparison with another build.
Observed formulas and results
=EXPAND(Data!C1,2,2,"pad") → #N/A(cell-value2)
Alternatives
Relationships
TAKE and DROP shrink where EXPAND grows, but note the argument-convention difference
described above: their counts are increments, EXPAND's are targets.
HSTACK and VSTACK pad implicitly with #N/A when the pieces do not conform. EXPAND
makes that padding explicit and lets you choose the fill value — which is the usual reason to
reach for it before stacking.
IFERROR is the standard partner when the #N/A default is not wanted after the fact;
supplying pad_with is the cheaper alternative.
SEQUENCE builds an array of a target shape from nothing; EXPAND reshapes one you have.
MAKEARRAY and the LAMBDA helpers construct padded results generatively, which is the
route to take when the pad value depends on position rather than being constant.