Template Design
Templates are often designed by people who aren't developers: a clerk who knows the invoice layout, working in your Windows Forms application or in MS Word. How a template is built decides whether every merge produces a clean document, whatever the data contains. Designers and developers who prepare templates together find here where templates are designed and with which data, how to store them, which layout rules hold up with growing data and how to test a template before it is used.
The parts of a template have pages of their own: Merge Fields, Merge Blocks, Conditional Content, Subtemplates and Images and Barcodes. The examples use the invoice template of Create a Template in a TextControl named textControl1.
Where Templates Are Designed
| Tool | Who uses it | What to know |
|---|---|---|
| Your application | Your users | A TextControl with the Reporting ribbon tab is a complete template designer. The tab lists the fields and blocks of the data source you load into it |
| TX Text Control Words | You, while you develop | The TX Words Reporting sample of the installation is a ready template designer with sample templates and a sample database |
| MS Word | Users who work with Word documents | Merge fields are MERGEFIELD fields. Load DOCX templates with LoadSettings that import the fields and the merge blocks |
| Code | Developers | MergeField inserts merge fields, and DataSourceManager.InsertMergeBlock inserts complete merge blocks |
Whichever tool is used, a template holds only the names of fields and blocks, never a connection to the data, so one template works with any data of the same structure.
In the Windows Forms designer, the MailMerge component offers the command Start Template Designer below its Properties window, which opens TX Text Control Words. Its other commands, TemplateFile... and ReportDataSourceConfigFile..., choose the files the component merges:

