Stop Using Do While Excel — Try This Instead

Excel has no DO WHILE function. But if you’re copying down formulas that depend on prior-row results — like running totals, cumulative flags, or inventory adjustments — you’re probably wrestling with circular references or bloated VBA.

The Problem

You’ve got a list of transactions in column A (dates), B (amounts), and C (running balance). You want cell C2 to start at $10,000, then C3 = C2 + B3, C4 = C3 + B4, and so on. Simple — until you try to write it as a single dynamic array formula. That’s where the 'Do While' fantasy crashes hard.

DateAmountBalance (Broken)
2024-02-01$1,200#REF! (C1+C2)
2024-02-03−$450#VALUE! (circular)
2024-02-05$2,100#SPILL! (array mismatch)
2024-02-07−$890#N/A (OFFSET not dynamic)
2024-02-10$3,400#CALC! (SCAN misused)

We’ve all done this: pasted C2 = 10000, then C3 = C2+B3, dragged down — only to find it breaks when new rows are inserted above row 2. Or worse: enabled iterative calculation (File > Options > Formulas > 'Enable iterative calculation') and watched Excel silently return wrong numbers after 100+ iterations. Trust me, I learned this the hard way debugging a payroll sheet where one employee’s bonus was off by $14,722 because Excel stopped calculating after 100 passes — and nobody noticed for three months.

The Solution

Use SCAN() with an initial value. It’s Excel’s closest functional equivalent to a 'Do While' loop — but without loops. It processes arrays left-to-right, carrying forward a result. No VBA. No iteration settings. Just clean, predictable math.

  1. In cell C2, type: =SCAN(10000,B2:B11,LAMBDA(a,b,a+b))
  2. Press Enter. Excel spills the full running balance down column C.
  3. To make it responsive to new rows, convert your data range to a table (Ctrl+T), then update the formula to =SCAN(10000,Table1[Amount],LAMBDA(a,b,a+b)).
  4. If your starting balance is in cell D1, reference it directly: =SCAN(D1,B2:B11,LAMBDA(a,b,a+b)).

This works because SCAN() doesn’t ‘loop’ — it recursively applies the LAMBDA to each element, using the prior output as the next input. Think of it as folding a list, not looping over it.

DateAmountBalance (Fixed)
2024-02-01$1,200$11,200
2024-02-03−$450$10,750
2024-02-05$2,100$12,850
2024-02-07−$890$11,960
2024-02-10$3,400$15,360
2024-02-12$0$15,360
2024-02-14−$1,950$13,410

Pro tip: If you need conditional logic — say, 'add amount only if date is after 2024-02-05' — wrap the second argument in a FILTER: =SCAN(10000,FILTER(B2:B11,A2:A11>"2024-02-05"),LAMBDA(a,b,a+b)). That’s safer than nesting IF inside SCAN, which can break spill behavior.

Going Further

You can simulate more complex 'Do While'-like logic using combinations:

  • Inventory roll-forward: Use REDUCE() to process batches where each step depends on both prior state AND external conditions (e.g., stock levels, reorder thresholds).
  • Flag first occurrence per group: =SCAN(0,Table1[Product],LAMBDA(a,b,IF(b=OFFSET(b,-1,0),a,a+1))) — though OFFSET is volatile; better use INDEX(Table1[Product],ROW()-ROW(Table1[#Headers])) for static referencing.
  • Dynamic text accumulation: =SCAN("",A2:A10,LAMBDA(a,b,IF(b="",a,a&", "&b))) builds comma-separated lists without CONCATENATE() drag-down hell.
  • For true iteration (e.g., Newton-Raphson root finding), use LET() with recursive naming — but limit depth to avoid #NUM! errors. Example: =LET(x,0.5,fx,LAMBDA(y,SIN(y)-y/2),next,LAMBDA(z,z-(fx(z))/(COS(z)-0.5)),next(next(next(x)))).

Surprising tip: SCAN() ignores blank cells *in the array being scanned* — but not blanks in the accumulator logic. So if column B has empty cells, use FILTER(B2:B11,B2:B11<>"") first. Otherwise, you’ll get repeated values.

When NOT to Use This

Don’t reach for SCAN when:

  • You need real-time, cell-by-cell recalculation (e.g., live sensor feeds updating every second) — Excel formulas aren’t event-driven.
  • Your dataset exceeds ~50,000 rows — SCAN performance degrades sharply beyond that, especially with nested LAMBDAs.
  • You’re supporting users on Excel 365 versions before Build 16.0.14326 — SCAN and REDUCE were added mid-2021 and aren’t in LTSC or older perpetual licenses.
  • The logic requires breaking out of iteration based on a condition (e.g., “stop when balance < $5,000”) — SCAN always processes the full array. For that, you’ll need VBA or Power Query.

Also: never combine SCAN with volatile functions like NOW(), RAND(), or INDIRECT() inside the LAMBDA — it forces full recalculation on every edit, even unrelated ones.

Keyboard Shortcuts

ActionShortcutNotes
Open Name ManagerCtrl + F3Useful for checking defined LAMBDA names
Toggle Formula ViewCtrl + `See all formulas at once — critical for debugging SCAN chains
Edit Active CellF2Essential when adjusting LAMBDA parameters inline
Evaluate Formula Step-by-StepAlt + M + VShows how SCAN accumulates — press Enter to advance each step
Lisa Anderson

Lisa Anderson

Lisa is a certified Microsoft trainer who writes step-by-step guides for Power Automate