How TEXTJOIN works
TEXTJOIN walks through every cell you give it, sticks the delimiter between each value, and returns one string. The first argument is the separator (a comma, a semicolon, a line break, anything you want). The second is a TRUE/FALSE switch that controls whether empty cells get skipped. Everything after that is the values to join, given as ranges or individual references.
The skip-blanks switch is the part that makes TEXTJOIN better than the old & operator and CONCATENATE. With ignore_empty=TRUE, empty cells in the middle of a range vanish from the output. No double commas, no trailing separators, no manual cleanup.
Pair TEXTJOIN with IF inside an array to filter the list before joining: rows that don't match get returned as empty strings, and ignore_empty=TRUE strips them out. That gives you a one-formula conditional join with no helper column.
Arguments
| Argument | Type | Required | Description |
|---|---|---|---|
| delimiter | text | ✓ Required | The separator placed between each value. Most common: ", " (comma-space), "; " (semicolon-space), or CHAR(10) for a line break. Can be a literal string or a cell reference. |
| ignore_empty | boolean | ✓ Required | TRUE skips empty cells so you don't get double delimiters. FALSE keeps every cell, blanks included, which produces strings like 'a,,b' when there are gaps. No default, you must supply this argument. |
| text1 | range or text | ✓ Required | The first value, range, or array to join. A range like A2:A10 joins every cell in order; a single cell or literal string also works. |
| text2, ... | range or text | ✗ Optional | Additional ranges or values to append. Up to 252 text arguments. Each one is joined onto the running string with the delimiter between. |
Join a column of names into one comma-separated string
The classic case. A list of names sitting in column A, and you want them rolled up into a single sentence-friendly string. Pick a delimiter, set ignore_empty to TRUE, point at the range.
=TEXTJOIN(", ", TRUE, A2:A6)- •
", "-> the delimiter: comma followed by a space, the most natural reading separator - •
TRUE-> skip empty cells, so a gap in the middle doesn't produce a double comma - •
A2:A6-> the range to join, in order, top to bottom - •
Result-> "Sarah, James, Maria, David, Alex" lands in a single cell - •
Read order-> TEXTJOIN walks the range top-down, left-to-right within rows, exactly the order you see them
| A | B | C | D | |
|---|---|---|---|---|
| 1 | Name | Roster | ||
| 2 | Sarah | Sarah, James, Maria, David, Alex | ||
| 3 | James | |||
| 4 | Maria | |||
| 5 | David | |||
| 6 | Alex |
ignore_empty: TRUE vs FALSE when the source has gaps
Real-world data has holes. A roster with cells someone forgot to fill, an export with missing rows, a list someone half-cleaned. The second argument decides whether TEXTJOIN treats those gaps as nothing or as empty values that still get a delimiter.
Same source range, two formulas, one tiny argument flip. The difference is what the result actually looks like when you paste it into an email.
=TEXTJOIN(", ", TRUE, A2:A8) vs =TEXTJOIN(", ", FALSE, A2:A8)- •
TRUE (column C)-> blanks vanish, output reads cleanly: 'Apple, Banana, Cherry, Date, Elderberry' - •
FALSE (column D)-> blanks still get a delimiter on each side: 'Apple, , Banana, Cherry, , Date, Elderberry' - •
Same range, same delimiter-> the only thing changing is the second argument - •
Default behavior-> neither value is the default, you must supply one or the other or Excel rejects the formula - •
Rule of thumb-> use TRUE 95% of the time, FALSE only when you specifically need a fixed-width style with placeholders
| A | B | C | D | |
|---|---|---|---|---|
| 1 | Fruit | ignore_empty = TRUE | ignore_empty = FALSE | |
| 2 | Apple | Apple, Banana, Cherry, Date, Elderberry | Apple, , Banana, Cherry, , Date, Elderberry | |
| 3 | ||||
| 4 | Banana | |||
| 5 | Cherry | |||
| 6 | ||||
| 7 | Date | |||
| 8 | Elderberry |
Stack address parts on separate lines with CHAR(10)
TEXTJOIN's delimiter doesn't have to be a comma. CHAR(10) is the line-feed character on every modern Excel, which means you can use it as a delimiter to stack values on separate lines inside one cell.
Pulling street, city, and zip into one mailing-label cell is the textbook use. The formula puts a line break between each piece and the result is a properly formatted three-line address sitting in a single cell.
=TEXTJOIN(CHAR(10), TRUE, A2:A4)- •
CHAR(10)-> the line-feed character, a hard line break inside a cell - •
TRUE-> skip blanks so a missing apartment line doesn't leave a gap - •
A2:A4-> the three address parts: street, city + state, zip - •
Visual catch-> the line breaks ARE in the cell, but they only render visually when Wrap Text is enabled - •
Output cell setup-> select C2, then ribbon Home tab, click Wrap Text, then drag the row taller so all three lines show
| A | B | C | D | |
|---|---|---|---|---|
| 1 | Address line | Mailing label | ||
| 2 | 742 Evergreen Terrace | 742 Evergreen Terrace Springfield, IL 62704 | ||
| 3 | Springfield, IL | |||
| 4 | 62704 | |||
| 5 | ||||
| 6 | ||||
| 7 | ||||
| 8 |
TEXTJOIN + IF: list only the active employees
Drop an IF expression inside TEXTJOIN's text argument and you get a one-formula filtered concatenation. The IF returns the name when the status matches, an empty string when it doesn't. ignore_empty=TRUE strips out the empties, leaving a clean comma-separated list of just the rows that qualify.
On Excel 365 you can type this and press Enter; on Excel 2019 wrap it in an array entry with Ctrl+Shift+Enter. Either way, no helper column.
=TEXTJOIN(", ", TRUE, IF(B2:B11="Active", A2:A11, ""))- •
", "-> delimiter between joined names - •
TRUE-> skip empties (the rows IF returned as blank) - •
IF(B2:B11="Active", A2:A11, "")-> row-by-row: if status is Active return the name, otherwise return empty string - •
B2:B11-> the criterion column (purple range) - •
A2:A11-> the value column to pull names from (blue range) - •
Result-> "Sarah Chen, Maria Santos, David Brown, Alex Kim, Jenny Liu, Mark Reilly", the six rows where status was Active
| A | B | C | D | E | |
|---|---|---|---|---|---|
| 1 | Employee | Status | Active list | ||
| 2 | Sarah Chen | Active | Sarah Chen, Maria Santos, David Brown, Alex Kim, Jenny Liu, Mark Reilly | ||
| 3 | James Miller | Inactive | |||
| 4 | Maria Santos | Active | |||
| 5 | David Brown | Active | |||
| 6 | Emma Davis | On leave | |||
| 7 | Alex Kim | Active | |||
| 8 | Carlos Gomez | Inactive | |||
| 9 | Jenny Liu | Active | |||
| 10 | Mark Reilly | Active | |||
| 11 | Rachel Wood | Inactive |
Build a paste-ready email distribution string
Outlook, Gmail, and almost every mail client accept a list of recipients separated by semicolons. If your team's emails live in a column, TEXTJOIN with '; ' as the delimiter turns that column into one string you can paste straight into the To: field.
=TEXTJOIN("; ", TRUE, A2:A11)- •
"; "-> semicolon-space, the format Outlook and most mail clients expect between recipients - •
TRUE-> skip blanks so a missing email doesn't produce an invalid double-semicolon - •
A2:A11-> the email column - •
Workflow-> click the result cell, copy, paste into Outlook's To: field, every address resolves - •
Comma version-> replace "; " with ", " for Gmail and most webmail clients
| A | B | C | D | |
|---|---|---|---|---|
| 1 | Distribution string | |||
| 2 | sarah.chen@acme.co | sarah.chen@acme.co; james.miller@acme.co; maria.santos@acme.co; david.brown@acme.co; emma.davis@acme.co; alex.kim@acme.co; carlos.gomez@acme.co; jenny.liu@acme.co; mark.reilly@acme.co; rachel.wood@acme.co | ||
| 3 | james.miller@acme.co | |||
| 4 | maria.santos@acme.co | |||
| 5 | david.brown@acme.co | |||
| 6 | emma.davis@acme.co | |||
| 7 | alex.kim@acme.co | |||
| 8 | carlos.gomez@acme.co | |||
| 9 | jenny.liu@acme.co | |||
| 10 | mark.reilly@acme.co | |||
| 11 | rachel.wood@acme.co |
Where people go wrong
- Forgetting the second argument or setting it to FALSE
If the source range has gaps and ignore_empty is FALSE (or omitted in a way that defaults to FALSE in older clients), the output looks like 'Sarah,,Alex' with double commas wherever a cell was blank. Looks broken to anyone reading it.
Fix: Default to TRUE for ignore_empty unless you have a specific reason to keep blanks. Type it explicitly every time: =TEXTJOIN(", ", TRUE, A2:A20). - Joining numbers without formatting them first
TEXTJOIN sees the underlying number, not the cell's display format. A cell showing '$1,234.50' joins as '1234.5' because that's the raw value Excel stores. Currency, percent, and thousands-separator formatting all evaporate.
Fix: Wrap each numeric reference in TEXT() with the format you want preserved: =TEXTJOIN(", ", TRUE, TEXT(B2:B20, "$#,##0.00")). The TEXT call locks the display format into the joined string. - CHAR(10) line breaks invisible because Wrap Text is off
You write =TEXTJOIN(CHAR(10), TRUE, A2:A4), expect three stacked lines, and the cell shows everything on one line with weird square boxes. The line breaks are in the cell, they're just not being rendered.
Fix: Select the result cell, ribbon Home tab, click Wrap Text. Then drag the row height taller until all the lines show. Wrap Text is per-cell, so applying it once doesn't carry to other cells you fill the formula into. - Hitting the 32,767-character cap on huge joins
TEXTJOIN's result is capped at 32,767 characters, the same limit as any Excel cell. Joining a column of 5,000 long descriptions returns #VALUE! when the string would exceed the cap. The error gives no hint that length was the cause.
Fix: Split the join into chunks (=TEXTJOIN(...) for the first 1,000, another for the next, then concatenate the chunks), or filter the source range first to cut the row count down. If you genuinely need that much text in one place, Excel is the wrong tool, use Power Query or a database.
Notes
- TEXTJOIN was added in Excel 2019. It's available on Excel 2019, Excel 2021, Excel 365, and Excel Online, on Windows, Mac, iOS, Android, and the web.
- CHAR(10) is the line-feed character on every modern Excel. CHAR(13) is carriage-return; you almost never need it on its own. Combine them as CHAR(13)&CHAR(10) only if you're exporting to a system that demands Windows-style CRLF inside the cell.
- The second argument (ignore_empty) is required, no default. Excel rejects =TEXTJOIN(", ", A2:A6) outright.
- text1, text2, ... can be ranges, single cells, or literal strings. Mix and match: =TEXTJOIN(", ", TRUE, "Team:", A2:A6) prefixes the joined list with the word Team:.
- Combine TEXTJOIN with IF (TEXTJOIN(", ", TRUE, IF(condition, value, ""))) for conditional concatenation in one cell, no helper column.
- Pair TEXTJOIN with TRIM if the source data has stray leading or trailing spaces: =TEXTJOIN(", ", TRUE, TRIM(A2:A20)). Cleans up imported data before it lands in the joined string.
- Older Excel versions (2016 and earlier) don't have TEXTJOIN. Falling back means using & (a&", "&b&", "&c) or CONCATENATE, neither of which can skip blanks, so empty cells leave double delimiters in the output.
Now prove it
Reading about TEXTJOIN is one thing.
Building a one-cell distribution string for a 200-person training program at 4:55pm on a Friday is completely different.
These exercises drop TEXTJOIN into real workplace situations where the alternative is a manual copy-paste-and-pray.
Here's the thing about TEXTJOIN.
You can read this page twice and still hesitate when ops drops a 400-row CSV on you and asks for one paste-ready email string by lunch.
That gap, between knowing what TEXTJOIN does and being able to write one cleanly 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 TEXTJOIN for free →