Available in:Excel 2024 or later (Works in Excel 2024, every later version, Microsoft 365 and Excel for the web)Category:Dynamic arrays

CHOOSECOLS

KIES.KOLOMMEN in Dutch Excel

Returns the columns you name by number, in the order you name them, as a block that spills; negative numbers count from the right.

Difficulty rating 3 of 5. The function itself only takes column numbers, but it spills a block, counts negative numbers from the right, and becomes robust only when you combine it with XMATCH.

Last updated: 13 October 2026

See the worked examples

Sheet excerpt: G2 holds the formula
RowABCDEFGHI
1EntryDateJournalAccountAmount
225-06013 Nov 2025INK45004500€2,480.00€ 2.480,0025-0601=CHOOSECOLS(A2:E6, 1, 4, 5)=CHOOSECOLS(A2:E6; 1; 4; 5)45004500€2,480.00€ 2.480,00
325-06025 Nov 2025VRK80008000€6,050.00€ 6.050,0025-060280008000€6,050.00€ 6.050,00
425-060312 Nov 2025BNK11001100€9,680.00€ 9.680,0025-060311001100€9,680.00€ 9.680,00
525-060418 Nov 2025MEM40004000€15,000.00€ 15.000,0025-060440004000€15,000.00€ 15.000,00
625-060524 Nov 2025INK45004500€1,210.00€ 1.210,0025-060545004500€1,210.00€ 1.210,00
Formula cell (G2)Spilled result
=CHOOSECOLS(A2:E6, 1, 4, 5)
=CHOOSECOLS(A2:E6; 1; 4; 5)

What CHOOSECOLS does and when to use it

What it does: it picks columns out of a range by their number and returns them in the order you name them, as a block that spills into the cells next to the formula, for example entry, account and amount from a journal export.

When to use it: when an export has more columns than your workpaper needs, or has them in the wrong order, and the result must follow the source. Combine it with XMATCH when column positions can change between exports.

Three main gains:

  • Select and reorder in one step: the columns come back in the order of your numbers.
  • Follows the source: paste a new export and the result updates, with no columns to delete or drag.
  • Counts from the right: -1 is the last column, so a closing column needs no counting.

How Excel evaluates it

Excel reads array and counts its columns. It then walks through your column numbers from left to right. For each number it checks that it is not 0 and not larger than the number of columns; a negative number is turned into a position from the right, so -1 becomes the last column. It copies that whole column, all rows, into the next column of the result.

If one number is invalid the whole result is #VALUE!. The finished block spills from the formula cell, as tall as array and as wide as the number of column numbers you gave.

Watch out: Fixed column numbers such as 1, 4, 6 point at positions, not at names: when next year's export has an extra column, the workpaper silently shows the wrong columns, without any error.

Mental model

Picking cards from a hand and laying them out in a new row: you decide which ones and in what order, and the hand itself stays untouched.

Terms used on this page: spill, array, range, cell

CHOOSECOLS(array, col_num1, [col_num2, ...], ...)
CHOOSECOLS(array; col_num1; [col_num2, ...]; ...)
Arguments
ArgumentTypeMeaning
arrayRequiredThe range or array that holds the columns you pick from.
col_num1RequiredNumber of the first column to return; negative counts from the right.
col_num2, ...OptionalFurther column numbers; each one adds a column to the result.

Return value:An array with the chosen columns of array, in the order of the column numbers

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

Pull entry, account and amount from a journal export

You received the XAF auditfile of Veldhuis Installatie BV as a sheet with five columns. For your workpaper you only need the entry number, the account and the amount, next to each other. One formula collects those three columns and leaves the export untouched.

Sheet excerpt: G2 holds the formula
RowABCDEFGHIJ
1EntryDateJournalAccountAmount
225-06013 Nov 2025INK45004500€2,480.00€ 2.480,0025-0601=CHOOSECOLS(A2:E6, 1, 4, 5)=CHOOSECOLS(A2:E6; 1; 4; 5)45004500€2,480.00€ 2.480,00
325-06025 Nov 2025VRK80008000€6,050.00€ 6.050,0025-060280008000€6,050.00€ 6.050,00
425-060312 Nov 2025BNK11001100€9,680.00€ 9.680,0025-060311001100€9,680.00€ 9.680,00
525-060418 Nov 2025MEM40004000€15,000.00€ 15.000,0025-060440004000€15,000.00€ 15.000,00
625-060524 Nov 2025INK45004500€1,210.00€ 1.210,0025-060545004500€1,210.00€ 1.210,00
7
Formula cell (G2)Spilled result

Formula in G2

