XpressDox Help Center

Use Google To Find Help Fast, e.g. xpressdox choosefromlist


Press Getting Started in the XpressDox toolbar for basic template development
Watch the tutorial videos
View command help from list of commands
Press F1 for help on a command in the Command Editor
Email support@xpressdox.com for assistance

Catalog

The Execute Function

Execute is used when a sequence of functions need to be executed one after the other. It is typically of assistance in the HotDocs® converter.

Here is an (admittedly artificial, but useful for illustration) example:

«OnExitSet(Name,Number,Value,(),Execute(SetV('X',12),IncrementV('X'),GetV('X')),,EvenWhenNotEmpty)»

After the focus leaves the Name field, the Number data element will have its value set to 13.


The Paragraph Command

«Paragraph()» will split a paragraph into two. Providing the name of a Word style, such as «Paragraph(ThisStyle)» will result in the second paragraph resulting from the split having style ThisStyle applied to it.


The Mod Function

Mod is used to get the remainder when dividing one number by another. It is typically used to divide sets of items into odd and even, or in a Rule.

For example:

«ForEach(Parent)»
«Name»
«End()»
«Rule(Parent,hard,(count(Parent) mod 2) = 0,'Please enter an even number of parents.')»


The HideFromPreview Command

By default, when the user selects to preview the results of an assembly (during the Interview process), the system will display the document generated by the template itself, and any document generated by the MergeTemplate function.

Sometimes, the template author may want to restrict the preview functionality to specific templates. In this case, including the command «HideFromPreview(Yes)» in a template will prevent any document generated by that template from being previewed by the user.




The CompareStrings Function

Comparing two strings for equality and inequality is straightforward.  However, because XpressDox relies heavily on XPATH (XPATH Tutorial), it also is constrained by some XPATH limitations. For example,

«If(('A' < 'B'))»less«Else()»not less«End()»
«If(('B' < 'A'))»less«Else()»not less«End()»

will result in

not less
not less

being put into the document.

This is because XPATH will only evaluate the comparisons = and != when applied to strings.

In order to test how we normally imagine a string comparison other than equality works, we need the XpressDox CompareStrings function. The usage of this function is illustrated as follows:

«If(CompareStrings('A','B') < 0)»less«Else()»not less«End()»
«If(CompareStrings('A','B') > 0)»greater«Else()»not greater«End()»
«If(CompareStrings('BBC','BBB') > 0)»greater«Else()»not greater«End()»
«If(CompareStrings('B','B') = 0)»Equal«End()»

this would output the following:

less
not greater
greater
Equal

into the document.


Document per Repeated Item

Problem Statement

Suppose you have an application which requires that one or more parties sign a suretyship document, with the requirement that each party signs their own document, not that they all sign the same document.

The first thing to do is set up the suretyship template, with the relevant fixed text, etc., just like any other template.  Suppose the template reads something like this:

I, «SuretyFirstNames» «SuretySurname» (Born on «FormatDate(SuretyDOB, “MMMM dd yyyy”)») hereby declare blah blah.
blah
Signed: «SuretyFirstNames» «SuretySurname»

Of course, this will only produce the information for one surety, and doesn’t indicate in any way that there can be more than one surety.

The normal way of indicating repeating data to XpressDox is the «ForEach» command, so it is tempting to try the following:

«ForEach(Surety)»I, «SuretyFirstNames» «SuretySurname» (Born on «FormatDate(SuretyDOB, "dd MMMM yyyy")») hereby declare blah blah.
blah
Signed: «SuretyFirstNames» «SuretySurname»
«End()»

But, of course, this will repeat the sureties’ information for all of the sureties one after the other on the same document.

One Document for each Repeater

In the above code snippet, the ForEach() defines the context of all the data elements before the End() – i.e. that they all belong to one repeater called Surety. The idea of the context is important, and can be applied to a whole template in the following way.

Firstly, the document which should be produced for each Surety must be authored in a template much like the first example, i.e. something like:

I, «SuretyFirstNames» «SuretySurname» (Born on «FormatDate(SuretyDOB, "MMMM dd yyyy")») hereby declare

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis urna.
Nunc viverra imperdiet enim. Fusce est. Vivamus a tellus.
Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Proin pharetra nonummy pede. Mauris et orci.

Signed: «SuretyFirstNames» «SuretySurname»

Let’s assume that a document like this is saved as an XpressDox template, and called DeclarationBySurety.xdtpx. Then, in your main document, you put the following:

