Fix Excel LET and LAMBDA #VALUE! Errors with Spilled Arrays
A user in the Microsoft Tech Community recently posted a common frustration: “I have a spilled range in A2#. I’m trying to use MAP to iterate through it and a LET function to perform some logic. However, as soon as my LET function references the spilled range A2# or tries to return an array, the whole cell just gives me a #VALUE! error. Why can’t Excel handle this?”
This issue typically stems from one of two things: referencing the “parent” spilled range inside a loop that is already iterating over it, or the “Array of Arrays” limitation.
Minimal Working Example
Section titled “Minimal Working Example”Tested on: Microsoft 365 (Version 2408) and Excel for the Web.
The Broken Formula
Section titled “The Broken Formula”In this scenario, the user is trying to find the rank of each number in a spilled range.
=MAP(A2#, LAMBDA(x, LET(full_range, A2#, MATCH(x, SORT(full_range), 0))))Result: #VALUE!
The Fixed Formula
Section titled “The Fixed Formula”To fix this, you must ensure the LET function isn’t trying to re-evaluate the spilled range in a way that creates nested array dependencies, or more commonly, ensure the result of the LAMBDA is a single value (scalar).
=LET(full_range, A2#, MAP(full_range, LAMBDA(x, MATCH(x, SORT(full_range), 0))))Why It Works: The “Array of Arrays” Rule
Section titled “Why It Works: The “Array of Arrays” Rule”Excel’s calculation engine currently has a limitation: It cannot handle an array that contains other arrays.
When you use a helper function like MAP, SCAN, or BYROW, Excel expects the LAMBDA to return a single value for every iteration. If your LET block performs a calculation that results in even a small array (e.g., a 1x1 array), the formula will fail with a #VALUE! error.
| Component | Role in Formula | The #VALUE! Trap |
|---|---|---|
MAP |
Iterates through each item in a range. | Expects the inner function to return a scalar (single value). |
LAMBDA |
The “engine” defining the logic. | Cannot return an array to the MAP function. |
LET |
Defines variables for efficiency. | Referencing a spilled range (#) inside the loop can cause dimension conflicts. |
A2# |
The spilled array reference. | Best defined outside the MAP function to avoid recalculating the range for every row. |
How to Adapt This to Your Data
Section titled “How to Adapt This to Your Data”If you are seeing the #VALUE! error while using LET and LAMBDA, follow these steps to debug:
- Move Range Definitions Outside: Instead of putting
LET(rng, A2#, ...)inside theLAMBDA, wrap the entireMAPfunction inside theLET. This defines the range once and makes it available to the loop without re-triggering the dynamic array engine. - Force a Scalar Result: If your
LETcalculation returns an array but you only need one value, wrap your result inINDEX(result, 1)orSUM(result)to ensure it isn’t passing an array back to theMAPfunction. - Check for Implicit Intersection: If you reference
A2(without the#) inside aMAPiterating overA2#, Excel might get confused about which row it should look at. Always use the variable defined in yourLAMBDA(e.g., thexinLAMBDA(x, ...)).
Frequently Asked Questions
Section titled “Frequently Asked Questions”What if I actually need to return multiple columns?
If your goal is to have MAP return more than one column per row (which usually causes the #VALUE! error), MAP is the wrong tool. Instead, use the REDUCE function combined with VSTACK or HSTACK. This allows you to build a complex array piece by piece.
Can I use this with filtered data?
Yes. If A2# is the result of a FILTER function, the logic remains the same. However, ensure that your LET variables are referencing the spilled range name, not the hardcoded coordinates, to keep the formula dynamic.
Why does LET work fine on its own but fail inside MAP?
Inside a MAP or BYROW function, Excel enters a “row-by-row” context. LET functions inside that context are subject to stricter memory and dimensionality rules. By defining your variables at the very beginning of the formula (the outermost level), you avoid the overhead of re-declaring those arrays for every single iteration of the loop.