Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore.

15 St Margarets, NY 10033
(+381) 11 123 4567



Document Generation With Dynamic Image Generation

One of the most fascinating aspects of Adobe Document Generation is how incredibly flexible it is. One aspect of the API that can really enhance the final result is the ability to include images in your template. In a typical use case, you would provide a static image defined in your data used with the API. In this blog post I’m going to demonstrate a more advanced example — dynamically generating images, in our case, charts, on the fly.

The Basics

Before we get into a more advanced demo, let’s quickly cover the basics. (My coworker has a very deep look into Document Generation and images you should check out as well.) As our docs describe, using a dynamic image in your Word template requires a few steps.

First, you add an image to your document. It doesn’t matter what image you pick, it’s just a placeholder, but you’ll want to place it in your document as you like and ensure you’ve sized it as expected. Once done, you right-click on the image and select the “Edit Alt Text” option. In that alt text, you supply JSON:

The location-path property must point to the key value used in your data that includes the image data. So for example, given the above location-path value, the data I use with the API could look like so:

As the example demonstrates, the image data must be a Base64 encoded version of the image. If you’ve never seen that before, it looks somewhat like this:


You can also use the Word Add On to insert images for you. If the sample data you added includes a Base64 value, then you can select it in the Images portion of the Advanced tab.

So at this point, you already have the ability to dynamically change the image in the final result PDF or Word document. To do so, you swap out the value. Imagine you’ve got two options for an image in your document, a picture of a cat or a picture of a dog. In the Word template, you embed a placeholder image and link it to a value, pet. Before sending your template and data to the Document Generation API, you would use the right value:

As you can see, depending on some particular boolean value, the data will either have the encoded version of the cat or dog picture. (Obviously one is better than the other and I’m talking about the cat of course.)

While this qualifies as dynamic, we can take it a step further.

Using Dynamic Images

For our scenario, we’re going to create a document describing the number of cats in a shelter over the previous six months. This data is returned from an internal reporting system and can be represented like so:

The data consists of an array of values ordered oldest to newest. Each item in the array has a date stamp and a numeric amount. Let’s start with a template that has a table of data.

Template with table of data

By itself, it’s nice and simple and outputs cleanly. Here’s what the PDF looks like when generated:

Generated PDF

It “works”, but a chart could make it a bit easier to read. You could more clearly see trends over time and make better judgements based on the data provided. But how do we get a dynamic chart into the Word template?

First, we need to find a service that can create the chart while also, and this is the crucial part, giving us access to the raw image data of the chart. You see, there’s a thousand or so charting services out there, specifically for web developers. However many of these charting libraries will render their library in a browser environment and when the JavaScript of a particular web page is viewed. What we need is a service that creates an actual image that could be requested via our server side code and translated into Base64.

For our demo we are going to make use of QuickChart. QuickChart is a “service wrapper” around the open source Chart.js package. It basically takes the functionality of Chart.js and lets you get static images of charts by crafting a URL. For example, consider this URL:

https://quickchart.io/chart?c={type:'bar',data:{labels:['Q1','Q2','Q3','Q4'], datasets:[{label:'Users',data:[50,60,70,180]},{label:'Revenue',data:[100,200,300,400]}]}}

You can see a URL parameter defining various aspects of chart, including the type (bar), the labels, and the actual data. You can see the result of that here:

Users and Revenue table

While the URL is a bit complex (and it can even more complex), it provides a solution to our issue. Given that we have our data from our internal API, all we have to do is “rewrite” it in a URL that works for QuickChart.

I built that first. It takes in my ordered data and uses that to create a URL on QuickChart that makes use of the line graph format and specifies a specific height and width. Here’s that function:

If I wanted to add more chart features, like custom colors perhaps, I would modify it here. With that done, I added a placeholder image to my Word doc and specified the size. Ben covers this as tip #6 in his great article, Adobe Document Generation API: Working with Images.

One thing I would add to this recommendation is to switch Word to use pixel height and width for images instead of inches. In your Word settings, under Advanced, go to Display and enable “Show pixels for HTML features”:

Enable “Show pixels for HTML features”

With this enabled, we can set a specific height and width (500 by 300) for the image and center it right beneath the table.

Set a specific height and width

The alt text for the image looks like so:

As a reminder, this means when we pass our data to the Document Generation API, it will expect the image key to contain Base64 data of our image. How do we do that? With another function!

The urlToBase64 function does exactly what it sounds like – hits a remote URL, gets the data, and then converts it. Now we have all the parts we need, let’s look at a complete example:

let data = arr.map(d => d.amount);

let url = `https://quickchart.io/chart?c={type:’line’,data:{labels:${JSON.stringify(labels)},datasets:[{label:’Cats’,data:${JSON.stringify(data)}}]}}&width=500&height=300`;
return url;

async function urlToBase64(url) {
let resp = await fetch(url);
let header = resp.headers.get(‘content-type’);
let body = await resp.arrayBuffer();

data=”data:” + resp.headers.get(‘content-type’) + ‘;base64,’ + Buffer.from(body).toString(‘base64’);
return data;

async function generateFromTemplate(template, data, dest, creds) {
return new Promise((resolve, reject) => {

// Initial setup, create credentials instance.
const credentials = PDFToolsSdk.Credentials

// Create an ExecutionContext using credentials.
const executionContext = PDFToolsSdk.ExecutionContext.create(credentials);

const documentMerge = PDFToolsSdk.DocumentMerge,
documentMergeOptions = documentMerge.options;

//dest determines if Word or PDF
let format;
let destExt = dest.split(‘.’).pop().toLowerCase();
if(destExt === ‘docx’) format = documentMergeOptions.OutputFormat.DOCX;
else if(destExt === ‘pdf’) format = documentMergeOptions.OutputFormat.PDF;
else throw(‘Invalid destination extension’)

// Create a new DocumentMerge options instance.
options = new documentMergeOptions.DocumentMergeOptions(data, format);

// Create a new operation instance using the options instance.
const documentMergeOperation = documentMerge.Operation.createNew(options);

// Set operation input document template from a source file.
const input = PDFToolsSdk.FileRef.createFromLocalFile(template);

// Execute the operation and Save the result to the specified location.
.then(result => result.saveAsFile(dest))
.then(() => resolve(true))
.catch(err => {
if(err instanceof PDFToolsSdk.Error.ServiceApiError
|| err instanceof PDFToolsSdk.Error.ServiceUsageError) {
console.log(‘Exception encountered while executing operation’, err);
} else {
console.log(‘Exception encountered while executing operation’, err);


}” data-lang=”text/javascript”>

Taking it from the top, I begin by specifying variables for my input, data, and output. My cat data in this case is a hard coded JSON file as shown above. I then call generateQuickChatURL with my data and assign the result to the image value. Finally, this gets passed to a utility function (generateFromTemplate) that uses our SDK to create the PDF. Here’s how the final PDF looks:

Final PDF

You can find this script, along with the Word template and PDF output, on my GitHub repo here: https://github.com/cfjedimaster/document-services-demos/tree/main/chart_demo

If you think this was cool, sign up for a free trial. If you have any questions, ask on our forum or on StackOverflow.

Credit: Source link

Previous Next
Test Caption
Test Description goes like this