Merge Fields
A merge field is more than a name in the template: it carries a format for numbers or dates, text that appears before and after its value and the case of its letters. Users set these options in the Merge Field Options dialog box of the Reporting tab, and your code sets them with the MergeField class. The sections below cover both, add date fields, decide what fields without data show, merge formatted HTML and fill form fields.
Inserting a first merge field with the ribbon and in code is part of the Getting Started tutorial Create a Template, and finding fields without data is part of Merge Data into Fields. The examples below use the same template, invoice.docx, shown in a TextControl named textControl1.
The MergeField Class
A merge field is an MS Word MERGEFIELD field, stored in the document as an ApplicationField. The MergeField class of the TXTextControl.DocumentServer.Fields namespace is an adapter for such a field: the constructor without parameters creates a new field, and the constructor with an ApplicationField wraps an existing one, so that changes to the adapter change the field in the document.
| Property | Sets | In the Merge Field Options dialog |
|---|---|---|
| Name | The name that is matched with the data | Name |
| Text | The text the field shows until it's merged | Text |
| TextFormat | The case of the letters: Uppercase, Lowercase, FirstCapital, TitleCase or None | Format |
| TextBefore, TextAfter | Text inserted before and after the value | Text to be inserted before, Text to be inserted after |
| DateTimeFormat | A format for dates and times, the MS Word switch \@ | Date / time format |
| NumericFormat | A format for numbers, the MS Word switch \# | Numeric format |
| PreserveFormatting | A flag that MailMerge itself doesn't use | Preserve formatting during updates |
| DataSourceCulture, MergeCulture | The cultures that parse the value and format it, for this field only |
The formatting of the field in the template, such as its font and color, is always kept.
Insert and Edit Fields in the Reporting Tab
Once data is loaded into the Reporting tab, Select Master Table in the Data Source group chooses the table whose columns the fields come from. Insert Merge Field in the Merge Fields group then lists the columns of that table, and a click inserts a field at the input position:

Merge Fields in Reporting Ribbon and Dialog Boxes describes the rest of the drop-down, including the fields of related tables.
Field Properties in the same group opens the Merge Field Options dialog box for the field at the input position. It has one control for each property of the table above:

Your code opens the same dialog box with ShowDialog of a MergeField that wraps the field at the input position, for example from a context menu of your own. Open the Dialog Boxes From Code shows the handler, which opens the options of merge fields and the other fields of a template.
Format Numbers and Dates
NumericFormat and DateTimeFormat take .NET format strings, the standard and custom numeric format strings and date and time format strings. For example, a field Price with the numeric format $#,###.00 shows the value 2.4 as $2.40, and a date field with MMMM d, yyyy shows September 1, 2026.
The currency symbol, the separators and the names of months depend on the culture that formats the value. MailMerge.MergeCulture sets it for all fields and MergeField.MergeCulture for a single field; both default to the culture of the current thread, which follows the user's regional settings. Set a culture when the documents must look the same on every computer. The blog article Format Numeric String Values with MailMerge shows the formats in use.
Set Formats on All Fields of a Template
Merge fields can be in the main text, in headers and footers and in text frames. TextControl.TextParts contains these parts, and each part has its own ApplicationFields collection. The following handler sets formats on the fields of the template in the editor, wherever they are:
using System;
using TXTextControl;
using TXTextControl.DocumentServer.Fields;
private void formatFieldsButton_Click(object sender, EventArgs e)
{
// The main text, text frames, headers and footers
foreach (IFormattedText textPart in textControl1.TextParts)
{
foreach (ApplicationField applicationField in textPart.ApplicationFields)
{
if (applicationField.TypeName != "MERGEFIELD")
{
continue;
}
MergeField mergeField = new MergeField(applicationField);
switch (mergeField.Name)
{
case "Company":
mergeField.TextFormat = TextFormatOptions.Uppercase;
break;
case "InvoiceNumber":
mergeField.TextBefore = "Invoice ";
break;
case "Price":
mergeField.NumericFormat = "$#,##0.00";
break;
}
}
}
}
The code works as follows:
- Each text part implements IFormattedText, whose ApplicationFields holds the fields of that part.
new MergeField(applicationField)wraps each merge field, and the new values apply to the field in the document at once.- After the handler, the company name is merged in capital letters, the invoice number is preceded by "Invoice " and the prices of the
Itemsblock are shown with a dollar sign and two decimals. Save the template to keep the settings.
Insert Date Fields
A DATE field shows the date of the merge in a format. Users insert one with Date in the Insert Special Field drop-down of the Reporting tab and choose the format in the Date Field Options dialog box:

