Mail merge is a powerful feature for creating personalized documents such as invoices, reports, and mail merge letters from a data source. However, there are scenarios in which you may not want to process all of the records during the merge. Whether you need to exclude certain customers from a marketing campaign, skip empty or incomplete records, or dynamically filter data based on user-defined criteria, having control over which records are merged is essential.

The MailMerge TX Text Control .NET Server for ASP.NET
DocumentServer Namespace
MailMerge Class
The MailMerge class is a .NET component that can be used to effortlessly merge template documents with database content in .NET projects, such as ASP.NET web applications, web services or Windows services.
class in TX Text Control typically follows the concept of "pre-formed" data, meaning that it simply merges all records from the provided data source without applying any additional filtering. This allows developers to pre-process and filter data before passing it to the MailMerge class. However, there are scenarios where dynamic filtering must occur during the merge process itself, such as skipping records based on real-time conditions, user input, or specific business rules that cannot be determined in advance.

In this article, we'll explore how to skip records during the merge process using the TX Text Control MailMerge class in .NET C#.

JSON Data Source

Let us take a look at this sample JSON data for a very simple merge process:

[
{
"name": "Doe",
"firstName": "John",
"address": "123 Main St",
"city": "Anytown",
"state": "CA"
},
{
"name": "Smith",
"firstName": "Jane",
"address": "456 Elm St",
"city": "Othertown",
"state": "NY"
},
{
"name": "Jones",
"firstName": "Jim",
"address": "789 Oak St",
"city": "Thistown",
"state": "TX"
}
]
view raw test.json hosted with ❤ by GitHub

Skipping Records

Each array entry should create a new instance of the template, and all instances will be appended to the same resulting PDF. This is the very basic template for this use case:

Template in TX Text Control

Merging this template with this data would produce a three-page document. But now we want to filter certain indices from the array. We will use the DataRowMerged event, which is fired after each successful merge of a row.

In this case, it is possible to manipulate the content of the generated line. In our case, we want to inject an empty document, which basically removes the entire row.

static void MailMerge_DataRowMerged(MailMerge.DataRowMergedEventArgs e, List<int> rowsToSkip, byte[] skippedRowData)
{
if (rowsToSkip.Contains(e.DataRowNumber))
{
e.MergedRow = skippedRowData;
}
}
view raw test.cs hosted with ❤ by GitHub

Here is the complete code including the call to the MergeJsonData TX Text Control .NET Server for ASP.NET
DocumentServer Namespace
MailMerge Class
MergeJsonData Method
Merges data given as a JSON string into a document template.
method:

using TXTextControl.DocumentServer;
List<int> rowsToSkip = new List<int> { 1 }; // Example: Skip row 1
MergeDocument("template.tx", "data.json", "output.pdf", rowsToSkip);
/// <summary>
/// Merges a template with JSON data and saves the output as a PDF, skipping specified row numbers.
/// </summary>
/// <param name="templatePath">Path to the template file.</param>
/// <param name="jsonDataPath">Path to the JSON data file.</param>
/// <param name="outputPath">Path to save the output PDF.</param>
/// <param name="rowsToSkip">List of row numbers to skip during merge.</param>
static void MergeDocument(string templatePath, string jsonDataPath, string outputPath, List<int> rowsToSkip)
{
using (TXTextControl.ServerTextControl tx = new TXTextControl.ServerTextControl())
{
tx.Create();
tx.Load(templatePath, TXTextControl.StreamType.InternalUnicodeFormat);
MailMerge mailMerge = new MailMerge { TextComponent = tx };
byte[] skippedRowData = GetSkippedRowData(tx);
mailMerge.DataRowMerged += (sender, e) => MailMerge_DataRowMerged(e, rowsToSkip, skippedRowData);
string jsonData = File.ReadAllText(jsonDataPath);
mailMerge.MergeJsonData(jsonData, true);
tx.Save(outputPath, TXTextControl.StreamType.AdobePDF);
}
}
/// <summary>
/// Handles the DataRowMerged event, allowing certain rows to be skipped.
/// </summary>
/// <param name="e">MailMerge event arguments.</param>
/// <param name="rowsToSkip">List of row numbers to skip.</param>
/// <param name="skippedRowData">Pre-generated data for skipped rows.</param>
static void MailMerge_DataRowMerged(MailMerge.DataRowMergedEventArgs e, List<int> rowsToSkip, byte[] skippedRowData)
{
if (rowsToSkip.Contains(e.DataRowNumber))
{
e.MergedRow = skippedRowData;
}
}
/// <summary>
/// Pre-generates the skipped row data to avoid redundant processing.
/// </summary>
/// <param name="tx">The TXTextControl instance.</param>
/// <returns>Byte array of the skipped row content.</returns>
static byte[] GetSkippedRowData(TXTextControl.ServerTextControl tx)
{
using (TXTextControl.ServerTextControl tempTx = new TXTextControl.ServerTextControl())
{
tempTx.Create();
tempTx.Save(out byte[] data, TXTextControl.BinaryStreamType.InternalUnicodeFormat);
return data;
}
}
view raw test.cs hosted with ❤ by GitHub

If you run this code, the resulting PDF will only contain the first and third pages. The second page is skipped by inserting a blank document into the merge process.

Conclusion

Skipping records during the merge process is a common requirement in mail merge scenarios. The DataRowMerged event in TX Text Control allows developers to dynamically filter records based on real-time conditions, user input, or specific business rules that cannot be determined in advance. By injecting a blank document into the merge process, you can effectively skip records that do not meet the specified criteria.