Available in:All versions (Works in Excel 2007, every later version, Microsoft 365 and Excel for the web)Examples need Excel 2021 or laterCategory:Lookup & reference

OFFSET

VERSCHUIVING in Dutch Excel

Returns a reference to the cell or block a set number of rows and columns from a start cell, optionally resized.

Difficulty rating 4 of 5. It builds a reference by counting rows and columns from a start cell, which is positional reasoning that is hard to audit, and it is volatile, so a workbook full of it slows down.

Last updated: 13 October 2026

See the worked examples

Sheet excerpt: F2 holds the formula
RowABCDEF
1AccountDescriptionBalanceLine no.Balance
211001100Bank€84,350.00€ 84.350,0044€645,200.00€ 645.200,00=OFFSET(C1, E2, 0)=OFFSET(C1; E2; 0)
313001300Trade receivables€212,480.00€ 212.480,00
416001600Trade payables-€156,920.00€ -156.920,00
540004000Personnel costs€645,200.00€ 645.200,00
645004500Housing costs€230,400.00€ 230.400,00
780008000Revenue-€1,482,600.00€ -1.482.600,00
Formula cell (F2)Input

Result: €645,200.00€ 645.200,00

=OFFSET(C1, E2, 0)
=OFFSET(C1; E2; 0)

What OFFSET does and when to use it

What it does: it starts at a cell, moves a number of rows and columns, and returns a reference to what it finds there, for example the balance of the trial balance line you pick by number.

When to use it: for ranges that move or grow, such as the last three months or a rolling four-week total. Inside SUM or AVERAGE it hands over a range whose position and size are calculated. It is volatile, so in large workbooks INDEX is often the lighter choice.

How Excel evaluates it

Excel works from the top-left cell of reference:

  • it moves rows down (or up when negative) and cols to the right (or left when negative)
  • it marks out a block height rows tall and width columns wide from the cell it lands on, defaulting to the size of reference
  • it returns a reference to that block, not a copy of the values, so the function around it works on the cells themselves

If any part of the block falls off the sheet, the result is #REF!.

Watch out: OFFSET is volatile, so Excel recalculates it after every change anywhere in the workbook. In large models INDEX is usually the better tool: INDEX(range, n):INDEX(range, m) builds the same moving range without being volatile.

Mental model

A picture frame you place on the grid: rows and cols say where to put its top-left corner relative to the anchor, height and width say how big the frame is, and the surrounding function reads whatever shows through it.

Terms used on this page: worksheet, reference, workbook, range, cell

OFFSET(reference, rows, cols, [height], [width])
OFFSET(reference; rows; cols; [height]; [width])
Arguments
ArgumentTypeMeaningDefault
referenceRequiredThe starting cell or range.
rowsRequiredHow many rows to move down; negative moves up.
colsRequiredHow many columns to move right; negative moves left.
heightOptionalThe number of rows in the result.height of reference
widthOptionalThe number of columns in the result.width of reference

Return value:A reference to a cell or range, which shows as the value of that cell or feeds another function

Formulas use commas (,) between arguments, as in English Excel. Formulas use semicolons (;) between arguments, as in Dutch Excel. Formulas use commas (,) between arguments, as in English Excel; Dutch Excel uses semicolons (;).

Worked examples

Beginner

Trial balance line chosen by number

You are tying a client's trial balance (saldibalans) to the general ledger. The list has one line per account, and Sanne de Vries, your senior, gives you the line numbers to check.

Type a line number and see that line's balance. Line 4 is account 4000, and it sits 4 rows below the header.

Sheet excerpt: F2 holds the formula
RowABCDEFG
1AccountDescriptionBalanceLine no.Balance
211001100Bank€84,350.00€ 84.350,0044€645,200.00€ 645.200,00=OFFSET(C1, E2, 0)=OFFSET(C1; E2; 0)
313001300Trade receivables€212,480.00€ 212.480,00
416001600Trade payables-€156,920.00€ -156.920,00
540004000Personnel costs€645,200.00€ 645.200,00
645004500Housing costs€230,400.00€ 230.400,00
780008000Revenue-€1,482,600.00€ -1.482.600,00
8
Formula cell (F2)Input

Formula in F2

=OFFSET(C1, E2, 0)
=OFFSET(C1; E2; 0)

Result: €645,200.00€ 645.200,00

Step by step
  1. Excel takes the anchor, C1, the Balance header.
  2. It reads E2: 4. It moves 4 rows down from C1: C2, C3, C4, C5. It lands on C5, the line for account 4000.
  3. cols is 0, so it stays in column C. height and width are left out, so the result is one cell, the same size as C1.
  4. OFFSET returns a reference to C5, and the cell shows its value: 645200, the balance of Personnel costs.
  5. Type 6 in E2 and OFFSET moves 6 rows to C7, the Revenue line: -1482600.