=CHOOSECOLS(A2:E6, 1, 4, 5)
=CHOOSECOLS(A2:E6; 1; 4; 5)

Result: 25-0601 | 4500 | €2,480.00 / 25-0602 | 8000 | €6,050.00 / 25-0603 | 1100 | €9,680.00 / 25-0604 | 4000 | €15,000.00 / 25-0605 | 4500 | €1,210.0025-0601 | 4500 | € 2.480,00 / 25-0602 | 8000 | € 6.050,00 / 25-0603 | 1100 | € 9.680,00 / 25-0604 | 4000 | € 15.000,00 / 25-0605 | 4500 | € 1.210,00

Step by step
  1. Excel reads array, A2:E6: 5 rows and 5 columns. The columns are numbered 1 to 5: Entry is 1, Date 2, Journal 3, Account 4, Amount 5.
  2. The first column number is 1, so column A goes into the first column of the result: 25-0601, 25-0602, 25-0603, 25-0604, 25-0605.
  3. The second number is 4, so column D, the account, goes in next: 4500, 8000, 1100, 4000, 4500. The third number is 5, so column E, the amount, closes the block: 2,4802.480, 6,0506.050, 9,6809.680, 15,00015.000, 1,2101.210.
  4. The result is 5 rows by 3 columns and spills from G2 to I6. Date and journal (columns B and C) are not in it.
  5. Change the formula to =CHOOSECOLS(A2:E6, 5, 1): the block is now 2 columns wide, with the amount first and the entry second. The order of your numbers is the order of the columns.

Watch out: The positions are counted inside A2:E6, not in the sheet. If you pass B2:F6 instead, number 1 now means column B. A number above 5 gives #VALUE!.

More on this example: why it works, 1 variation

Why it works

Every column number is a position in array, counted from the left starting at 1. Excel does not look at the headers, so it works the same with any content. All rows come along, because CHOOSECOLS only decides which columns to keep.

Variations

=CHOOSECOLS(A2:E6, 4, 4, 5)
=CHOOSECOLS(A2:E6; 4; 4; 5)

Repeat a number to get a column twice, for example when you want the account next to itself for a lookup key.

Intermediate

Pick the relation, then the overdue days and amount, counting from the right

From the receivables aging list of Veldhuis Installatie BV you need, per customer, the days overdue and the open amount, in that order, as the start of the confirmation list. Both columns are always the last two of the file, and the client sometimes adds columns in front, so you count from the right with negative numbers. One invoice has no due date, so its days overdue are blank.

Sheet excerpt: G2 holds the formula
RowABCDEFGHIJ
1RelationInvoiceDue dateOpen amountDays overdue
2D100125-120128 Aug 2025€4,235.00€ 4.235,00125125D1001=CHOOSECOLS(A2:E7, 1, -1, -2)=CHOOSECOLS(A2:E7; 1; -1; -2)125125€4,235.00€ 4.235,00
3D100225-12022 Oct 2025€12,100.00€ 12.100,009090D10029090€12,100.00€ 12.100,00
4D100325-120326 Nov 2025€2,420.00€ 2.420,003535D10033535€2,420.00€ 2.420,00
5D100425-1204€7,865.00€ 7.865,00D100400€7,865.00€ 7.865,00
6D100525-120515 Dec 2025€1,815.00€ 1.815,001616D10051616€1,815.00€ 1.815,00
7D100625-120630 Jun 2025€9,680.00€ 9.680,00184184D1006184184€9,680.00€ 9.680,00
8
Formula cell (G2)Spilled resultNote: Days overdue are counted at 31 December 2025.

Formula in G2

=CHOOSECOLS(A2:E7, 1, -1, -2)
=CHOOSECOLS(A2:E7; 1; -1; -2)

Result: D1001 | 125 | €4,235.00 / D1002 | 90 | €12,100.00 / D1003 | 35 | €2,420.00 / D1004 | 0 | €7,865.00 / D1005 | 16 | €1,815.00 / D1006 | 184 | €9,680.00D1001 | 125 | € 4.235,00 / D1002 | 90 | € 12.100,00 / D1003 | 35 | € 2.420,00 / D1004 | 0 | € 7.865,00 / D1005 | 16 | € 1.815,00 / D1006 | 184 | € 9.680,00

