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.
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
.
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 aSet<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:
YEAR | Frequency | Currency | Amount |
---|---|---|---|
<<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>>