Watch out: Type 0 in E2 and you get the header text, Balance. Type 7 and OFFSET points at the empty C8, which shows 0: a plausible balance for an account that is not on the list.

More on this example: why it works, 1 more pitfall

Why it works

Anchoring on the header means the line number and the number of rows to move are the same thing: line 1 is one row below the header. OFFSET only counts; it never checks which account is in the row, so the layout of the list is what makes the answer right.

More to watch out for

  • The client sends a new version with a total line inserted between the header and account 1100. The accounts shift down while the anchor stays at C1, so every line number now returns the account before it. INDEX(C2:C7, E2) moves its range along with the data.

Intermediate

Last four periods of payroll costs

You reconcile account 4000 (Personeelskosten) from the XAF auditfile to the client's payroll summary (loonjournaal) per period. Veldhuis Installatie BV has not booked period 5 yet, so that cell is blank. Type the last period and get the total of that period and the three before it, to compare with the specification.

Sheet excerpt: E2 holds the formula
RowABCDEF
1PeriodDebit 4000Last period77
211€118,400.00€ 118.400,00Total 4 periods€374,900.00€ 374.900,00=SUM(OFFSET(B1, E1 - 3, 0, 4, 1))=SUM(OFFSET(B1; E1 - 3; 0; 4; 1))
322€121,050.00€ 121.050,00
433€119,800.00€ 119.800,00
544€123,300.00€ 123.300,00
655
766€126,900.00€ 126.900,00
877€124,700.00€ 124.700,00
988€125,350.00€ 125.350,00
10
Formula cell (E2)Input

Formula in E2

=SUM(OFFSET(B1, E1 - 3, 0, 4, 1))
=SUM(OFFSET(B1; E1 - 3; 0; 4; 1))

Result: €374,900.00€ 374.900,00

Step by step
  1. Excel calculates rows first: E1 - 3 = 7 - 3 = 4. The window must start three periods before period 7, at period 4.
  2. OFFSET moves 4 rows down from B1 and lands on B5, the period 4 row.
  3. height is 4 and width is 1, so OFFSET stretches the result to B5:B8: periods 4, 5, 6 and 7.
  4. SUM adds the block. B6 (period 5) is blank and SUM skips it: 123300 + 126900 + 124700 = 374900.
  5. Without height and width, OFFSET would return only B5, the size of the anchor, and the result would be 123300. The two optional arguments turn one cell into a window.
  6. Change E1 to 8: rows becomes 5, the window is B6:B9, and the total is 0 + 126900 + 124700 + 125350 = 376950.

Watch out: Enter period 2 or lower. rows becomes -1 or less, which points above row 1, and the result is #REF!. Period 3 gives rows 0: the window is B1:B4, the header is ignored by SUM, and you silently get periods 1 to 3: 359250.

More on this example: why it works, 1 more pitfall, 1 variation

Why it works

rows decides where the window starts and height decides how long it is, so moving the last period moves the whole window without changing its size. OFFSET hands SUM a real range, which is why the unbooked period is skipped instead of breaking the total.

More to watch out for

  • The unbooked period counts as one of the four, so this total covers three periods of payroll. The difference with the loonjournaal is then a missing booking, not an error in the formula.

Variations

=SUM(INDEX(B2:B9, E1 - 3):INDEX(B2:B9, E1))
=SUM(INDEX(B2:B9; E1 - 3):INDEX(B2:B9; E1))

The non-volatile version: two INDEX functions mark the first and last cell of the window.

Advanced

Average of the last three month-end balances in a growing list

Your working paper on debtors (account 1300) takes the month-end balance from the receivables aging list (ouderdomsanalyse debiteuren) as the client delivers each month. The sheet is laid out for the whole year, but only the months delivered so far are filled in. A cell must always show the average of the three most recent month-ends, for your analytical review, without editing the formula each month.

Sheet excerpt: D2 holds the formula
RowABCDE
1MonthDebtors 1300Average last 3
2Jan€198,500.00€ 198.500,00€219,300.00€ 219.300,00=AVERAGE(OFFSET(B1, COUNT(B2:B9) - 2, 0, 3, 1))=AVERAGE(OFFSET(B1; COUNT(B2:B9) - 2; 0; 3; 1))
3Feb€205,300.00€ 205.300,00
4Mar€214,800.00€ 214.800,00
5Apr€209,600.00€ 209.600,00
6May€221,400.00€ 221.400,00
7Jun€226,900.00€ 226.900,00
8Jul
9Aug
10
Formula cell (D2)InputNote: In the real sheet the list runs to December; the empty rows wait for the months the client has not delivered yet.

