# Add Repeating Merge Blocks

> Add a merge block to a Windows Forms template that repeats a table row for each item, with the Reporting tab or in code, and merge JSON or business objects.

- **Product:** TX Text Control .NET for Windows Forms
- **Section:** Documentation
- **Kind:** Topic
- **Path:** TX Text Control .NET for Windows Forms > Getting Started > Mail Merge > Add Repeating Merge Blocks
- **2447 words**
- **Web URL:** https://docs.textcontrol.com/tx-text-control-dotnet-winforms/getting-started/mail-merge/blocks/
- **LLMs URL:** https://docs.textcontrol.com/tx-text-control-dotnet-winforms/getting-started/mail-merge/blocks/llms.txt
- **LLMs-Full URL:** https://docs.textcontrol.com/tx-text-control-dotnet-winforms/getting-started/mail-merge/blocks/llms-full.txt

---

An invoice has one customer but many items, and the template cannot know how many. A merge block solves this: a part of the template, such as a table row, that is repeated once for each record of a list in the data. Following on from the invoice of the previous tutorials, you add a block for the `Items` of *invoice.json*, merge it, and see the same result with business objects.

### Prerequisites

- The application from [Create a Template](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/getting-started/mail-merge/template/llms-full.txt), which loads *invoice.json* into the Reporting tab when the form opens.
- The merge code from [Merge Data into Fields](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/getting-started/mail-merge/fields/llms-full.txt).

### How Merge Blocks Work

A merge block is a named part of the document whose name starts with `txmb_`, followed by the name of a list in the data. Here the block is `txmb_Items`, and the list is the `Items` array of the JSON data. During the merge, the block is copied once for each item, with its formatting, and the merge fields inside it receive the values of that item: `Description`, `Quantity` and `Price`.

A block can be a table row, a complete table, paragraphs or other content. For an invoice, a table row is the natural choice: the table grows by one row per item. In the following template of the Windows Forms mail merge sample, the highlighted table row is a merge block:

