Recently, we looked at how to use the ADD and CLEAR instructions in HotDocs to dynamically create an option for widows and widowers, so that regardless of gender of our client, the user was always presented with a gender appropriate reference, that still had an identical option under the hood.  This time, we’re going to look at the real power of these instructions: with dynamic repeating content.  For this article, we’re going to look at a situation where we have to address a single letter to multiple vendors and have those vendors specified by the user during the interview.  Here’s the pieces:

VENDOR RPT – repeating dialog that collects vendor data
VENDS Name Full TE – the full name of the vendor on VENDOR RPT
VENDS Addr Block CO – a computation that calculates for address block for each vendor (code not listed, it could just as easily be a text/memo field that is filled in)
LETT Vendors MS – a multi select, multiple choice variable that will ask the user which vendors they wish to send a letter to (dynamically created)
flt LETT Vendors CO – a filter that will look at the user selections in LETT Vendors MS, and filter out the ones that weren’t selected.
COUNTER – the HotDocs system variable that will return the number (as a number) of the current repeating dialog. This can ONLY be used inside a repeat instruction.

Here are the steps:

1) Clear LETT Vendors MS and ADD all vendors to it
2) Present LETT Vendors MS to the user for selection
3) REPEAT VENDORS RPT in the template with the appopriate filter, so only those vendors selected in LETT Vendors MS appear in the resulting document.

Firstly, somewhere in your interview process (you DO use interview computations to calculate, control and regulate data collection for your templates, right?), you will have ASKed the user to fill in the vendor details.  Presuming that we have already collected our vendor details, we now need to build the multiple choice variable.  So somewhere in your interview computation, but AFTER you have ASKed VENDOR RPT, we do this:

CLEAR LETT Vendors MS //clear first, then ADD
ADD "«COUNTER»|«VENDS Name Full TE»" TO LETT Vendors MS //the option is the counter, the prompt is their name
//you could wrap the add instruction inside an IF statement, if you are uncertain as to whether VENDS Name Full TE is ANSWERED() or some other logic particular to your system

We now have LETT Vendors MS containing a full list of all vendors.  So at somepoint after the above script runs, you would ASK LETT Vendors MS, most likely as part of a dialog that relates to the letter we are drafting.  Now for what our FILTER looks like.

"«LETT Vendors MS::a|b|c»" CONTAINS "«COUNTER»"

This is a little tricky.  Multiple choice variables store their results as text, but multi-select multiple choices store their values as an ARRAY of text – much like a repeat.  Because of this, a multi-select variable cannot be directly compared to a straight line of “regular” text.  Additionally, no multi choice variable can be compared directly to a number.  So there are three solutions in that one line of code.  The value of LETT Vendors MS is converted to a REGULAR line of text, using the chevrons embedded inside double quotes.  That’s the first solution.  The second solution is to use a custom list format, “a|b|c”, which means that each selection is split by a pipe | character.  I’ll explain this in a later!  The third solution was to wrap COUNTER in chevrons and quotes, which takes COUNTER – a numeric value, and converts it to a string.  With all of this going on, we can now use CONTAINS to correctly compare the selections of LETT Vendors MS and the value of COUNTER.

Now, for the template….

«VENDS Name Full TE»
«VENDS Addr Block CO»

Dear «Some Variable Here»

Some letter content here....

{-- conditional page break --}

This instruction will repeat the template infinitely whilever there are iterations inside VENDOR RPT, but will ONLY include iterations where the filter is true.  For the sake of this article, lets say there are three vendors: 1) John Doe 2) Jane Doe and 3) Billy Blogs.  When presented with LETT Vendors MS, it looks like this (brackets contains options):

(1) John Doe
(2) Jane Doe
(3) Billy Blogs

Lets say the user selects 1 and 3.  Here’s what our FILTER looked like:

“«LETT Vendors MS::a|b|c»” CONTAINS “«COUNTER»”

Here’s what happens when our template repeats:

Repeat #1: “1|3” CONTAINS “1” (evaluates to TRUE, John is included)
Repeat #2: “1|3” CONTAINS “2” (evaluates to FALSE, Jane is excluded)
Repeat #3: “1|3” CONTAINS “3” (evaluates to TRUE, Billy is included)

