
Research
Two Malicious Rust Crates Impersonate Popular Logger to Steal Wallet Keys
Socket uncovers malicious Rust crates impersonating fast_log to steal Solana and Ethereum wallet keys from source code.
n8n-nodes-docxtemplater
Advanced tools
n8n node to create Word/Excel/Powerpoint documents from template documents, using docxtemplater
[!TIP] If you're interested in generating documents using N8N from a Word/Excel/Powerpoint template, you may also be interested in the
n8n-nodes-carbonejs
node, which uses Carbone as the rendering engine.Carbone has a different syntax for filters/formatters and its node is simpler to use than this one, at the expense of less configurable functionality (no custom Transforms or data sources, no Modules)
This is an n8n community node. It lets you use docxtemplater in your n8n workflows.
docxtemplater is a library that generates DOCX, PPTX and XLSX documents from templates and a database containing the custom data. This enables you to automate large-scale document generation efficiently.
The docxtemplater tags (e.g. { object.data | filter1 | filter2 }
) can
use Jexl syntax: binary operators such as +
and -, comparisons such as == or !=, and transforms
such as | lower
that work like shell pipes.
This node lets you transform this template document:
into this document:
It also allows you to use N8N's Advanced AI Tool nodes, like those that are used to provide "Tool Calling" functionality on LLMs. These can be used to provide custom formatters/filters/transforms that can transform data:
n8n is a fair-code licensed workflow automation platform.
Installation
Operations
Compatibility
Usage
→Transforms
→Docxtemplater Modules
→Data Resolving
Resources
Version history
Follow the installation guide in the n8n community nodes documentation.
This operation receives a DOCX, PPTX or XLSX document (1), plus a "context" (a JSON document) (2), and outputs another
DOCX, PPTX or XLSX document (3). The input document can have "tags" such as { value }
, which will be replaced with the
corresponding data in the context.
With the context in the image above, it's possible to write tags like this (and, in general, anything else that is supported by Jexl, AKA Javascript Expression language in the Word document:
{ first_name }
: Will simply be replaced by the corresponding JSON field, so the output document will contain Joe
{ first_name + " " + last_name }
: Will execute a string concatenation, so the output will be Joe Doe
{ first_name ? "Hello, " + first_name : "Hello!" }
: Supports
the ternary operator (if X then Y else Z), and
special syntax for an operation similar to null-coalescing: { user.first_name ?: "Person" }
{ first_name | uppercase }
: Will read the first_name
property and then call
a transform on it (must be implemented!
See below). This may output, if so implemented, JOE
if first_name
is Joe
{ positions["Chief of " in .title] }
: Will filter the
positions
array array such that only positions
that mention "Chief of ..." are kept{ getUsers("ACTIVE") }
: Functions, with and without arguments,
are also supported at the top level (as the first
element, not just as transforms after a pipe)All these can be freely mixed with Docxtemplater syntax, such as loops or conditionals:
turns into
This node has been developed on N8N v1.80.5. It should work with older versions as long as they include Tools for AI nodes. If you encounter any problems, please open an issue!
Since document tags (e.g. { some_field }
) in the template document use
the Jexl format, they also
support transforms), expressed with the pipe |
character:
{ some_field | uppercase }
{ some_field | split(" ") }
{ some_field | lower | split(" ") }
Transforms work like Filters in the docxtemplater Angular parser, formatters in Carbone, pipes in Angular or in Unix shells, or filters in web frameworks like Jinja or Django: they receive a piece of data as input, optionally some other parameters, and they output another piece of data that is usually some sort of transformation of the input data.
Simple transforms take no arguments other than their input data:
{ some_field | uppercase }
The | uppercase
transform reads its input, uppercases it (which implies that it should only be called on strings) and
returns the uppercased string.
Other transforms require parameters/arguments to further customize their behavior:
{ now | timeformat("yyyy-MM-dd HH:mm") }
Filters can be chained as long as the output of the previous filter can be used as the input to the next filter:
{ some_field | lower | split(" ") | first | length }
If some_field
is a string, | lower
receives it and outputs another string, a lowercased version of it.
| split(" ")
can receive this string and split it into an array of strings. | first
can receive this array and pick
out its first element, which will be a string. | length
receives that string and returns a number, the count of
characters in the first word of some_field
.
The following transforms are bundled with this N8N node. Feel free to open an issue if you know of other transforms that could be useful to more people (for example, transforms that are commonly bundled with similar software):
| JSONstringify
: Receives any data and returns a string, the result of JSON-serializing it. Use if your output Word
document displays data like [Object object]
(that's the sign of a JS object trying to be converted to a string)| JSONparse
: The opposite of | JSONstringify
, reads in a string that should contain a JSON-encoded document and
outputs the actual document. Use when the render data contains JSON-encoded data| length
: Receives something that has a "length" (e.g. strings or arrays) and returns a number with the length of
the data. If it's a string, the length is the number of characters. if it's an array, it's the number of elementsThis functionality is powered by N8N's Advanced AI "Tools" feature, normally used to provide "Tool Calling" functionality to LLMs. Tools are sub-nodes that can be "provided" to a main node, and may be called by the main node if necessary (e.g. when the LLM generates a tool call document while generating some text).
You can add your own custom transforms by attaching them to the Transforms connection point below the node:
These will be exposed as filters/transforms/pipe operators in the template document.
N8N has many nodes that have been enabled to function as Tools, so they can be used with LLMs. These can all be used by this node.
For example, the Wikipedia tool receives a piece of text, which should be the name of a Wikipedia article, and returns Markdown text with the beginning of the article:
There are many other tools, such as Wolfram|Alpha and Calculator that can run mathematical operations, HTTP Request that can run arbitrary HTTP requests with the provided data, as well as many N8N nodes that have been tool-ified, such as Airtable, Asana, AWS, Crypto, Discord, Facebook, Gmail, Linear, OneDrive, Postgres, S3, Slack, and many more.
If your desired transform isn't available and is better expressed as a piece of code, you can use the Custom Code Tool to implement a transform:
| transform_name
) with which it'll
be invokedquery
or its sub-field query.input
:
{ some_var | uppercase }
, it must read from query
directly:
query
in the code will contain whatever value some_var
has{ some_var | split(" ") }
, it must read the input data from
query.input
and the additional args from query.args
. query.args
is an array where additional args are passed
in order (in this example, it'll be a 1-element array [" "]
whose single element is a string with a single space).
Additionally, if the tool takes additional arguments, they will be exposed as arg0
, arg1
and so on (in other
words, you can also access the first transform argument as query.arg0
). This is provided to allow the use of
tools that can't index into arrays, such as
the HTTP Request Tool
that only accepts placeholders like {arg0}
of type String, but not {args.0}
or {args[0]}
with args
of type
Arrayjson { "input": "sample input", "args": [" "] }
JSON.stringify(...)
(for JS) on it before returning so it returns as a string
{ some_field | transformA | transformB }
: If | transformA
is
forced to stringify its return object, | transformB
will receive the real object as query
or query.input
Example of a transform with no params, where the input can be accessed using the query
name:
{ first_name | toupper }
Example of a transform with additional params, where the input can be accessed on query.input
and the transform args
on query.args[0]
, query.args[1]
and so on. Notice that a custom Schema has been provided, informing N8N that this
transform receives a string as its main input and additionally one other parameter that is also a string:
{ date | split("/") }
This node supports Docxtemplater modules, either the Docxtemplater-provided paid modules, third-party modules, or (TODO) modules that you write yourself.
Docxtemplater modules extend the functionality of Docxtemplater, such as
allowing variable images with the syntax {%fieldWithImagePath}
or raw HML with the syntax {~~fieldWithHtml}
.
You first need to install the modules into the same Node.js environment used by N8N so they're available for importing.
In general, if you can successfully run require("docxtemplater-module-name")
in a JS Code node, you should be able to
use it in this node.
[!TIP] If you have already installed NPM packages for the Code node, you can use that same workflow here, it should work (please raise an issue if not so I can add better instructions!). Otherwise, see below.
If using the npm install (native, no Docker), you can run
npm install -g docxtemplater docxtemplater-module-name
(the same command
used when installing N8N itself) so the
modules are installed in a place where the node can reach them.
If using the Docker install, you should probably use a custom
Dockerfile in which you run the npm install -g docxtemplater docxtemplater-module-name
command,
as outlined here.
[!NOTE] In either case, you must also install the
docxtemplater
package, not just thedocxtemplater-module-X
package for the module itself. Docxtemplater modules depend ondocxtemplater
the main package as a dependency, so they'll error out if it isn't installed
docxtemplater*module*
that are available in the same location as the N8N package itself (location varies per OS, and depending on whether
you're using NVM or straight NPM)new NameModule(...)
calllet opts = {}
and returns itnew FootnoteModule({})
. The default code works for this moduleimageOptions
object in the sample code). Use the docs' code as a starting pointrequire(...)
ing Node modules, or
accesing $item
and other execution variablesSee example configuration below:
const fs = require("fs");
let opts = {};
const getbinary = this.helpers.getBinaryDataBuffer;
opts.getImage = async function (tagValue, tagName) {
const url = await tagValue;
if (url.match(/^https?:\/\//)) { // URL, download it
return fetch(url).then(r => r.arrayBuffer())
} else if (url.match(/^file:\/\//) || url.startsWith("/")) { // local file
const path = url.replace("file://", "");
return fs.readFileSync(path);
} else if (url.match(/binary:\/\//)) { // Ref to N8N binary data, read and return it
const name = url.replace("binary://", "");
return getbinary($itemIndex, name)
} else {
throw new Error(`Unable to handle image ${url}! URLs (http:// or https://) and local files (file:///path/to/file or /path/to/file) are supported.`);
}
}
opts.getSize = function (img, tagValue, tagName) {
return [150, 150];
}
return opts;
Note that:
require(...)
Node.js packages, subject to the
usual admin-configurable restrictions on which nodes can be importedfetch()
function is also available so HTTP
requests can be made$item
, $json
, $binary
, the
helpers
property of
IExecuteFuntions
,
and any properties of
IWorkflowDataProxyData
Docxtemplater supports async data resolving, which means that it can fetch data in the middle of rendering the template. In a "normal" templating engine, data must be fetched before the template is rendered, and it must be passed (typically in the form of a JSON document) to the rendering step. This means that the template can't control the data fetched, since when the template is read the data has already been fetched.
By contrast, Docxtemplater (and also docx-templates
, by Guillermo Grau,
and maybe other libraries) can allow the template to control the fetched data. In Docxtemplater, this is done by
passing Promise-returning functions, or equivalently async functions, to the
renderAsync
function, where normally the
content of each tag is passed. Docxtemplater transparently awaits any Promise-containing tags such that they can be
referenced in the template as if they were normal, data-carrying tags.
You can use the same Tools in Data Resolvers as in Transforms, such as Code snippets, HTTP requests, and database requests.
Note that since Data Resolvers are the first step in a (potential) chain of Transforms, they don't have "input data" in
the same sense as a Transform that receives some data+optionally some params, and returns some data. Data Resolvers only
receive optional params, and return some data. This means that you can't access query
or query.input
(it'll be
empty).
Access the parameters passed to the resolver function, if any, as arg0
, arg1
and so on. In the Code tool, they must
be accessed as query.arg0
, query.arg1
and so on (remember to also Specify Input Schema in the Code tool, and specify
the Placeholders in the HTTP Request tool).
Template | Tool | Notes | Data Resolver |
---|---|---|---|
{ getUsers() } | HTTP Request | Takes no params | ![]() |
{ getUserById(1) } | HTTP Request | arg0 will be available on tool, as a Number | ![]() |
{ (getUserById(1) | JSONparse).first_name | toUpper } | HTTP Request | Gets the user as above, parses JSON response, accesses a property and then applies a custom Transform | (same as above) |
{ getPosts() } | Postgres | Takes no params | ![]() |
{ getPost(1).title } | Postgres | Takes arg0 , using the $fromAI() function | ![]() |
{ complicatedcalculation(1) } | Code | Takes arg0 , which appears as query.arg0 in Code tools | ![]() |
{ something | transformA }
and { something | transform("param") }
){ getData() }
and { getData("param") }
)FAQs
n8n node to create Word/Excel/Powerpoint documents from template documents, using docxtemplater
We found that n8n-nodes-docxtemplater demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Socket uncovers malicious Rust crates impersonating fast_log to steal Solana and Ethereum wallet keys from source code.
Research
A malicious package uses a QR code as steganography in an innovative technique.
Research
/Security News
Socket identified 80 fake candidates targeting engineering roles, including suspected North Korean operators, exposing the new reality of hiring as a security function.