SORT

SORT returns the contents of a range sorted, spilling into the cells below. The modern dynamic-array way to keep a list ordered without manual re-sort or autofilter.

ArrayIntermediate
Purpose
Return a range sorted in ascending or descending order, as a spilled dynamic array.
Returns
All rows of the source range, reordered, spilled into adjacent cells below and to the right
Syntax
=SORT(array, [sort_index], [sort_order], [by_col])
Excel version
Excel 365 and Excel 2021+

How SORT works

SORT takes a range and reorders it. By default it sorts the first column ascending and spills the result. Pass a different sort_index (1-based) to sort by the second, third, or Nth column instead. Pass -1 as sort_order for descending.

The result is live: edit, add, or remove a row in the source and the spilled output re-sorts itself instantly. No re-clicking the sort button, no broken formulas pointing at stale rows.

When you need to sort by multiple keys (e.g. department ascending, then hire date descending within each department), reach for SORTBY instead. SORTBY accepts pairs of by_array + order, so you can stack as many sort keys as you need.

= SORT(array, [sort_index], [sort_order], [by_col])

Arguments

ArgumentTypeRequiredDescription
arrayrange✓ RequiredThe range to sort. Can be one column, one row, or a 2D block. The result spills with the same shape - same number of rows and columns as the source.
sort_indexnumber✗ OptionalWhich column (or row, if by_col is TRUE) to sort by. 1-based. Default is 1, meaning sort by the first column. Out of range values give #VALUE!.
sort_ordernumber✗ Optional1 for ascending (default), -1 for descending. Note: it is the literal numbers 1 and -1, not TRUE/FALSE and not the strings 'asc'/'desc'.
by_colboolean✗ OptionalFALSE (default) sorts rows top-to-bottom. TRUE sorts columns left-to-right - rare, but useful when your data is laid out horizontally.

SORT basic: alphabetize a name list

The simplest case: one column of names in random order, you want them alphabetized. SORT walks the column, returns it sorted ascending, and spills the result.

=SORT(A2:A11)
  • A2:A11 -> the column to sort (10 names, unordered)
  • sort_index -> omitted, defaults to 1 - sort by the only column there is
  • sort_order -> omitted, defaults to 1 - ascending (A to Z)
  • Spill -> 10 rows of input means 10 rows of output, in the cells below the formula
C2
fx
=SORT(A2:A11)
ABCD
1EmployeeSorted A-Z
2Maria SantosAlex Kim
3James MillerCarlos Gomez
4Sarah ChenDavid Brown
5David BrownEmma Davis
6Emma DavisJames Miller
7Carlos GomezJenny Liu
8Alex KimMaria Santos
9Rachel WoodMark Reilly
10Jenny LiuRachel Wood
11Mark ReillySarah Chen
12
13
14
15
16
Formula entered in cell C2 - result spills down through C11 with all 10 names in alphabetical order.
Ten names in, ten names out. The formula sits in C2 (the green-bordered cell) and the result spills down through C11. Add an eleventh name to column A and the spill stretches to C12 automatically.

SORT descending: biggest orders on top

Two-column source, sort by the second column (Amount), and put the biggest numbers at the top. This is the everyday 'top N spenders' pattern that used to require manual re-sort every refresh.

=SORT(A2:B11, 2, -1)
  • A2:B11 -> the order log (Order ID + Amount, two columns)
  • 2 -> sort_index - sort by the second column (Amount)
  • -1 -> sort_order - descending, so the biggest number lands at the top
  • Spill shape -> result is the same shape as the source: 10 rows by 2 columns
D2
fx
=SORT(A2:B11, 2, -1)
ABCDEF
1OrderAmountOrderAmount
2PO-1001$450PO-1007$5,020
3PO-1002$2,400PO-1004$3,150
4PO-1003$890PO-1002$2,400
5PO-1004$3,150PO-1009$2,000
6PO-1005$1,250PO-1005$1,250
7PO-1006$700PO-1003$890
8PO-1007$5,020PO-1006$700
9PO-1008$320PO-1010$580
10PO-1009$2,000PO-1001$450
11PO-1010$580PO-1008$320
12
13
14
15
16
Formula entered in cell D2 - result spills through D-E for 10 rows, biggest amount on top.
All 10 orders spill in column D-E, sorted by Amount descending. PO-1007 at $5,020 lands on top, PO-1008 at $320 lands at the bottom. Same data, completely reordered, no extra clicks.
sort_order is the literal number -1, not 'desc' and not FALSE. Pass a string and you get #VALUE!. Pass FALSE and Excel coerces to 0, which is also invalid.

