> For the complete documentation index, see [llms.txt](https://docs.apryse.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.apryse.com/core/create/generate-via-template/advanced.md).

# Document Generation Advanced Features on Server/Desktop

Discover advanced features for office templates including custom tag delimiters, strict mode, and explicit loop scope. Learn how to optimize your document creation process effectively. The Apryse Serv

## Overview

This is a collection of [advanced features for office templates](/core/create/generate-via-template.md). See here for an [overview of basic features and the data model](/core/generate-via-template/data-model.md).

## Custom tag delimiters

The default tag delimiters are `{{` and `}}`. If you wish to use a different set of delimiters, you can use the functions `OfficeToPDFOptions#SetTemplateLeftDelimiter` `OfficeToPDFOptions#SetTemplateRightDelimiter`

## Strict mode

If a tag's key cannot be located in the data JSON, it will silently be removed from the document. If strict mode is enabled it will instead result in an error. To enable strict mode, use the function `OfficeToPDFOptions#SetTemplateStrictMode` By default, strict mode is disabled.

## Behavior for empty loops and false conditionals

In both the cases where a loop is given a json value of `[]` and a conditional is given a json value of `false`, the body is entirely removed. If the loop/conditional construct was the only thing in it's parent element, it will also remove the parent element.

For example, if an empty loop is the only text in a paragraph, the paragraph will be removed and the proceeding content will be moved up. Another example is an empty row loop, the row itself will be removed.

If this behavior is not desired, a possible workaround is to add a single space character outside of the loop/conditional.

## Explicit loop scope

By default, keys are "unspecified scope". Their value is taken dynamically from the most-specific (tightest) loop that contains that key.

For example, a [loop](/core/generate-via-template/data-model.md#loops) `{{loop arr}} {{key}} {{endloop}}` with the JSON data

{% tabs %}
{% tab title="JSON" %}
{% code lineNumbers="true" %}

```json
{
    "key": "*global",
    "arr": [
        {"key": "*local"},
        {}
    ]
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

Will result in `*local *global`.

In order to restrict a template tag to use values from a specific loop, you can specify a scope: `{{arr::key}}`. The top-level global scope is `{{::key}}` and in a nested loop you can have a nested scope: `{{outer::inner::key}}`.\`

## Table row insertion with insert\_rows ([.docx](https://www.pdftron.com/docs/tg_demo_table.docx), [.json](https://www.pdftron.com/docs/template_params_utf8.json))

This is an alternative to [table row loops](/core/generate-via-template/data-model.md#table-row-loops), which should be preferred in most cases.

Table row insertion values are JSON objects, and can only serve as the value for a template key that is in the first row of a table. They have the following required properties:

* `insert_rows`: \[array of arrays] An array of rows, representing the content to be added. If a table had 3 columns and you wanted to insert two rows within it, `insert_rows` would expect an array containing two arrays of three items each. The items within the three-member row arrays would be any allowed template value, such as text or an image.

![](https://3779731113-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fziw3GiL98Xfj63F3He8h%2Fuploads%2Fgit-blob-d18b2f04cfcd7706437e556319f8e42bd70b13f0%2Fdae06b22d1e4a9e588278dbffebbc56cf6f507b1-1440x480.png?alt=media)

{% tabs %}
{% tab title="JSON" %}
{% code lineNumbers="true" %}

```json
{
	"tblh1":"Services",
	"tblh3":"Charge",
	"billed_items": {"insert_rows": [["Wireless", "", "$42.34"], "..."]},
	"totals": {"insert_rows": [["", "Tax:", "$8.37"],["", "Balance:","..."]]}
}
```

{% endcode %}
{% endtab %}
{% endtabs %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.apryse.com/core/create/generate-via-template/advanced.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
