TL;DR —
OFFSETreturns a reference that starts at an anchor cell, walks a given number of rows down and columns right, and can optionally grab a block of a given height and width. Syntax:=OFFSET(reference, rows, cols, [height], [width]).=OFFSET(A1, 2, 1)is the cell two rows down and one column right of A1 (i.e. B3). Because it returns a reference, not a value, you can wrap it inSUM,AVERAGE, orCOUNTand it resizes on demand. Two cautions: it is volatile (recalculates on every edit), and for simply picking a cell by position, non-volatileINDEXdoes the same job without the performance cost. KeepOFFSETfor windows that genuinely move.
=SUM(OFFSET(A1, 0, 0, COUNTA(A:A), 1)) ' sum column A however tall it grows
=SUM(OFFSET(B2, COUNT(B:B)-3, 0, 3, 1)) ' sum the last 3 numbers in column B
Most people meet OFFSET as the engine behind a "dynamic range" — a named range
or chart source that auto-expands as rows are added. It's good at that, and at a
handful of moving-window problems nothing else expresses as neatly. But it's also
volatile and easy to over-reach with, and modern Excel has quietly made half of
its old use cases obsolete. This guide gives you the mental model, the traps, and
a clear line on when to switch to INDEX instead.
What you'll learn
- The mental model: start at an anchor, move, then optionally grab a block
- Why
OFFSETreturns a reference — and why that letsSUMwrap it - The volatility cost, and the
#REF!-off-the-edge trap - The classic dynamic named range — and why a Table or spill range now beats it
- The genuinely hard-to-replace niche: moving windows and rolling totals
- The judgment call:
OFFSETvs non-volatileINDEX
The mental model: start here, walk this far, grab this much
OFFSET has five arguments, but they tell one simple story. Start at the
anchor, take rows steps down and cols steps right to land on a new
cell, then — if you give height and width — expand from that landing cell
into a block of that size:
=OFFSET(A1, 2, 1) ' land on B3 (2 down, 1 right), one cell
=OFFSET(A1, 2, 1, 3, 2) ' a 3-row × 2-col block starting at B3 -> B3:C5
=OFFSET(A1, -1, 0) ' negative walks UP -> row above A1 (here, #REF!)
Positive numbers move down and right; negative numbers move up and left. Leave
height and width out and the result is the same size as the anchor (usually a
single cell). That's the entire function — a movable pointer that can also
stretch into a rectangle.
Why it returns a reference, not a value
This is the trait that makes OFFSET useful and confuses newcomers. OFFSET
doesn't hand back the contents of the block — it hands back the reference to
the block. On its own in a cell, =OFFSET(A1,2,1,3,2) will spill or show the top
value, but its real purpose is to be fed to another function:
=SUM(OFFSET(A1, 0, 0, 12, 1)) ' sum a 12-row block anchored at A1
=AVERAGE(OFFSET(A1, 0, 0, 12, 1)) ' average that same block
Because the block's height is an argument, you can make it a formula —
COUNTA(A:A), MATCH(...), a cell the user types into — and the range resizes
itself. That is the whole basis of every "dynamic range" built on OFFSET.
The classic dynamic range — and its modern replacement
For years, the standard way to make a chart or dropdown grow with your data was
an OFFSET named range:
' Name "SalesData" = OFFSET($A$1, 0, 0, COUNTA($A:$A), 1)
' auto-expands to however many rows column A currently has
It works. But on any current version of Excel it is the wrong default, for
two reasons. First, OFFSET is volatile — a workbook full of these recalcs
on every keystroke and starts to feel slow. Second, Excel now has non-volatile
tools that do the same thing more legibly:
- An Excel Table (
Ctrl+T) grows automatically; reference it asTable1[Sales]and every chart,SUMIFS, and dropdown pointed at it expands on its own — no formula, no volatility. - A spill range from a dynamic-array formula uses the
#operator: if=FILTER(...)spills from E2, thenE2#is the live range, always the right size.
The verdict: if you're reaching for an OFFSET dynamic named range in 2026,
reach for a Table or a spill reference instead. Keep OFFSET ranges only for
legacy workbooks you're maintaining, not new ones.
The trap: walking off the edge returns #REF!
OFFSET fails loudly when you send it somewhere that doesn't exist. Move above
row 1 or left of column A — or size a block that runs past the sheet's last row —
and you get #REF!:
=OFFSET(A1, -1, 0) ' #REF! — there's no row above A1
=OFFSET(A1, 0, 0, 0, 1) ' #REF! — a block can't have zero height
The subtle version bites in dynamic ranges: if COUNTA($A:$A) counts a stray
value far down the column, or counts zero on an empty column, the height
argument goes wrong and the whole range collapses or errors. Anchor at the true
top of your data and make sure the sizing formula can't return 0.
The niche OFFSET keeps: moving windows
Here is where OFFSET still earns its place — a window that slides, where
both the start and the size move together. Rolling totals and "last N rows" are
the signature cases:
' Rolling sum of the most recent 3 entries in column B
=SUM(OFFSET(B2, COUNT(B2:B1000)-3, 0, 3, 1))
' Value N rows below a matched header (a moving read point)
=OFFSET($A$1, MATCH("Total", $A:$A, 0)-1, 1)
That "anchor, then jump to a position a formula computes, then read a window
around it" motion is genuinely awkward to express any other way. Even here, a
date-based rolling total is often cleaner as SUMIFS
with a ">="&cutoff condition — but for a positional, row-count window, OFFSET
is still the tightest tool.
The judgment call: OFFSET vs INDEX
The one rule that will fix most OFFSET overuse: if you're using OFFSET to
index into a range — "give me the cell at this position" — switch to INDEX.
INDEX also returns a reference, does the same positional pick, and is not
volatile:
=OFFSET($A$1, n, 0) ' volatile way to get the (n+1)-th cell in column A
=INDEX($A:$A, n+1) ' same cell, non-volatile, Excel can trace it
- Pick a cell/row/column by position →
INDEX. Non-volatile, traceable, reads more clearly. This covers the large majority of what people useOFFSETfor. - Grow a range as data is added → a Table or a spill
#reference. - A genuinely moving window (rolling total, last N rows, read-around-a-match)
→
OFFSETis still the right call, kept deliberately and in small numbers.
The strong opinion: OFFSET is a specialist, not a staple. Every volatile
OFFSET you replace with INDEX, a Table, or a spill range makes the workbook
faster and easier for the next person to trace — and you lose nothing but the
recalculation lag.
How ExcelMaster helps
OFFSET formulas are where spreadsheets get slow and unreadable — nested
COUNTA, off-by-one heights, and volatility no one notices until the file
crawls. ExcelMaster reads the goal — a chart that grows with the data, a
rolling 3-month total, the value next to the row that says "Total" — and
writes it the modern way: a Table or spill range when you just need growth,
INDEX when you're indexing by position, and a tight OFFSET only when a moving
window truly calls for one. You get the dynamic behaviour without inheriting a
volatile formula to babysit.
Frequently asked questions
What does the OFFSET function do in Excel?
It returns a reference located a given number of rows and columns from a
starting anchor, optionally resized to a block: =OFFSET(A1, 2, 1) is the cell
two rows down and one column right of A1. Because it returns a reference, you
usually wrap it in SUM, AVERAGE, or COUNT.
Why is OFFSET considered volatile?
Excel can't predict which cells OFFSET will point to until it calculates, so it
re-evaluates on every recalculation, not just when its inputs change. A few
are harmless; thousands slow the workbook noticeably. That's the main reason to
prefer INDEX or a Table where you can.
OFFSET vs INDEX — which should I use?
For picking a cell by position, use INDEX — it returns a reference just like
OFFSET but is non-volatile and traceable. Keep OFFSET for genuinely
moving windows (rolling totals, "last N rows") where the start and size shift
together.
How do I make a dynamic range with OFFSET?
The classic pattern is =OFFSET($A$1, 0, 0, COUNTA($A:$A), 1) in a named range,
which grows as column A fills. On modern Excel, prefer an Excel Table or a
spill reference (A2#) instead — both auto-expand without volatility.
Why does my OFFSET return #REF!?
You've moved off the edge of the sheet (negative rows above row 1, past the last
column) or given a block a height or width of 0. In dynamic ranges, this usually
means the height formula (like COUNTA) returned 0 or an unexpected count. Check
the anchor and the sizing arguments.
Tested in
Tested in: Excel 365 (Windows 11) — last verified 2026-07-01.
Related guides: Excel INDIRECT · Excel ADDRESS · Excel SUMIFS · Excel FILTER · Excel XLOOKUP
