# Template Design

> Design templates for your data: sample JSON from .NET classes, a datasource excerpt, an invoice template built in the editor and the fonts it can use.

- **Product:** ReportingCloud
- **Section:** Documentation
- **Kind:** Topic
- **Path:** ReportingCloud > Mail Merge > Template Design
- **2994 words**
- **Web URL:** https://docs.textcontrol.com/reporting-cloud/mail-merge/template-design/
- **LLMs URL:** https://docs.textcontrol.com/reporting-cloud/mail-merge/template-design/llms.txt
- **LLMs-Full URL:** https://docs.textcontrol.com/reporting-cloud/mail-merge/template-design/llms-full.txt

---

Designing a template starts with the data, not with the layout: the names of the merge fields and merge blocks must be the names of the data you merge later. With sample data of the right structure, you design a template in the template editor of the ReportingCloud portal that fits your application's data before the application sends any. The walkthrough below turns .NET classes into sample data, designs an invoice template for them and merges it.

The editor itself is described in [Template Editor](https://docs.textcontrol.com/reporting-cloud/portal/template-editor/llms-full.txt), and the sample data it works with in [Datasource Excerpts](https://docs.textcontrol.com/reporting-cloud/portal/datasource-excerpts/llms-full.txt). The elements of a template have pages of their own: [Merge Fields](https://docs.textcontrol.com/reporting-cloud/mail-merge/fields/llms-full.txt), [Merge Blocks](https://docs.textcontrol.com/reporting-cloud/mail-merge/blocks/llms-full.txt), [Images](https://docs.textcontrol.com/reporting-cloud/mail-merge/images/llms-full.txt) and [Conditional Blocks](https://docs.textcontrol.com/reporting-cloud/mail-merge/conditional-content/llms-full.txt).

### How a Template Fits Its Data

A template contains the layout of the document and the names of its merge fields and merge blocks, never the data. The names connect the two: a merge field is named like a value of a record, such as `InvoiceNumber`, and a merge block like an array, such as `Items`, as [Merge Data](https://docs.textcontrol.com/reporting-cloud/mail-merge/data-sources/llms-full.txt) describes. A template therefore works with any data of the same structure.

You design it against *sample data*: data with the structure and the names of the real data and made-up values. In the portal, sample data is a *datasource excerpt*, which fills the lists and the merge preview of the template editor and is never sent with a merge request.

### Where Templates Come From

| Source | What you do | Described in |
|---|---|---|
| The template editor of the portal | Create a template with **New Template...**, open it with a datasource excerpt and insert fields, blocks and image placeholders from the ribbon | [Template Editor](https://docs.textcontrol.com/reporting-cloud/portal/template-editor/llms-full.txt) |
| MS Word or another word processor that supports MS Word formats | Design the document, add merge fields named like the data, save it as DOCX, DOC or RTF and upload it to the template storage | [Template Storage](https://docs.textcontrol.com/reporting-cloud/portal/templates/llms-full.txt), [Managing Templates](https://docs.textcontrol.com/reporting-cloud/document-processing/templates/llms-full.txt) |
| The Sample Template Gallery of the portal | Copy a sample template and its sample data source to your storage with **Add to My Templates** and change it | [Template Storage](https://docs.textcontrol.com/reporting-cloud/portal/templates/llms-full.txt) |

The template storage takes templates in the formats RTF, DOC, DOCX and TX. A template doesn't have to be stored: a merge request can also send it in the `template` property of the `MergeBody`, as [Overview](https://docs.textcontrol.com/reporting-cloud/mail-merge/overview/llms-full.txt) explains.

### Prepare Sample Data From .NET Classes

When your application merges .NET objects, serialize instances of the same classes, filled with sample values, and the sample data has the structure and the names of your classes. The following console application describes an invoice with a customer and a list of products:

1. Create a console application and add the package `Newtonsoft.Json`:

    ```bash
    dotnet new console -n InvoiceExcerpt
    cd InvoiceExcerpt
    dotnet add package Newtonsoft.Json
    ```
2. Replace the content of *Program.cs* with the following code:

```csharp
using Newtonsoft.Json;

List<Invoice> invoices = new List<Invoice>
{
    new Invoice
    {
        InvoiceNumber = "I778977622",
        Customer = new Customer
        {
            Name = "Peter Thiel",
            Street = "123 Microsoft Way",
            Zip = 22282,
            City = "Charlotte"
        },
        Items = new List<Product>
        {
            new Product { Name = "Product 1", Description = "Product 1 Description" },
            new Product { Name = "Product 2", Description = "Product 2 Description" }
        }
    }
};

// An array of records, the format the editor and document/merge expect
string json = JsonConvert.SerializeObject(invoices, Formatting.Indented);

File.WriteAllText("invoice_data.json", json);
Console.WriteLine(json);

public class Invoice
{
    public string? InvoiceNumber { get; set; }
    public Customer? Customer { get; set; }
    public List<Product>? Items { get; set; }
}

public class Customer
{
    public string? Name { get; set; }
    public string? Street { get; set; }
    public int Zip { get; set; }
    public string? City { get; set; }
}

public class Product
{
    public string? Name { get; set; }
    public string? Description { get; set; }
}
```

1. Run it with `dotnet run`. It prints the JSON and saves it as *invoice\_data.json*.

The list of invoices becomes a JSON array with one record. `Customer` becomes a nested object and `Items` an array of two products. In Visual Studio, you can also stop at a breakpoint after `SerializeObject` and copy the string from the Text Visualizer:

![Text Visualizer of Visual Studio with the serialized invoice JSON: InvoiceNumber, the Customer object and the Items array with two products](https://docs.textcontrol.com/assets/img/reporting-cloud/vs-text-visualizer-json.dc4adaa7.webp)

### Create the Datasource Excerpt

1. Log in to the [portal](https://portal.reporting.cloud/) and open **My Datasource Excerpts**.
2. Enter a name, such as *invoice\_data*, and paste the JSON into **Datasource Excerpt**. The form confirms valid JSON with "JSON object is valid". Save the excerpt with **Create Excerpt**.

    ![New Datasource Excerpt File form with the name invoice_data and the pasted invoice JSON, marked as valid](https://docs.textcontrol.com/assets/img/reporting-cloud/invoice-datasource-excerpt.c0c10d31.webp)

### Design the Invoice Template

1. Open **My Templates** and choose **New Template...**. Type a name such as *invoice\_test*, choose a format such as DOCX and confirm with **OK**.

    ![Create a new template dialog with the file name invoice_test and the format Office Open XML DOCX](https://docs.textcontrol.com/assets/img/reporting-cloud/new-template-dialog.02d9a768.webp)
2. In the next dialog, click **Edit Template**. Choose *invoice\_data.json* in the drop-down list of datasource excerpts and confirm with **Edit Template**.

    ![Select Datasource Excerpt page for invoice_test.docx with the drop-down list open and invoice_data.json selected](https://docs.textcontrol.com/assets/img/reporting-cloud/choose-invoice-excerpt.031ceb95.webp)
3. The editor opens. On the **Reporting** tab, open the **Merge Field** drop-down, point to **master** and choose **invoicenumber**. The drop-down lists the excerpt as the tables **master**, **customer** and **items**, with all names in lowercase.

    ![Merge Field drop-down of the Reports tab with the tables customer, items and master, and the master submenu with invoicenumber, master_id, customer and items](https://docs.textcontrol.com/assets/img/reporting-cloud/insert-merge-field-menu.549a6a14.webp)
4. Insert some blank lines after the field. Then open **Merge Block** and choose **items**. In the **Insert Merge Block** dialog, check **description** and **name**, keep **Table Row** and **Add table header row** selected and confirm with **OK**.

    ![Insert Merge Block dialog with the columns description and name checked, master_id unchecked, Table Row selected and Add table header row checked](https://docs.textcontrol.com/assets/img/reporting-cloud/insert-merge-block-dialog.fc2759a3.webp)
5. The editor inserts a table with a header row and a row for the block, marked in red. The row is repeated for each element of `Items`:

    ![Template with the invoicenumber field and a table whose header row shows description and name and whose red block row holds the fields «description» and «name»](https://docs.textcontrol.com/assets/img/reporting-cloud/repeating-merge-block.5fc9a5b1.webp)
6. Click **Preview Merge Results** in the **Preview** group and confirm the dialog box with **OK**. The preview merges the excerpt: the invoice number and one table row for each product:

    ![Merge results preview with the invoice number I778977622 and the table rows Product 1 Description and Product 2 Description with their names](https://docs.textcontrol.com/assets/img/reporting-cloud/preview-merge-results.be416e93.webp)
7. Finish the design, save it with **Save template** and return to the dashboard with **Back**.

### Merge the Template

The JSON of the excerpt is valid merge data, so the template can be merged with it right away. The merge matches names without regard to letter case, so the lowercase fields and blocks of the editor receive the values of `InvoiceNumber` and `Items`, as [Merge Fields](https://docs.textcontrol.com/reporting-cloud/mail-merge/fields/#name-fields-after-the-data) explains. In your application, the same structure comes from the list of `Invoice` objects. The following commands merge *invoice\_test.docx* with *invoice\_data.json*:

```bash
# Wrap the records of the sample data in a MergeBody
jq '{mergeData: .}' invoice_data.json > merge.json

curl -X POST "https://api.reporting.cloud/v1/document/merge?templateName=invoice_test.docx&returnFormat=PDF" \
  -H "Authorization: ReportingCloud-APIKey $REPORTINGCLOUD_API_KEY" \
  -H "Content-Type: application/json" \
  --data-binary @merge.json \
  -o result.json

jq -r '.[0]' result.json | base64 -d > invoice.pdf
```

The commands are those of the [Overview](https://docs.textcontrol.com/reporting-cloud/mail-merge/overview/#merge-a-template-from-the-template-storage), with the template and the data of this walkthrough. The API key comes from the environment variable `REPORTINGCLOUD_API_KEY`, as [API Keys](https://docs.textcontrol.com/reporting-cloud/installation/api-keys/llms-full.txt) explains.

### Use the Fonts of ReportingCloud

A template can use every font that is installed on the ReportingCloud servers: Windows fonts, such as Arial, Calibri and Times New Roman, and many Google Fonts, but not every Google Font. Inter, Roboto Condensed, Roboto Mono and Ubuntu, for example, are missing. The template editor lists the available fonts in the font drop-down of the **Home** tab, and documents merged with the Web API are rendered with the same fonts as the editor.

A template designed in MS Word can use fonts that ReportingCloud doesn't have. Before you upload such a template, check its fonts against the list that [GET /v1/fonts/list](https://docs.textcontrol.com/reporting-cloud/reference/web-api/fonts/list/get/llms-full.txt) returns as a JSON array of font names:

```bash
curl -H "Authorization: ReportingCloud-APIKey $REPORTINGCLOUD_API_KEY" \
  https://api.reporting.cloud/v1/fonts/list \
  -o fonts.json

# Prints true when the font is available
jq 'any(.[]; rtrimstr(" ") == "Arial")' fonts.json
```

Four names of the list end with a space, such as `"Pompiere "`, so the command compares each name without it. The .NET SDK returns the same list with `ListFonts`, and the PHP SDK with `getFontList`, which trims the names.

### Next Steps

- [Template Editor](https://docs.textcontrol.com/reporting-cloud/portal/template-editor/llms-full.txt): the ribbon, the dialogs and the preview of the editor.
- [Merge Blocks](https://docs.textcontrol.com/reporting-cloud/mail-merge/blocks/llms-full.txt): repeat rows and sections for each element of an array.
- [Nested Blocks](https://docs.textcontrol.com/reporting-cloud/mail-merge/nested-blocks/llms-full.txt): design blocks inside blocks.
- [Merge Settings](https://docs.textcontrol.com/reporting-cloud/mail-merge/settings/llms-full.txt): control how empty fields, blocks and images are handled.

---

## Nearby

- **Previous:** [Culture](https://docs.textcontrol.com/reporting-cloud/mail-merge/culture/llms-full.txt)
- **Next:** [Document Processing](https://docs.textcontrol.com/reporting-cloud/document-processing/llms-full.txt)