![A template in the Windows Forms mail merge sample with merge fields above a table whose highlighted second row is a merge block.](https://docs.textcontrol.com/assets/img/tx-text-control-dotnet-winforms/merge-block-sample-template.321446fd.webp)

After the merge, the table has one row for each record of the block's data:

![The merged document in the Windows Forms mail merge sample, in which the table has two rows created from the merge block.](https://docs.textcontrol.com/assets/img/tx-text-control-dotnet-winforms/merge-block-merged-rows.7bf0c5ba.webp)

### Insert the Block With the Ribbon

1. Press **F5** and design the template as in [Create a Template](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/getting-started/mail-merge/template/llms-full.txt).
2. Place the input position where the table of items goes.
3. Open the **Insert Merge Block** drop-down in the **Merge Blocks** group of the **Reporting** tab and select **Items**. The drop-down lists the tables of the data source that can become a block:

    ![The Insert Merge Block drop-down of the Reporting tab, here listing the tables of another data source, with Insert Custom Merge Block and Highlight Merge Blocks below them.](https://docs.textcontrol.com/assets/img/tx-text-control-dotnet-winforms/insert-merge-block-menu.fa8d7908.webp)
4. In the dialog box, select the columns **Description**, **Quantity** and **Price** and confirm with **OK**. **Table Row** and **Add table header row** create the block as a table row below a header row:

    ![The Insert Merge Block dialog box with checked columns, the buttons Move up, Move down and Filter & Sort, the options Table Row and Plain paragraph, Add table header row and Color.](https://docs.textcontrol.com/assets/img/tx-text-control-dotnet-winforms/insert-merge-block-dialog.9f32db99.webp)
5. Save the template again as *invoice.docx*.

The Reporting tab inserts a table row with the three merge fields and marks it as the block.

### Insert the Block in Code

The same block can be inserted by your code. Add the following `using` directives and methods to `Form1`:

```csharp
using System.Collections.Generic;
using TXTextControl.DocumentServer.DataSources;
using TXTextControl.DocumentServer.Windows.Forms;
```

```csharp
private void insertItemsBlockButton_Click(object sender, EventArgs e)
{
    // The Items block and the merge fields it contains
    MergeBlockInfo mergeBlockInfo = new MergeBlockInfo("Items")
    {
        ColumnNames = new List<string> { "Description", "Quantity", "Price" }
    };

    // A table row that is repeated for each item, below a header row
    MergeBlockSettings mergeBlockSettings = new MergeBlockSettings(BlockTemplateType.TableRow, true);

    // Insert the block at the current input position
    ribbonReportingTab1.DataSourceManager.InsertMergeBlock(textControl1, mergeBlockInfo, mergeBlockSettings);
}

private void insertItemsBlockDialogButton_Click(object sender, EventArgs e)
{
    DataSourceManager dataSourceManager = ribbonReportingTab1.DataSourceManager;

    // Let the user choose the columns of the Items block
    using (InsertMergeBlockDialog dialog = new InsertMergeBlockDialog(
        dataSourceManager, textControl1, dataSourceManager.DataTables["Items"]))
    {
        dialog.ShowDialog(this);
    }
}
```

The code works as follows:

- [MergeBlockInfo](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol-documentserver-datasources/mergeblockinfo/llms-full.txt) names the list of the data, and its [ColumnNames](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol-documentserver-datasources/mergeblockinfo/columnnames-property/llms-full.txt) are the merge fields of the block.
- [MergeBlockSettings](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol-documentserver-datasources/mergeblocksettings/llms-full.txt) with `BlockTemplateType.TableRow` creates the block as a table row, and `true` adds a header row above it.
- [InsertMergeBlock](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol-documentserver-datasources/datasourcemanager/insertmergeblock-method/llms-full.txt) inserts the block at the input position of `textControl1`.
- [InsertMergeBlockDialog](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol-documentserver-windows-forms/insertmergeblockdialog/llms-full.txt) is the dialog box of the Reporting tab. [DataTables](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol-documentserver-datasources/datasourcemanager/datatables-property/llms-full.txt) returns the table of the loaded data by its name.

### Merge the Template

The merge code of [Merge Data into Fields](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/getting-started/mail-merge/fields/llms-full.txt) does not change. It loads the template with `LoadSubTextParts` set to `true`, which imports the block, and `MergeJsonData` fills the block from the `Items` array, like the fields from the other properties.

Click **mergeButton**. The invoice now has a table with one row for *Consulting* and one for *Training*. The content of a block without data is removed, because [RemoveEmptyBlocks](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol-documentserver/mailmerge/removeemptyblocks-property/llms-full.txt) is `true` by default.

### Merge Business Objects Instead

The same template works with business objects. A property whose type is a collection fills the block of the same name:

```csharp
using System.Collections.Generic;

public class Invoice
{
    public string Company { get; set; }
    public string Name { get; set; }
    public string InvoiceNumber { get; set; }
    public List<InvoiceItem> Items { get; set; } = new List<InvoiceItem>();
}

public class InvoiceItem
{
    public string Description { get; set; }
    public int Quantity { get; set; }
    public decimal Price { get; set; }
}
```

In the merge code, replace the call of `MergeJsonData` with [MergeObject](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol-documentserver/mailmerge/mergeobject-method/llms-full.txt):

```csharp
Invoice invoice = new Invoice { Company = "Contoso Ltd.", Name = "Jane Miller", InvoiceNumber = "INV-1001" };
invoice.Items.Add(new InvoiceItem { Description = "Consulting", Quantity = 2, Price = 150.00m });
invoice.Items.Add(new InvoiceItem { Description = "Training", Quantity = 1, Price = 480.00m });

mailMerge.MergeObject(invoice);
```

### Next Steps

- [Merge Blocks](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/mail-merge/blocks/llms-full.txt): block types, empty blocks and block events in detail.
- [Nested Blocks and Master-Detail Reports](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/mail-merge/nested-blocks/llms-full.txt): blocks inside blocks.
- [Sorting and Filtering](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/mail-merge/sorting-filtering/llms-full.txt): sort and filter the rows of a block.
- The blog article [Mail Merge: Inserting Merge Blocks using the DataSourceManager in C#](https://www.textcontrol.com/blog/2024/10/02/mail-merge-inserting-merge-blocks-using-the-datasourcemanager-in-csharp/): inserting blocks in code.

---

## Nearby

- **Previous:** [Merge Data Into Fields](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/getting-started/mail-merge/fields/llms-full.txt)
- **Next:** [PDF Processing](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/getting-started/pdf/llms-full.txt)
