# Excel (XLSX)

## Getting Started

You can use Excel Spread Sheets ( .xlsx is the supported format ) as your document template, you can build your document in Ms Excel, Google Sheets or other supporting platforms and then upload it to Docupilot as a .xlsx file. Replace the info in excel sheet like client name, client company name to {{client.name}} and {{client.company}}.

![Excel Spread Sheet (.xlsx) template overview.](https://191679573-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LDwD-wIOendMUiQ8uVr%2F-MWSzXWKy4Tp9X70eU5S%2F-MWTNTe3hldvklresAqm%2FXLsx.png?alt=media\&token=eb99081a-e804-4275-a157-e7e8f0b54486)

### Uploading XLSX

![](https://191679573-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LDwD-wIOendMUiQ8uVr%2Fuploads%2FMq3wp0QAPyTnXkYZxuBS%2Fexcel%20page1.gif?alt=media\&token=70e1afac-c837-47a2-8644-1919d8b3f7f6)

### Updating XLSX

If you want to make changes to your Excel Spread Sheet make changes in MS Excel, Google Sheets etc , and upload it to Docupilot as a .xlsx file.

![](https://191679573-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LDwD-wIOendMUiQ8uVr%2Fuploads%2FpEBpFlbjQp7AzlXAF25m%2Fexcel%20page2.gif?alt=media\&token=d660e389-da65-48f6-ba2f-a5b2ae669701)

## Types of Merge Fields <a href="#types-of-merge-fields" id="types-of-merge-fields"></a>

Docupilot supports a variety of merge fields for you to use.

* Tokens (Merge Field)
* Condition (`if-else`)
* Iterating inside a cell
* Tables

### Tokens (Merge Field) <a href="#tokens-merge-field" id="tokens-merge-field"></a>

These are simple fields embraced in `{{}}`. When you provide your custom data, **Docupilot** will replace these fields with the data. For example **{{email}}, {{clientname}}, {{company\_name}}**.

If you want to group your fields you can use dot(.) while defining the tokens. For example your client has first name & last name, you can write the tokens as **{{client.first\_name}}, {{client.last\_name}}.**

### Condition (`if-else`)

You can use conditional statements to show or hide contents based on your data. For example, If you are creating an invoice, you want to display CASH if the payment\_mode is cash, else if the payment\_mode is the card you want to show CARD.

```
{{#if (payment_mode == "cash")}}
CASH
{{else if (payment_mode == "card")}}
CARD
{{else}}
Please Insert preferred Mode of Payment{{/if}}
```

To use conditional statement for checking inverse or negation of a condition, use the **not** in the condition. For example, to add an instruction requesting to add secure link if payment mode is not available on record:

```
{{#if (not payment_mode)}}
Please Add your payment details in this secure link: <your secure payment link>
{{/if}}
```

{% hint style="info" %}
Note: The `if/else` statements work only when added inside a single cell. For example:

![](https://191679573-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LDwD-wIOendMUiQ8uVr%2Fuploads%2Fulq24l8GgiWFllGJEz1R%2Fimage.png?alt=media\&token=e25f723d-29dd-43b1-9950-3c6f2ac17332)
{% endhint %}

You can use the conditional statements in the following ways

* `if`&#x20;
* `if-else`&#x20;
* `if-else if`
* `if-else if-else`&#x20;
* `if-else if-else if`
* `if-else if-else if-else`&#x20;
* and so on...

Below are a few examples:

| <p><code>{{#if show\_payment\_details}}</code></p><p><code>ACH to {{acNumber}}</code></p><p><code>{{/if}}</code></p>                                                                                                                                                   | prints the text `ACH to xxxxxxxxx` if `show_payment_details` is present and not `false`.                                                                                                                                                                 |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <p><code>{{#if (payment\_status == "paid")}}</code></p><p><code>payment cleared</code></p><p><code>{{/if}}</code></p>                                                                                                                                                  | prints `payment cleared` if `payment_status` equals to `"paid"` (case-sensitive)                                                                                                                                                                         |
| <p><code>{{#if (payment\_status != "paid")}}</code></p><p><code>unpaid</code></p><p> <code>{{/if}}</code></p>                                                                                                                                                          | prints `unpaid` if `payment_status` not equal to `"paid"` (case-sensitive)                                                                                                                                                                               |
| <p><code>{{#if (payment\_status == "paid")}}</code></p><p><code>paid</code></p><p><code>{{else}}</code></p><p><code>unpaid</code></p><p><code>{{/if}}</code></p>                                                                                                       | prints `paid` if `payment_status` equals to `"paid"` otherwise prints `unpaid`                                                                                                                                                                           |
| <p><code>{{#if (payment\_status == "paid")}}</code></p><p><code>paid</code></p><p><code>{{else if (payment\_status == "initiated")}}</code></p><p><code>payment initiated</code></p><p><code>{{else}}</code></p><p><code>pending</code></p><p><code>{{/if}}</code></p> | <p>prints <code>paid</code> if <code>payment\_status</code> equals to <code>"paid"</code> </p><p>prints <code>payment initiated</code> if <code>payment\_status</code> equals to <code>initiated</code> </p><p>otherwise prints <code>pending</code></p> |
| <p><code>{{#if (price > 1000)}}</code></p><p><code>good deal</code></p><p><code>{{/if}}</code></p>                                                                                                                                                                     | prints the text `good deal` if price is greater than 1000                                                                                                                                                                                                |
| <p><code>{{#if (price >= 1000)}}</code></p><p><code>decent deal</code></p><p><code>{{/if}}</code></p>                                                                                                                                                                  | prints text `decent deal` if price is greater than or equal to 1000                                                                                                                                                                                      |
| <p><code>{{#if (price < 1000)}}</code></p><p><code>small deal</code></p><p><code>{{/if}}</code></p>                                                                                                                                                                    | prints text `small deal` If price less than 1000                                                                                                                                                                                                         |
| <p><code>{{#if (price <= 1000)}}</code></p><p><code>okay-ish deal</code></p><p><code>{{/if}}</code></p>                                                                                                                                                                | prints text `okay-ish deal` If price less than or equal to 1000                                                                                                                                                                                          |
| <p><code>{{#if (payment\_message contains "paid")}}</code></p><p><code>Payment is cleared</code><br><code>{{/if}}</code></p>                                                                                                                                           | prints `Payment is cleared` if `payment_message` contains the text `paid` *(for example, `this invoice has been paid` contains the text `paid` in it)*                                                                                                   |
| <p><code>{{#if (payment\_message not\_contains "paid")}}</code></p><p><code>Payment is due</code><br><code>{{/if}}</code></p>                                                                                                                                          | prints `Payment is due` if `payment_message` does not contain the text `paid` *(for example, `this invoice is not cleared` does not contain the text `paid` in it)*                                                                                      |
| <p><code>{{#if (status == "open" or status == "on-hold")}}</code></p><p><code>Payment is pending</code></p><p><code>{{/if}}</code></p>                                                                                                                                 | prints `Payment is pending` if `status` is `open` OR `on-hold`                                                                                                                                                                                           |
| <p><code>{{#if (status == "open" or status == "on-hold" or status == "under review")}}</code></p><p><code>Payment is pending</code></p><p><code>{{/if}}</code></p>                                                                                                     | prints `Payment is pending` if `status` is `open` OR `on-hold` OR `under review`                                                                                                                                                                         |
| <p><code>{{#if (status != "open" and status != "on-hold")}}</code></p><p><code>Payment is not pending</code></p><p><code>{{/if}}</code></p>                                                                                                                            | prints `Payment is not pending` if `status` is not `open` AND not `on-hold`                                                                                                                                                                              |
| <p><code>{{#if (status == "open" and priority == "high")}}</code></p><p><code>High priority open task</code></p><p><code>{{/if}}</code></p>                                                                                                                            | prints `High priority open task` if `status` is `open` AND if `priority` is `high`                                                                                                                                                                       |
| <p><code>{{#if (payment\_status != "paid")}}Please Clear the Dues within 30 days</code> </p><p><code>{{/if}}</code></p>                                                                                                                                                | prints `Please Clear the Dues within 30 days` if the `payment_status` is not equal to `paid`                                                                                                                                                             |
| <p><code>{{#if (status in "open,pending")}}In Progress... Please stay tuned for further updates.</code></p><p><code>{{/if}}</code></p>                                                                                                                                 | prints `In Progress... Please stay tuned for further updates.` if `status` is sub-string of `"open,pending"`                                                                                                                                             |

#### Hiding Empty Sections & Lines

In the following example, when the `address` field has a value, it gives desired outcome. If the address is empty, it leaves an empty line in the output.

```
{{customer_name}},
{{#if address}}{{address}},{{/if}}
{{city}}, {{country}}
```

<table><thead><tr><th>Data</th><th>Output</th></tr></thead><tbody><tr><td><pre><code>customer_name = John Doe
city = NY
country = US
</code></pre></td><td><pre><code>John Doe,

NY, US </code></pre></td></tr><tr><td><pre><code>customer\_name = John Doe
street = WinWood St.
city = NY
country = US </code></pre></td><td><pre><code>John Doe,
WinWood St.,
NY, US </code></pre></td></tr></tbody></table>

To hide empty lines, we should open the `if` condition in previous line or close it in next line. Here are examples on how the output will look like when street address is passed and when it is not:

<table><thead><tr><th>Syntax</th><th>Data</th><th>Output</th></tr></thead><tbody><tr><td><pre><code>{{customer_name}},{{#if street}}
{{street}},{{/if}}
{{city}}, {{country}}
</code></pre></td><td><pre><code>customer_name = John Doe
city = NY
country = US
</code></pre></td><td><pre><code>John Doe,
NY, US
</code></pre></td></tr><tr><td><pre><code>{{customer_name}},{{#if street}}
{{street}},{{/if}}
{{city}}, {{country}}
</code></pre></td><td><pre><code>customer_name = John Doe
street = WinWood St.
city = NY
country = US
</code></pre></td><td><pre><code>John Doe,
WinWood St.,
NY, US
</code></pre></td></tr><tr><td><pre><code>{{customer_name}},
{{#if street}}{{street}},
{{/if}}{{city}}, {{country}}
</code></pre></td><td><pre><code>customer_name = John Doe
city = NY
country = US
</code></pre></td><td><pre><code>John Doe,
NY, US
</code></pre></td></tr><tr><td><pre><code>{{customer_name}},
{{#if street}}{{street}},
{{/if}}{{city}}, {{country}}
</code></pre></td><td><pre><code>customer_name = John Doe
street = WinWood St.
city = NY
country = US
</code></pre></td><td><pre><code>John Doe,
WinWood St.,
NY, US
</code></pre></td></tr></tbody></table>

### Iterating inside a cell

Multiple entries inside a cell can be incorporated by using the following syntax.

![Iterating a list inside a cell in Excel](https://191679573-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LDwD-wIOendMUiQ8uVr%2F-MX8BVHq1OCZWW5UyyCh%2F-MX8D-i6bpwL6ww6QuuF%2Flistxlsx1.jpg?alt=media\&token=90bbdde3-6929-487f-b401-7e3e5be58bbf)

![Output for iterating a list inside a cell in Excel](https://191679573-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LDwD-wIOendMUiQ8uVr%2F-MXVez3L76T_DgaIq4I1%2F-MXVfA5yXu14cfBaIEi5%2Flistxlsx1.jpg?alt=media\&token=07781979-7b81-4409-9580-e788e07408b9)

## **Tables**&#x20;

Dynamic tables allow a template to repeat a row for each item in a list, automatically adjusting during merging. Instead of setting a fixed number of rows, use loop tags `{{#each ...}}` ... `{{/each}}`. The result is a well-organized table—ideal for invoices, order summaries, schedules, or reports where record count changes.

Following are different ways in which a Dynamic Table can be created:

### Simple Table

A simple and straight forward table which addresses most use-cases. To create a simple table which repeat one or many rows for each item in a list, follow these instructions:

1. Identify the cell where table should start. *(ex: B3)*
2. Identify number of columns that are to be repeated as part of the Dynamic Table. *(ex: 3)*
3. Now, merge the number of cells starting from the start cell. *(ex: Merge B3 -> D3)*
4. Add the loop's opening tag `{{#each YOUR_TOKEN_NAME}}` . *(ex: `{{#each invoice_items}}` )*
5. In the next row, add the content for your columns.
   1. The content in each cell can be a dynamic placeholder (like `{{name}}`) or fixed text (like `Item Name`) or a combination (like `Item Name: {{name}}`).
   2. [Formatters/Modifiers](https://help.docupilot.app/document-template/formatting-your-data) can be used to format or style dynamic data in a cell. *(For example, adding `{{upper name}}` in B4 will display the names in uppercase.)*
   3. For *ex: consider an invoice invoice, where the item name, qty, and price are to be printed in 3 adjacent columns. Just `{{name}}` , `{{quantity}}`, and `{{price}}` in cells B4, C4 and D4*
6. If another row is to be repeated configure the next row as mentioned in 5.a. This can be done for as many rows as desired.
7. Once the repeated rows are configured, in the next row merge the cells similar to what was done in step 3. *(ex: Merge B5 -> D5)*
   1. Merged cell width should be same as the number of columns that need to be repeated. This is also same as the width of the cell where loop's opening tag is added.
8. Add the loop's closing tag `{{/each}}` in this merged cell *(ex: add `{{/each}}` in merged cell B5)*

Below is an example screenshot from an excel template which uses Dynamic table to print list of invoice line items. This example also demonstrates calculating the total price using [aggregate modifier](https://help.docupilot.app/formatting-your-data#aggregate).

![Inserting a Dynamic Table in Excel](https://191679573-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LDwD-wIOendMUiQ8uVr%2Fuploads%2Fhi9oZE7MwLhhLHsPHpkw%2FSimple%20loop%20table%20example.png?alt=media\&token=ae3a27c2-c4cd-45c3-adb1-7cfcf5b9b127)

{% hint style="info" %}
Note that the loop's opening cell and closing cell should be merged and span across same number of columns. The cells sand-witched in between the opening cell and closing cell will be repeated. Cells to the left and to the right will not be disturbed by dynamic table.
{% endhint %}

![Example output of a Dynamic Table in Excel](https://191679573-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LDwD-wIOendMUiQ8uVr%2Fuploads%2FaqwO13zUzVevBkMoIGQd%2FExample%20output%20for%20simple%20loop%20in%20a%20table.png?alt=media\&token=7a08fa73-d081-479c-b9c3-83965909bdf7)

### Nested Tables

A **Nested Table** is more than 1 simple table nested inside one another. Nested tables allow you to repeat a nested list of items. For example, to print a list of Departments and Employee details in each Department.

To create a nested table, follow the same instructions as explained under [Simple Tables](#simple-table). When configuring the cells after creating the opening cell, follow the same instructions atop to create a child dynamic table.

The image below depicts a Dynamic Table that iterates over a list of departments, prints the Department's name and then iterates over a list of Employees in each Department and prints their ID, Name, Designation and Salary.

<figure><img src="https://191679573-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LDwD-wIOendMUiQ8uVr%2Fuploads%2FvLeCMjrQxm1Uf8vRn57A%2FScreenshot%202025-05-07%20at%205.04.12%E2%80%AFPM.png?alt=media&#x26;token=bcf0e5fc-21b8-4aa9-913d-5608b248c7ef" alt=""><figcaption><p>Nested Dynamic Tables in Excel</p></figcaption></figure>

<figure><img src="https://191679573-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LDwD-wIOendMUiQ8uVr%2Fuploads%2FKIluwdbydjfnLwhxs9ap%2FSample%20output%20for%20nested%20loops.png?alt=media&#x26;token=b68c79f7-eea6-4387-87c4-548ba1ccb5b1" alt=""><figcaption><p>Example output of a Nested Dynamic Tables in Excel</p></figcaption></figure>

{% hint style="info" %}
The example above shows Nested Dynamic tables with a 2 level nesting. There is currently no limit on the number of nesting levels supported.
{% endhint %}

### Legacy Tables

This section acts as a reference for templates that use older Dynamic Table syntax. This syntax has many limitations and is not recommended for use.

Syntax: `{{table:YOUR_LIST.PROPERTY_NAME}}`&#x20;

Example:

* `{{table:line_items.name}}`
* `{{table:line_items.qty}}`
* `{{table:line_items.amount}}`

Here for the field named `line_items` – `name`, `amount` and `qty` are defined as the property of each `line_item`. The image below shows how this example looks like when implemented.

<figure><img src="https://191679573-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LDwD-wIOendMUiQ8uVr%2Fuploads%2FbNaa6bh77GlNsoaskBrA%2FInsert%20tables.png?alt=media&#x26;token=767b1ea1-f2a7-48f4-bcea-061d17c7b06d" alt=""><figcaption><p>Legacy Dynamic Table in Excel</p></figcaption></figure>

<figure><img src="https://191679573-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LDwD-wIOendMUiQ8uVr%2Fuploads%2FiHSxFE9xMZpAoyyr6L8Y%2FExample.png?alt=media&#x26;token=8c467a07-6b4e-464f-aa7c-1cc45bb6a46a" alt=""><figcaption><p>Example output of a Legacy Dynamic Table in Excel</p></figcaption></figure>

{% hint style="info" %}
Legacy tables are very limited in terms of functionality. The new style Dynamic Tables are flexible, scalable and are recommended over Legacy Dynamic Tables.
{% endhint %}

## Inserting a dynamic image

An image can be dynamically added into XLSX template from a URL. The URL should be a publicly available URL. To add image dynamically, add the following syntax in one of the desired cells:

Syntax : `{{insert_image image width="width" height="height"}}`

Example: `{{insert_image image width=300 height=300}}`

If you want to automatically adjust the height to keep proportions, you can use:  `{{insert_image image width=300}}`

Similarly to automatically adjust the width to keep proportions, you can use `{{insert_image image height=300}}`

{% hint style="info" %}
The image inserted will be aligned to the cell top left corner.

The image URL needs to be publicly accessible so we can download and insert it in the document.

To insert images from google drive, reach out to our support.
{% endhint %}

## Adjust orientation for output PDF <a href="#types-of-merge-fields" id="types-of-merge-fields"></a>

To generate a PDF in landscape mode from an XLSX template, follow these steps:

1. Open your XLSX template and navigate to the '**Page Layout**' settings.
2. Select '**Page** **Orientation**' and choose '**Landscape**.'
3. Upload the XLSX template to Docupilot, and the output will be in landscape format when converted to PDF.

<figure><img src="https://191679573-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LDwD-wIOendMUiQ8uVr%2Fuploads%2FxRMbSijZg006fbKunLv0%2FXLSX.gif?alt=media&#x26;token=7558525d-615e-4d13-9ca7-306369a3dccb" alt=""><figcaption><p><strong>Page</strong> <strong>Orientation updated on a XLSX file</strong></p></figcaption></figure>