Congratulations.  Your multi select multiple choice variable has allowed you to quickly present a list of ALL vendors to the user and ask them which one gets a letter.  No databases (although you could use one), nothing too heavy; simply collect the vendors, build the multiple choice variable in HotDocs, ask which vendors get the letter, then repeat and filter for the selected values.

Now, I promised a bit more explanation on the whole “a|b|c” thing.  To do that, lets look at a concept called DELIMITING.  Delimiting is simply putting a specific character between each value you want to look at.  Common delimters are commas and pipes.  I prefer pipes, as they aren’t ever used in names, addresses and other pieces of data – they truly do identify the end of one bit of data and the start of the next one.  But lets say we DIDNT delimit our selections from LETT Vendors MS.  Lets say we have 14 vendors (wow!), and the user selected 1, 4, 5, 6, 12.  The value might look like this:


That’s right – its just a string of numbers.  This would mean our filter would “break” when repeating vendor #14.  Because the text “14” appears inside “145612”, even though the user did not selection option #14.  However, with delimiters, our value looks like this:


And 14 does NOT appear in that value, so the comparison is run correctly.

Clear as mud? Its a bit to get your head around, but when comparing multiple selections in multiple choice options, it is definitely best practice to delimit your strings and use CONTAINS instructions.


Two of the more useful instruction models in HotDocs for dynamic interviews and variables are ADD and CLEAR, which go hand in hand to dynamically construct multiple choice variables.  This is the first of two HotDocs tips, which will deal with the basic CLEAR/ADD instructions with “static” content.  The next article will be about dynamically building a multiple choice variable in HotDocs with a REPEAT instruction.

Lets say we wish to ask for a client’s gender (CLI Gender MC) and their marital status (CLI Marriage MC).  Because we have different language in our template that concerns married clients versus divorced or widowed clients, we need this variable.  However, if a client is a widow/widower, there are two options based on their gender.  Because our language content is the SAME for a widow or widower (with gender specific references), we only want ONE option to denote the widow(er) marriage status.  Here’s how we do it.  We create a computation (say, called build CLI Marriage CO)

CLEAR CLI Marriage MC //always CLEAR before ADD, as ADD simply appends options to the multiple choice variable
ADD "Single" TO CLI Marriage MC
ADD "Married" TO CLI Marriage MC
IF CLI Gender MC"Male"
ADD "Widow|Widower" TO CLI Marriage MC
ELSE IF CLI Gender MC"Female"
ADD "Widow" TO CLI Marriage MC
ADD "Widow|Widow/Widower" TO CLI Marriage MC

If the client is male, we add “Widow” as the option, but “Widower” as the prompt.  That’s what the pipe | character is for.  Anything BEFORE the pipe is the option. Everything AFTER the pipe is the prompt for that option, which is what the user sees.  Note that because we chose “Widow” as the generic option for someone who’s partner has deceased, we don’t actually need a prompt for the female specific entry – the option IS the prompt.  If there is no client gender specified, we run with a generic prompt, but the option NEVER actually changes for the widow(er) option.  That means we lessen our code on the template end of things, because our option value is generic.

So now, we have a dynamic looking MC variable that will produce its own options based upon the gender of the client.  No doubt, in the dialog that these variables appear on, you would have something like the following script:

IF !ANSWERED ( CLI Marriage MC )
build CLI Marriage MC

The dialog script basically says that if CLI Marriage MC is NOT answered, then run the computation that builds the options.  This would likely be a part of a SHOW instruction, so that the variable doesn’t show up until it has options.  Depending on your version of HotDocs, there may be alternate ways to structure this to ensure smooth running of the dialog.

And that’s all there is to it.  This is a very simple way to use logic and the CLEAR/ADD instructions in HotDocs.  It is far more powerful to use ADD in conjunction with a repeat, which we’ll be looking at in my next article.


This tip covered the expression models: ANSWERED(VAR) and ANSWERED(DIALOG).  Most often these are used in templates, but they are also used in computations to test whether a variable or a dialog has been answered.  Hotdocs scripts will be interrupted if the value of any required variable is not known.  For this reason, the use of the”answered” function gives a value where no value is known.