In code, the DateField adapter creates the field:
using System;
using System.Globalization;
using TXTextControl.DocumentServer.Fields;
private void insertDateButton_Click(object sender, EventArgs e)
{
DateField dateField = new DateField
{
Format = "MMMM d, yyyy",
Culture = CultureInfo.GetCultureInfo("en-US"),
Date = DateTime.Now
};
textControl1.ApplicationFields.Add(dateField.ApplicationField);
}
Format is a standard .NET date and time format string, Culture the culture that applies it, and Date sets the date the field shows in the template. During the merge, the field receives the local date and time of the computer. MailMerge.DateFieldUtcOffset applies an offset from UTC in minutes instead; it is null by default.
Show a Text for Fields Without Data
A field whose name the data doesn't contain is removed, because RemoveEmptyFields is true by default. To show a text instead, keep such fields and change their text in the FieldMerged event, which occurs for every field, with or without data:
using System;
using System.IO;
using TXTextControl.DocumentServer;
using TXTextControl.DocumentServer.Fields;
private void mergeWithPlaceholdersButton_Click(object sender, EventArgs e)
{
using (MailMerge mailMerge = new MailMerge
{
TextComponent = textControl1,
RemoveEmptyFields = false
})
{
mailMerge.FieldMerged += (s, args) =>
{
if (!args.Merged && args.MailMergeFieldAdapter is MergeField mergeField)
{
mergeField.Text = "n/a";
}
};
mailMerge.MergeJsonData(File.ReadAllText("invoice.json"));
}
}
Merged is false for a field without data, and MailMergeFieldAdapter is the field, here a MergeField whose text becomes "n/a". Add a field named Phone, which invoice.json doesn't contain, to see the text. Merge Events describes the other arguments of the event.
Merge Formatted Text
A merge field receives plain text. When the data holds formatted text, such as HTML notes, replace the merged content in FieldMerged: load the value into a ServerTextControl, save it in the internal TX Text Control format and assign the bytes to MergedField. The Preserve formatting during updates check box of the Merge Field Options dialog box is a convenient marker for such fields: MailMerge ignores it, but your handler can read it as PreserveFormatting:
mailMerge.FieldMerged += (s, args) =>
{
// Only fields with "Preserve formatting during updates" checked
if (args.Merged && args.MailMergeFieldAdapter is MergeField mergeField && mergeField.PreserveFormatting)
{
using (ServerTextControl htmlText = new ServerTextControl())
{
htmlText.Create();
htmlText.Load(mergeField.Text, StringStreamType.HTMLFormat);
byte[] data;
htmlText.Save(out data, BinaryStreamType.InternalUnicodeFormat);
args.MergedField = data;
}
}
};
With a value such as <p>Thank you for your <strong>business</strong>.</p> in the data, the merged document shows the text with business in bold instead of the HTML tags. The blog article Reporting: Merge Formatted HTML into Merge Fields introduced this technique with XML data.
Keep Merge Fields After the Merge
After a merge, a field that received data is gone: its value is ordinary text of the document. That suits a finished letter, but not a document that users edit in the TextControl and merge again later, or a preview that should still show the fields. Assign MergedField to itself in FieldMerged, and the merged fields stay fields with the merged value as their text:
using (MailMerge mailMerge = new MailMerge { TextComponent = textControl1 })
{
// Assigning MergedField to itself keeps the merged fields in the result
mailMerge.FieldMerged += (s, args) => args.MergedField = args.MergedField;
mailMerge.MergeJsonData(File.ReadAllText("invoice.json"));
}
Fields without data are a separate case: RemoveEmptyFields set to false keeps them, as Show a Text for Fields Without Data does. The blog article Merging Templates with MailMerge with Different Merge Field Settings in C# compares both settings with screenshots of the results.
Merge Form Fields
Templates can also contain form fields, such as text boxes, check boxes and drop-downs that users fill in later. MailMerge.FormFieldMergeType decides what the merge does with them:
| Value | Form fields |
|---|---|
None (default) | Aren't merged |
Preselect | Keep their controls, and their content is preselected with the data where possible; fields without a matching column stay unchanged |
Replace | Are replaced with the data, so the result contains no form fields; empty form fields are removed according to RemoveEmptyFields |
The FormFieldMerged event reports each form field and whether it received data:
using (MailMerge mailMerge = new MailMerge
{
TextComponent = textControl1,
FormFieldMergeType = FormFieldMergeType.Preselect
})
{
mailMerge.FormFieldMerged += (s, args) =>
{
if (!args.Merged)
{
System.Diagnostics.Debug.WriteLine($"No data for form field {args.FormField.Name}");
}
};
mailMerge.MergeJsonData(File.ReadAllText("invoice.json"));
}
With Preselect, users see a form in the editor that is already filled out where the data allows it. Data that users must not change belongs in merge fields; values they may correct belong in preselected form fields. Form Fields in the Document Editor section describes the form fields themselves, and the blog article Merging Form Fields using the MailMerge Class shows a form template with both kinds of fields.
Prefixes in Field Names
A dot in a field name addresses related data: Customer.City is the value City of the nested object or related table Customer, and longer paths reach further levels. The prefix image: marks a merge field that is merged as an image, as Images and Barcodes describes.
Prefixes also work inside merge blocks, where they start at the table of the block. The sample database of TX Words has an order table, Sales_SalesOrderHeader, which is related to the order lines in Sales_SalesOrderDetail, and each order line to a product in Production_Product:

With Sales_SalesOrderHeader as the master table, a merge block Sales_SalesOrderDetail repeats the order lines. Inside it, OrderQty, UnitPrice and LineTotal need no prefix, because they are columns of the block's own table, while Production_Product.ProductNumber and Production_Product.Name take the number and the name of the product of the current line.

A path can follow several relations in a row. The product photo of each order line is an image placeholder in the same block, and its name leads from the product through the table that links products and photos to the photo itself:
Production_Product.Production_ProductProductPhoto.Production_ProductPhoto.ThumbNailPhoto
Each part before the last is a related table, and ThumbNailPhoto is the column with the image data. MailMerge follows the relations by itself; you pass only the master table. The Insert Merge Field drop-down offers related tables as submenus and inserts their fields with the prefix, as Reporting Ribbon and Dialog Boxes shows.
The merged invoice shows the order, its lines with the product numbers and names and the product photos, all filled from the related tables:

Next Steps
- Conditional Content: insert text with
IFfields depending on the data. - Formatting and Styling: format merged cells and rows.
- Merge Blocks: repeat fields for each record of a list.
- Reporting Ribbon and Dialog Boxes: the other commands of the Reporting tab.