Formula in D2

=AVERAGE(OFFSET(B1, COUNT(B2:B9) - 2, 0, 3, 1))
=AVERAGE(OFFSET(B1; COUNT(B2:B9) - 2; 0; 3; 1))

Result: €219,300.00€ 219.300,00

Step by step
  1. Excel starts inside: COUNT(B2:B9) counts the cells that hold numbers. January to June are filled, July and August are blank, so COUNT returns 6.
  2. rows becomes 6 - 2 = 4. The last filled month is 6 rows below B1, and a three-month window has to start two rows earlier.
  3. OFFSET moves 4 rows down from B1 to B5 (April) and, with height 3 and width 1, returns B5:B7: April, May and June.
  4. AVERAGE works on that range: (209600 + 221400 + 226900) / 3 = 657900 / 3 = 219300.
  5. Enter 231500 for July in B8. COUNT becomes 7, rows becomes 5, the window moves to B6:B8, and the average becomes (221400 + 226900 + 231500) / 3 = 679800 / 3 = 226600.

Watch out: If a month is skipped, say March is left blank while July is filled, COUNT is still 6, but the last balance sits in B8. The window stays at B5:B7 and silently leaves out July.

More on this example: why it works, 2 more pitfalls, 2 variations

Why it works

COUNT turns 'how far has the list grown?' into a number, and OFFSET turns that number into a position. Because the balances are entered top to bottom without gaps, the count of numbers equals the row of the last balance, which is the assumption the whole formula rests on.

More to watch out for

  • A balance pasted from the client's export as text, for example 226900 with a trailing space, is not counted by COUNT and not averaged. The window shifts and the average changes without an error.
  • With fewer than 3 balances, rows drops to 0 or below and the window includes the header or falls off the sheet.

Variations

=AVERAGE(INDEX(B2:B9, COUNT(B2:B9) - 2):INDEX(B2:B9, COUNT(B2:B9)))
=AVERAGE(INDEX(B2:B9; COUNT(B2:B9) - 2):INDEX(B2:B9; COUNT(B2:B9)))

The same window built with INDEX: not volatile, so it recalculates only when the balances change.

=AVERAGE(TAKE(FILTER(B2:B9, B2:B9 <> ""), -3))
=AVERAGE(TAKE(FILTER(B2:B9; B2:B9 <> ""); -3))

Excel 2024 or Microsoft 365: FILTER drops the blanks and TAKE keeps the last three, so a skipped month no longer shifts the window.

MasterExcel 2021 or later (This example needs Excel 2021 or later)

Cost account movement over a chosen window of periods

You test the movement of cost accounts per period from the XAF auditfile against the client's specification. Pick an account, an end period and a number of periods, and get the total over that trailing window.

Early in the year the window may be longer than the periods available, and the formula must cope instead of reaching into the account column.

Sheet excerpt: I4 holds the formula
RowABCDEFGHIJ
1AccountJanFebMarAprMayAccount45004500
240004000€118,400.00€ 118.400,00€121,050.00€ 121.050,00€119,800.00€ 119.800,00€123,300.00€ 123.300,00€126,900.00€ 126.900,00End periodApr
345004500€18,500.00€ 18.500,00€18,500.00€ 18.500,00€18,500.00€ 18.500,00€19,200.00€ 19.200,00€19,200.00€ 19.200,00Periods33
446004600€6,240.00€ 6.240,00€5,890.00€ 5.890,00€7,120.00€ 7.120,00€6,480.00€ 6.480,00€6,955.00€ 6.955,00Total€56,200.00€ 56.200,00=LET( accRow, MATCH(I1, A2:A5, 0), perCol, MATCH(I2, B1:F1, 0), span, MIN(I3, perCol), SUM(OFFSET(A1, accRow, perCol - span + 1, 1, span)) )=LET( accRow; MATCH(I1; A2:A5; 0); perCol; MATCH(I2; B1:F1; 0); span; MIN(I3; perCol); SUM(OFFSET(A1; accRow; perCol - span + 1; 1; span)) )
547004700€3,120.00€ 3.120,00€2,870.00€ 2.870,00€3,410.00€ 3.410,00€2,950.00€ 2.950,00€3,680.00€ 3.680,00
6
Formula cell (I4)Input

Formula in I4

