TOROW
NAAR.RIJ in Dutch Excel
Turns a range or array of any shape into one row, reading it row by row or column by column and optionally skipping blanks and errors.
Last updated: 13 October 2026
| Row | A | B | C | D | E | F | G | H | I | J |
|---|---|---|---|---|---|---|---|---|---|---|
| 1 | Sanne | Tom | Aisha | |||||||
| 2 | 25-1101 | 25-1104 | 25-1109 | 25-1101=TOROW(A2:C3)=TOROW(A2:C3) | 25-1104 | 25-1109 | 25-1102 | 25-1105 | 25-1110 | |
| 3 | 25-1102 | 25-1105 | 25-1110 |
Swipe sideways to see all columns
=TOROW(A2:C3)
=TOROW(A2:C3)
What TOROW does and when to use it
What it does: it lays every value of a block of cells out in one row, for example the sampled invoices of three columns on one line.
When to use it: when a grid has to become a list: as input for TEXTJOIN or UNIQUE, for a duplicate test across several columns, or as a header row built from a column of names. The row spills to the right. It is the horizontal twin of TOCOL. To swap rows and columns and keep the grid shape, use TRANSPOSE.
Two main gains:
- Stays live: Paste Special with Transpose is a one-off copy, while the row updates when the source changes.
- Skips blanks and errors:
ignoreleaves out empty cells, errors or both.
How Excel evaluates it
Excel first evaluates array, which can be a range or the result of another formula. It then checks ignore:
- 0 keeps everything
- 1 drops blank cells
- 2 drops errors
- 3 drops blank cells and errors
It reads the remaining cells in the order set by scan_by_column: across each row by default, or down each column when you pass TRUE. All items are placed in a single row, one per column, spilling to the right of the formula cell. If a cell in that spill area is occupied, you get #SPILL! instead.
Watch out: With the default ignore of 0, a blank cell in the grid comes back as a 0 in the row.
Mental model
Cutting a grid of tiles into strips and gluing the strips end to end in one long line: scan_by_column decides whether you cut along the rows or along the columns.
TOROW(array,[ignore], [scan_by_column])
TOROW(array;[ignore]; [scan_by_column])
| Argument | Type | Meaning | Default |
|---|---|---|---|
array | Required | The range or array to flatten into one row. | |
ignore | Optional | What to skip: 0 nothing, 1 blanks, 2 errors, 3 blanks and errors. | 0 |
scan_by_column | Optional | FALSE reads row by row (default); TRUE reads column by column. | FALSE |
Return value:A single row holding every kept value of array, in the order it was read
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
Put a sample drawn in three columns on one row
At Veldhuis Installatie BV your team drew a sample of purchase invoices. Sanne, Tom and Aisha each pasted their selection under their own name, so the sample sits in a grid of three columns. For the workpaper header you want all six invoice numbers on a single row.
| Row | A | B | C | D | E | F | G | H | I | J | K |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | Sanne | Tom | Aisha | ||||||||
| 2 | 25-1101 | 25-1104 | 25-1109 | 25-1101=TOROW(A2:C3)=TOROW(A2:C3) | 25-1104 | 25-1109 | 25-1102 | 25-1105 | 25-1110 | ||
| 3 | 25-1102 | 25-1105 | 25-1110 | ||||||||
| 4 |
Swipe sideways to see all columns
Formula in E2
=TOROW(A2:C3)
=TOROW(A2:C3)
Result: 25-1101 | 25-1104 | 25-1109 | 25-1102 | 25-1105 | 25-111025-1101 | 25-1104 | 25-1109 | 25-1102 | 25-1105 | 25-1110
Step by step
- The array is
A2:C3: 2 rows and 3 columns, so 6 cells. The header row 1 is not part of it. ignore and scan_by_column are left out, so every cell is kept and the grid is read row by row. - The first row of the grid, left to right, gives
25-1101,25-1104and25-1109. - The second row gives
25-1102,25-1105and25-1110. - The 6 items are placed side by side, so the result spills from
E2toJ2: 1 row and 6 columns. Counted off, the 4th item is25-1102, because it is the first value of row 2 and not the 4th value of column A. - Change
B3to25-1199and the 5th item in the row changes with it, because the row is a live view of the grid and not a copy.
Watch out: If anything is typed in F2:J2, the formula shows #SPILL! instead of the row. Keep the cells to the right of a TOROW empty.
More on this example: why it works, 1 variation
Why it works
TOROW visits the cells in a fixed order and writes each one into the next column of a single row. With no optional arguments the order is the one you read a page in: left to right, then down.
Variations
=TOROW(A2:C3,0, TRUE)
=TOROW(A2:C3;0; TRUE)
Read column by column instead: Sanne's two invoices first, then Tom's, then Aisha's. Prefer it when the columns are meaningful groups.
Intermediate
Flatten bank reconciling items and skip the empty cells
The client's bank reconciliation lists reconciling items in a grid: one column per bank account, with gaps where an account has no item on that line. You want one row with only the amounts, so you can count the items and compare their sum with the difference to explain.
A plain flattening would add a 0 for every gap.
| Row | A | B | C | D | E | F | G | H | I | J | K |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | Current account | Savings account | Foreign currency | ||||||||
| 2 | €1,250.00€ 1.250,00 | €480.00€ 480,00 | €1,250.00€ 1.250,00=TOROW(A2:C5, 1)=TOROW(A2:C5; 1) | €480.00€ 480,00 | €3,000.00€ 3.000,00 | -€725.00€ -725,00 | €1,900.00€ 1.900,00 | €615.00€ 615,00 | |||
| 3 | €3,000.00€ 3.000,00 | ||||||||||
| 4 | -€725.00€ -725,00 | €1,900.00€ 1.900,00 | |||||||||
| 5 | €615.00€ 615,00 | ||||||||||
| 6 |
Swipe sideways to see all columns
Formula in E2
=TOROW(A2:C5,1)
=TOROW(A2:C5;1)
Result: €1,250.00 | €480.00 | €3,000.00 | -€725.00 | €1,900.00 | €615.00€ 1.250,00 | € 480,00 | € 3.000,00 | € -725,00 | € 1.900,00 | € 615,00
Step by step
- The array is
A2:C5: 4 rows and 3 columns, 12 cells, of which 6 are blank (B2,A3,C3,B4,A5,B5). ignore is 1, so blanks are dropped. - Row 2 left to right: 1250, blank (skipped), 480. Row 3: blank, 3000, blank, which leaves 3000.
- Row 4: -725, blank, 1900. Row 5: blank, blank, 615, which leaves 615.
- Six values remain and spill from
E2toJ2: 1250, 480, 3000, -725, 1900, 615. Their sum is 1250 + 480 + 3000 - 725 + 1900 + 615 = 6520. - Without the 1, the same formula would return 12 items, because each of the 6 blanks comes back as 0: 1250, 0, 480, 0, 3000, 0, -725, 0, 1900, 0, 0, 615. The sum stays 6520, but a count of the row would say 12 items instead of 6.
Watch out: A cell that looks empty but holds a space or a formula returning an empty text is not blank for ignore 1. It stays in the row as text. If the count is higher than the number of visible items, check those cells with ISBLANK.
More on this example: why it works, 1 variation
Why it works
ignore filters while the cells are read, before the row is built, so the row closes up over the gaps. The negative item -725 is kept because it is a real value; ignore 1 removes only cells that are empty, not zeros you typed.
Variations
=TOROW(A2:C5,1, TRUE)
=TOROW(A2:C5;1; TRUE)
Same items grouped per bank account: 1250, -725, 3000, 480, 1900, 615. Prefer it when you want to see each account's items together.
Advanced
List invoices to confirm in one line, grouped by quarter
From the receivables list of Veldhuis Installatie BV you select every invoice of at least the confirmation threshold in H1, to put in one cell of the confirmation request log. Invoice numbers per quarter sit in B:C and the amounts in D:E.
You want them listed quarter by quarter, so the Q3 invoices come before the Q4 invoices. Invoices below the threshold must not appear.
| Row | A | B | C | D | E | F | G | H | I |
|---|---|---|---|---|---|---|---|---|---|
| 1 | Customer | Invoice Q3 | Invoice Q4 | Amount Q3 | Amount Q4 | Confirm from | 2000020000 | ||
| 2 | Kaya Design BV | 25-2011 | 25-2087 | €18,400.00€ 18.400,00 | €31,250.00€ 31.250,00 | ||||
| 3 | Molenaar Bouw BV | 25-2014 | €42,000.00€ 42.000,00 | 25-2014, 25-2019, 25-2087, 25-2101, 25-2105=TEXTJOIN(", ", TRUE, TOROW(IF(D2:E6>=H1, B2:C6, NA()), 2, TRUE))=TEXTJOIN(", "; TRUE; TOROW(IF(D2:E6>=H1; B2:C6; NA()); 2; TRUE)) | |||||
| 4 | Van Dijk Transport BV | 25-2019 | 25-2093 | €27,500.00€ 27.500,00 | €9,800.00€ 9.800,00 | ||||
| 5 | Hendriks Metaal BV | 25-2101 | €20,000.00€ 20.000,00 | ||||||
| 6 | Smits Bouw BV | 25-2024 | 25-2105 | €6,200.00€ 6.200,00 | €55,400.00€ 55.400,00 | ||||
| 7 |
Swipe sideways to see all columns
Formula in G3
=TEXTJOIN(", ",TRUE, TOROW(IF(D2:E6>=H1, B2:C6, NA()), 2, TRUE))
=TEXTJOIN(", ";TRUE; TOROW(IF(D2:E6>=H1; B2:C6; NA()); 2; TRUE))
Result: 25-2014, 25-2019, 25-2087, 25-2101, 25-2105
Step by step
Inside out, first the test D2:E6>=H1 with H1 = 20000.
Column D: 18400 FALSE, 42000 TRUE, 27500 TRUE, blank FALSE (counts as 0), 6200 FALSE. Column E: 31250 TRUE, blank FALSE, 9800 FALSE, 20000 TRUE (equal counts, because of >=), 55400 TRUE.
IF replaces each TRUE with the invoice number at the same position in B2:C6 and each FALSE with #N/A. The grid becomes:
- row 2 is #N/A and 25-2087
- row 3 is 25-2014 and #N/A
- row 4 is 25-2019 and #N/A
- row 5 is #N/A and 25-2101
- row 6 is #N/A and 25-2105
- TOROW reads that grid column by column because scan_by_column is TRUE. First column: #N/A, 25-2014, 25-2019, #N/A, #N/A. Second column: 25-2087, #N/A, #N/A, 25-2101, 25-2105.
- ignore is 2, so the five errors are dropped and the row 25-2014, 25-2019, 25-2087, 25-2101, 25-2105 remains.
- TEXTJOIN glues the five items together with a comma and a space between them: 25-2014, 25-2019, 25-2087, 25-2101, 25-2105. The result is one text in
G3. - Raise
H1to 30000: only 42000, 31250 and 55400 qualify, andG3becomes 25-2014, 25-2087, 25-2105.
Watch out: Silent error: if a large amount has no invoice number (blank in B or C), IF returns 0 for that position and 0 appears in the text. Compare the number of items with a COUNTIF on the amounts.
More on this example: why it works, 1 more pitfall, 2 variations
Why it works
IF over a whole grid keeps the grid's shape, so TOROW can flatten it in one go, and the errors from NA() act as 'skip this one' markers that ignore 2 removes. scan_by_column then sets the order to quarter by quarter.
TEXTJOIN alone would pass the errors on, so the flattening with error removal is what makes the join work.
More to watch out for
- Leave ignore at 0 and the five #N/A values stay in the row, so TEXTJOIN returns #N/A and no list at all.
Variations
=TEXTJOIN(", ",TRUE, TOROW(IF(D2:E6>=H1, B2:C6, NA()), 2))
=TEXTJOIN(", ";TRUE; TOROW(IF(D2:E6>=H1; B2:C6; NA()); 2))
Without scan_by_column the list runs customer by customer: 25-2087, 25-2014, 25-2019, 25-2101, 25-2105. Prefer it when the customer order matters more than the quarter.
=TEXTJOIN(", ",TRUE, IF(D2:E6>=H1, B2:C6, ""))
=TEXTJOIN(", ";TRUE; IF(D2:E6>=H1; B2:C6; ""))
Shorter: empty texts instead of errors, which TEXTJOIN skips by itself. It reads row by row only, so use TOROW when you need the column order or the grid already contains errors.
Master
Find invoices paid in more than one payment file
For the duplicate payment test at Veldhuis Installatie BV you received three weekly payment files, pasted next to each other in columns A to C. Files differ in length, so the shorter ones end in blanks.
You want the invoice numbers that occur more than once anywhere in the grid, as a row for your workpaper, with a message when there are none.
| Row | A | B | C | D | E | F | G | H |
|---|---|---|---|---|---|---|---|---|
| 1 | Payment file week 40 | Payment file week 41 | Payment file week 42 | |||||
| 2 | 25-3101 | 25-3103 | 25-3104 | 25-3105=LET( paid, TOROW(A2:C7, 1), distinct, UNIQUE(paid, TRUE), once, UNIQUE(paid, TRUE, TRUE), FILTER(distinct, ISNA(XMATCH(distinct, once)), "No duplicate payments") )=LET( paid; TOROW(A2:C7; 1); distinct; UNIQUE(paid; TRUE); once; UNIQUE(paid; TRUE; TRUE); FILTER(distinct; ISNA(XMATCH(distinct; once)); "No duplicate payments") ) | 25-3107 | 25-3110 | ||
| 3 | 25-3102 | 25-3105 | 25-3107 | |||||
| 4 | 25-3105 | 25-3108 | 25-3109 | |||||
| 5 | 25-3107 | 25-3110 | 25-3105 | |||||
| 6 | 25-3110 | |||||||
| 7 | 25-3112 | |||||||
| 8 |
Swipe sideways to see all columns
Formula in E2
=LET( paid,TOROW(A2:C7, 1), distinct, UNIQUE(paid, TRUE), once, UNIQUE(paid, TRUE, TRUE), FILTER(distinct, ISNA(XMATCH(distinct, once)), "No duplicate payments") )
=LET( paid;TOROW(A2:C7; 1); distinct; UNIQUE(paid; TRUE); once; UNIQUE(paid; TRUE; TRUE); FILTER(distinct; ISNA(XMATCH(distinct; once)); "No duplicate payments") )
Result: 25-3105 | 25-3107 | 25-311025-3105 | 25-3107 | 25-3110
Step by step
- paid is TOROW(A2:C7, 1): 18 cells, of which 4 are blank (
B6,C6,B7,C7). Read row by row with the blanks skipped, it holds 14 items: 25-3101, 25-3103, 25-3104, 25-3102, 25-3105, 25-3107, 25-3105, 25-3108, 25-3109, 25-3107, 25-3110, 25-3105, 25-3110, 25-3112. - distinct is UNIQUE(paid, TRUE). by_col TRUE is needed because paid is a row. It keeps each invoice once, in order of first appearance: 25-3101, 25-3103, 25-3104, 25-3102, 25-3105, 25-3107, 25-3108, 25-3109, 25-3110, 25-3112. That is 10 invoices.
- once is UNIQUE(paid, TRUE, TRUE), with exactly_once TRUE: only invoices that occur a single time. 25-3105 occurs 3 times, 25-3107 twice and 25-3110 twice, so 7 invoices remain: 25-3101, 25-3103, 25-3104, 25-3102, 25-3108, 25-3109, 25-3112. Check: 10 distinct = 7 once + 3 repeated.
- XMATCH(distinct, once) looks up each of the 10 distinct invoices in once. For the 7 singles it returns a position, for 25-3105, 25-3107 and 25-3110 it returns #N/A. ISNA turns that into TRUE only for those three: FALSE for the first four, TRUE for 25-3105, TRUE for 25-3107, FALSE, FALSE, TRUE for 25-3110, FALSE for 25-3112.
- FILTER receives distinct and a row of 10 TRUE/FALSE values of the same width, so it keeps columns: 25-3105, 25-3107 and 25-3110. The result spills from
E2toG2. - Clear
A4,A5,A6andC5, so every invoice occurs once: once then equals distinct, ISNA is FALSE everywhere, FILTER finds no TRUE andE2shows No duplicate payments.
Watch out: The mirror-image mistake is leaving ignore at 0. The 4 blanks then come back as four 0 values, UNIQUE counts 0 four times, and the result gets a fourth hit, 0, next to the three real duplicates. It looks like a plausible extra finding.
More on this example: why it works, 2 more pitfalls, 1 variation
Why it works
UNIQUE and FILTER see a grid as separate rows and columns, so a test across the whole grid needs it in one dimension first, and TOROW with ignore 1 does that and drops the padding blanks.
Do not use this when the invoice numbers sit in one column: UNIQUE or COUNTIF work there directly, and the LET adds nothing. An alternative that works in every Excel version is a helper grid with =COUNTIF($A$2:$C$7, A2)>1 and conditional formatting; it marks the duplicates in place but does not produce a list.
More to watch out for
- An invoice number exported with a trailing space,
"25-3105 ", counts as a different invoice and the duplicate is missed without any error. Wrap the flattening in TRIM: TRIM(TOROW(A2:C7, 1)). If every invoice occurs more than once, UNIQUE(paid, TRUE, TRUE) finds nothing and returns #CALC!. XMATCH then returns #CALC! for every item, ISNA of #CALC! is FALSE, so FILTER keeps nothing and shows the no-duplicates message although every invoice is a duplicate.
That is the dangerous part. Check this case, or guard the once list, for example by comparing ROWS of distinct with the count of duplicates.
Variations
=LET( paid,TOROW(A2:C7, 1), SORT(UNIQUE(FILTER(paid, ISNA(XMATCH(paid, UNIQUE(paid, TRUE, TRUE)))), TRUE), 1, 1, TRUE) )
=LET( paid;TOROW(A2:C7; 1); SORT(UNIQUE(FILTER(paid; ISNA(XMATCH(paid; UNIQUE(paid; TRUE; TRUE)))); TRUE); 1; 1; TRUE) )
Sorted in ascending order and without the none message. It filters paid directly, so repeated hits are removed by an extra UNIQUE; use it when you want the list in invoice order.
Common mistakes
| Symptom | Cause | Fix |
|---|---|---|
| Unexpected zeros and a count that is too high | The row contains zeros you did not expect, and a count of the items is too high. | Pass 1 to skip blanks, or 3 to skip blanks and errors. |
| The items come out in an unexpected order | The items come out in a different order than you read the grid, so the third item is not the third value in the first column. | TOROW reads row by row unless told otherwise. Pass TRUE as scan_by_column to read down the first column, then the second. |
| #N/A in a TEXTJOIN or SUM around the row | Errors such as #N/A in the grid end up in the row, and a TEXTJOIN or SUM around it returns #N/A as well. | ignore 1 skips only blanks. Use 2 to skip errors or 3 to skip both. Only do this when the errors mean 'no value', not when they signal a real problem. |
| #SPILL! although the formula is correct | The result is #SPILL! even though the formula is correct. | Something sits in the cells to the right of the formula that the row needs. Click the error, choose Select Obstructing Cells, and clear them. |
| #NAME? when a colleague opens the file | The formula shows #NAME? when the file is opened by a colleague. | TOROW exists only in Excel 2024, Microsoft 365 and Excel for the web. For older versions use TRANSPOSE on a single column. |