The MailMerge class in TX Text Control is a robust library designed to automate document creation through the process of merging data into templates. It serves as a bridge between structured data (e.g., from databases, JSON, or XML) and dynamic document generation, making it invaluable for applications that require automated document workflows. At its core, the MailMerge class simplifies the complex task of creating professional, data-driven documents by allowing developers to easily merge fields in templates with data sources. Templates are designed using the TX Text Control word processing interface, with merge fields representing dynamic content. Merge Blocks Merge blocks are a key concept in TX Text Control's MailMerge class, which allows for the dynamic generation of structured, repeatable content in documents. Merge blocks allow developers to effectively handle repeating data structures such as lists, tables, or nested regions in templates. At a high level, a merge block is a defined section within a template that corresponds to a collection or table of data. During the merge process, MailMerge iterates through the data source, dynamically creating content for each record. These merge blocks can be conditionally rendered, filtered, and sorted using the out-of-the-box functionality of the MailMerge class. Code-Level Manipulation But the MailMerge class also allows very detailed, code-level manipulation during the merge process. This includes handling merge events, customizing the merge process, and programmatically controlling the output of the merge operation. This level of control is essential for complex document generation scenarios that require fine-grained control over the merge process. This article describes how to use the FieldMerged event to manipulate a table cell that is returned by the event when the merged field is inside a table cell. For this example, we will use a very simple template consisting of two merge fields and a simple repeating block highlighted in red. To merge the template, we will use the following simplified JSON data. [ { "invoice-id": "1", "invoice-date": "2019-01-01", "line-items": [ { "product-id": "1", "quantity": "1", "unit-price": "8" }, { "product-id": "2", "quantity": "2", "unit-price": "200" }, { "product-id": "3", "quantity": "1", "unit-price": "100" }, { "product-id": "4", "quantity": "1", "unit-price": "3" } ] } ] In order to merge this template, the following code will be used: textControl1.Load("template.tx", TXTextControl.StreamType.InternalUnicodeFormat); MailMerge mailMerge = new MailMerge(); mailMerge.TextComponent = textControl1; string jsonData = File.ReadAllText("data.json"); mailMerge.MergeJsonData(jsonData); This results in the following merged document: FieldMerged Event Now let's attach the FieldMerged event to manipulate the merge process. textControl1.Load("template.tx", TXTextControl.StreamType.InternalUnicodeFormat); MailMerge mailMerge = new MailMerge(); mailMerge.TextComponent = textControl1; mailMerge.FieldMerged += MailMerge_FieldMerged; string jsonData = File.ReadAllText("data.json"); mailMerge.MergeJsonData(jsonData); Each time a merge field is merged (successfully or not), this event is invoked. A TableCell is returned if the field is located within a table cell. In this event, we check that the TableCell property is not null. If it is not null, we set the background color of the cell. private void MailMerge_FieldMerged(object sender, MailMerge.FieldMergedEventArgs e) { if (e.TableCell != null) { e.TableCell.CellFormat.BackColor = Color.Red; e.TableCell.CellFormat.BottomBorderWidth = 60; e.TableCell.CellFormat.BottomBorderColor = Color.Blue; } } As a result, all merged cells are colored during the merge process. Dynamic Cell Colors Let's make this process dynamic by adding some logic. The CellFilterInstructions class is used to compare a value with a given value to return a specific color. using System; using System.Drawing; using System.Linq; public class CellFilterInstructions { public double? CompareValue { get; set; } = null; public RelationalOperator? Operator { get; set; } = null; public Color TrueColor { get; set; } = Color.White; public Color FalseColor { get; set; } = Color.White; public enum RelationalOperator { Equals = 0, NotEqual, LessThan, GreaterThan, } // evaluates the instruction and returns the proper color public Color? GetColor(string value) { if (Double.TryParse(ParseToNumber(value), out double dValue) == true) { switch (Operator) { case RelationalOperator.Equals: return (dValue == CompareValue ? TrueColor : FalseColor); case RelationalOperator.NotEqual: return (dValue != CompareValue ? TrueColor : FalseColor); case RelationalOperator.GreaterThan: return (dValue > CompareValue ? TrueColor : FalseColor); case RelationalOperator.LessThan: return (dValue < CompareValue ? TrueColor : FalseColor); default: return null; } } else return null; } private string ParseToNumber(string text) { var numericChars = "0123456789,.".ToCharArray(); return new String(text.Where(c => numericChars.Any(n => n == c)).ToArray()); } } The following code creates a new rule that returns green if the value is greater than 10 and red if it is not. This rule is serialized and stored in the Name property of a table cell. textControl1.Load("template.tx", TXTextControl.StreamType.InternalUnicodeFormat); CellFilterInstructions cellFilterInstructions = new CellFilterInstructions() { CompareValue = 10, Operator = CellFilterInstructions.RelationalOperator.GreaterThan, TrueColor = Color.Green, FalseColor = Color.Red }; textControl1.Tables[1].Cells[2,2].Name = JsonConvert.SerializeObject(cellFilterInstructions); MailMerge mailMerge = new MailMerge(); mailMerge.TextComponent = textControl1; mailMerge.FieldMerged += MailMerge_FieldMerged; string jsonData = File.ReadAllText("data.json"); mailMerge.MergeJsonData(jsonData); In the FieldMerged event, this rule is deserted and evaluated. The color returned is then applied to the TableCellFormat of the table cell. private void MailMerge_FieldMerged(object sender, MailMerge.FieldMergedEventArgs e) { // custom field handling if (e.TableCell == null) return; if (e.TableCell.Name != "") { CellFilterInstructions instructions = (CellFilterInstructions)JsonConvert.DeserializeObject( e.TableCell.Name, typeof(CellFilterInstructions)); // retrieve the color Color? color = instructions.GetColor(e.MailMergeFieldAdapter.ApplicationField.Text); // apply the color if (color != null) e.TableCell.CellFormat.BackColor = (Color)color; } } The following screenshot shows the result of this merge process: Conclusion The MailMerge class in TX Text Control provides a powerful and flexible solution for automating document generation processes. Using merge blocks and code-level manipulation, developers can easily create dynamic, data-driven documents. The FieldMerged event provides fine-grained control over the merge process, allowing developers to customize output based on specific conditions. This level of control is essential for complex document generation scenarios that require precise handling of data and content.