Create Dynamic Word Documents
Master document logic. Implement conditionals, loops for lists, and text variables to automate contracts and reports.
How it works?
Instead of writing "John Doe", you write {{client_name}}. When you upload your file and data, we fill everything automatically.
Text Variables
Use double curly braces to insert dynamic data anywhere in the document.
Simple Variables
Cliente: {{ data.cliente.nombre }}
Fecha: {{ data.fecha }}
Monto: ${{ data.monto }}Nested Data
Contacto: {{ data.cliente.contacto.nombre }}
Email: {{ data.cliente.contacto.email }}
Cargo: {{ data.cliente.contacto.cargo }}Images
Insert dynamic images from URLs or base64 data. Two methods available:
1Text Token
The image is inserted at its original size (max 6 inches wide).
{{#picture logo}}JSON:
{
"logo": "https://ejemplo.com/logo.png"
}2Placeholder Image
The image adjusts to the placeholder size maintaining proportions.
Simple Steps:
1. Insert an example image
2. Right click → Alt Text
3. Write the variable name (e.g., logo)
JSON:
{
"logo": "data:image/png;base64,iVBO..."
}Supported formats
- URL pública (https://...)
- Base64 data URI (data:image/png;base64,...)
- Formatos: PNG, JPG, GIF, BMP
Smart Tables
Tables expand automatically when they detect array variables. No special syntax needed - just use normal variables.
Example: Product Table
IN YOUR TEMPLATE:
| Product | Price |
|---|---|
| {{ products.name }} | {{ products.price }} |
YOUR JSON DATA:
{
"products": [
{ "name": "Laptop", "price": 1000 },
{ "name": "Mouse", "price": 25 }
]
}TIPSpecial Variable: Auto Numbering
Use {{#index}} to number rows automatically (1, 2, 3...).
{{ #index }} - {{ products.name }}Lists
No need to declare loops. The engine automatically detects when a variable is a collection and repeats the list item for each item.
Bulleted List
Create a list in Word and add tokens:
- {{ items.name }}
Numbered List
Same principle with numbered lists:
- {{ items.name }}
Nesting
You can nest collections within other collections. The engine automatically duplicates necessary elements.
Example: Companies with Projects
{{ companies.name }}
Projects:
- {{ companies.projects.name }}
companies.projects.name accesses projects within each company.
Tip: Duplicable Objects
The engine looks for the nearest duplicable object: table cell, list item, or paragraph. If you need to repeat content that is none of these, use a single-cell table with transparent borders.
Conditional Logic
Show or hide content based on your data.
If/Else
{% if price > 100 %}
Oferta Especial
{% else %}
Precio Regular
{% endif %}Check Existence
{% if discount %}
Descuento: {{ discount }}%
{% endif %}Functions and Filters
Transform and manipulate your data
Text Transformation
| Custom Filters | Example | Result |
|---|---|---|
| title_case | {{ "hello world" | title_case }} | Hello World |
| upper | {{ name | upper }} | JUAN PÉREZ |
| lower | {{ title | lower }} | documento |
| replace | {{ text | replace("old", "new") }} | text new |
| length | {{ "Hello" | length }} | 5 |
Number and Date Formatting
| Custom Filters | Example | Result |
|---|---|---|
| format | {{ 1234.5 | format("N2") }} | 1,234.50 |
| format (currency) | {{ price | format("C") }} | $1,500.00 |
| format (date) | {{ date | format("%d/%m/%Y") }} | 25/12/2024 |
| num2words | {{ 42 | num2words }} | forty-two |
List Operations
| Custom Filters | Example | Result |
|---|---|---|
| count | {{ products | count }} | 5 |
| join | {{ names | join(", ") }} | Ana, Carlos, Luis |
| sort | {{ items | sort("name") }} | [sorted A-Z] |
| filter | {{ items | filter("active == true") }} | [only active] |
| sum | {{ orders | sum("total") }} | 4,500.00 |
| avg | {{ scores | avg }} | 85.5 |
Checks
| Custom Filters | Example | Result |
|---|---|---|
| is_empty | {% if list | is_empty %}No data{% endif %} | true/false |
| contains | {{ email | contains("@gmail") }} | true/false |
| starts_with | {{ code | starts_with("PRO-") }} | true/false |
| ends_with | {{ file | ends_with(".pdf") }} | true/false |
| default | {{ name | default("N/A") }} | N/A |
Advanced Data Access
Filters to access complex and nested data in your JSON.
| Custom Filters | Syntax |
|---|---|
| find | Finds the first element where a field equals a value |
| first / last | Gets the first or last element of a list |
| attr | Gets an attribute of an object |
| selectattr | Filters elements by attribute |
| map_attr | Extracts an attribute from each element |
Example: Filter and Access Sublines
To iterate only FINANCE sublines:
{% set finance = data.catalogo_global.lineas_negocio | find("codigo", "FINANCE") %}
{% for sub in finance.sublineas %}
• {{ sub.nombre }}
{% endfor %}Result: Treasury Management, Working Capital Management, Financial Operations...
NUMERACIÓNAutomatic Section Numbering
Numbers sections automatically, even when some are hidden with {%if%} (Jinja2).
Syntax
{{ #section(7) }} Introducción
{% if show_overview %}
{{ #section(7) }} Resumen General
{% endif %}
{{ #section(7) }} Detalles del ProyectoWithout auto-numbering (show_overview=false)
7.1 Introducción 7.3 Detalles (hueco)
With auto-numbering
7.1 Introducción 7.2 Detalles ✓
Tip: Supports multiple levels: {{ #section(7.1) }} → 7.1.1, 7.1.2...
LÓGICALogical Operations
If/Else
{% if cliente.tipo == 'premium' %}
Estimado cliente VIP,
{% elif cliente.tipo == 'regular' %}
Estimado cliente,
{% else %}
A quien corresponda,
{% endif %}Combining with Filters
{% if items | is_empty %}
No hay elementos
{% else %}
Total: {{ items | count }} elementos
Suma: {{ items | sum("precio") | format("C") }}
{% endif %}Best Practices
- •Combine filters:
{{ items | filter("activo == true") | count }} - •Use default for missing values
- •Format numbers and dates for professional presentation