What are the elements?

  • ANSWERED: The function
  • VAR: Any variable.  All variables will have an “answered” or “unanswered” status.  Note, that you can force an answered status on a variable under two conditions: (1) if the variable has a “default” and the dialog on which the variable appears has been asked, or (2) the variable is a True/False variable on a dialog with an Ask All setting and that dialog has been asked.
  • DIALOG: Any dialog.  This tests whether the dialog has been “asked” in an interview.

Usage of ANSWERED expression:

  • Usage is disparaged by the software developers as “unnecessary”.  A properly designed template should have sufficient nesting of logic such that you need not test whether a particular variable has been answered.  This is particularly true when you use variable in IF EXPRESSIONS.


  • It is also disparaged because the way HotDocs does (or rather does NOT) clear data.  If a variable is “hidden” based on a dialog scripting rule, the hidden variable still retains its value.  For this reason, you should not depend on the answered status of a variable to determine whether a phrase should be included if there are parent conditions not expressed in the template.


  • Usage is recommended if you want something special to happen, other than the ordinary, if a variable has not been answered.  While you can use “tokens” in the advanced properties of a variable, you may want to put the rules into a computation.

CLIENT Address 1 TE
“ + CLIENT Address 2 TE

Expression Model: AGE(DATE)

This tip covers the instruction model: AGE(DATE).  Use this expression if you want to know the age in terms of years as of the current date.  If you want to know the age as of a specific date, other than today, then you will need to use YEARS FROM( DATE , DATE )

What are the elements?

  • AGE: The function 
  • DATE: The start date for measuring the age.  It can be a birth date or the date a debt was incurred.

How do you use it?

AGE(CLIENT Date of Birth DA)

Expression Model: ABSOLUTE VALUE(NUM)

This tip covers the instruction model: ABSOLUTE VALUE(NUM). This model returns the positive (or absolute) value of a number variable.  In some accounting formulas, the result of the formula will be a negative number.  You may want to not the value as a negative, but still be able to treat and format the number based on its positive value

What are the elements?

  • ABSOLUTE VALUE: The function


  • NUM: A number value, positive or negative

How do you use it?

Use it in a fillpoint or computation for a variable entered in the system


Use it to test the result of a calculation

ABSOLUTE VALUE(Gross Revenue NUExpenses NU)

Expression Model: ZERO(NUM)

This tip covers the use of the instruction model: ZERO(NUM).  When is a number not a number?  When it has no value.  That doesn’t present an issue unless you start running calculations based on an unanswered number.  The solution is ZERO(NUM).

What ZERO expression does is return the number value (if there is a number) or zero.

Use for a sum of different number variables

SET Fruit Total NU TO ZERO(Apples CNT) + ZERO(Oranges CNT) + ZERO(Tangerines CNT)

Use to provide a Total off a Repeat

REPEAT Inventory RPT

Future of Document Assembly

For better or worse, the future of document assembly is on the Web. The web offers cheaper maintenance, quicker updates, and a more consistent look and feel. The web is also the most cost-effective on total cost of ownership (“TCO”).  The catch is that startup costs are much greater for web deployment of automated templates.  Particularly since most law firms wish to “dip before they dunk”, the presence of desktop or networked document assembly solutions is critical to the development of automated content.  In the past five years, millions of dollars have been invested in innovative web-delivery of automated document creation systems.  By contrast, the investment in client/server based document assembly software has been minimal.

The sole exception has been LexisNexis’s continuing development of the HotDocs platform.  Korbitec, once the leading rival to LexisNexis, has ceased further development of its powerful GhostFill document assembly engine.  No other viable vendor has stepped up to fill the gap and compete head-on with LexisNexis.  LexisNexis deserves real credit for investing resources in building an ever-more powerful version of HotDocs.  They should be encouraged to keep up the good work and rewarded with license sales.  As I have written in my review of HotDocs 2006 posted in Technolawyer, the HotDocs platform has been transformed into a toolkit that can do some amazing things to manipulate data and forms.  However, in the absence of a viable direct competitor on the client/server space, there needs to be a clear reason for LexisNexis to continue to innovate.

