logoBack to home screen

Word Templates

This documentation shows how to use the WordTemplateToWord service request to apply data to a Word template.

The idea is that a Word file has placeholders and processing instructions that are filled out / processed according to the additional data provided in the service request.

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

  • Search/replacing text in the Word file. Any String replacement can be performed on the document.

  • Search replacing 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 three ways is represented by separate properties in this service request. The following sections will explain how to apply them.

Search/replace

A WordTemplateToWord service request may take one or more WordTemplateReplacements objects which define what to search/replace in the Word document (in the stringReplacements property). It is also possible to influence whether the search should be case sensitive and / or whether full words should be matched only.

It is also possible to specify such search/replacement pairs depending on the tags present with the Resource. So, only a specific set of word pairs can be applied on a specific Recource.

Regular expressions

Similar to the stringReplacements explained above, the regexReplacements property contains a map of regular expressions and the value that should be used instead of matching text parts. Here, again, this map can also be specifed per 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.

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's 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.

The context is built based on the mapRecord (or type com.braintribe.model.record.MapRecord) property of the WordTemplateToWord service request (note: there is a separate definition of map records per id). A mapRecord is basically a key/value map, where the values can be anything (e.g., another mapRecord or a com.braintribe.model.record.ListRecord), as long as it can 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.

Example:

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

As the mapRecord can be containing other, nested MapRecords, the eval method can be used to navigate through the MapRecords.

Example:

<<[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.

Example:

<<[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 that 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).

Example:

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

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

Example:

<<[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.