=LET(
  accRow, MATCH(I1, A2:A5, 0),
  perCol, MATCH(I2, B1:F1, 0),
  span, MIN(I3, perCol),
  SUM(OFFSET(A1, accRow, perCol - span + 1, 1, span))
)
=LET(
  accRow; MATCH(I1; A2:A5; 0);
  perCol; MATCH(I2; B1:F1; 0);
  span; MIN(I3; perCol);
  SUM(OFFSET(A1; accRow; perCol - span + 1; 1; span))
)

Result: €56,200.00€ 56.200,00

Step by step
  1. accRow: MATCH finds 4500 in the second cell of A2:A5, so accRow is 2. Counting from A1, that is row 3 of the sheet.
  2. perCol: MATCH finds Apr in the fourth cell of B1:F1, so perCol is 4. Counting from column A, that is column E.
  3. span: MIN(3, 4) = 3. Three periods fit up to April, so the requested window is kept.
  4. OFFSET starts at A1, moves accRow = 2 rows down and perCol - span + 1 = 4 - 3 + 1 = 2 columns right, landing on C3 (February). With height 1 and width 3 it returns C3:E3: February, March and April.
  5. SUM adds the window: 18500 + 18500 + 19200 = 56200.
  6. Set I3 to 6. span becomes MIN(6, 4) = 4, the column offset becomes 4 - 4 + 1 = 1, the window is B3:E3, and the total is 18500 + 18500 + 18500 + 19200 = 74700. Without MIN, the offset would be -1, left of column A, and the result #REF!.

Watch out: The mirror-image mistake: swapping height and width, OFFSET(A1, accRow, perCol - span + 1, span, 1). It returns C3:C5, February for three different accounts: 18500 + 5890 + 2870 = 27260. A plausible number with the wrong meaning.

More on this example: why it works, 2 more pitfalls, 2 variations

Why it works

Anchoring on A1, the corner of the grid, makes both MATCH positions usable as offsets without any +1 or -1 corrections; only the window start needs the + 1. MIN caps the window at the periods that exist, an edge case OFFSET would otherwise turn into #REF! or, with a window one period too long, into a silent sum that includes the account column.

Do not use this construction in a large model with many such cells: OFFSET is volatile and recalculates after every edit in the workbook.

The alternative is SUM(INDEX(B2:F5, accRow, perCol - span + 1):INDEX(B2:F5, accRow, perCol)), which gives the same 56200 and recalculates only when its inputs change, at the cost of a longer formula.

More to watch out for

  • Dropping the + 1 shifts the window one period back, to January through March: 18500 + 18500 + 18500 = 55500. Test with a window of 1 period, which must return the end period alone.
  • A window of 0 periods makes span 0, and OFFSET with width 0 returns #REF!. Validate I3 with data validation if people type it by hand.

Variations

=SUM(OFFSET(A1, MATCH(I1, A2:A5, 0), MATCH(I2, B1:F1, 0) - I3 + 1, 1, I3))
=SUM(OFFSET(A1; MATCH(I1; A2:A5; 0); MATCH(I2; B1:F1; 0) - I3 + 1; 1; I3))

The same without LET and without the cap: shorter, and fine when the window can never be longer than the periods available.

=LET(
  accRow, MATCH(I1, A2:A5, 0),
  perCol, MATCH(I2, B1:F1, 0),
  span, MIN(I3, perCol),
  SUM(INDEX(B2:F5, accRow, perCol - span + 1):INDEX(B2:F5, accRow, perCol))
)
=LET(
  accRow; MATCH(I1; A2:A5; 0);
  perCol; MATCH(I2; B1:F1; 0);
  span; MIN(I3; perCol);
  SUM(INDEX(B2:F5; accRow; perCol - span + 1):INDEX(B2:F5; accRow; perCol))
)

The non-volatile INDEX version of the same logic, for large workbooks.

Common mistakes

Common mistakes
SymptomCauseFix
Every result is one row offCounting from the first data row instead of the anchor, so every result is one row off.rows = 0 is the anchor itself. Anchor on the header cell when you want rows = 1 to mean the first data row.
The workbook pauses after every editThe workbook becomes sluggish: every edit triggers a pause while Excel recalculates.Replace OFFSET with INDEX:INDEX ranges, which recalculate only when their inputs change.
A plausible number from the wrong placeheight and width are swapped with rows and cols, and the formula returns a number from the wrong place that still looks plausible.Read the arguments as 'move rows, move columns, then size rows, size columns', and test with an input where you know the answer.
Three values spill, or only oneA cell with only =OFFSET(B1, 1, 0, 3, 1) shows three values spilling down. In versions before dynamic arrays it shows a single value instead: the one on the formula's own row, or #VALUE! when none lines up.A multi-cell OFFSET needs a function around it, such as SUM or AVERAGE, when you want one number.