The source code of the TX Words Reporting sample is in %USERPROFILE%\Documents\TX Text Control 34.0.NET for Windows Forms\CSharp\TX Words\Reporting. Mail Merge Examples lists it with the other samples.
Design in TX Words, Merge in Your Form
TX Words and the MailMerge component work together without any template code: you design the template in TX Words against the sample database of the installation, point the component to the saved file and merge the same database in your form. The sample database is the XML file sample_db.xml, which the TX Words Reporting sample loads with its Load Sample Database button. The setup installs it in C:\Program Files\Text Control GmbH\TX Text Control 34.0.NET for Windows Forms\Samples\Demo.
Create a Windows Forms application with a
TextControlnamedtextControl1, as Create Your First Windows Forms Application shows. Drop aMailMergecomponent from the TX Text Control 34.0 toolbox tab onto the form and selecttextControl1in itsTextComponentproperty.Click Start Template Designer below the Properties window of
mailMerge1. TX Words opens.In TX Words, open the Reporting tab, click Select Data Source and choose Load Sample Database, the command the sample adds to the drop-down that Data Source shows.
Open the sample invoice template from the application menu. The sample templates of TX Words are made for the sample database.
In Select Master Table, make sure that
Sales_SalesOrderHeaderis selected. Its columns are the merge fields outside of blocks, and the order lines ofSales_SalesOrderDetailfill the merge block of the invoice.Save the template as a DOCX file, for example invoice.docx, and close TX Words.
Back in Visual Studio, click TemplateFile... below the Properties window of
mailMerge1and select invoice.docx. TemplateFile loads the template when the component merges, in place of a call ofLoadTemplate.Add a button named
mergeButtonto the form, double-click it and add the following code to itsClickhandler. Change the path if TX Text Control is installed in another folder:private void mergeButton_Click(object sender, EventArgs e) { string databasePath = @"C:\Program Files\Text Control GmbH\TX Text Control 34.0.NET for Windows Forms\Samples\Demo\sample_db.xml"; // Read the tables and relations of the sample database System.Data.DataSet dataSet = new System.Data.DataSet(); dataSet.ReadXml(databasePath); // One invoice per order, combined into one document mailMerge1.Merge(dataSet.Tables["Sales_SalesOrderHeader"], true); }Press F5 and click the button. The editor shows the merged invoices, one after the other.
DataSet.ReadXml reads the tables of the XML file and the relations between them. Merge takes the master table, follows its relations for the merge blocks and the prefixed fields, and with true for append combines the results into one document. DataSets and DataTables describes this kind of data in detail.
Design With Sample Data
Templates are designed against sample data: data with the structure and names of the real data, and made-up values. Loaded into the DataSourceManager of the Reporting tab, it fills the drop-downs of the tab: the columns of the master table become merge fields, related tables become merge blocks, and fields of related tables are offered with their table name as a prefix. At merge time, any data with the same structure fills the template.
Your code loads sample data with a method of DataSourceManager that matches the data: LoadJson, LoadSingleObject, LoadObjects, LoadDataSet or LoadXmlFile. A good source is an object of the class that your application merges later, filled with sample values: the names in the tab are then exactly the names of the merge. Data Sources shows each kind of data in the tab.
Fields of related tables appear in submenus of Insert Merge Field. Inside a merge block, a field such as Production_Product.Name takes its value from the related record:

Choose the Storage Format
Templates are stored in the TX Text Control format or as DOCX files. The two differ in what they keep and in how they are loaded:
| TX Text Control format | DOCX | |
|---|---|---|
| Save | StreamType.InternalUnicodeFormat | StreamType.WordprocessingML |
| Merge fields and blocks | Kept as fields and subtext parts | Saved as MS Word fields and bookmarks |
| Load for a merge | Without load settings | With LoadSettings: ApplicationFieldFormat set to MSWord and LoadSubTextParts set to true |
| Edit in MS Word | No | Yes |
Store templates that your users design in your application in the TX Text Control format, and use DOCX for templates that must stay editable in MS Word. Two buttons save and open the template in the TX Text Control format:
private void saveTemplateButton_Click(object sender, EventArgs e)
{
// The TX Text Control format keeps fields, merge blocks and their rules
textControl1.Save("invoice.tx", StreamType.InternalUnicodeFormat);
}
private void openTemplateButton_Click(object sender, EventArgs e)
{
textControl1.Load("invoice.tx", StreamType.InternalUnicodeFormat);
}
LoadSubTextParts applies to DOCX, DOC and RTF only: in these formats, a merge block is a bookmark, which the setting turns into a subtext part again. Sorting and Filtering explains the rules that blocks carry.
Follow Layout Rules That Merge Well
Merged content grows and shrinks with the data, so a template that looks right with sample data can break with real data. The following rules avoid the typical problems:
- Use "page break before" instead of page breaks. A forced page break can leave an empty page when the text before it grows. Set the page break on the paragraph, ideally in its paragraph style, as the blog article Document Templates Tip: Say No to Forced Page Breaks explains.
- Control how tables break. Mark header rows so that they're repeated on each page, and keep rows together that belong together, as described in Why Table Control in Templates is Important for Professional PDF Creation in C#.
- Put per-record headers into the block. A header row outside a merge block appears once with the same content. Make the whole table the block when each record needs its own header, as Repeat Table Headers per Block explains.
- Avoid empty lines.
RemoveEmptyLinesofMailMergeremoves a line that is empty after the merge, but only when nothing else is on it; put optional fields on lines of their own. - Use blocks and IF fields for optional content. Text that depends on the data goes into an
IFfield or a merge block, as Conditional Content describes. - Share content with subtemplates. Terms and conditions or an address area that many templates use belong in a subtemplate that an
INCLUDETEXTfield includes. See Subtemplates.
The blog article Designing the Perfect Contract Template for MailMerge in C# builds a contract template along these rules.
Check What a Template Contains
While designing, users see the structure of the template in the editor:
- Highlight Merge Fields at the end of the Insert Merge Field drop-down and Highlight Merge Blocks at the end of Insert Merge Block mark the fields and blocks in the text.
- Field Navigation in the View group opens a sidebar that lists the merge blocks and merge fields of the document, as Reporting Ribbon and Dialog Boxes shows.
- A preview merges the template with the sample data in the editor, so the designer sees the result. Template Preview builds one.
Test a Template
Before a template goes live, merge it with sample data and check what didn't receive data. The following handler of a Test Template button merges the template in the editor with invoice.json, lists its merge blocks and every merge field without data, and saves the result for a visual check:
using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;
using TXTextControl;
using TXTextControl.DocumentServer;
using TXTextControl.DocumentServer.Fields;
private void testTemplateButton_Click(object sender, EventArgs e)
{
List<string> report = new List<string>();
using (ServerTextControl tx = new ServerTextControl())
{
tx.Create();
// Test the template as it is in the editor
byte[] template;
textControl1.Save(out template, BinaryStreamType.InternalUnicodeFormat);
tx.Load(template, BinaryStreamType.InternalUnicodeFormat);
using (MailMerge mailMerge = new MailMerge { TextComponent = tx })
{
report.Add("Merge blocks: " + string.Join(", ", mailMerge.GetBlockNames()));
// Note every merge field that the sample data doesn't fill
mailMerge.FieldMerged += (s, args) =>
{
if (!args.Merged && args.MailMergeFieldAdapter is MergeField mergeField)
{
string block = args.MergeBlockName == "" ? "" : $" in block {args.MergeBlockName}";
report.Add($"No data for {mergeField.Name}{block}");
}
};
mailMerge.MergeJsonData(File.ReadAllText("invoice.json"));
}
tx.Save("invoice-test.pdf", StreamType.AdobePDF);
}
MessageBox.Show(this, string.Join(Environment.NewLine, report), "Template Test");
}
The code works as follows:
- The template is taken from the editor as a byte array and merged in a
ServerTextControl, so the template in the editor stays unchanged. - GetBlockNames returns the names of the merge blocks of the template.
- FieldMerged occurs for each field. Merged is
falsewhen the field received no data, and MergeBlockName names the block it is in.
With the invoice template and its data, the message lists the merge block of the items and no field without data. A misspelled field name, such as Compny, would appear in the list.
A template can also look different on another computer when a font or a linked image is missing there. The blog article Check TX Text Control Template Dependencies Before Deployment checks fonts, linked images and field names before a template is deployed.
Next Steps
- Reporting Ribbon and Dialog Boxes: every button and dialog box of the Reporting tab.
- Template Preview: show the merged result while designing.
- Formatting and Styling: formatting that depends on the data.
- Data Sources: the data that fills the template.