Before I talk about the future, let me talk about the present. Let’s look at the pricing of document assembly software.  HotDocs Standard desktop costs $300 and HotDocs Professional costs $850 per license.  What that means is that for a small user base (1-10 users) your software investment is very small. As the user base increases beyond 50 users, the cost of software starts to become a factor. The reality is that most document assembly installations start out as departmental efforts (under 20 users) or occur where the firm purchases a form set (in which case the “player software” is free). By contrast, online software starts at $12,500 and goes up to $100,000 for the server software.  These fees do not include the server hardware, the consulting services configuring (and securing) the webserver, or the usage fees charged by a number of vendors.

It is this GAP which forces many users to look at the “cheap” software and get locked in.  This benefits LexisNexis which offers both cheap HotDocs desktop software and a much more expensive HotDocs Server product.  The cost, however, is that the web-based developers (Business Integrity, iXio, Exari, Perfectus and others), have template development environments that offer alternative design philosophies some of which may be better suited to your firm or company.  But because the startup (or prototype) costs are so high, such software is only available to the AmLaw 100 law firms and large corporations.

The FUTURE of document assembly.

Microsoft, with the release of Vista and Office2007 has closely aligned its software with the web through Sharepoint webservices, integrated throughout.  The 2-ton gorilla in the room is Microsoft which is starting to move into the “vertical” space and recognize the needs of legal.  Microsoft Legal is currently using Business Integrity’s DealBuilder product, which means that they have had an opportunity to evaluate closely a very power and flexible automation system.  It is only a matter of time before some of the features of DealBuilder show up in future versions of Office and Sharepoint.

Exari has announced the conquest of the “holy grail” in document assembly—The ability to assemble a document, send the result out for comments and editing, and then to bring the document back into the automation environment so that the variables and business logic continue to function on what is now the “customized template”.  They offer a feature which previously was only available in Smartwords (now defunct) and Rapidocs via a proprietary word-processor.  With the advent of WordML (a new open file format of XML files packaged together) it is possible to “safely store metadata” about the rules and structures of a word document, separating content, structure and format.  All of the web based developers are looking at what can be done with WordML to allow the “round tripping” of templates and documents.

Word currently allows you through macros and forms (including InfoPath and Taskbar data entry) to do much of what document assembly software does.  The catch, is that building such system requires specialized expertise in programming.  That means, to do court forms, form agreements and other automated documents requires hiring an experienced programmer.  The strength of the document assembly software is the “easy markup” which can be understood by the lawyers and managers who work with these forms, and the ease of deploying updates. Also with the separation of “business logic” from the word document, such document assembly systems allow the templates to run on multiple versions of Word (and WordPerfect) without recompiling macros.

LexisNexis is continuing to explore new options for its HotDocs platform.  A while back, it built into HotDocs Professional the ability to “Publish Templates” for HotDocs Server.  This means that for a very low investment, you can develop templates for internal use, and when the templates (and users) hit a critical mass, then invest in HotDocs Server.  We at Basha Systems, now work with Accudraft and offer HotDocs Online hosting services for our clients.  We offer our clients NO STARTUP COSTS and NO HARDWARE COST hosting.  For a nominal monthly fee, plus ongoing document automation consulting, we can put a law firm or company online.

So the future is ONLINE … it is just a matter of time.

Limit Spreadsheet Lines Appearing

You want to control the number of lines that appear on a dialog that displays in “Spreadsheet” style.  Quite often, the default number of lines visible on a spreadsheet style dialog are aesthetically offensive. We need to control this for two reasons: 1) its ugly; and 2) screen real estate is quite often at a premium.

Basha Systems use a CNT prefix for specific purpose number variables, to differentiate between a “true” number variable used in document assembly templates, and those number variables used for tracking, counting & limiting. Lets presume we are dealing with a spreadsheet to enter in children’s names and DOB’s. In the dialog PRIOR to the spreadsheet dialog relating to children, create a variable something similar to Var_CNT. The prompt should be something like “How many children do you wish to enter?” In the script of the spreadsheet dialog, place the following:


This will ensure that the spreadsheet is LIMITed to the number of lines that the user has indicated are required. You may wish to REQUIRE the Var_CNT variable, so the user must enter a number to gain access.