Step by step
  1. Excel reads array, A2:E7: 6 rows, 5 columns. Counted from the right, -1 is column 5 (Days overdue) and -2 is column 4 (Open amount).
  2. The first number, 1, puts column A (the relation) first: D1001, D1002, D1003, D1004, D1005, D1006.
  3. The second number, -1, adds column E: 125, 90, 35, blank, 16, 184. The blank cell E5 comes through as 0, because an array cannot hold an empty cell.
  4. The third number, -2, adds column D: 4,2354.235, 12,10012.100, 2,4202.420, 7,8657.865, 1,8151.815, 9,6809.680.
  5. The result is 6 rows by 3 columns and spills from G2 to I7. Invoice D1004 shows 0 days overdue and 7,8657.865, although the true answer is unknown, because its due date is missing.
  6. Suppose the client inserts a column between B and C next year. The range becomes A2:F7, and -1 and -2 still point at the last two columns. With fixed numbers 5 and 4 you would now get the wrong columns without an error.

Watch out: The blank in E5 shows as 0 and looks like a current invoice. It is a missing due date that you still have to follow up with the client.

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

Why it works

A negative number is a position counted from the right edge of array, so it stays correct as long as the columns you need stay at the end. A positive and a negative number can be mixed freely in one call, and each of them gives one column in the order you wrote them.

More to watch out for

  • Negative indexes count from the right, so if the client adds a column between the amount and the days overdue (or at the far right) instead of in front, -2 or -1 suddenly points at the wrong column and still gives no error. Check the headers of the result against the source.

Variations

=CHOOSECOLS(A2:E7, 1, 5, 4)
=CHOOSECOLS(A2:E7; 1; 5; 4)

The same result with positive numbers. Prefer this when the layout of the file is fixed, because 5 and 4 read faster than -1 and -2.

Advanced

Pick purchase columns by header name with XMATCH

For the VAT recalculation at Veldhuis Installatie BV you take purchase postings from the auditfile and only need the entry, the VAT code and the amount including VAT. Last year the export had the columns in another order, so you do not want to type column numbers. The names of the columns you want sit in I1:K1, and the formula looks up their positions in the header row.

Sheet excerpt: H3 holds the formula
RowABCDEFGHIJKL
1EntryDateJournalAccountVAT codeAmountColumnsEntryVAT codeAmount
225-07016 Oct 2025INK45004500V21€2,420.00€ 2.420,00
325-070214 Oct 2025INK40004000V9€1,090.00€ 1.090,0025-0701=CHOOSECOLS(A2:F7, XMATCH(I1:K1, A1:F1))=CHOOSECOLS(A2:F7; XMATCH(I1:K1; A1:F1))V21€2,420.00€ 2.420,00
425-070321 Oct 2025INK45004500V21€6,050.00€ 6.050,0025-0702V9€1,090.00€ 1.090,00
525-07044 Nov 2025INK45004500V0€880.00€ 880,0025-0703V21€6,050.00€ 6.050,00
625-070518 Nov 2025INK40004000V21€3,267.00€ 3.267,0025-0704V0€880.00€ 880,00
725-07062 Dec 2025INK45004500V9€545.00€ 545,0025-0705V21€3,267.00€ 3.267,00
825-0706V9€545.00€ 545,00
9
Formula cell (H3)InputSpilled result

Formula in H3

=CHOOSECOLS(A2:F7, XMATCH(I1:K1, A1:F1))
=CHOOSECOLS(A2:F7; XMATCH(I1:K1; A1:F1))

Result: 25-0701 | V21 | €2,420.00 / 25-0702 | V9 | €1,090.00 / 25-0703 | V21 | €6,050.00 / 25-0704 | V0 | €880.00 / 25-0705 | V21 | €3,267.00 / 25-0706 | V9 | €545.0025-0701 | V21 | € 2.420,00 / 25-0702 | V9 | € 1.090,00 / 25-0703 | V21 | € 6.050,00 / 25-0704 | V0 | € 880,00 / 25-0705 | V21 | € 3.267,00 / 25-0706 | V9 | € 545,00

Step by step
  1. Excel starts with the inner function, XMATCH(I1:K1, A1:F1). It looks up each of the three names in the header row A1:F1.
  2. Entry is the 1st header, VAT code is the 5th and Amount is the 6th. XMATCH returns the array {1,5,6}, one position per name.
  3. CHOOSECOLS(A2:F7, {1,5,6}) now takes column 1 (entries), column 5 (VAT codes) and column 6 (amounts) from the six data rows.
  4. The block is 6 rows by 3 columns and spills from H3 to J8. Row 1 is 25-0701, V21, 2,4202.420; row 4 is 25-0704, V0, 880; row 6 is 25-0706, V9, 545.
  5. Type Account in K1 instead of Amount. XMATCH now returns {1,5,4}, and the third column of the block shows 4500, 4000, 4500, 4500, 4000, 4500. Only the names changed, not the formula.
  6. Type a name that is not in the headers, such as Amounts. XMATCH returns #N/A for it and the formula returns #N/A instead of the block. The error tells you at once that the name is wrong.

