Using DocAssemble to create Word Documents and send them ready made to a front end application

Paul Hands
5 min readAug 7, 2020

--

DocAssemble is an open source system used for guided interviews, and document assembly based on those interviews, primarily built upon Python, YAML and Markdown. However with a bit of ingenuity it provides a powerful engine to allow you to do “Mail merge” in Microsoft Word Documents in a cloud based fashion.

In case I’m betraying my age a little bit, mail merge was the concept of having a word document saved locally as a template, and allowing someone to determine parameters and feed them into the template. Word would do some technical behind the scenes work and voila! you now have a Word Doc with your parameters in place of the template. All locally stored however. Enter DocAssemble, and now the possibilities are there to host the template online, send your variables to it via a HTTP post request and receive back a Word Document, all merged with the variables, packaged in a way it can be sent on to a different location for downloading / saving / printing etc.

This isn’t particularly complicated, but there are a few steps to it (as I have discovered this week!), so I figured I would put down the step by step guide of how I solved this problem for my own setup, in the hope it might help someone else in the future.

Setting up your DocAssemble

(I recommend you follow the handy guide already present — Installing on Docker to get an instance of DocAssemble running locally and set up so you can access the playground)

The first thing we need is to upload a .docx template and create our YAML file:

In the playground you should automatically be on the page that allows you to add new files. In this example I’ve constructed a YAML file called hello_there.yaml, which references a .docx file template I have created called Hello_There_Template.docx. You can see the way the yaml file has been constructed in the image below (note the content_type, which is important for making sure the document is correctly encoded and decoded later).

Construction of the YAML file in the playground

For completeness, the word doc is very basic indeed:

Our (very basic) word document we are using docAssemble with

We now need to create a template, this is done by navigating to folders and selecting the templates option from the dropdown. Here you can upload your Hello_There_Template to the playground.

Use the upload option to add your word document to docAssemble

Once that has been uploaded the last thing we need to do is construct and install a package (which can be selected from the same menu as the templates). Give it a name, select the yaml file from interview files and the word template from template files, and then save and importantly ‘install’ the package (if you don’t, then you won’t let docAssemble have access to the template and yaml file and you’ll end up getting errors). We are going to call our package ‘HelloThere’

Make sure once you save your package you then ‘Install’

Your docAssemble is now configured, and we can sort out getting the updated document and passing it through to the client!

(I recommend using Postman or similar to test that you definitely can follow the steps below before checking your integration code)

Linking your service to docAssemble

Now we have our docAssemble package set up in the playground, we need to configure our service to interact with it. I’m using a nodeJS backend, and using the package ‘node-fetch’ to interact with the docAssemble API. In the screenshots I’m using my locally booted up version of docAssemble on port 8080.

The first thing we need to do is construct a GET request to retrieve the secret and session from the API so we can hit the endpoints with our variables. This combines the information we already have from our set up yaml and package, and needs our API key (the default fetch is a get request).

Retrieving our docAssemble secret and session

Next we need to retrieve our docAssemble-d document using the secret and the session we get from the createDocAssembleSession. Once we retrieve the information in the body we buffer it (On the assumption the word document isn’t gigabytes big!) and encode it using base64 encoding.

How to retrieve the encoded data from docAssemble

(In this example I’ve hard coded our variables inside the function code, it could easily be passed in as a function parameter).

Now we can hit our services (I use REST requests from the client in my real life case) and we will be returned our encoded string as the response body.

Linking your client to your service

On the client we need to decode the string and put it into a Uint8Array, wrap it in a blob and then use our file save package to save the file to our client computer. We are using an npm package called ‘downloadjs’ to do this. In the example the endpoint is being mocked with a call to services.getDocAssembleDocument.

Client side decoding, blob-ifying and saving of the document

A couple of important points:

  • atob is doing the grunt work of the decoding of the base 64 string
  • The blob type needs to application/octet-stream for a .docx document
  • Note the the third argument of download is the same as the content_type we defined in the yaml file

When this is all done, the client computer should save a file to the local storage labelled ‘hello_there.docx’ with the variables defined by the endpoint request.

The finished (filled in) template

Voila! We have managed to hit the docAssemble API from a client without actually exposing any API keys, or allowing the end user access to any of the templates, yaml files, secrets or sessions. This means we can use various logic (IP whitelisting, custom permission logic on the services etc.) to limit who can hit the docAssemble API and also who can retrieve the documents specified by the interview in question.

This doesn’t consider the more complicated cases of including custom images or tables or other logic, because docAssemble has a lot of documentation for that. However I was disappointed on reading (for a long time) and not finding a comprehensive step by step on how to go

client -> service -> docAssemble -> service -> client.

Hence I’ve written one!

--

--

Paul Hands
Paul Hands

Written by Paul Hands

Software developer. Agile enthusiast. Toddler parent. Dad joke lover

Responses (1)