Best Of
Re: Combine emails into a multiple-contact column / multi-contact column
@Brian_Richardson and @Neil Egsgard , I believe I found another choice that works better.
Instead of using split text, use javascript. It's more robust and gets past all the errors previously brought up.
BRIDGE METHOD 2 (Pretty fast and doesn't error due to extra characters)
Key Value: fast and flexible and doesn't error out due to extra delimeters. Also works for both semicolons and comma separated values.
Key Drawback: I don't know of any besides what was brought up earlier. Works great and reliably for me.
Here's the setup:
IMPORTANT: The column name where you place the comma separated emails is called "Combined Emails". The column where the contacts will go is called "Combined Contacts". Combined Contacts must be a contact column with "Allow multiple contacts per cell" Selected.
- Triggers:
- One trigger for when Rows are Changed in the "Combined Emails" column.
- One trigger for when Rows are Added
- Add the Smartsheet: Get Sheet step to your workflow with the following settings:
- Sheet: {{runtime.sheetID}}
- Add the Smartsheet: Get Row step to your workflow with the following settings:
- Sheet: {{runtime.sheetID}}
- Row ID: {{runtime.event.id}}
- Add the Smartsheet: Run Script (Javascript) step to your workflow with the following settings:
- Script Name: Choose any script name. Eg. Build Multi Contact From Combined Emails
- Script Parameters:
- Key #1: columns
- Value #1: Reference from your "Get Sheet" step, copy reference to "Columns". Eg. {{states.Get Column IDs.smartsheet.get_sheet.sheet.columns}}
- Key #2: columns
- Value #2: Reference from your "Get Row" step, copy reference to "Row". Eg. {{states.Get Row IDs.smartsheet.get_row.row}}
- Key #3: emailColumnTitle
- Value #3: Combined Emails
- USE THE SCRIPT I WILL PASTE BELOW THIS LIST CALLED "SCRIPT"
- Add the Smartsheet: Update Row step to your workflow with the following settings:
- Sheet: {{runtime.sheetID}}
- Row ID: {{runtime.event.id}}
- Cells:
- Key #1: Combined Contacts
- Value #1: Reference from the output of your Javascript step. Eg. {{states.Build Combined Contacts String.javascript.run_script.result}}
SCRIPT:
// Build Multi Contact From Combined Emails
// Returns a comma-separated email STRING for use in Smartsheet Update Row (multi-contact column).
// No limit on number of emails; uses all valid, deduped emails found.
function normalizeTitle(s) {
return String(s || "").trim().toLowerCase();
}
function isObject(x) {
return x !== null && typeof x === "object" && !Array.isArray(x);
}
function asColumns(columnsParam) {
if (Array.isArray(columnsParam)) return columnsParam;
if (isObject(columnsParam)) {
if (Array.isArray(columnsParam.sheet?.columns)) return columnsParam.sheet.columns;
if (Array.isArray(columnsParam.columns)) return columnsParam.columns;
}
throw new Error("columns must be an array (or an object containing sheet.columns)");
}
function asRow(rowParam) {
if (isObject(rowParam)) {
if (rowParam.cells) return rowParam;
if (isObject(rowParam.row) && rowParam.row.cells) return rowParam.row;
if (isObject(rowParam.result) && rowParam.result.cells) return rowParam.result;
if (isObject(rowParam.result?.row) && rowParam.result.row.cells) return rowParam.result.row;
}
throw new Error("row must be a row object (or an object containing row.cells)");
}
function getColumnIdByTitle(columnsArr, title) {
const wanted = normalizeTitle(title);
const col = (columnsArr || []).find((c) => normalizeTitle(c.title) === wanted);
if (!col || col.id == null) throw new Error("Column not found by title: " + title);
return Number(col.id);
}
function getCellValueByColumnId(rowObj, columnId) {
const cells = rowObj.cells;
if (Array.isArray(cells)) {
const cell = cells.find((c) => c && Number(c.columnId) === Number(columnId));
return cell ? (cell.value ?? cell.displayValue ?? "") : "";
}
if (isObject(cells)) {
for (const k of Object.keys(cells)) {
const cell = cells[k];
if (cell && Number(cell.columnId) === Number(columnId)) {
return cell.value ?? cell.displayValue ?? "";
}
}
}
return "";
}
function parseEmails(raw) {
const text = String(raw || "");
if (!text.trim()) return [];
// Handles extra commas, commas with spaces, semicolons, and newlines
const parts = text
.split(/[,;\n\r\t]+/g)
.map((s) => s.trim())
.filter(Boolean);
// Dedupe case-insensitively, preserve first occurrence casing
const seen = new Set();
const out = [];
for (const p of parts) {
const key = p.toLowerCase();
if (seen.has(key)) continue;
seen.add(key);
out.push(p);
}
return out;
}
function isValidEmail(email) {
return /^[^\s@]+@[^\s@]+.[^\s@]+$/.test(email);
}
// Script Parameters are variables directly in Bridge:
// columns, row, emailColumnTitle
if (!emailColumnTitle) throw new Error("emailColumnTitle is required");
const cols = asColumns(columns);
const r = asRow(row);
const emailColId = getColumnIdByTitle(cols, emailColumnTitle);
const combinedEmails = getCellValueByColumnId(r, emailColId);
const emails = parseEmails(combinedEmails).filter(isValidEmail);
// If blank, return empty string (Update Row will clear the cell if you pass empty)
if (emails.length === 0) return "";
// Return a comma-separated string (no spaces) for Update Row
return emails.join(",");
NeilKY
Re: Combine emails into a multiple-contact column / multi-contact column
FYI, currently there's a bug with Datamesh that will update ALL rows in the target column, if only ONE row is updated, if the source emails are not in alphabetical order and the destination is a multi-contact.
This can be very bad if you have an automation that updates the source email list and notifies people when an assignment has been made.
"Overwrite cells" must also be checked so unchecking this is a good workaround if it's feasible for you. Or just use one of the other methods above.
Hopefully this will be resolved soon.
NeilKY
Re: Combine emails into a multiple-contact column / multi-contact column
UPDATE - CORE OPTION!
@Joe Goetschel identified an option to combine contacts using the core app, no addons needed! It leverages cell linking to pull a text list of email addresses into a contact cell as contacts.
Note that this method requires manual intervention to set up, you cannot create cell links automatically in Smartsheet unless you use an addon like Control Center, Data Mesh, or Bridge; or you have a third party tool that can leverage the Smartsheet API or SDK.
Sheet 1: have your contacts listed as email addresses separated by commas, CHAR(10), or semicolon in a Text/Number column. You can use a formula to "piece together" your list of emails. For example, if you have three columns with emails in them, a simple =JOIN(Column1@row:Column3@row,",") will combine them and separate them with a comma.
You should have a text column cell with something like email1@email.com,email2@email.com,email3@email.com
NOTE - you must use email addresses here, not names. This won't work if you have names in the mix.
Sheet 2: in a Contact column, set to Allow multiple contacts, right click a cell and choose Link from Cell in Other Sheet. Choose the text cell from the first sheet that contains the list of emails.
That's it! It can take a few seconds, but you should see the contacts appear as working contacts in your second sheet.
Note that you could then use any number of methods to pull the resulting combined contact list back into your Sheet 1. An Index/Match, a Vlookup, another cell link, all would work to get the contacts back to the first sheet for use.
Brian_Richardson
Re: New Membership versus License Model
It is not helpful that that the term "Free" users is being applied to what was previously called "collaborators" because they are (or were) entirely different things. A Free user had a basic level account to try out smartsheet to see if it is the right solution for them and it was quite limited in its capabilities. The collaborators are people who interact with the sheets that licensed users build. They have no ability to edit the structure / formulas etc of the smartsheet they are given shared access to. They can only edit data in the cells (where access is given). They can be allocated access to "Admin", "Editor can share", "Editor cannot share", "Commenter" or "Viewer". full details of who can do what in the old and new model seems to be laid out in this article:
Its possible, BUT NOT CLEAR, that those with legacy collaborator model licenses may be able to continue to operate that way for the life of their licenes, but if not then this is a huge change to all the existing (legacy) smartsheet license holders. I hear people in smartsheet talking about the new model but no-one seems to be making it clear who that model applies to. The moment the member model is applied to my business that will trigger a change of platform for me.
This is my 10th year of being a licensed (legacy) user of Smartsheet and I currently have 10 licensed users on my account. Not a huge account but I bet thousands upon thousands of other business users are similar usage to mine.
If Smartsheet intends to force "legacy collaborators" into the new member model - the hundreds of collaborators (colleagues, clients and suppliers) who check boxes, select choices from drop-downs, put in comments in comments fields, fill out forms etc on our sheets created by the licensed users will ALL now be considered as "members" and required to have a full member license.
IF that is the case then Smartsheet just completely destroyed the model and I will have no choice other than to change to a different platform because there is no way that the collaborators (or myself) are going to pay for a full license for the miniscule amount of usage they have by updating fields in sheets.
Interesting how this massive change in license policy coincides with the acquisition of Smartsheet by Blackstone and Vista Equity Partners.
Barry Bowles
Re: Function() or @argument for "currently logged in user" for use in Sheet formulas
I see what you're saying. I did a little experimentation, and you can combine the contact columns in a helper column using the 'Join' command and a "," as a separator (actually works better just using both column names with +", "+ in between). However, the contacts have to be email addresses and not the email alias. Filtering off of the 'combined contacts' column from the sheet, I was able to filter off either/or in Dynamic View
Alan P.
Re: Count multiple criteria across 2 columns
1.) add 3 COUNTIFS
Use this if each row can only match one subgroup (no double-count risk):
=COUNTIFS([Project Name]:[Project Name], "House", Group:Group, HAS(@cell , "Server"))
COUNTIFS([Project Name]:[Project Name], "House", Group:Group, HAS(@cell , "Database"))
COUNTIFS([Project Name]:[Project Name], "House", Group:Group, HAS(@cell , "Help Desk"))
2.) If Group can contain multiple values: formula-driven helper (no clicking)
Create an [IT?] checkbox (or flag) column with a column formula:
=OR(HAS([Group]@row , "Server"), HAS([Group]@row , "Database"), HAS([Group]@row , "Help Desk"))
Then count:
=COUNTIFS([Project Name]:[Project Name], "House", [IT?]:[IT?], 1)
Re: Project Selector in Dashboard
@Ranjana No, but the Workable options:
- Project list (recommended)
- Create a “Project Index” sheet with columns: Domain, Project Name, Project Dashboard Link (URL)
- Build a report filtered to the Domain
- Add that report to the Domain dashboard (Report widget)
- Users click the link for the project they want (closest to a selector)
- Shortcut widget list
- Add a Shortcut widget with links to each project dashboard (works best if you have fewer projects)
- WorkApps navigation
- If you’re using WorkApps, create a Projects page/list and link each project dashboard there (users navigate/click; still not auto-open on dropdown)
Re: IF Formula
@HRrmc hi
You’re getting #UNPARSEABLE because the parentheses/commas in your second IF are off—your multiplication term accidentally includes an extra ,"" inside it.
Use this corrected formula:
=IF([Salary Per]@row = "Hourly", [Proposed Hourly Rate]@row * 2080, IF([Salary Per]@row = "Annually", [Current Salary Rate]@row * (1 + [Increase Percentage Salary]@row ), ""))
A couple quick checks:
- Make sure the text values match exactly:
"Hourly"and"Annually"(spelling/case/spaces). - [Increase Percentage Salary]@row should be stored as a percent (e.g., 5%) or a decimal (0.05)—your math assumes that.
Re: Docusign license required??
Yes, if you’re using the Smartsheet + DocuSign workflow action to generate documents, at least one person on your team must have a DocuSign license, even if the document doesn’t require signatures.
There isn’t a true “workflow workaround” for DocuSign-based generation without a license; the practical alternative is to generate documents using Smartsheet Document Builder without the DocuSign integration (i.e., don’t use the DocuSign workflow action).
Re: Join us for the Jumpstart 2026 Festival with Community!
Excited for festival season.