If the spreadsheet dialog is actually “Spreadsheet on Parent”, you should script the dialog so that it doesn’t even appear until such time as the Var_CNT variable has been answered. Using this approach, the REQUIRE option is redundant.

Instruction Model: ADD TEXT TO MULT_CHOICE

This tip covers when to use and how to use the HotDocs Instruction Model: ADD TEXT TO MULT_CHOICE.  HotDocs supports dynamic multiple choice variables.  A list of options (and their associated prompts) for a multiple choice variable can be seen in the definition of a particular component. However, this restricts the user to options known at the time that a component file is authored. This instruction model lets the developer dynamically change the option values and their associated prompts based on answers given by the user during an assembly.

What are the elements?

  • ADD: The instruction to Add Text
  • TEXT: A Text Value, a Text Variable, or a Text String consisting of Text and Variables
  • MULT_CHOICE: A Multiple Choice Variable (Single select and Multi-Select)

Other Related Instructions?

  • CLEAR MULT_CHOICE:  Will clear ALL options and prompts for a Multiple Choice Variable

How do you use it?

1. Build from a Repeat

The sample below is used to set the options for a Beneficiary selector.  This option could itself appear on a REPEAT.  The beneficary variable is first CLEARed. Then the script loops through the list of children, adding each child’s name, one at a time to the option list.


2. Build from a Script

The sample below is used to set the options for a Beneficiary selector.  This option could itself appear on a REPEAT.  The beneficary variable is first CLEARed. Then the script loops through the list of children, adding each child’s name, one at a time to the option list.

ADD "Married|Client is married" TO CLI Married MC
ADD "Single|Client is single" TO CLI Married MC
ADD "Divorced|Client is divorced" TO CLI Married MC
ADD "Widowed|Client is widowed" TO CLI Married MC

3. Build from a Repeat and Add Custom Prompt

The sample below is used to set the options for a list of children to disinherit from a will.  The variable is first CLEARed. Then the script loops through the list of children.  For the option value, it adds each child’s name.  However, for the prompt, it puts in the child’s relationship to the , one at a time to the option list.

CLEAR HEIR Disinherit Name MS
// Change prompt based on gender of child
IF CHLD Gender MC = "Male"
ADD "«CHLD Name TE»|Client's son «CHLD Name TE»" TO HEIR Disinherit Name MS
ADD "«CHLD Name TE»|Client's daughter «CHLD Name TE»" TO HEIR Disinherit Name MS


  • You must create the Variable and assign a default option (e.g. “Name Goes Here” or “1″)


  • You must use a computation script for the CLEAR and ADD instructions.


  • The script must be processed before you display the Multiple Choice Variable.


  • However, given the way the HotDocs interview works, you can accomplish this by putting the computation on the Dialog Script where the Mutiple Choice Variable is used, or in an INTERVIEW script.  If you choose the latter option, it can go anywhere in the script.

SET Command and GRAYed Variables

You need to SET the value of a variable, but want users to be able to edit the value even after it is SET.  HotDocs will GRAY a variable (prohibiting editing) if the SET command is processed on the dialog, and DEFAULT will not overwrite a variable’s value.

A “regular” script to SET a variable to a value (based upon a Multiple Choice variable) probably looks something like this:

IF Var_MC = “1”
SET Var1_TE TO “red”
SET Var1_TE TO “blue”

As soon as Var_MC is answered, Var_TE will acquire an appropriate value, and subsequently GRAYed out – because it is processed dynamically by the dialog script, and whilever those conditions are met, the variable will not be editable.

We need to avoid HotDocs GRAYIng the variable. The solution? A button that calls a computation.

Lets say we create a variable called Var1_CO – this is the variable that will be called by the button on our dialog. The content of this computation will be exactly the same as the script above. We don’t wish to do anything different, we just wish to shift the source of the SET command.

In our dialog additional text section, we type

@COMPUTE:Var1_CO: Populate

@COMPUTE is the command to tell HotDocs we want a button to call a computation. Var1_CO is the name of the computation variable we are calling. Populate is the button text which will be displayed. When we click this button, the value is SET (provided all conditions have been made), and the variable is editable.