Skip to main content
Version: 2.10

Using Word templates

The WordTemplateToWord service enables applying data to a Word template.

Word files have placeholders and processing instructions that are filled out and processed according to the additional data provided in service requests.

There are three ways of applying data to a Word template:

  • Searching and replacing text in a Word file. Any String replacement can be performed on a document.
  • Searching and replacing text by using regular expressions. This allows for more flexible text replacements.
  • Using the LINQ message syntax (see Aspose LINQ) to have complex Word templates.

Each of these ways is represented by separate properties in this service request. The following sections will explain how to apply them.

Search and replace

A WordTemplateToWord service request may take one or more WordTemplateReplacements objects which define what to search and replace in a Word document (in the stringReplacements property).

It is also possible:

  • To define whether the search should be case sensitive
  • To define whether full words should be matched only.
  • To specify search and replacement pairs depending on the tags present on the resource. So, only a specific set of word pairs can be applied on a specific Resource.

Regular expressions

Similar to the stringReplacements, the regexReplacements property contains a map of regular expressions and values that should be used instead of matching text parts. This map can also be specified per the Resource tag. The syntax of the regular expression is based on the Java regex syntax.

LINQ reporting engine

The most versatile (and complex) way of building a Word template is to use the language features of the LINQ Reporting Engine. This template engine is part of the Aspose library and supports a C#-like (or, Java-like) syntax for if/else blocks, variables, loops, etc.

Word template example

Here's a quick example of what the Word template could look like:

<<if [!context.evalBoolean("Children")]>>
Only the above person(s) is insured under this Plan and all of its additional benefits.
<<else>>
No only the above person(s) is insured under this Plan.
<</if>>

Let us take a look at the context first. It is a combination of the input data provided in the service request and additional methods for working with this data.

info

The context is built based on the mapRecord (or type com.braintribe.model.record.MapRecord) property of the WordTemplateToWord service request. Note that there is a separate definition of the map records per ID.

mapRecord is a key/value map where values can be anything (for example, another mapRecord or a com.braintribe.model.record.ListRecord), as long as it can be serialized into a JSON structure as this is the way how it is stored with the result conversion job.

You can access any value of the mapRecord provided in the service request by calling the GET method on the context.

<<[content.get("somekey")]>>

As the mapRecord can contain other nested mapRecord instances, the eval method can be used to navigate through the mapRecord instances.

<<[content.eval("somekey")]>>

This would do the same as the GET method exemplified above. However, the eval method can take a full path to nested maps.

<<[content.eval("level1key -> level2key -> somekey")]>>

So, if the value of level1key is a mapRecord, it is expected to have an entry with the key level2key. This, in turn, is expected to have a value for the key somekey.

Note

This method throws an exception when the record cannot be found. Hence, there is a variant of this eval method where you can specify whether the value is required or not (in the latter case, only NULL will be returned).

<<[content.eval("level1key -> level2key -> somekey", false)]>>

Alternatively, the exists method can be used to check the availability of a path in the mapRecords.

<<[content.exists("level1key -> level2key -> somekey")]>>

This will return either true of false, depending on the existence of the provided path.

It is also possible to cast the returned value to a specific type (which is necessary for LINQ), as it is not very helpful with types in general.

So, the following variants of the eval method exist:

  • evalList
  • evalMap
  • evalEntrySet (this will return a Set<Map.Entry> object)
  • evalSet
  • evalString
  • evalLong
  • evalBoolean (especially needed for <<if>> blocks)

As stated above, LINQ is not very helpful with types. It is sometimes necessary to cast an object before it can be used. Imagine the mapRecord contains an entry where the key is COLLECTION and the value is a ListRecord, containing multiple MapRecords with the keys YEAR, FREQUENCY, CURRENCY, and PREMIUM_AMOUNT.

The example would look like:

YEARFrequencyCurrencyAmount
<<foreach [entry in context.evalList("COLLECTION")]>><<var [MapRecord map = entry]>> <<[map.get("YEAR")]>> <<[map.get("FREQUENCY")]>><<[map.get("CURRENCY")]>><<[map.get("PREMIUM_AMOUNT")]>><</foreach>

This would create a Word table, one row for each entry in the COLLECTION list. The variable entry specified in the forEach is of type Object for the template engine. Hence, it has to be cast to a MapRecord object first by creating a new variable. A direct entry.get("FREQUENCY") would result in an error.

Everything between these angle brackets <<....>> is interpreted as a LINQ command.

For convenience, all top level elements in the mapRecord are also used as an input for search/replace functionality.

So, the following two lines would have (almost) the same effect:

Currency: <<CURRENCY>>
Currency: <<[context.eval("CURRENCY")]>>

However, if CURRENCY is not defined, the first line would remain unchanged (which would break the LINQ interpreter as it would not be able to parse <<CURRENCY>> as a valid processing instruction). The second line would produce an exception as the eval method (without an additional boolean parameter) assumes that the value has to exist.

Replacing variables in imported documents

When your Word template imports another document, as in the case below:

<<doc [context.openRemoteResourceByRefEval("HEADER")] >>

Where HEADER has another variable:

Great Insurance Inc. <<year>>

The <<year>> does not get replaced by default. If you want it to be replaced, add the -build suffix to the original variable, as in:

<<doc [context.openRemoteResourceByRefEval("HEADER")] -build>>