Watch out: Typing the numbers 1, 5, 6 by hand works today but returns the wrong columns without any error once the client inserts a column. The header lookup removes that risk.

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

Why it works

XMATCH turns names into positions, and CHOOSECOLS turns positions into columns, so the link between your workpaper and the export is the header text instead of a fixed place. If the client moves a column, the positions change and the result stays correct.

More to watch out for

  • A header with a trailing space, such as 'Amount ' in the export, is not found by XMATCH. You see #N/A, and the fix is to correct the name in I1:K1 or clean the header with TRIM.

Variations

=CHOOSECOLS(A2:F7, 1, 5, 6)
=CHOOSECOLS(A2:F7; 1; 5; 6)

Fixed numbers: shorter and fine for a one-off check on a file you have in front of you, but it does not survive a change in the layout.

=HSTACK(A2:A7, E2:F7)
=HSTACK(A2:A7; E2:F7)

Joining separate ranges with HSTACK gives the same block here, but it needs one reference per run of columns and does not follow a header name.

Master

Trial balance extract by header name, only balances above a threshold

You receive the trial balance (saldibalans) of Veldhuis Installatie BV as a sheet with six columns. Your workpaper needs account, name and closing balance, and only for accounts at or above the reporting threshold in I2, debit or credit.

The column names are in I1:K1 and the column to test is in I3, so the next reviewer can change them. The formula must name its parts and say clearly when nothing qualifies.

Sheet excerpt: H5 holds the formula
RowABCDEFGHIJKL
1AccountNameOpeningDebitCreditClosingColumnsAccountNameClosing
211001100Bank€52,000.00€ 52.000,00€310,000.00€ 310.000,00€295,000.00€ 295.000,00€67,000.00€ 67.000,00Reporting threshold500500
313001300Receivables€84,000.00€ 84.000,00€520,000.00€ 520.000,00€498,000.00€ 498.000,00€106,000.00€ 106.000,00Test onClosing
416001600Payables-€61,000.00€ -61.000,00€205,000.00€ 205.000,00€214,500.00€ 214.500,00-€70,500.00€ -70.500,00
518001800VAT payable-€9,500.00€ -9.500,00€41,000.00€ 41.000,00€43,200.00€ 43.200,00-€11,700.00€ -11.700,0011001100=LET( heads, A1:F1, data, A2:F9, view, CHOOSECOLS(data, XMATCH(I1:K1, heads)), size, ABS(CHOOSECOLS(data, XMATCH(I3, heads))), keep, size >= I2, IF(SUM(keep * 1) = 0, "No balances at or above the threshold", FILTER(view, keep)) )=LET( heads; A1:F1; data; A2:F9; view; CHOOSECOLS(data; XMATCH(I1:K1; heads)); size; ABS(CHOOSECOLS(data; XMATCH(I3; heads))); keep; size >= I2; IF(SUM(keep * 1) = 0; "No balances at or above the threshold"; FILTER(view; keep)) )Bank€67,000.00€ 67.000,00
640004000Payroll costs€0.00€ 0,00€338,470.00€ 338.470,00€0.00€ 0,00€338,470.00€ 338.470,0013001300Receivables€106,000.00€ 106.000,00
745004500Housing costs€0.00€ 0,00€420.00€ 420,00€0.00€ 0,00€420.00€ 420,0016001600Payables-€70,500.00€ -70.500,00
849504950Office expenses€0.00€ 0,00€310.00€ 310,00€0.00€ 0,00€310.00€ 310,0018001800VAT payable-€11,700.00€ -11.700,00
980008000Revenue€0.00€ 0,00€0.00€ 0,00€430,000.00€ 430.000,00-€430,000.00€ -430.000,0040004000Payroll costs€338,470.00€ 338.470,00
1080008000Revenue-€430,000.00€ -430.000,00
11
Formula cell (H5)InputSpilled result

Formula in H5

=LET(
  heads, A1:F1,
  data, A2:F9,
  view, CHOOSECOLS(data, XMATCH(I1:K1, heads)),
  size, ABS(CHOOSECOLS(data, XMATCH(I3, heads))),
  keep, size >= I2,
  IF(SUM(keep * 1) = 0, "No balances at or above the threshold", FILTER(view, keep))
)
=LET(
  heads; A1:F1;
  data; A2:F9;
  view; CHOOSECOLS(data; XMATCH(I1:K1; heads));
  size; ABS(CHOOSECOLS(data; XMATCH(I3; heads)));
  keep; size >= I2;
  IF(SUM(keep * 1) = 0; "No balances at or above the threshold"; FILTER(view; keep))
)