«ForEach(Surety
«MergeTemplate('DeclarationBySurety.xdtpx','Surety',position())»
«End()»

In the above MergeTemplate, the ‘Surety‘ and position() provide the context for the entire DeclarationBySurety.xdtpx template. By definition of the MergeTemplate function, each of the MergeTemplates in the ForEach will cause a separate document to be created.

One Section for each Repeater in the Same Document

Also, you could use the same DeclarationBySurety template to create one long document with declarations for all of the sureties in the same document, by replacing MergeTemplate with IncludeTemplate in the above, getting this:

«ForEach(Surety
«IncludeTemplate(DeclarationBySurety)»
«Comment(Include XpressDox and Word commands here to insert page or section breaks after each Declaration. See Working with Section Breaks for information on this.)»
«End()»

Filtering

Suppose you want to produce a separate document for each of the Sureties, but only for the sureties born before a particular date (July 1 2001). Have a look at this:

«ForEach(Surety
«If(DateAsNumber(SuretyDOB) < 20010701)»
«MergeTemplate('DeclarationBySurety.xdtpx','Surety',position())»
«End()»
«End()»

Note that you might be tempted to write (using XpressDox’s powerful XPATH capabilities):
«ForEach(Surety[DateAsNumber(SuretyDOB) < 20010701]
«MergeTemplate('DeclarationBySurety.xdtpx','Surety',position())»
«End()»
The problem with this is that the position() function gives the position of the Surety relative to those conforming to the condition in the predicate (i.e. the bits between the [ and ]), whereas the MergeTemplate needs to the context to reflect the position() in the complete list of Surety repeaters.

The Interview

The way that MergeTemplate functions, is that no interview is prepared for the data elements used in the template being merged – in this case the DeclarationBySurety.xdtpx. This means that all the data elements must be assigned a value in the template which calls the MergeTemplate function. The values can be assigned by retrieving them from a data source (The ChooseFromDataSource Command, or The LinkToDataSource Command, or The IncludeDataSourceData Command), or letting the user capture them in the interview.


Use a SQL SELECT as a data source

It may be that you are developing a set of templates using data from a database, but you are not the database administrator, and so can’t create your own views or stored procedures in the database.  Using the feature described here, you could at least address the database with a fairly complex SQL query.

This example assumes that you are familiar with configuring and using data sources. If this is not the case, please have a look at Configure a Data Source for a Database. Also, the example uses the Microsoft Adventureworks sample database, which you can download from Download the AdventureWorks Database.

The configuration follows the normal path until the step where you would provide the name of a database table for the data source.  You will notice that there is a fairly large area into which you could enter a SELECT instead of choosing a table (or view or stored procedure). The example is a SELECT statement lifted from one of the AdventureWorks stored procedures, which you can copy and paste from here, if you would like to try it yourself:

SELECT DealerPrice = plph.[ListPrice] * @DealerDiscount
FROM [Production].[Product] p
INNER JOIN [Production].[ProductListPriceHistory] plph
ON p.[ProductID] = plph.[ProductID]
AND p.[ProductID] = @ProductID
AND @OrderDate BETWEEN plph.[StartDate] AND COALESCE(plph.[EndDate], CONVERT(datetime, ‘99991231’, 112))

Notice that there are three SQL Server scalar variables defined in the SELECT statement, viz. @DealerDiscount, @ProductID, and @OrderDate. The datasource configuration wizard regards these as making up the ID of the data source, and your template will need to provide actual values for these at the time that the template is being run. Here is an example of a template which uses the LinkToDataSource command to access the DealerPrice using that datasource duing the interview phase of the assembly:

«DealerDiscount»
«ProductID»
«FormatDate(OrderDate,'yyyy-MM-dd')»
«Button(Button)»
«LinkToDataSource(Button,DealerPrice,NoRefresh,id=<DealerDiscount>|<ProductID>|<OrderDate>)»
«DealerPrice»

If you run that template, and enter 0.6 for DealerDiscount, 707 for the ProductID and 2001-07-02 as the OrderDate, then, when you press the button, it should display the value 20.18652 as the DealerPrice.

Now, replace the LinkToDataSource and DealerPrice fillpoints with these:

«LinkToDataSource(Button,DealerPrice,NoRefresh,range=@DealerDiscount=<DealerDiscount> and @ProductID=<ProductID> and @OrderDate=<OrderDate>)»
«Production.Product/DealerPrice»

Run the template again. Notice that when the ID variable values are supplied as “id=” in the LinkToDataSource, then a data element is returned into the root of the data set, but when they are supplied as a “range=”, then the same element is returned, but as part of a repeater. If you were the author of the SELECT statement, you would know whether the result of the SELECT was a single row or not, and so you would know which of the id= or range= is applicable.


Dynamic Captions – changing captions on the fly

With the advent of The OnExitSet and OnEnterSet Commands, it became possible to have the captions (or footing text or heading text) of a data element in the interview change in response to the user entering data.

Getting the features around this to work was not all that easy for the template author, and so now we have introduce the concept of the Dynamic Caption. This feature also applies to heading and footing text.

Getting Started

Suppose you want the First Name, Last Name and Date of Birth of someone to be entered in the interview. In the case where there are a number of names of various parties to be entered, it might become confusing, when it comes to the Date Of Birth, as to whose Date of Birth should be entered. Here’s an example of how easy the Dynamic Caption feature makes this:

«Caption(DateOfBirth,Enter the Date of Birth of <FirstName||[First Name of Person]> <LastName||[Last Name of Person]>)»

When the interview is first displayed, the caption for the Date of Birth will read:

Enter the Date of Birth of [First Name of Person] [Last Name of Person]

If the value “John” is entered for FirstName and “Smith” for LastName, then as soon as those values have been typed in, then caption for Date Of Birth will read:

Enter the Date of Birth of John Smith

Some Advanced Techniques

If you are going to need the FirstName and LastName in a number of different captions (or headings or footings) in the interview, then you could define the dynamic caption in a Script, and use that Script name where ever you want the dynamic caption. For example:

«Script(FullName)»«concat(FirstName, ' ', LastName)»«ScriptEnd()»

«Caption(DateOfBirth,Enter the Date of Birth of <FullName()||[Primary Contact]>)»

«Footing(RegistrationCertificate,|Make sure the the Registration Certificate for <FullName()||[Defendant Name]> is available.)»