
You have probably written the same row summary formula down a whole column: SUM in F2, drag to F2000, wait for the recalc, then hide the column because it is just clutter. BYROW replaces that pattern. Hand it a range and a small LAMBDA, and it hands back one value per row — no helper column, no fill-down, no accidental gap when someone inserts a row halfway through. BYCOL does the same across the other axis. Both take a little getting used to, and both have a set of quiet gotchas worth knowing before you rewrite half a workbook around them.
What BYROW and BYCOL actually do
Give BYROW a two-dimensional range plus a LAMBDA that reduces one row to a single value. BYROW walks top to bottom, calls the LAMBDA once per row, and stacks the results into a single column. BYCOL does the mirror image: left to right, one call per column, results stacked into a single row. The LAMBDA‘s parameter is a name of your choice — row, r, col — and inside the function it is the current slice of the array.
A concrete example: monthly sales sit in B2:E5, one product per row, four months across. To get one row total in F2 that spills down through F5:
=BYROW(B2:E5, LAMBDA(row, SUM(row)))
The output is a 4×1 dynamic array. No fill-down, no reference drift when a row gets inserted at the top. The grid below shows what the sheet looks like end to end.
| A | B | C | D | E | F | |
|---|---|---|---|---|---|---|
| 1 | Product | Jan | Feb | Mar | Apr | Total |
| 2 | Widget | 120 | 150 | 90 | 200 | =BYROW(B2:E5, LAMBDA(row, SUM(row))) |
| 3 | Gadget | 80 | 110 | 140 | 160 | 490 |
| 4 | Sprocket | 200 | 170 | 210 | 180 | 760 |
| 5 | Frame | 60 | 70 | 85 | 95 | 310 |
Two things to know up front. The LAMBDA must return a single scalar. Return an array per row and Excel throws #CALC!, its shorthand for “this can’t nest cleanly.” Second, BYROW cannot see which row it is on. If you need the row’s position — say, to look up a matching header or offset back into the sheet — use a plain LAMBDA with MAP and pass a helper index array. BYROW gives you the row’s values but not its coordinates.
The helper-column pattern they replace
Almost every mature workbook has a “temp column” or two: a per-row calculation the author never quite deleted. Before dynamic arrays, that was the only reasonable way to summarize a row. BYROW collapses the entire column into one cell that spills. The migration is usually mechanical.
F2: =SUM(B2:E2)
...fill down F2:F2000
Breaks if someone deletes the fill range or inserts a row without extending the formula.
F2: =BYROW(B2:E2000, LAMBDA(r, SUM(r)))
One formula, spills the full length of the input range, resizes automatically.
The single-cell version has three quiet advantages. It cannot go out of sync with the data range, because there is nothing to keep in sync. A protected sheet only needs one cell unlocked instead of two thousand. And when you eventually pair the input range with a Table or a spilled source, the output grows and shrinks along with it — no VBA, no dynamic named range, no OFFSET.
The trade-off is discoverability. A helper column is visible; a spilled BYROW result is one formula pretending to be a column. Team members editing the sheet may not realize the cells below F2 are inhabited by a spill. Add a header comment, or wrap the output range with a light fill so it reads as computed rather than editable.
Common recipes with LAMBDA
The syntax rewards keeping the LAMBDA tiny. Most useful patterns are one line long — a single call to SUM, MAX, SUMPRODUCT, or TEXTJOIN. Here are four that cover the majority of daily use.
Row total, the “hello world” example. The row argument is the horizontal slice, and SUM reduces it to one number:
=BYROW(B2:E5, LAMBDA(row, SUM(row)))
Count how many months in each row cleared a 100-unit threshold. COUNTIF is one of the few “IF” functions that plays well with an array argument, because it accepts an array where it expects a range:
=BYROW(B2:E5, LAMBDA(row, SUMPRODUCT((row>=100)*1)))
The SUMPRODUCT((row>=100)*1) pattern is the safe substitute for COUNTIF when you want zero surprises. It works because multiplying the boolean array by 1 coerces to numbers before summing.
Weighted average per row, with the weight vector hard-coded. Useful for scorecards where the four inputs are not equally important:
=BYROW(B2:E5, LAMBDA(row, SUMPRODUCT(row * {0.1, 0.2, 0.3, 0.4})))
Column maximum with BYCOL. Same shape, different axis. This spills across as a single row above the data — a compact “column high” strip:
=BYCOL(B2:E5, LAMBDA(col, MAX(col)))
LET so the range only resolves once. The LET function lets you name the range and reuse it inside the LAMBDA, which reads better and skips a second evaluation of the same expression.
The IFS trap and other functions that break inside
The first time a BYROW returns #CALC! or #VALUE! with no obvious cause, the culprit is almost always a nested function that wants a real worksheet range instead of the in-memory array chunk BYROW passes it. The *IFS family — COUNTIFS, SUMIFS, AVERAGEIFS, MAXIFS, MINIFS — is the usual offender. Their criteria arguments are declared as ranges, and the array slice does not qualify.
Two error codes, two different meanings:
| Error | What Excel is saying | Usual cause |
|---|---|---|
| #CALC! | Your LAMBDA returned something other than a single value. | Returned an array per row, or forgot the LAMBDA entirely. |
| #VALUE! | The LAMBDA signature or its arguments do not match what Excel expected. | Wrong number of parameters, or a nested function refused the array slice. |
The fix for the IFS family is to rewrite the criterion as boolean math and wrap it in SUMPRODUCT or plain SUM. Instead of COUNTIFS(row, ">=100"), use SUMPRODUCT((row>=100)*1). Instead of SUMIFS(row, row, ">0"), use SUM(IF(row>0, row, 0)). Both work with the array chunk because they never look up the range dimensions the *IFS parser insists on.
INDEX is the other common trip point. Passing an array to its row_num or column_num argument returns #VALUE! inside BYROW even when the same expression works in a normal cell. If you need indexed access, use CHOOSECOLS or INDEX with scalar indices generated by SEQUENCE outside the LAMBDA, then reference the extracted values inside.
When BYROW is overkill
Not every row summary needs a LAMBDA. Three simpler tools usually get there first, and reaching for BYROW when one of them fits makes the formula slower and harder to read.
Fill-down is still the right answer for one-off exploration in a small range. If a table has thirty rows and it will not grow, a filled SUM in a helper column is faster to type and easier for a colleague to follow. BYROW pays off when the range is dynamic, when the target sheet must stay clean, or when the calculation would repeat in many cells and you want one source of truth.
SUMPRODUCT alone handles many row-wise problems without any wrapper. If every row needs the same weighted sum against a shared constant, MMULT or a single SUMPRODUCT against the whole range often returns the same result in one pass and runs faster than BYROW, which calls the LAMBDA once per row.
GROUPBY is the right choice when the “row” is actually a category and you want a grouped aggregate — one total per region across a long transaction list, not one total per literal row of a rectangular range.
- ✓ Range grows or shrinks over time (backing a Table, a spilled range, or a live import)
- ✓ Calculation involves a
LAMBDAor two-step logic that would be ugly to inline in every row - ✓ Sheet has to stay visually clean, with no helper columns hanging around
- ✓ You want the summary and the source range to resize together, no manual maintenance
Version availability and the Google Sheets equivalent
BYROW and BYCOL both ship in Microsoft 365 and Excel 2024. Older desktop builds — Excel 2019 and Excel 2021 — do not have them, and neither do the file formats those versions produce. A workbook that opens fine in your 365 install shows the formula as _xlfn.BYROW(...) and a #NAME? error when the recipient is on 2021. Microsoft lists the versions explicitly on the official BYROW reference; treat that as the source of truth before you commit a shared file to the pattern.
#NAME?.
Google Sheets covers the same territory with two other tools. MAP takes one or more ranges and a LAMBDA, which is the closer match. ARRAYFORMULA(SUM(...)) patterns handle simple row aggregates without any LAMBDA at all. Neither is a drop-in translation, so if a workbook needs to work in both engines, keep the summary logic explicit — a filled column with a plain SUM — rather than committing to BYROW on the Excel side and hoping the export survives.
A rewrite pass that pays off
Once BYROW clicks, the natural next step is to sweep the workbook for helper columns that exist only to hold a single formula filled down. Most of them collapse to one BYROW call. The refactor is safe: the output is still a range, still readable, still auditable — it just lives in one cell instead of two thousand. Start with the column that hurts most (usually the one the data-entry team keeps overwriting by accident), rewrite it, and see how the sheet feels lighter before touching the next one.
Two rules keep the rewrite from turning into a chore:
- ✓ Do not migrate a calculation that is genuinely faster as a filled formula on a small fixed range.
- ✓ Do not nest a
*IFSfunction inside aLAMBDAwithout checking that it accepts an array first; rewrite as boolean math if it does not. - ✓ Before shipping to a colleague on Excel 2021, confirm the file will actually recalculate on their machine — otherwise fall back to a filled formula.
A tighter workbook is one cleanup pass away.
