Word documents, The Relay Way™
Bridging Word templates, GraphQL queries and JavaScript snippets
TL;DR Sometimes you have to set aside your developer work and do some office stuff. And sometimes that includes generating Word reports with dynamic contents. What if you could bridge Word, GraphQL and JavaScript to help you with these chores? docx-templates helps you do exactly that.
Every once in a while you need to produce a Microsoft Word document with dynamic contents. Maybe it’s a project report, or the boring economic section of a tender. Chances are you’re working within a team, and you absolutely need your document to be in the de facto standard for non-nerdy output: Word.
You don’t want to write hundreds of tables by hand, so you start thinking about docx automation. And since you’re a proud Node.js developer, you stumble upon these types of modules from the top of npm’s search results:
- Fully programmatic generators, like docx, which provide functions to create paragraphs, text runs, and so on.
- Template-based generators, like docx-templates, which let you start with an ordinary Word document, adding commands as needed to insert dynamic contents.
The benefits of the second approach are numerous:
- You don’t need the library to support every tiny little feature of Word. The input template will be used transparently, so the output will be compatible with whatever version of Office you’re using.
- You don’t need to write code to generate static parts of your document.
- You can even write documents à la Relay. What am I talking about? Well, just keep on reading!
Colocating queries
One of the key ideas in Relay is colocation. It’s literally front and center in its home page, and what it basically means is that data requirements (the query) are declared very close to the components that need the data.
If we translate this idea to report generation, wouldn’t it be nice if we just wrote the data query in the document itself? A very simple template would look like this:
We’re using the Star Wars API with the GraphQL wrapper for maximum convenience, but docx-templates
doesn’t really care about the language you choose for queries, as long as they eventually resolve to some data.
With the data requirements in place, we can write a short JavaScript snippet to execute the embedded query and create the report.
// swapi.js
const createReport = require('docx-templates');
require('isomorphic-fetch'); // assuming a modern Node, you need no Promise polyfill
createReport({
template: process.argv[2],
data: query =>
fetch('http://graphql-swapi.parseapp.com', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({ query }),
})
.then(res => res.json())
.then(res => res.data),
});
Run this script with node swapi swapi-simple-template.docx
and voilà, both trilogies come up in your report (alas, no Force Awakens data yet in the GraphQL wrapper 😱):
docx-templates
A more complex example
GraphQL is really great for describing complex data requirements. Imagine you want to summarize all Star Wars films with some basic data and a table of characters with their species, home planet, and ships (i.e. vehicles with hyperdrive) they appear in. Really nerdy stuff, huh? No problem with GraphQL:
+++QUERY { allFilms { films {
title, releaseDate, director, producers, openingCrawl
characterConnection { characters {
name
species { name }
homeworld { name }
starshipConnection { starships { name crew passengers } }
} }
} } }+++
Your Word template might look like this (right after the query):
This templates demonstrates other features of docx-templates
:
- You can embed JavaScript in your
INS
(shorthand notation:=
),FOR
and other commands. - You can define aliases (
ALIAS
) for complete commands, which you can then resolve with the*<alias-name>
shorthand. We found it quite useful when templating tables. - Loop variables (e.g.
$film
,$character
) can be used from embedded JavaScript snippets, just like any other property of the query result.
Want to see the generated document? Just run node swapi swapi-complex-template.docx
and there it is, in all its geeky splendor:
docx-templates
A final word
docx-templates
is a young project and still evolving with our needs. If you use it and have suggestions or —even better— want to contribute, please visit its GitHub repo!
Originally published at Math.random() on January 1, 2017.