January 25, 2011

Select templates using a master template

You have an application which requires a fairly large number of templates to be merged, but you do not want the user to have to choose the correct templates to run using the XpressDox Explorer, you rather want to use document assembly commands to select the templates to be run depending on data or user choices.

You could use the RunTemplates command, which is fine if you know beforehand which templates should be run.  The «RunTemplates()» command will also present an interview for each template in its list.  This might be what you want, but if you want to be able to select the templates to be run depending on data captured, then RunTemplates is not what is required.

The MergeTemplate command is almost the same as RunTemplates, but can be subject to an «If()» command, and so can be run depending on conditions that the template author dictates.  Also, MergeTemplate does not present a new interview for the template to be merged (as does RunTemplates), XpressDox uses the data set which was used for the preceding template for this.

A code sample of how this might work in practice would be the following snippet:

«ChooseUsingCheckBox(CoveringLetter,Y,N,N)»
«ChooseUsingCheckBox(Account,Y,N,N)»
«ChooseUsingCheckBox(Contract,Y,N,N)»



«ChooseFromRDBList(ContractType,,A~~Contract Type A - Service Agreement,B~~ContractType B - Renewal of Service Agreement)»
…  (somewhere in this template (or a template included by «IncludeTemplate()») would be commands to make sure that the interview captures all the information needed on the templates to be merged)

«If(CoveringLetter = 'Y')»«MergeTemplate('Covering Letter')»«End()»
«If(Account = 'Y')»«MergeTemplate('Account')»«End()»
«If(Contract = 'Y')»«MergeTemplate(concat('Contract',ContractType))»«End()»

If you call this template something like “MasterTemplate”, then all the user needs to do is run that one MasterTemplate, and all the decisions as to which further templates to be run are effectively made for them by the template logic.

Build all the subsidiary templates into one single document

Sometimes the requirement is that all the chosen documents are merged into one long document, rather than each being a separate document (the MergeTemplate command will create a separate Word document for each template merged).

This could be done by using the IncludeTemplate command in the place where MergeTemplate is used above.  The drawback of this is that IncludeTemplate will include the entire text of the template BEFORE the interview is presented, and if that text is excluded via an If command, that is done while the template is being merged.  This is satisfactory if there are not too many long templates thus included, but if the included templates are large and/or many then the resulting pre-interview text can be enormous and give rise to memory problems.

In a situation like this, the solution would be to use the InsertTemplate command.  The InsertTemplate command is very similar in effect to IncludeTemplate, except that the text of the template is inserted into the merged document during the phase when the template is being merged. (The different phases of XpressDox are described in The Processing Phases of XpressDox).

There are some issues surrounding the insertion of one Word document into another (regardless of which command is used), these are Source and destination formatting, and Word section processing, specifically with regard to headers and footers and paragraph and page numbering.

It is highly recommended that Destination formatting be used.  It means that care has to be taken to make sure that styles used in the inserted template are also defined (correctly) in the master template, and that Word skills are used to make sure that any paragraph numbering starts off at 1 again on the inserted document.  That is all the subject of another article, yet to be written.

In order that headers and footers in the inserted document are included correctly into the master document, the command needs to be issued with the PreserveHeaders parameter:

«InsertTemplate('letters:Covering Letter',Destination,PreserveHeaders)»

The next issue to be catered for is the question of encouraging Word to put its section breaks into the correct place.  You will probably want to experiment yourself, but an example that works would look something like this:


================= Section Break (Continuous) ========================
«If(CoveringLetter = 'Y')»
================== Section Break (Next Page) ========================
«InsertTemplate('Covering Letter',Destination,PreserveHeaders)»
«End()»
«If(Account = 'Y')»

================== Section Break (Next Page) ========================
«InsertTemplate('Account',Destination,PreserveHeaders)»
«End()»
«If(Contract = 'Y')»

================== Section Break (Next Page) ========================
«InsertTemplate(concat('Contract',ContractType),Destination,PreserveHeaders)»
«End()»

Actually, that example will not work correctly, as each template inserted will be preceded by a Section Break (Next Page) whereas only the first template needs that Section Break. This then needs some code to make sure that it happens only once, and the following example will do it:


«SetVr('SB','Y')»
================= Section Break (Continuous) ========================
«If(CoveringLetter = 'Y')»
================== Section Break (Next Page) ========================
«InsertTemplate('Covering Letter',Destination,PreserveHeaders)»
«SetVr('SB','N')»
«End()»
«If(Account = 'Y')»
«If(GetV('SB') = 'Y')»

================== Section Break (Next Page) ========================
«End()»
«InsertTemplate('Account',Destination,PreserveHeaders)»
«SetVr('SB','N')»
«End()»
«If(Contract = 'Y')»
«If(GetV('SB') = 'Y')»

================== Section Break (Next Page) ========================
«End()»
«InsertTemplate(concat('Contract',ContractType),Destination,PreserveHeaders)»
«End()»

How this works is that the XpressDox variable SB determines whether a Section Break (Next Page) should be inserted or not. It starts off its life with the value ‘Y’ so that the first template which is inserted will be preceded by a section break. But then after each template is inserted, the variable is set to ‘N’ so that for each subsequently inserted template, the section break will not be inserted.