SORT by column index: highest paid first

Three columns wide: name, department, salary. Sort the whole block by salary descending. The sort_index is 3 because Salary is the third column inside the array argument - 1-based, counted from the leftmost column of the source range.

=SORT(A2:C10, 3, -1)
  • A2:C10 -> the roster (Name + Department + Salary, three columns)
  • 3 -> sort_index - sort by the third column (Salary)
  • -1 -> descending, so the highest paid lands on top
  • Whole row moves -> when SORT reorders, every column travels together - the salary stays glued to its name
E2
fx
=SORT(A2:C10, 3, -1)
ABCDEFGH
1EmployeeDepartmentSalaryEmployeeDepartmentSalary
2Sarah ChenEngineering$95,000David BrownEngineering$102,000
3James MillerEngineering$88,000Sarah ChenEngineering$95,000
4Maria SantosMarketing$72,000Alex KimEngineering$91,000
5David BrownEngineering$102,000James MillerEngineering$88,000
6Emma DavisSales$68,000Jenny LiuMarketing$78,000
7Alex KimEngineering$91,000Carlos GomezOperations$75,000
8Carlos GomezOperations$75,000Maria SantosMarketing$72,000
9Jenny LiuMarketing$78,000Emma DavisSales$68,000
10Mark ReillySales$65,000Mark ReillySales$65,000
11
12
13
14
15
16
Formula entered in cell E2 - result spills through E-G for 9 rows, sorted by salary descending.
All 9 employees spill in E-G, ranked by salary. David Brown at $102,000 lands on top, Mark Reilly at $65,000 at the bottom. Department travels with each name - the rows stay intact when SORT reorders them.

SORT + FILTER: top performers, sorted

FILTER subsets the rows that meet a threshold. SORT wraps that subset and orders it. The combination is the everyday 'top N who scored 80 or above' report - one formula, no helper columns, no manual re-sort when scores change.

=SORT(FILTER(A2:B11, B2:B11>=80), 2, -1)
  • FILTER(A2:B11, B2:B11>=80) -> inner step - keep only rows with a score of 80 or higher
  • SORT(..., 2, -1) -> outer step - sort the filtered rows by column 2 (Score) descending
  • 6 of 10 rows clear 80 -> so the spill is 6 rows tall, not 10
  • Live -> edit any score in column B and the spill rewrites itself - filter and sort both refresh
D2
fx
=SORT(FILTER(A2:B11, B2:B11>=80), 2, -1)
ABCDEF
1EmployeeScoreTop performersScore
2Sarah Chen92Alex Kim95
3James Miller78Sarah Chen92
4Maria Santos85Mark Reilly90
5David Brown71Emma Davis88
6Emma Davis88Maria Santos85
7Alex Kim95Jenny Liu82
8Carlos Gomez64
9Jenny Liu82
10Mark Reilly90
11Rachel Wood73
Formula entered in cell D2. FILTER keeps 6 rows that scored 80+, SORT orders them - spill stops at D7.
Six rows clear 80 (highlighted green in column B). FILTER keeps those six, SORT puts them in score order: Alex 95, Sarah 92, Mark 90, Emma 88, Maria 85, Jenny 82. The four under 80 fall out entirely.
Wrap-and-sort is the canonical pattern. Build the inner FILTER first, confirm it returns the rows you want, then wrap it in SORT. Reading from the inside out matches the order Excel evaluates.

SORTBY: department asc, hire date desc

When you need two or more sort keys, SORT alone runs out. SORTBY accepts pairs of by_array + order, so you can stack as many keys as you need. Here we group employees by department alphabetically, and within each department put the most recent hire on top.

=SORTBY(A2:C10, B2:B10, 1, C2:C10, -1)
  • A2:C10 -> the array to reorder (Name + Dept + Hire date)
  • B2:B10, 1 -> first key: department, ascending - groups the rows by dept alphabetically
  • C2:C10, -1 -> second key: hire date, descending - within each dept, newest first
  • Stack more keys -> add more pairs as the function grows: by_array3, order3, by_array4, order4, …
