---
title: "JOIN and TEXTJOIN in Google Sheets: syntax and examples"
canonical: "https://www.owox.com/blog/articles/join-textjoin-functions-google-sheets"
updated: "2026-10-05"
---

# JOIN and TEXTJOIN in Google Sheets: join a range into one cell

JOIN and TEXTJOIN merge the values of a range into one text, with a separator between them. TEXTJOIN can skip empty cells and accepts ranges of any shape; JOIN takes single rows or columns only. This guide shows both, with lists built by FILTER, UNIQUE and SORT, line breaks as a separator, and joining row by row.

[Google Sheets Tips](/blog/topics/google-sheets-tips) · Updated October 2, 2026 · [Vadym Kramarenko](/team/vadym-kramarenko) · 7 min read

![JOIN and TEXTJOIN in Google Sheets: join a range into one cell](https://cdn.owox.ai/www/webflow/6a1493275a86f318cbe4f1e0_MASTER-TEXT-JOINING.png/public)

JOIN and TEXTJOIN merge the values of a range into one text, with a separator of your choice between them:

> `=JOIN(", ", B3:B10)`

> `=TEXTJOIN(", ", TRUE, B3:B10)`

Both return a list such as “Apple, Samsung, Dell”. TEXTJOIN has one more argument, which decides what happens to empty cells, and accepts ranges of any shape.

|  | JOIN | TEXTJOIN |
| --- | --- | --- |
| Syntax | `JOIN(delimiter, value_or_array1, ...)` | `TEXTJOIN(delimiter, ignore_empty, text1, ...)` |
| Empty cells | Always included, so separators double up | Skipped when ignore\_empty is TRUE |
| A range of several rows and columns | #VALUE! | Joined row by row |
| Several ranges in one formula | Yes | Yes |

In practice TEXTJOIN with TRUE covers everything JOIN does, and it is the one to learn. JOIN remains a shorter spelling for a clean row or column.

## JOIN

> `=JOIN(delimiter, value_or_array1, [value_or_array2, ...])`

*   **delimiter:** the text to put between the values. It can be empty, `""`.
*   **value\_or\_array:** values, or ranges of a single row or a single column.

> `=JOIN("/", B3:E3)`

![Google Sheets with brand, item, model and price in columns B to E and the formula =JOIN(“/”, B3:E3) returning Apple/Laptop/MacBook Air M2/999](https://cdn.owox.ai/www/webflow/67ee79e06c2d5acf10fd2c8c_AD_4nXcM55m6KombcupJGd2k1raBJzaIgUMn0mcnzrWCXMyqtHiDHG3B_x2Xuavz8d2gigHnu-wNawdi0BTcPlGSCpbOD93lRhRvik4NX1S1CP7a4r_omREDWQt5qXioKGIeu98ORp9Q9w.png/public)

Numbers and dates are joined the way the cells display them, with their thousands separator or date format:

> `=JOIN("/", E3:F3)`

![Google Sheets with arrival and despatch dates in two columns and the formula =JOIN(“/”, E3:F3) returning the two dates as text](https://cdn.owox.ai/www/webflow/67ee79df808bb4bee00e116d_AD_4nXcFLP1YeW0ZeBoWJGUKq__EGfU-V4y5BgaMybUkg_48PCrrWiAHD6qT12zOI2uDYoqFec-5HlxMfQSSiEL7NRJzSlw1OdB93CzfnU-zkJJVe5IGO9TwDaaLE8Khsx5g47Jnn6D.png/public)

That is a difference from the ampersand: `=E3 & "/" & F3` on the same cells returns the underlying serial numbers, such as 45583/45588. More on the ampersand in the guide to [CONCATENATE](/blog/articles/concatenate-and-ampersand-google-sheets).

JOIN accepts several ranges, joined one after another:

> `=JOIN("-", B3:B5, C3:C5)`

![Google Sheets with brands in column B and representatives in column C and the formula =JOIN(“-”, B3:B5, C3:C5) returning the three brands followed by the three names](https://cdn.owox.ai/www/webflow/67ee79df4b51ae10caae9944_AD_4nXexdSjZEwthOcSQkDlpSy9m25w9jGqafyGI5zWMfx80o3EoqNAlc_X68eQgms1-69foN3gsrGJTpdfq1GzghLpEi2Z4jjqJ3NEYh2DbE_QqpHqh5rJOUbpqc_Hq8SwngmrtlI_0RQ.png/public)

## TEXTJOIN

> `=TEXTJOIN(delimiter, ignore_empty, text1, [text2, ...])`

*   **delimiter:** the text between the values.
*   **ignore\_empty:** TRUE to skip empty cells, FALSE to keep them.
*   **text1, text2, …:** values or ranges, of any shape.

With FALSE, an empty cell leaves two separators in a row:

> `=TEXTJOIN("/", FALSE, B3:E3)`

![Google Sheets where some rows have an empty model cell and the formula =TEXTJOIN(“/”, FALSE, B3:E3) returns texts with a double slash, such as Apple/Laptop//999](https://cdn.owox.ai/www/webflow/67ee79df9f84d939892bd575_AD_4nXd88CuI7xOTpb9NlpNjEXRIHbQwDUQPYq3CwWUph-SDqd3KULPL8SgEUaCim6UDV51HKCJSxWijkERegCmkQ5pGujbOdN10wNjyBpHN0FxhJwSPZYq-Tttb_y5aDlI0hDZw1v-Q.png/public)

With TRUE, the gap disappears:

> `=TEXTJOIN("/", TRUE, C3, B3, D3, E3)`

![Google Sheets with the formula =TEXTJOIN(“/”, TRUE, C3, B3, D3, E3) returning the values of each row without double slashes where a cell is empty](https://cdn.owox.ai/www/webflow/67ee79e05926dde1ca3bf12c_AD_4nXcLuHBw-QUJucnieUcuIPgLC30XarAgyDsms4tUnIm_lic48jhH33dt7fNj6xEtClsThjjRHk4R2RE-ZUicQVTNe3SwigBc5A0VqpFAhGOFYdWMB6lLvBsMxkMjrRvmtSrmsmAwyg.png/public)

The arguments can be single cells in any order, which lets the formula rearrange the columns as it joins them: here the item comes before the brand.

> `=TEXTJOIN(" ", TRUE, E3, B3, C3, D3)`

![Google Sheets with a call-to-action text in column E and the formula =TEXTJOIN(” “, TRUE, E3, B3, C3, D3) returning phrases such as Buy from us Apple Laptop MacBook Air M2](https://cdn.owox.ai/www/webflow/67ee79df79e77e25784894ee_AD_4nXcqtID7w6lVrdDIp2Z1LfJya0a30YGXyb5iAqfh91dBEgJlqwL01jggkWQZymoJmooG7TTeKrpXKa3ZFoSO98FpQ-Z90bAnRnRZ-X_8kq5ziIWR3E6EtnN_Qnt1C96I_F3EdgVAbw.png/public)

## The Turning Point

OWOX Data Marts

See your first report built in real time. _15 minutes._

1.  Connect your data warehouse
2.  Pick your metrics
3.  Get a live Google Sheets report

In the time it takes to write a ticket. Then imagine never writing that ticket again.

[Book a Demo](/book-a-call)

We'll use your actual use case

## A column into a list

The most common use: a column of values turned into one comma-separated cell, for a filter, an email field or a query.

> `=TEXTJOIN(",", TRUE, B3:B10)`

![Google Sheets with brands in B3:B10 and the formula =TEXTJOIN(“,”, TRUE, B3:B10) returning all of them in one cell, separated by commas](https://cdn.owox.ai/www/webflow/67ee79e012ed14c8c1e736a1_AD_4nXesdiLm2B2ZuG481jOBIkosl76VRLRu40LgTANeNmQ5vfk2eE1IFSy6KvGtYVvZjrjs1nJNtWZJIncN1iKRsera1XY4FMEZ5ndrXO2sFmsv9mGKWfX6GnW9tvqYQLPcQriBfvYJ.png/public)

### Without duplicates, sorted

> `=TEXTJOIN(", ", TRUE, SORT(UNIQUE(B3:B10)))`

![Google Sheets with repeated brands in column B and a formula with SORT and UNIQUE returning Apple, Dell, Lenovo, Samsung](https://cdn.owox.ai/www/webflow/67ee79e1dd0a6b1316f12dc2_AD_4nXdPw9wzkLVHQtx5k3pSgEW9T-9GYADTWPUaeyque-aayuz1lAATYZ6pkTC7YtCP_1tJSRuxPvZJOZRAda79qkUcpkGQvRMJz_FpvQZyhim_OZObs0UkpXNpdbhdHPzuKnp2aaVWlg.png/public)

[UNIQUE](/blog/articles/unique-function-google-sheets) removes the repeats and [SORT](/blog/articles/sort-and-sortn-functions-google-sheets) orders what is left.

### Only the rows that meet a condition

> `=TEXTJOIN(", ", TRUE, FILTER(D3:D10, E3:E10 > 1000))`

![Google Sheets with models in column D and prices in column E and a TEXTJOIN formula over FILTER returning Galaxy S23, XPS 13 Plus, ThinkPad X1](https://cdn.owox.ai/www/webflow/67ee79df918b0aeff3135ccd_AD_4nXejpvJvMmfCqZp3v_JMHEMDl8Bg8n6MTldWceuvFpQynJ1LR3gxgLaFSetwh_o11nK3Lymq9T3MMfNDG79V0NbBh82ckcSeT353KRX9YOcszsEbtQybwK73uaf7ppCLqqksja2tSg.png/public)

[FILTER](/blog/articles/google-sheets-filter-function) keeps the models priced above 1000 and TEXTJOIN lists them. When no row matches, FILTER returns #N/A and so does the formula; wrap it in IFNA to show a text: `=IFNA(TEXTJOIN(", ", TRUE, FILTER(D3:D10, E3:E10 > 5000)), "none")`.

### Each value with a label

Build the pieces with ampersands inside ARRAYFORMULA, then join them:

> `=ARRAYFORMULA(JOIN("; ", C3:C4 & " <" & D3:D4 & ">"))`

![Google Sheets with names in column C and email addresses in column D and a formula returning each name followed by its address in angle brackets, separated by semicolons](https://cdn.owox.ai/www/webflow/67ee79e0cae088d1431a8c2e_AD_4nXfcInXMCXzxaMNODD8TJ1A7QX_FidGLV7ROZ8CLA6L54U2q60ArWGx76MY5U1MMQ2KBM9QLmtLjXc0_IReUHyAUnJL3AOkllOsd8sV0bv6T9t62bc9_Pdt7j70RF4CW1r_SNycr.png/public)

The result can be pasted into the “To” field of an email. If some rows are incomplete, JOIN keeps the empty shells:

![Google Sheets where a missing name or email leaves an address without a name and a name with empty angle brackets in the joined list](https://cdn.owox.ai/www/webflow/67ee79e022771a3754432b55_AD_4nXfSCVf-sqylBHAA17YbaVQywQ-fBZqhJzduAsKAmysw4NTF0QVcluBlka7mq-Hol3-43obNDhhpf_Tv6lvIPnw71F___gLgU9MvgL6vGqClPbCgm-nO8FH3v2Er1_TjwNM12VBT.png/public)

Filter the incomplete rows out before joining: `FILTER(C3:C6 & " <" & D3:D6 & ">", C3:C6 <> "", D3:D6 <> "")`.

## A line break as the separator

[CHAR(10)](/blog/articles/char-function-google-sheets) is a line break, so the joined values appear one under another inside the cell:

> `=TEXTJOIN(CHAR(10), TRUE, C3:D3)`

![Google Sheets with the formula =TEXTJOIN(CHAR(10), TRUE, C3:D3) returning the item and the model on two lines in one cell](https://cdn.owox.ai/www/webflow/67ee79df41b9ade55dc14459_AD_4nXe2BDUctmWaf5RXIU63Dz5B-DUETUBnWs_fupnFm6hnMFseRV10MZL92iZ1Lf_RIervwpIpg0GGfRiR-dUuKUpGTaeOK93m1CQDjj5-7aflETBF4ksbZ069VjC4-gb9udezx0HS.png/public)

## One joined text per row

TEXTJOIN returns a single value, also inside ARRAYFORMULA: given a table, it joins everything into one cell. To get one result for each row from a single formula, apply it row by row with BYROW:

> `=BYROW(B3:D10, LAMBDA(row, TEXTJOIN(" ", TRUE, row)))`

BYROW passes each row of B3:D10 to TEXTJOIN in turn and returns a column of results. The alternative is the plain formula `=TEXTJOIN(" ", TRUE, B3:D3)` filled down.

## Split and join again

[SPLIT](/blog/articles/how-to-split-cells-in-google-sheets) cuts a text into parts and JOIN puts them back with another separator, which changes the delimiter of a list in one step:

> `=JOIN(", ", SPLIT(D3, " "))`

![Google Sheets with model names in column D and the formula =JOIN(“, “, SPLIT(D3, “ “)) returning MacBook, Air, M2](https://cdn.owox.ai/www/webflow/67ee79e01abeead185972572_AD_4nXdZ0xC8-FIgNnxKFEUrJ6KrXsGGdKOD9IWw9agTuOu5RQyEOnqb8cbiwVuVvKVl67C2e6moBRX6RDzvxI5mlYzrbji7u949pHmv_ME96K_wIxqZ_u6Jn7FtxNjkzHk46pqw_I81Ig.png/public)

For a plain replacement of one separator with another, [SUBSTITUTE](/blog/articles/substitute-function-google-sheets) is shorter: `=SUBSTITUTE(D3, " ", ", ")`.

## Errors and wrong results

**⚠️ Error:** #VALUE! in JOIN.

✅ **Solution:** The range has several rows and several columns. JOIN takes a single row or a single column; use TEXTJOIN for a block.

**⚠️ Error:** #N/A

✅ **Solution:** A FILTER or a lookup inside the formula found nothing. Wrap the formula in IFNA.

**⚠️ Error:** Separators with nothing between them: “A, , B”.

✅ **Solution:** There are empty cells in the range. Use TEXTJOIN with TRUE as the second argument. Cells that hold a space are not empty; clean them with [TRIM](/blog/articles/trim-clean-t-functions-google-sheets).

**⚠️ Error:** A date is joined as a number such as 45583.

✅ **Solution:** The date was joined with an ampersand, or calculated inside the formula. Format it with [TEXT](/blog/articles/text-function-google-sheets): `TEXT(A2, "yyyy-mm-dd")`.

**⚠️ Error:** The joined number cannot be used in calculations.

✅ **Solution:** The result of JOIN and TEXTJOIN is always text.

## Related Google Sheets functions

*   [CONCATENATE and the ampersand](/blog/articles/concatenate-and-ampersand-google-sheets): Join a few cells.
*   [How to split cells](/blog/articles/how-to-split-cells-in-google-sheets): The reverse operation.
*   [FILTER](/blog/articles/google-sheets-filter-function): Choose what goes into the list.
*   [UNIQUE](/blog/articles/unique-function-google-sheets): Remove repeats before joining.
*   [CHAR](/blog/articles/char-function-google-sheets): Line breaks and special characters as separators.
*   [Array formulas](/blog/articles/array-formulas-google-sheets): Build the pieces for a whole range.
*   [QUERY with CONCATENATE](/blog/articles/query-with-concatenate-google-sheets): Joined columns in a query.

## A joined list is a report built by hand

TEXTJOIN over FILTER is a small report: “all products above 1000, in one cell”. It is correct for the rows in the range today. When the rows come from an export, the list is as old as the export, and nothing in the cell says so; the next person copies the list into an email as if it were current.

The [OWOX Data Marts extension for Google Sheets](https://workspace.google.com/marketplace/app/owox_data_marts/94902851409) covers that half. A data analyst publishes a data mart (a table or an SQL query in your data warehouse) and makes it available for reports. In Sheets you open the extension, pick the data mart, tick the columns you want and run it. The rows land in a tab, ready for your formulas.

![Google Sheets with the OWOX Data Marts extension open beside an ad spend table: the Unified Ad Spend data mart, nine of fourteen columns ticked and a Save & Run button – the rows in the sheet come from a governed data mart, not a pasted export](https://cdn.owox.ai/www/content-marketing-article/join-textjoin-functions-google-sheets/screens/1.png/public)

What changes for the person who maintains the sheet:

*   **Refresh replaces re-export.** _Refresh current report_ in the extension menu re-runs the same pull, and a scheduled refresh keeps the tab current without anyone touching it.
*   **The source is written on the sheet.** The header cell of an imported tab carries a note with the data mart it came from, the time of the import and a link to the report.
*   **No SQL and no warehouse access needed.** The analyst decides which data marts and columns are available. You choose from that list.

The extension does not write or change the analyst’s SQL. The lists your formulas build are then drawn from the current rows on every refresh. The extension comes with the OWOX Cloud plans of [OWOX Data Marts](https://www.owox.com/app-signup); [spreadsheet reporting](/features/spreadsheet-reporting) describes both ways data reaches a sheet.

## Your New Normal

Turn your data into decisions.

Governed data marts give you the clean foundation ML needs to actually work.

*   No AI hallucinations
*   Analyst-governed definitions
*   Every number traces to SQL

[Get started free](https://www.owox.com/app-signup)

## FAQ

## Frequently Asked Questions

Are there any limitations when using JOIN and TEXTJOIN in formulas?

JOIN accepts only single rows or single columns: a block of several rows and columns returns #VALUE!, while TEXTJOIN joins it row by row. JOIN cannot skip empty cells, so separators double up. Both always return text, both return one value even inside ARRAYFORMULA (use BYROW for one result per row), and the result has to fit into a single cell.

How does TEXTJOIN differ from CONCATENATE in Google Sheets?

TEXTJOIN simplifies concatenation by working with ranges instead of individual cells and offers features like skipping empty cells. CONCATENATE requires manual selection of each cell and doesn’t allow custom delimiters, making TEXTJOIN a more efficient and flexible option for most scenarios.

What delimiters can be used with JOIN and TEXTJOIN?

Both JOIN and TEXTJOIN support any custom delimiter, including commas, spaces, semicolons, or even line breaks using CHAR(10). You can specify the delimiter to suit your needs, ensuring your combined data is formatted for readability or compatibility with other tools.

Can I use JOIN and TEXTJOIN to combine data from multiple ranges?

Yes, both accept several ranges in one formula: JOIN("-", B3:B5, C3:C5) joins the first range and then the second. The difference is the shape of each range: JOIN needs single rows or columns, TEXTJOIN also takes blocks, and only TEXTJOIN can skip the empty cells.

How does the TEXTJOIN function handle empty cells?

The TEXTJOIN function can ignore empty cells if the ignore\_empty parameter is set to TRUE. This ensures cleaner, more cohesive results by excluding blanks from the output, making it ideal for working with incomplete datasets or irregularly populated ranges.

What is the purpose of the JOIN function in Google Sheets?

The JOIN function combines values from a single row or column into a single text string, separated by a specified delimiter. It’s useful for creating summaries, formatted lists, or consolidated data outputs, making it an essential tool for organizing and presenting information effectively.

## Who wrote this

![Vadym Kramarenko](https://cdn.owox.ai/www/webflow/6798e703afdf787334941cde_Vadym-Kramarenko.png/public)

[Vadym Kramarenko](/team/vadym-kramarenko) · Growth Marketing Manager

Vadym Kramarenko is a Growth Marketing Manager at OWOX, where he drives user acquisition and product-led growth strategies. He hosts the OWOX podcast, interviewing analytics professionals about data-driven marketing, attribution, and reporting best practices. Vadym specializes in turning complex analytics concepts into practical, actionable marketing frameworks.

[LinkedIn](https://www.linkedin.com/in/vadim-kramarenko/) · [All articles](/team/vadym-kramarenko)

[Google Sheets Tips](/blog/topics/google-sheets-tips)

## Related articles

[Google Sheets Tips · UNIQUE function in Google Sheets: syntax, examples and errors · October 2, 2026](/blog/articles/unique-function-google-sheets)

[Google Sheets Tips · VLOOKUP in Google Sheets: formula, another sheet and examples · October 2, 2026](/blog/articles/vlookup-in-google-sheets)

[Google Sheets Tips · ARRAYFORMULA in Google Sheets: how to use array formulas · October 2, 2026](/blog/articles/array-formulas-google-sheets)

[See all articles →](/blog/articles)

## Book a call

You are booked. The invitation is on its way to , with the calendar invite and the meeting link.

[Reschedule](#)

[Cancel](#)

## Links

Pages this page links to, on this site and on docs.owox.com. Where the page has a Markdown twin, its address follows the link.

- [Google Sheets Tips](https://www.owox.com/blog/topics/google-sheets-tips) — /blog/topics/google-sheets-tips.md
- [Vadym Kramarenko](https://www.owox.com/team/vadym-kramarenko) — /team/vadym-kramarenko.md
- [CONCATENATE](https://www.owox.com/blog/articles/concatenate-and-ampersand-google-sheets) — /blog/articles/concatenate-and-ampersand-google-sheets.md
- [Book a Demo](https://www.owox.com/book-a-call) — /book-a-call.md
- [UNIQUE](https://www.owox.com/blog/articles/unique-function-google-sheets) — /blog/articles/unique-function-google-sheets.md
- [SORT](https://www.owox.com/blog/articles/sort-and-sortn-functions-google-sheets) — /blog/articles/sort-and-sortn-functions-google-sheets.md
- [FILTER](https://www.owox.com/blog/articles/google-sheets-filter-function) — /blog/articles/google-sheets-filter-function.md
- [CHAR(10)](https://www.owox.com/blog/articles/char-function-google-sheets) — /blog/articles/char-function-google-sheets.md
- [SPLIT](https://www.owox.com/blog/articles/how-to-split-cells-in-google-sheets) — /blog/articles/how-to-split-cells-in-google-sheets.md
- [SUBSTITUTE](https://www.owox.com/blog/articles/substitute-function-google-sheets) — /blog/articles/substitute-function-google-sheets.md
- [TRIM](https://www.owox.com/blog/articles/trim-clean-t-functions-google-sheets) — /blog/articles/trim-clean-t-functions-google-sheets.md
- [TEXT](https://www.owox.com/blog/articles/text-function-google-sheets) — /blog/articles/text-function-google-sheets.md
- [Array formulas](https://www.owox.com/blog/articles/array-formulas-google-sheets) — /blog/articles/array-formulas-google-sheets.md
- [QUERY with CONCATENATE](https://www.owox.com/blog/articles/query-with-concatenate-google-sheets) — /blog/articles/query-with-concatenate-google-sheets.md
- [OWOX Data Marts](https://www.owox.com/app-signup)
- [spreadsheet reporting](https://www.owox.com/features/spreadsheet-reporting) — /features/spreadsheet-reporting.md
- [Google Sheets Tips · VLOOKUP in Google Sheets: formula, another sheet and examples · October 2, 2026](https://www.owox.com/blog/articles/vlookup-in-google-sheets) — /blog/articles/vlookup-in-google-sheets.md
- [See all articles →](https://www.owox.com/blog/articles) — /blog/articles.md
