How to Do a Mail Merge Without Microsoft Word

✉️ Document automation⏱️ 7 min readFree tool included

Mail merge has a reputation for needing Word, a wizard with six dialogs, and a spreadsheet wired in through ODBC. None of that is true anymore. The whole job — one template, many records, one document each — reduces to replacing placeholders in a file format that turns out to be a plain ZIP of XML. Here's the Word-free way, including the parts wizards traditionally handle: repeating rows and conditional paragraphs.

Advertisement

Why Word is optional: the tag-based approach

The classic stack couples three things: a field-code dialect (MERGEFIELD), a data connection (your spreadsheet through Word's wizard), and the app itself. The modern alternative decouples them. You write {{name}}, {{amount}}, {{due_date}} as ordinary text wherever the variable content goes. Your data lives in a CSV with a header row whose names match the tags. A merge engine — any merge engine — reads the document, swaps the tags, and writes one output per data row.

Plain-text tags have a quiet advantage beyond escaping Microsoft: they're readable by humans. Open the template in anything and the intent is obvious on the page, and the same template works in Word, Google Docs, LibreOffice, and any tool that understands double-brace syntax. A MERGEFIELD is a live field object that only Word fully understands; a tag is just text.

Step 1: write the template

Author the document wherever you like — Word without any special features, Google Docs (download as .docx), or LibreOffice. Where personalized content goes, type the tag: Dear {{name}}, … your starting salary of {{salary}} … signed, {{signer}}. Save as .docx. Two rules keep things smooth: tag names are case-sensitive, and a tag whose data is missing merges as an empty string, so {{Salarry}} won't error — it'll silently vanish, which is worse. Match names exactly.

Step 2: prepare the data

A CSV with a header row is enough for letters: name,role,salary,date,signer on the first line, one recipient per line after, quotes around values containing commas. For anything nested — a table of line items per invoice, a list of bonus milestones per offer — use JSON instead, where a field can hold an array of objects. Google Sheets exports CSV directly (File > Download > Comma Separated Values), and Excel's Save As CSV works the same way.

Step 3: merge in the browser

Open our DOCX Mail Merge tool, load the template, paste the CSV (or the JSON), and hit Merge. The tool reads the tags out of the template and shows which columns match — the misspelled-column warning is where you catch the silent-blank problem before it ships. Each row becomes a .docx; multiple rows arrive as a ZIP. Everything runs locally: the template is unzipped in memory, tags are replaced — including tags that Word's internal formatting splits across invisible run boundaries, the detail that defeats naive find-and-replace — and the package is rebuilt. Nothing uploads, which matters when the data is salaries, settlements, or patient letters.

The parts a wizard does: loops and conditionals

Repeating table rows are the feature people assume they need Word for. The syntax is a block: put {{#bonuses}} at the start of the first cell of the template row and {{/bonuses}} at the end of the last cell, with {{amount}} and {{due}} tags in between. Give that tag array data, and the row repeats once per item. In a verified run, an offer letter with a 2-row bonus table rendered 3 total rows (header + 2) for one candidate and 4 (header + 3) for another with three milestones — same template, different data. Conditionals use the same block shape: {{#vip}}{{/vip}} shows the enclosed text only when the value is truthy, which is how you add a line only some recipients should see. Headers and footers merge too, so CONFIDENTIAL — {{name}} in the header personalizes every page.

You wantTag syntaxData shape
Personalized greetingDear {{name}},String per row
Row repeats per item{{#items}} … {{/items}}Array of objects
Paragraph for some records only{{#vip}} … {{/vip}}Boolean or truthy/falsy
Nested value{{manager.name}}Object (JSON mode)
Personalized header/footerSame tags, placed in headerAny

What about my old MERGEFIELD templates?

If you have years of Word mail-merge templates, don't rebuild them. Open one in Word, replace each field with its plain-text equivalent (select the field, unlink it with Ctrl+Shift+F9, then retype or find-and-replace into {{tag}} form), and save. That one-time conversion makes the template portable to every tag-based tool, including ours. The reverse also works: a {{tag}} template opened in Word is a perfectly normal document — Word simply shows the tags as text until something merges it.

Scale, privacy, and honest limits

A browser-side merge has no per-document pricing and no server queue; the ceiling is device memory, and a few hundred letters at ~8 KB each is routine. The privacy property is structural rather than a policy promise: there is no upload endpoint involved at all, so your spreadsheet cannot leak through one. The honest limits: it outputs .docx, not printer-ready envelopes (print from Word or LibreOffice afterwards), it doesn't fetch data from a live database the way an enterprise system would, and heavy formatting inside a loop block can confuse the row repetition if the block markers drift into different tables — keep {{#…}} and {{/…}} inside the same row and it just works.

Merge a document right now

Load a .docx with {{tags}}, paste your CSV, hit Merge. One document per row, built entirely in your browser.

DOCX Mail Merge →

The bottom line

Mail merge without Word is three small ideas: plain-text tags instead of field codes, a CSV instead of a wired-up data source, and a merge engine that runs where your files already are. Write the template anywhere, keep the data in a spreadsheet, merge locally, and convert to PDF with Word to PDF when recipients shouldn't edit. Before sending anything out, run the results through Document Metadata Remover — every saved .docx carries an author field, and a merged batch shouldn't leak yours.

Advertisement