Skip to content

Fix Excel #CALC Error in REDUCE and VSTACK Dynamic Arrays

A user on the Microsoft Tech Community recently posted: “I am using a LET function with REDUCE and VSTACK to combine filtered data from multiple sheets. It works for small datasets, but as soon as I try to process more than 200 rows, Excel throws a #CALC! error. Is there a way to increase the stack limit?”

This is a common bottleneck in Excel 365. When you nest dynamic arrays (like using VSTACK inside the REDUCE accumulator), Excel consumes a portion of its “calculation stack” for every iteration. Once that stack is exhausted—usually around 1,000 simple iterations, but much fewer when handling large arrays—the formula collapses into a #CALC! error.

Method Best For Pros Cons
Optimized REDUCE Small to Medium data (< 500 rows) Quick to write; stay within one cell. Still prone to #CALC! if data grows.
MAKEARRAY Approach Large dynamic datasets Bypasses the recursive stack entirely. More complex logic required.
Power Query Very large or external data Highly stable; no memory limits. Not “instant” (requires manual refresh).

Tested on Microsoft 365 (Version 2408) as of late 2024.

Instead of building a result row-by-row (which causes the stack to grow), we pre-calculate the total size and use MAKEARRAY to “fill in the blanks.” This approach is significantly more stable for complex LET functions.

Inside your LET function, identify the total count of rows you expect in your final array.

MAKEARRAY asks for the number of rows and columns, then allows you to define a LAMBDA to fetch the data for every specific coordinate.

=LET(
source_data, A2:B500,
filter_criteria, "Active",
/* Calculate the count first to avoid recursive growth */
filtered_rows, FILTER(source_data, B2:B500 = filter_criteria),
total_rows, ROWS(filtered_rows),
total_cols, COLUMNS(filtered_rows),
/* Use MAKEARRAY to construct the output without stacking */
result, MAKEARRAY(total_rows, total_cols, LAMBDA(r, c, INDEX(filtered_rows, r, c))),
result
)

The #CALC! error occurs because REDUCE creates a “nested” structure. If you VSTACK a row onto an existing array 100 times, Excel is essentially keeping 100 versions of that array in its memory stack simultaneously.

MAKEARRAY (or using INDEX over a predefined range) is a “flat” calculation. Excel allocates the memory for the final grid size once and then populates the cells. This bypasses the recursion depth limit entirely.

  1. Empty Arrays: If your FILTER or source data returns no results, MAKEARRAY will receive a 0 or an error for the row count, resulting in a #VALUE! or #CALC! error. Always wrap your row count in an IFERROR or check: IF(total_rows=0, "No Results", MAKEARRAY(...)).
  2. Memory Exhaustion: While this fix solves the stack limit, you can still hit RAM limits if your array exceeds millions of cells. If Excel becomes sluggish, it is time to move the logic to Power Query.
  3. Volatile Functions: Avoid putting functions like INDIRECT or OFFSET inside the LAMBDA of your MAKEARRAY. This will cause the formula to recalculate every time you click any cell, leading to “Calculating…” freezes.

What if I need to combine data from different sheets? If the sheets have the same structure, use the “3D reference” syntax with VSTACK first: VSTACK(Sheet1:Sheet5!A2:B100). Use this as the source_data in the LET formula above. This is much more efficient than using REDUCE to loop through sheet names.

Can I automate this with VBA or Office Scripts? Yes, but it is usually unnecessary. Dynamic Array formulas are faster than VBA for UI-level updates. However, if you are hitting #CALC! errors even with the MAKEARRAY method, an Office Script (for Excel Web) or VBA (for Desktop) can be used to write the data to a static range, which clears the memory buffer.

Does this apply to the SCAN function as well? Yes. SCAN and REDUCE share the same underlying engine. If you are using SCAN to generate a running total of an array and it hits a #CALC! error, the same stack overflow is likely the culprit. For running totals, it is often better to use a math-based approach (like MMULT) if the dataset is large.