Recipes / Recipe 8
Clean messy data: spaces, names, phone numbers, emails and 'numbers stored as text'
Formulas to normalize the data you get from forms and exports, plus a one-click script that strips the invisible characters that break lookups.
You'll need: Google Sheets (formulas also work in Excel 365 except REGEX functions).
Formulas (put them in a helper column)
=TRIM(SUBSTITUTE(A2, CHAR(160), " "))=LOWER(TRIM(A2))=PROPER(TRIM(A2))=REGEXEXTRACT(TRIM(A2), "^\S+")
=REGEXEXTRACT(TRIM(A2), "\S+$")=LET(d, REGEXREPLACE(TO_TEXT(A2), "\D", ""), d10, IF(AND(LEN(d)=11, LEFT(d,1)="1"), RIGHT(d, 10), d), IF(LEN(d10)=10, REGEXREPLACE(d10, "(\d{3})(\d{3})(\d{4})", "($1) $2-$3"), "CHECK: "&A2))=IFERROR(VALUE(REGEXREPLACE(TO_TEXT(A2), "[^0-9.\-]", "")), "")=ARRAYFORMULA(IF(A2:A="", , LOWER(TRIM(A2:A))))One-click clean-up script
Trims every selected cell in place and removes non-breaking spaces and zero-width characters (common in data pasted from websites and PDFs). Formulas are left alone.
- Extensions → Apps Script, paste, save, reload the sheet.
- Select the cells to clean, then Cleanup → Clean selected cells.
/**
* Clean the selected cells in place: trims spaces, removes non-breaking and zero-width
* characters that break lookups, and collapses double spaces. Formulas are left untouched.
*/
function onOpen() {
SpreadsheetApp.getUi()
.createMenu('Cleanup')
.addItem('Clean selected cells', 'cleanSelection')
.addToUi();
}
/** Pure function: clean one value. Non-text values (numbers, dates) pass through. */
function cleanValue(value) {
if (typeof value !== 'string') return value;
return value
.replace(/[\u200B-\u200D\uFEFF]/g, '') // zero-width characters
.replace(/\u00A0/g, ' ') // non-breaking spaces
.replace(/[ \t]+/g, ' ') // runs of spaces/tabs
.replace(/ *\n */g, '\n') // spaces around line breaks
.trim();
}
function cleanSelection() {
const range = SpreadsheetApp.getActiveRange();
if (!range) return;
const values = range.getValues();
const formulas = range.getFormulas();
let changed = 0;
const next = values.map((row, r) => row.map((v, c) => {
if (formulas[r][c]) return formulas[r][c]; // keep formulas as formulas
const cleaned = cleanValue(v);
if (cleaned !== v) changed++;
return cleaned;
}));
// setValues treats strings starting with "=" as formulas, which restores them unchanged.
range.setValues(next);
SpreadsheetApp.getActiveSpreadsheet().toast('Cleaned ' + changed + ' cell(s).');
}
Good to know
- When you're happy with a helper column, copy it and use Paste special → Values only over the original.
- The phone formula is for US/Canada numbers. International numbers need country-specific rules; flagging them with “CHECK” is safer than guessing.
- If you use both this script and the dedupe script in one project, keep just one
onOpenand add both menu items to it.
Do it yourself
Recipe Club: $12/month
Prefer to set things up yourself? Join the Recipe Club and get access to a private GitHub repository of ready-made, tested automations for Sheets, Apps Script, Python and Node. Each one comes with setup notes and sample data.
- A new recipe added every week
- Everything in the free library, plus the longer, more complete versions
- Use them in your own business as much as you like
- Cancel anytime by email (or the Stripe customer portal once available)
Recipe Club opens soon: join the waitlist
You'll need a free GitHub account. After checkout, reply with your GitHub username and we'll send the repo invite, usually within one business day.
Or buy a one-time recipe pack ($19–$29)
- Clean Data Pack $19
Dedupe, cleaning, merging and normalizing scripts and formulas for messy exports, with a sample sheet.
Coming soon - Forms & Inbox Pack $19
Form auto-replies, request routing, a lead log and follow-up nudges, ready to paste into Apps Script.
Coming soon - Money Ops Pack $29
Invoice reminders, a monthly revenue dashboard with QUERY, a receipts log and nightly backups.
Coming soon
Written with AI assistance. Script logic is unit-tested; formulas follow documented Google Sheets behavior. Always try new automations on a copy of your sheet first.