# Formatting and Styling

> Format merged documents in Windows Forms: formatting kept from the template, NEXT fields and BlockRowMerged for row colors, FieldMerged cell rules.

- **Product:** TX Text Control .NET for Windows Forms
- **Section:** Documentation
- **Kind:** Topic
- **Path:** TX Text Control .NET for Windows Forms > Mail Merge and Reporting > Formatting and Styling
- **3909 words**
- **Web URL:** https://docs.textcontrol.com/tx-text-control-dotnet-winforms/mail-merge/styling/
- **LLMs URL:** https://docs.textcontrol.com/tx-text-control-dotnet-winforms/mail-merge/styling/llms.txt
- **LLMs-Full URL:** https://docs.textcontrol.com/tx-text-control-dotnet-winforms/mail-merge/styling/llms-full.txt

---

A merged invoice looks the way its template was designed: the fonts, colors, table borders and paragraph settings that a user gives the template in the editor stay while the data is merged. What depends on the data, such as a gray background on every second row or a highlighted price, comes either from fields in the template or from a few lines in the events of `MailMerge`.

Number and date formats of single merge fields are set in the **Merge Field Options** dialog box and described in [Merge Fields](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/mail-merge/fields/#format-numbers-and-dates). The examples below extend the invoice of the Getting Started tutorials: the template *invoice.docx* with a table row block `Items` and the data *invoice.json*, whose two items are *Consulting* (quantity 2, price 150.00) and *Training* (quantity 1, price 480.00). They are introduced in [Add Repeating Merge Blocks](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/getting-started/mail-merge/blocks/llms-full.txt).

### What the Merge Keeps

The template is designed with the formatting features of the editor, and the merge doesn't change them:

- **Merge fields keep their formatting.** A field formatted bold and red in the template inserts its value bold and red.
- **Merge blocks are copied with their formatting.** Each record gets a copy of the block, including its table formatting, paragraph settings and styles.
- **Letter case** is a setting of the field. The **Format** list of the **Merge Field Options** dialog box offers UPPERCASE, lowercase, First capital and Title Case.

In the TX Words sample, the **Home** tab formats a template like any other document, here the font color of a merge field:

![TX Text Control Words with an invoice template, the Font Color menu of the Home tab open and merge fields such as Customer_Customer.Name in an address table](https://docs.textcontrol.com/assets/img/tx-text-control-dotnet-winforms/template-formatting.2bca4aed.webp)

Format the template and keep the data free of formatting. [Template Design](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/mail-merge/template-design/llms-full.txt) collects the layout rules that hold up when the data grows.

### Alternate Row Colors in the Template

Alternating row colors need no code. Make the merge block two table rows with the same merge fields and different background colors, and put a `NEXT` field at the end of the first row. The `NEXT` field moves on to the next record, so the second row shows the following record in its own color. Users insert the field with **Insert Special Field** in the **Merge Fields** group of the **Reporting** tab.

When the number of records is odd, the second row of the last copy stays empty. The blog article [Reporting: Removing Empty Table Rows](https://www.textcontrol.com/blog/2014/09/30/reporting-removing-empty-table-rows/) shows such a template and removes the empty row in the `BlockRowMerged` event.

### Alternate Row Colors in Code

With a block of one row, your code colors the rows instead. [BlockRowMerged](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol-documentserver/mailmerge/blockrowmerged-event/llms-full.txt) occurs after each row of a merge block has been merged and hands your handler the merged row as a document. The following code in *Form1.cs* merges the invoice in a `ServerTextControl`, colors every second row of the `Items` block and shows the result in `textControl1`. Add a button named `colorRowsButton` next to the `mergeButton` of the Getting Started tutorials, and create its `Click` handler by double-clicking it in the designer:

```csharp
using System;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using TXTextControl;
using TXTextControl.DocumentServer;
using TXTextControl.DocumentServer.Fields;
```

```csharp
private int itemRowCount;

private void colorRowsButton_Click(object sender, EventArgs e)
{
    byte[] result;

    using (ServerTextControl tx = new ServerTextControl())
    {
        tx.Create();

        LoadSettings loadSettings = new LoadSettings
        {
            ApplicationFieldFormat = ApplicationFieldFormat.MSWord,
            LoadSubTextParts = true
        };

        tx.Load("invoice.docx", StreamType.WordprocessingML, loadSettings);

        using (MailMerge mailMerge = new MailMerge { TextComponent = tx })
        {
            mailMerge.BlockMerging += MailMerge_BlockMerging;
            mailMerge.BlockRowMerged += MailMerge_BlockRowMerged;

            mailMerge.MergeJsonData(File.ReadAllText("invoice.json"));
        }

        tx.Save(out result, BinaryStreamType.InternalUnicodeFormat);
    }

    // Show the merged invoice in the editor
    textControl1.Load(result, BinaryStreamType.InternalUnicodeFormat);
}

private void MailMerge_BlockMerging(object sender, MailMerge.BlockMergingEventArgs e)
{
    // Start counting again for each Items block
    if (e.BlockName == "Items")
    {
        itemRowCount = 0;
    }
}

private void MailMerge_BlockRowMerged(object sender, MailMerge.BlockRowMergedEventArgs e)
{
    if (e.MergeBlockName != "Items")
    {
        return;
    }

    // Color every second row of the block
    itemRowCount++;

    if (itemRowCount % 2 != 0)
    {
        return;
    }

    using (ServerTextControl rowText = new ServerTextControl())
    {
        rowText.Create();
        rowText.Load(e.MergedBlockRow, BinaryStreamType.InternalUnicodeFormat);

        foreach (Table table in rowText.Tables)
        {
            foreach (TableRow row in table.Rows)
            {
                TableCellFormat cellFormat = row.CellFormat;
                cellFormat.BackColor = Color.LightGray;
                row.CellFormat = cellFormat;
            }
        }

        byte[] data;
        rowText.Save(out data, BinaryStreamType.InternalUnicodeFormat);
        e.MergedBlockRow = data;
    }
}
```

The code works as follows:

- [BlockMerging](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol-documentserver/mailmerge/blockmerging-event/llms-full.txt) occurs before a block is merged. Its [BlockName](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol-documentserver/mailmerge-blockmergingeventargs/blockname-property/llms-full.txt) resets the counter, so that each invoice of a larger JSON array starts with a white row.
- [MergeBlockName](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol-documentserver/mailmerge-blockrowmergedeventargs/mergeblockname-property/llms-full.txt) tells which block the row belongs to, so other blocks stay as they are.
- [MergedBlockRow](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol-documentserver/mailmerge-blockrowmergedeventargs/mergedblockrow-property/llms-full.txt) holds the merged row in the internal TX Text Control format. A second `ServerTextControl` loads it, [TableRow.CellFormat](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/tablerow/cellformat-property/llms-full.txt) sets the background of all cells of the row, and the saved bytes replace the row in the document.

Click **colorRowsButton**. The *Training* row, the second item, has a gray background.

### Highlight Cells Depending on Their Values

The [FieldMerged](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol-documentserver/mailmerge/fieldmerged-event/llms-full.txt) event tells your handler whether a merged field is in a table cell. With the cell and the data of the record, a rule formats the cell by its value. Add this handler to the form and attach it next to the others with `mailMerge.FieldMerged += MailMerge_FieldMerged;`:

```csharp
private void MailMerge_FieldMerged(object sender, MailMerge.FieldMergedEventArgs e)
{
    // Highlight quantities above 1
    if (e.TableCell != null &&
        e.MailMergeFieldAdapter is MergeField mergeField &&
        mergeField.Name == "Quantity" &&
        Convert.ToInt32(e.DataRow["Quantity"]) > 1)
    {
        TableCellFormat cellFormat = e.TableCell.CellFormat;
        cellFormat.BackColor = Color.LightYellow;
        e.TableCell.CellFormat = cellFormat;
    }
}
```

- [TableCell](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol-documentserver/mailmerge-fieldmergedeventargs/tablecell-property/llms-full.txt) is the cell that contains the field, or `null` for a field outside a table.
- [MailMergeFieldAdapter](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol-documentserver/mailmerge-fieldmergedeventargs/mailmergefieldadapter-property/llms-full.txt) is the merged field; for a merge field it is a [MergeField](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol-documentserver-fields/mergefield/llms-full.txt) with its name.
- [DataRow](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol-documentserver/mailmerge-fieldmergedeventargs/datarow-property/llms-full.txt) returns the values of the current record by column name.

After the merge, the quantity cell of *Consulting* is yellow. The blog article [Manipulating Table Cells During the MailMerge Process in .NET C#](https://www.textcontrol.com/blog/2024/12/03/manipulating-table-cells-during-the-mailmerge-process-in-net-csharp/) builds more rules of this kind, and [MailMerge: Conditional Table Cell Colors using Filter Instructions](https://www.textcontrol.com/blog/2019/06/06/mailmerge-conditional-table-cell-colors-using-filter-instructions/) lets users store such a rule in a table cell of the template.

### Color the Text of a Merged Field

To format the merged text rather than its cell, replace the content of the field in `FieldMerged`. [MergedField](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol-documentserver/mailmerge-fieldmergedeventargs/mergedfield-property/llms-full.txt) contains the merged field with its formatting. The following handler shows prices above 400 in red; attach it with `mailMerge.FieldMerged += ColorPrice_FieldMerged;`:

```csharp
private void ColorPrice_FieldMerged(object sender, MailMerge.FieldMergedEventArgs e)
{
    if (e.Merged &&
        e.MailMergeFieldAdapter is MergeField mergeField &&
        mergeField.Name == "Price" &&
        Convert.ToDecimal(e.DataRow["Price"], System.Globalization.CultureInfo.InvariantCulture) > 400)
    {
        using (ServerTextControl fieldText = new ServerTextControl())
        {
            fieldText.Create();
            fieldText.Load(e.MergedField, BinaryStreamType.InternalUnicodeFormat);

            // Keep the text, remove the field, and color the text
            fieldText.ApplicationFields.Clear(true);
            fieldText.SelectAll();
            fieldText.Selection.ForeColor = Color.Red;

            byte[] data;
            fieldText.Save(out data, BinaryStreamType.InternalUnicodeFormat);
            e.MergedField = data;
        }
    }
}
```

[Merged](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol-documentserver/mailmerge-fieldmergedeventargs/merged-property/llms-full.txt) is `true` when the field received data. [ApplicationFields.Clear](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/applicationfieldcollection/clear-method/llms-full.txt) with `true` removes the field but keeps its text, which then gets the color. The font and size of the field stay, because the merged field is loaded with its formatting.

### Number Formats and Formulas in Merged Tables

Table cells have number formats of their own. When a cell's text type is a number, [TableCellFormat.NumberFormat](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/tablecellformat/numberformat-property/llms-full.txt) formats the numbers in it, and this also applies to the value of a merge field in the cell, as the blog article [Formatting Numbers in Table Cells](https://www.textcontrol.com/blog/2022/06/21/formatting-numbers-in-table-cells/) shows.

Cells can calculate with formulas as well. In an invoice template, the items come from the data while formula cells calculate the line totals and the total from the merged values. [Calculate With Formulas](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/document-processing/tables/#calculate-with-formulas) in Document Processing describes formulas and number formats.

### Next Steps

- [Merge Fields](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/mail-merge/fields/llms-full.txt): number and date formats, text before and after a field and formatted text.
- [Template Design](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/mail-merge/template-design/llms-full.txt): design templates that look right with any data.
- [Merge Events](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/mail-merge/events/llms-full.txt): every event of the merge and its arguments.
- [Tables and Calculations](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/document-processing/tables/llms-full.txt): format tables and cells in code.

---

## Nearby

- **Previous:** [Sorting and Filtering](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/mail-merge/sorting-filtering/llms-full.txt)
- **Next:** [Template Design](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/mail-merge/template-design/llms-full.txt)
