Document generation with mail merge is the trick of reading values from a data source and dropping each one into the matching placeholder in a template. You keep two things: a template that holds the merge fields (the variables waiting to be filled) and a data source that supplies the values plus everything that stays the same on every copy. PDF4me's reporting engine takes those two files and hands back a finished document.
PDF4me accepts Word, HTML, and PDF templates, and the richest of the three is Word. With a small, readable syntax you can design one Word template that covers invoices, receipts, contracts, quotes, or any personalized document, then generate thousands of them from data. This guide walks through the whole syntax — merge fields, conditions, formatting, tables, images, and inline HTML — with copy-paste examples and a sample template you can download and run. Every syntax link points at the exact page in the Word Template Syntax documentation.
Write placeholders as <<[FieldName]>> in a Word document. Add conditions, formatting, loops, images, and HTML with a handful of extra tokens. Send that template plus a JSON (or XML) data file to the PDF4me Generate Document action, and you get a finished, personalized document back — one call, or thousands.
How do you design a Word template?
The whole thing starts with one placeholder. Anywhere you want a value dropped in, type the field name wrapped in double angle brackets and square brackets:
<<[FieldName]>>
The name inside the brackets has to match a property in your data source. Keep names descriptive, stick to one convention (camelCase or PascalCase), and avoid special characters. Here is a minimal template and the data that fills it:
Dear <<[CustomerName]>>,
Thank you for your order #<<[OrderNumber]>>.
{
"CustomerName": "John Smith",
"OrderNumber": "12345"
}
The engine returns:
Dear John Smith,
Thank you for your order #12345.
That is the entire idea. Everything below is a variation on the same theme — conditions, loops, and formatting all wrap around ordinary merge fields. Full details live in the Syntax Overview.
How do you add conditions to a template?
The Generate Document action can branch on your data. Based on whether a condition is true, it drops in one block of content or another. The basic if / elseif / else shape reads like this:
<<if [condition1]>> Add the first block
<<elseif [condition2]>> Add the second block
<<else>> Add the fallback block
<</if>>
Conditions can test a value directly or lean on the enumeration methods (more on those below), for example <<if [employees.Any(p => p.Age > 50)]>>. For the full set of comparison and logical operators, see Conditional Logic.
How do you format values in a template?
Often a raw value needs shaping before it lands — a date in a particular style, a number rounded, text forced to uppercase. Add a format specification after the field name, separated by a colon and wrapped in quotes:
<<[token]:"format">>
Dates take a .NET-style pattern:
Invoice Date: <<[invoiceDate]:"dd.MM.yyyy">>
Due Date: <<[dueDate]:"MMMM dd, yyyy">>
Text case has its own short switches — :upper, :caps (capitalize each word), and :firstCap:
Customer: <<[customerName]:upper>>
Product: <<[productName]:caps>>
Numbers use standard numeric formats, so <<[price]:"F2">> fixes a value to two decimal places. The complete list of date, text, and number patterns is in Formatting in Templates.
How do you build tables from a list?
Tables are where document generation earns its keep — one template row expands into as many rows as your data has. Build a normal Word table, open a <<foreach>> loop in the first cell, add a merge field in each following cell, and close the loop in the last cell:
Column 1: <<foreach [product in products]>><<[product.productName]>>
Column 2: <<[product.manufactured]:"yyyy.MM.dd">>
Column 3: <<[product.price]>><</foreach>>
Each object in the products array becomes one row, and you can format cells inline just like anywhere else. More table patterns, including filtered and aggregated rows, are covered in Tables in Templates.
How do you repeat paragraphs and sections?
The same <<foreach>> loop works outside of tables too. Wrap any block of content — a paragraph, a heading plus body, a whole section — and it repeats once per item in the collection:
<<foreach [item in collection]>>
Content with <<[item.property]>>
<</foreach>>
Loops can nest (a section per department, a line per employee inside it) and can filter or sort the collection as they go. See Repeat Paragraphs & Sections for nested and conditional examples.
How do you add images to a template?
PDF4me can pull images into a generated document from a public URL or a Base64 string. One rule matters: the image field has to sit inside a Word Text Box. Create the text box where you want the image, then add the field.
From a public URL:
<<image [imageUrl]>>
From a Base64-encoded string:
<<image [imageBase64]>>
You can control sizing with switches such as -keepRatio, -fitHeight, -fitWidth, and -fitSize, e.g. <<image [companyLogo] -keepRatio>>. The full sizing reference and per-row image examples are in Insert Images.
How do you insert HTML into a template?
If your data already holds formatted HTML, render it in place with the -html switch instead of escaping it as plain text:
<<[token] -html>>
The engine parses the field value as HTML and applies the formatting — bold, italics, lists, headings, colored spans, and more — inside the generated document. Supported tags and styling are listed in Insert HTML.
Work with your data using enumeration methods
Beyond simple fields, the engine exposes IEnumerable-style methods you can call right inside a token — filter, sort, count, average, and more. A few examples:
Total products: <<[products.Count()]>>
Average price: $<<[products.Average(p => p.price)]:"F2">>
Top items: <<foreach [p in products.OrderByDescending(x => x.price).Take(5)]>><<[p.name]>><</foreach>>
These pair naturally with conditions and loops. The complete method list — Where, OrderBy, GroupBy, Sum, Any, First, and the rest — is in Enumeration in Templates.
Grab a ready-made Word template and its JSON data, then run them through the Generate Document action to see the whole thing work end to end.
The sample data looks like this — a vendor, a customer, and a product list the template loops over:
{
"VendorName": "PDF4me",
"VendorCity": "Zurich",
"VendorCountry": "Switzerland",
"VendorZip": "8630",
"VendorContact": "123456",
"InvoiceDate": "22-08-2022",
"CustomerName": "John Doe",
"CustomerCity": "Start City",
"CustomerCountry": "US",
"CustomerZip": "3214",
"products": [
{ "productName": "PDF Converter", "value": 2000, "expires": "01/08/2025" },
{ "productName": "PDF API", "value": 1250, "expires": "18/02/2029" },
{ "productName": "PDF Editor", "value": 1999, "expires": "12/12/2027" }
],
"comments": "This document is <b>computer generated</b> and does not require a signature."
}
Notice comments carries HTML — pair it with the <<[comments] -html>> switch and the <b> tag renders as bold in the output.
Quick links for designing your template
Common questions
How do I create merge fields in a Word template?
Type the field name inside double angle brackets and square brackets, like <<[CustomerName]>>, wherever you want a value dropped in. The name has to match a property in your JSON or XML data source. You can add fields manually anywhere in the document — headings, paragraphs, table cells, or text boxes.
What template formats does PDF4me support?
Word (.docx, .doc), HTML, and PDF. All three use the same merge-field syntax, so what you learn for a Word template carries across. Word gives you the fullest control over layout, conditions, tables, and images.
Can I add if / else conditions to a Word template?
Yes. Wrap content in <<if [condition]>> ... <<elseif [condition]>> ... <<else>> ... <</if>>. A condition can compare a field directly or call an enumeration method such as Any() or Count(). This lets a single template handle every variation in your data instead of maintaining one file per case.
How do I format dates and numbers in a template?
Put the format after the field name in quotes: <<[invoiceDate]:"dd.MM.yyyy">> for a date, <<[price]:"F2">> for a number with two decimals. Text case has shortcut switches — :upper, :caps, and :firstCap.
How do I generate a table that grows with my data?
Build a Word table, open <<foreach [item in collection]>> in the first cell, put a merge field in each remaining cell, and close with <</foreach>> in the last cell. Each item in the collection becomes one row automatically.
Troubleshooting
Next steps
Design the template once, wire it to your data, and PDF4me turns out personalized invoices, contracts, and reports on demand — from a single API call or an automation running thousands at a time.