Result: 1100 | Bank | €67,000.00 / 1300 | Receivables | €106,000.00 / 1600 | Payables | -€70,500.00 / 1800 | VAT payable | -€11,700.00 / 4000 | Payroll costs | €338,470.00 / 8000 | Revenue | -€430,000.001100 | Bank | € 67.000,00 / 1300 | Receivables | € 106.000,00 / 1600 | Payables | € -70.500,00 / 1800 | VAT payable | € -11.700,00 / 4000 | Payroll costs | € 338.470,00 / 8000 | Revenue | € -430.000,00

Step by step
  1. LET names the first two parts: heads is the header row A1:F1 and data is the body A2:F9, eight accounts. Nothing is calculated yet.
  2. view: XMATCH(I1:K1, heads) looks up Account, Name and Closing in the headers and returns {1,2,6}. CHOOSECOLS(data, {1,2,6}) gives an 8 by 3 block: account, name and closing balance of all eight accounts.
  3. size: I3 holds Closing, XMATCH returns 6, and CHOOSECOLS(data, 6) is the closing column: 67,00067.000; 106,000106.000; -70,50070.500; -11,70011.700; 338,470338.470; 420; 310; -430,000430.000. ABS removes the signs: 67,00067.000; 106,000106.000; 70,50070.500; 11,70011.700; 338,470338.470; 420; 310; 430,000430.000.
  4. keep compares each size with I2, 500: 1, 1, 1, 1, 1, 0, 0, 1. Housing costs (420) and office expenses (310) fall below the threshold.
  5. SUM(keep * 1) is 6, not 0, so IF takes the FILTER branch. FILTER(view, keep) keeps rows 1, 2, 3, 4, 5 and 8 of the 8 by 3 block.
  6. The result spills from H5 to J10: 1100, Bank, 67,00067.000 down to 8000, Revenue, -430,000430.000. Set I2 to 500000 and every size is below it, SUM(keep * 1) is 0, and H5 shows No balances at or above the threshold.

Watch out: The mirror-image mistake is to leave out ABS: size >= I2 then drops every credit balance, because -70,50070.500, -11,70011.700 and -430,000430.000 are all below 500. Payables, VAT payable and revenue vanish from the list and the list still looks tidy.

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

Why it works

CHOOSECOLS is used twice on the same data with different jobs: once to build the columns you show, once to extract the column you test. Because the test column is not part of the output, the filter can use it without displaying it.

Do not use this when the layout of the file never changes and you need only a few columns: =CHOOSECOLS(A2:F9, 1, 2, 6) is simpler to review, and in Excel 2021 or earlier it does not work at all. A static alternative is Power Query, which also selects columns by name and survives layout changes, at the cost of refreshing by hand when the source changes.

More to watch out for

  • If the name in I3 does not match any header exactly, XMATCH returns #N/A, size is an error and the whole formula shows #N/A. Because the IF only tests SUM(keep * 1), the error is not hidden by the message text.
  • Pointing data at whole columns such as A:F makes Excel test about a million rows on every recalculation, and the empty rows count as balances of 0. Use the exact range or a Table.

Variations

=FILTER(CHOOSECOLS(A2:F9, 1, 2, 6), ABS(F2:F9) >= I2, "No balances at or above the threshold")
=FILTER(CHOOSECOLS(A2:F9; 1; 2; 6); ABS(F2:F9) >= I2; "No balances at or above the threshold")

Without LET and without header lookup: shorter, and if_empty is safe here because nothing is nested around it. Prefer it when the layout is fixed.

Common mistakes

Common mistakes
SymptomCauseFix
#VALUE! with no obvious causeThe formula returns #VALUE! and you cannot see why.One of the column numbers is 0 or larger than the width of array, for example 6 for a five-column range. Count the columns of the range you pass, not of the sheet.
0 where the source cell is emptyAn empty cell in a chosen column shows up as 0 in the result.Excel turns blanks in an array into 0. Format the column so zeros stay readable, or test the source column with ISBLANK before you read a 0 as a real figure.
Wrong columns after the export changedThe column numbers are typed in as fixed numbers and the layout of the export changes.Look the positions up with XMATCH on the header row, or use negative numbers when the column you need is always the last one.
#SPILL! although the formula is correctThe result is #SPILL! although the formula is correct.Something already sits in the cells the block needs. Click the error, choose Select Obstructing Cells and clear them.