E2
fx
=SORTBY(A2:C10, B2:B10, 1, C2:C10, -1)
ABCDEFGH
1EmployeeDepartmentHire dateEmployeeDepartmentHire date
2Sarah ChenEngineering2021-03-15David BrownEngineering2023-01-10
3James MillerEngineering2019-08-22Sarah ChenEngineering2021-03-15
4David BrownEngineering2023-01-10James MillerEngineering2019-08-22
5Maria SantosMarketing2020-06-05Jenny LiuMarketing2022-11-18
6Jenny LiuMarketing2022-11-18Maria SantosMarketing2020-06-05
7Emma DavisSales2018-04-30Alex KimOperations2023-07-25
8Mark ReillySales2024-02-14Carlos GomezOperations2020-09-12
9Carlos GomezOperations2020-09-12Mark ReillySales2024-02-14
10Alex KimOperations2023-07-25Emma DavisSales2018-04-30
11
12
13
14
15
16
Formula entered in cell E2. Two-key sort: dept ascending, then hire date descending within each dept.
All 9 employees spill in E-G. Departments come out in alphabetical order (Engineering, Marketing, Operations, Sales) and inside each group the newest hire sits on top: David before Sarah before James, Mark before Emma, and so on.

Where people go wrong

  1. Passing 'asc'/'desc' or TRUE/FALSE for sort_order

    sort_order is the literal number 1 or -1, not a string and not a boolean. =SORT(A2:A10, 1, "desc") returns #VALUE!. =SORT(A2:A10, 1, FALSE) coerces FALSE to 0, also invalid.

    Fix: Use 1 for ascending, -1 for descending. Memorize the pair: 1 = up, -1 = down.
  2. Spill blocked by content below

    SORT spills downward (and rightward for 2D ranges). If a cell underneath your formula already has data, you get a #SPILL! error. Same gotcha as FILTER and UNIQUE.

    Fix: Clear every cell inside the spill range, or move the formula somewhere with empty space below it. Hover the #SPILL! cell - Excel highlights the obstructing cell with a dashed outline.
  3. sort_index of 0 or out of range

    sort_index is 1-based, not 0-based. =SORT(A2:C10, 0) returns #VALUE!, and so does =SORT(A2:C10, 4) when the source only has 3 columns. Off-by-one is the most common cause.

    Fix: Count your columns from the leftmost column of the array argument. First column is 1, second is 2, third is 3 - never 0.
  4. Forgetting that the result is volatile to its source

    SORT does not snapshot the source. If a value in the source changes, the spilled output re-sorts itself instantly. Sometimes you want that; sometimes you wanted a frozen view of yesterday's order.

    Fix: If you need a snapshot, copy the spill (Ctrl+Shift+Down to select, Ctrl+C, Paste Values). Live SORT is great for dashboards, paste-values is great for archived reports.

Notes

  • SORT is a dynamic-array function. The result spills into adjacent cells - you cannot put other content in the spill range without breaking it.
  • Available in Excel 365 and Excel 2021. Older versions do not have it; share files cautiously.
  • sort_index is 1-based, counted from the leftmost column of the array argument.
  • sort_order is the literal number 1 (ascending) or -1 (descending) - never a string, never a boolean.
  • Text comparison is case-insensitive. "alpha" and "ALPHA" sort as equal.
  • Pair with FILTER and UNIQUE for the canonical 'subset, dedupe, sort' workflow in one formula.
  • Reach for SORTBY when you need multiple sort keys or want to sort by a column that is not in the array argument.

Now prove it

Reading about SORT is one thing.

Writing one in front of a finance director who wants the top 10 largest invoices on this morning's dashboard, sorted, live, with no manual refresh, is completely different.

These exercises put SORT in real workplace patterns: leaderboards, top-N reports, multi-key rosters.

Here is the thing about SORT.

You can read this page twice and still hesitate when the team needs a live dashboard cell that shows the five highest-value contracts, refreshed every time the source updates, ranked exactly how the CFO asked for it.

That gap, between knowing what SORT does and being able to write one fluently under pressure, is exactly what CellSkill is built to close.

Not with more reading.

With practice on scenarios that look like your actual job.

Start practicing SORT for free →
Free account . No credit card . Cancel anytime
Browse exercises
SORT in Excel: Sort Data Without Touching the Source · CellSkill