Route Section


Table of contents

  1. Introduction
  2. ASK to display a question
  3. Conditional routing
  4. Computation/calculations
  5. Messages, Warnings & Checks
  6. Canvas
  7. Operations with lists
  8. Randomise/Rotate list of choices and question order
  9. Playing audio and video files
  10. Printing individual responses to a pdf file


The ROUTE section can be used to define:

  • the order in which questions are asked
  • conditions under which questions asked.
  • display options
  • checks
  • computations

Actions in the ROUTE section are defined using keywords and functions some of which are used in the examples that follow. See list of dsc keywords and functions for descriptions of the keywords and functions that can be used.

The route section begins with the ROUTE reserved word in the dsc file.

Example - ask question q1 then ask question q2 if the answer to q1 is yes


Back to start

ASK To display a question


The ASK causes the question to be displayed. NEWPAGE() and ENDPAGE() delimit the contents of the page. One or more questions can be displayed on each page.

ASK Parameters

Parameters can be added to the ASK to modify the display of the question. Some examples are shown below.

Adding text

Text can be added to the left or right of the entry box.

txtr adds text to the right of the response box: ASK(Q1,"txtr=@NS$years") [ ] years

txtl adds text to the left of the response box. ASK(Q1,"txtl=You are@NS$") You are [ ]

@NS$ in the above examples inserts a space to improve the display.

Styles for response categories


This will modify the display of odd and even rows using the styles defined for the class classrows in the css file.

Shuffle rows and columns of questions

ASK(Q6,"shufflerows=Q6") ASK(Q7,"shufflecols=Q7")

To randomise the order of display of the rows of question Q6 and the columns of Q7 where Q7 is a grid question.

Transpose a question

ASK(Q7,"transpose=yes") Assuming Q7 is a grid question then the items usually displayed as rows will be displayed as columns.

Asking individual elements of array questions

Array questions defined with one dimension are often displayed as grids with the array elements used as the rows of the grid.

It is also possible to ASK the question with each array element asked individually.

Example to ask the question for the 4th element in the array question Qgrid: ASK(Qgrid[4])

The example below involves a 2 dimensional question. It will display 4 pages, one for each fruit. Each page will be a grid with days of the week as rows and yes/no as columns.

DEFINITIONS lst_fruits = { 1 "Apples",2 "Oranges",3 "Bananas",4 "Grapes"} lst_Days = {1 "Mon",2 "Tue",3 "Wed",4 "Thu",5 "Fri",6 "Sat",7 "Sun"} VARIABLES i_fruit : lst_fruits QUESTIONS ftoday[lst_fruits][lst_Days] "Please record whether you ate @ITEXT$ on each day?" : {yes,no} ROUTE FOREACH i_fruit IN lst_fruits DO { NEWPAGE() ASK(ftoday[i_fruit][*]) //[*] to indicate that all days should be displayed ENDPAGE() }

Note: i_fruit in the FOREACH command above will loop through the four fruits and @ITEXT$ in the question text for ftoday will be substituted by the text for each fruit.

First of the four questions displayed:

Back to start

Conditional Routing

Conditions are logical expressions that can be used to control when questions are asked and to program other computations in the ROUTE section.

Example 1: Only ask Q3 if the answer to Q2 is 'Yes'.

Q2 "Do you have children?" { Y "Yes", N "No" }REQUIRED Q3 "How many children do you have ?" : 1..20 REQUIRED


Example 2: To screen out an individual. The interview stops for anybody aged less than 18 years of age. (txtr=@NS$years displays the text "years" next to the entry box).

Q1 "How old are you?" : 0..99 REQUIRED


NEWPAGE() ASK(Q1,"txtr=@NS$years") ENDPAGE()


Example 3: Routing within a page

Note that in Example 1 above the routing condition (IF(Q2 IN {Y}) THEN {) is outside NEWPAGE()/ENDPAGE() which bracket questions to be displayed on the same page. It is possible to control which questions are displayed within a page. In the following example the page will first display only cr1 and then either cr2 or cr3 will be displayed depending on the answer to cr1.

cr1 "Did you attend last week?" : {yes,no} cr2 "How useful did you find it?" :{ very "very useful", mod "moderately useful", not "not useful" } : "if=cr1{yes}" cr3 "Why did you not attend?" : OPENTEXT : "if=cr1{no}"


A list of conditions can be defined and a question asked if ANY of those conditions is true. For example:

HowMany "How many?" : 1..10 : "if=qa{1}:qb{1}:qc{1}"


The operators listed below can be used to define conditions for subsequent actions to be performed. For example whether a question should be asked.

==equal to
<> not equal to
IN included/contains
> < greater than, less than
>= <= greater than or equal, less than or equal
AND && logical AND
OR || logical OR
NOT logical NOT
=~ contains
!~ does not contain
= assignment

Back to start

Computations and calculations

Complex programming and computations can be done in the scripting language.

Program language features include:

The following arithmetic operators can be used in computations:


A number of functions are also available to perform useful computations or other tasks. For example the SETQTXT function can be used to change the text of a question.

Back to start

Messages, Warnings & Checks

There are two types of message :

  • Information "I am now going to ask you some questions about your job"
  • Warnings "Please fill in the 'other' response."

Information messages

NEWPAGE() MESSAGE("We now will show you a series of products. Please look at them carefully.") ENDPAGE()

Warnings and Checks

Checks can be added to ensure the respondent has entered complete and/or consistent responses. A CHECK usually involves a condition and a warning message. If the condition is not satisfied the warning message is displayed and the respondent cannot move on to the following page until the error is corrected.


NEWPAGE() ASK(Q1) ENDPAGE() NEWPAGE() ASK(Q2) CHECK : { IF(Q1 IN {Yes} AND Q2 IN {None}) THEN WARNING(Q2,"You selected Yes at the previous question so cannot select None at this question") } ENDPAGE()

Back to start


The canvas (table) provides a way of referring to and operating on the different elements of question responses (the response labels and data entry/selection buttons).

The elements of question responses can be treated as if laid out in a table and the elements referred to using the row and column numbers of that table.

Amongst other things the canvas can be used to:

  • move rows or columns
  • prevent rows and/or columns from being displayed
  • to move and/or copy table cells
  • set styles for particular elements

To make use of the canvas, declare a canvas variable in the variables section and add BEGINCANVAS() and ENDCANVAS() around the ASK as shown below. Then add the actions to be performed on the CANVAS (skiprows in the example below) and use DISPLAYCANVAS() to display the result.



Canvas operations can be defined to act on a single cell or blocks of cells. The cells to which the action should apply can be specified as follows:

SETBLOCK(canvas_name:row number of first cell, column number of first cell, row number of last cell, column number of last cell).

The row and column indexes start at 0

Example :


To select the first row: SETBLOCK(c:0,0,0,3)

To select the two middle cells: SETBLOCK(c:1,1,1,2)

To select the last column: SETBLOCK(c:0,3,2,3)

Note that if asking a grid variable then the first row will contain the column headers. If multiple questions are asked on the same page then canvas treats the whole page as single table. So, for example, the second of 2 questions could be moved to be displayed alongside the first question.

The line below can be included in the project .ini file as an aid to developing and checking canvas operations.


This will display canvas coordinates when the cursor hovers over a cell.

Once selected cells can be randomised, hidden or have styles and classes changed using canvas parameters.


SETBLOCK(c:0,2,25,2,"skipcol=yes") - do not display column 2 SETBLOCK(c:11,0,11,1,"skiprow=yes") - do not display row 11

List of CANVAS parameters:

  • "class=even" assign a css class
  • "classrows=even:odd" set different classes for even and odd row. css can then be used to set different styles.
  • "copy=yes" copy an element and not move
  • "disabled=yes"do not allow contents of selected cells to be changed
  • "display=none"do not display selected cells
  • "id=form1" assign an id to an element
  • "merge=@NS$" merge (usually to merge 2 columns into 1)
  • "inscols=yes" insert a new column before the selected column
  • "insrows=yes" insert a new row before the selected row
  • "shufflecols=yes" Columns specified will be displayed in random order for the rows specified.
  • "shufflefullcols=yes" column randomisation for all rows
  • "shufflerows=yes" Row randomisation is done on the columns specified.
  • "shufflefullrows=yes" randomise row order of all columns
  • "skipcol=yes" to prevent display of column 5 of the canvas table
  • "skiprow=yes" to prevent display of row 4 of the canvas table

When using SETBLOCK() for a canvas all the parameters which are not known canvas parameters are interpreted as css style instructions. For example, the following code emboldens and right aligns the selected cells:


Example: to insert row header text:

SETBLOCK(c:6,0,6,1,"insrows=yes") SETBLOCK(c:6,1,6,1,"Group 3") SETBLOCK(c:3,0,3,1,"insrows=yes") SETBLOCK(c:3,1,3,1,"Group 2") SETBLOCK(c:0,0,0,1,"insrows=yes") SETBLOCK(c:0,1,0,1,"Group 1")

Here the inserts are done from the bottom upwards so that row references above the insert remain the same.

Blocks of cells can be copied using the COPYBLOCK command. For example to move row 1 to row 10:


"copy=yes" can be added to copy cells and leave the original cells unchanged.

SETCANVAS can be used to defines the cells that will be displayed.

For example to display the 9 cells in rows 0-2 and columns 3-5


Back to start

Operations with lists

Many surveys display a list (e.g. brands, services, devices, appliances) to respondents and then display the list or a subset of the list in subsequent questions.

Functions SETQLIST and SETQARRAY can be used to control which subsets of lists are displayed. is a simple questionnaire demonstrating the use of lists.

Lists are defined in the DEFINITIONS section.

DEFINITIONS lst_brands={ 1 "Brand 1", 2 "Brand 2", 3 "Brand 3", 4 "Brand 4", 5 "Brand 5", 6 "Brand 6", None "None of these" }

The list can then be used to define the response categories for a questions.


Q1 "Which brand do you prefer?" : lst_brands Q2 "Any other brands used?" : lst_brands{*}

List operators and functions

List operators can be used to control which items in a list or lists are displayed at a question. The operators available to build lists are shown below. The examples that follow show how these can be used in practice.

| set union of lists{a,b,c} | {b,d} = {a,b,c,d}
& intersection of lists{a,b,c} & {b,d} = {b)
\ set difference between lists{a,b,c} \ {b,d} = {a,c}
SHUFFLE randomise listSHUFFLE({a,b,c}) = {b,a,c} for example
ROTATE rotate listROTATE({a,b,c,d,e}) = {c,d,e,a,b} for example
REPLACE replace item in a list with another listREPLACE(list1,list2,list3)
? element numberlst_items?3 for 3rd item in list lst_items

Examples : list operators for list of choices questions

The examples below show how list operators and the SETQLIST command can be used to control which choices in a list are displayed at each question.

The examples are based on questions all defined with lst_brands for the response categories.

First declare variables used in the examples below

VARIABLES i_brands "To be used for loops" : lst_brands just_brands "To define brand list excluding none" : lst_brands select_brands "To be used when creating selection lists" : lst_brands i : INTEGER c : CANVAS

q1: Brand list with 'None of these' not displayed. (The CHECK is in this example computes the response selected into the next question and is not related to SETQLIST)

SETQLIST(Q1,{1,2,3,4,5,6}) ASK(Q1) CHECK: { IF NOT((Q2 IN Q1)) THEN {Q2 = Q1} }

Note: The same filter on Q1 could be done with the two examples below.

SETQLIST(Q1,lst_brands \ {None})

just_brands = lst_brands \ {None} SETQLIST(Q1,just_brands)

Q2: Prefilled with response from Q1. CANVAS used to prevent respondent from unchecking the code that has been copied in from Q1.

BEGINCANVAS(c) ASK(Q2) ENDCANVAS(c) i = 0 FOREACH i_brands IN lst_brands DO { IF (Q1 IN i_brands) THEN {SETBLOCK(c:i,0,i,1,"disabled=yes")} i = i + 1 } DISPLAYCANVAS(c)

Q3: Only display brands selected at Q2


Q4: Display brands NOT selected at Q2

SETQLIST(Q4,(lst_brands \ Q2)) ASK(Q4)

Q5: Brands selected at either Q3 OR Q4

SETQLIST(Q5,(Q3 | Q4)) ASK(Q5)

Q6: Brands selected at either Q3 OR Q4 with brand order preserved

SETQLIST(Q6,(lst_brands & (Q3 | Q4))) ASK(Q6)

Q7: Brands selected at both Q5 AND Q6. With condition to ensure at least one brand to display

select_brands = (lst_brands & (Q5 & Q6)) IF (COUNT(select_brands) > 0) THEN { NEWPAGE() select_brands = (lst_brands & (Q5 & Q6)) SETQLIST(Q7,select_brands) ASK(Q7) ENDPAGE() }

Note: select_brands recomputed inside NEWPAGE()/ENDPAGE(). This is because select_brand is reused in later questions and needs to be set correctly if the back/previous button is used.

Q8: Brands selected at Q7 but with Brands 1 & 2 always displayed as well.

select_brands = (lst_brands & (Q7 | {1,2})) SETQLIST(Q8,select_brands) ASK(Q8)

Q9: Shuffle brands but use REPLACE function to keep brands 3 & 4 together

select_brands = SHUFFLE(select_brands \ {4}) // Shuffle all brands apart from 4 select_brands = REPLACE(select_brands,{3},SHUFFLE({3,4})) // Replace brand 3 with SHUFFLE({3,4}) SETQLIST(Q9,select_brands) ASK(Q9)

See REPLACE function for more examples

Example : SETQARRAY for grid questions

If the question being displayed is a grid then use SETQARRAY to control which elements in the list should be displayed.

QUESTIONS Q9 "Which of these did you use in the last month?" : lst_brands{*} Q10 [lst_brands] "On how many days did you use each of these brands" : 1..7

Then in the ROUTE section:


Example using FOREACH to create a list from responses to a grid question.

QUESTIONS Q11[lst_brands] "How often do you buy these brands" : {Never,Sometimes,Often} Q12 "Of the brands bought sometimes/often which brand will you buy next?"

Then in the ROUTE section:

just_brands = lst_brands \ {None} SETQARRAY(Q11,0,just_brands) ASK(Q11)

select_brands = {} FOREACH i_brands IN lst_brands DO { IF (Q11[i_brands] IN {Sometimes,Often}) THEN { select_brands = (select_brands | i_brands) } } SETQLIST(Q12,select_brands) ASK(Q12)

Back to start

Randomise/Rotate list of choices and question order

In some surveys the lists of choices or a group of questions have to be presented in random order to different respondents. For example to avoid potential bias because of the order in which response choices or questions are presented.

There are parameters that can be used to do simple randomisation of lists of choices with the canvas and in the ASK statement. More complex randomisation can be done with the list SHUFFLE function as in the example below.

In some surveys response choices have to be rotated. This is like cutting a deck of cards into 2 piles and putting the bottom pile on top. So one choice is chosen at random to be the first and other choices follow in the original order. For example:

item1, item2, item3, item4, item5 -> item3, item4, item5, item1, item2

The examples below use the SHUFFLE function but the same syntax can be used with the ROTATE function for rotation instead of random ordering.

Examples: SHUFFLE to randomise the order of lists

The first example below randomises the order of display of a list of items, ensuring that the 'Other','Dont Know' options remain at the bottom of the list.

DEFINITIONS lst_items = { 1 "Item 1", 2 "Item 2", 3 "Item 3", 4 "Item 4", 5 "Item 5", 6 "Item 6", 7 "Item 7", 91 "Other, please specify" + OTH : TEXT[40] : "size=40", 99 "Don't know" }

QUESTIONS Q1 "Which is your preferred item?": lst_items Q2[lst_items] "How many of each of the items did you use last week" : INTEGER

VARIABLES rand_items : lst_items

ROUTE IF (NOANSWER(rand_items)) THEN rand_items = SHUFFLE(lst_items \ {91,99}) | {91,99} NEWPAGE() SETQLIST(Q1,rand_items) ASK(Q1) ENDPAGE() NEWPAGE() SETQARRAY(Q2,0,rand_items) ASK(Q2) ENDPAGE()

Example to shuffle when the items belong in 2 groups to be kept together.

rand_items = (SHUFFLE({1,2,3,4}) | SHUFFLE({5,6,7}) | {91,99})

Example: SHUFFLE and XASK to randomise the order in which questions are asked

This example computes a random order for questions Q1, Q2 and Q3 to be asked.

It uses XASK which can use a computed string for the name of the question to be asked.

//Define the list of question names:

DEFINITIONS lst_questions = { "Q1", "Q2", "Q3" } yesno = { 1 "Yes", 2 "No" }

//Define the questions:

QUESTIONS Q1 "Question about brand 1" : yesno Q2 "Question about brand 2" : yesno Q3 "Question about brand 3" : yesno

//Define the VARIABLE needed to hold the list of questions in random order.

VARIABLES question_list : lst_questions

//Create the list of questions in random order and use XASK to ask in that order. The ? operator is used to get the 1st, 2nd, and 3rd elements of the shuffled list of question names.

ROUTE IF (NOANSWER(question_list)) THEN question_list = SHUFFLE(lst_questions) NEWPAGE() XASK(question_list?1) XASK(question_list?2) XASK(question_list?3) ENDPAGE()

Back to start

Playing audio and video files

Audio and video files can be played during the interview.

audio : play an audio file

The @AUDIO:myclip$ tag, where myclip is the name of an audio file, can be used to add an audio clip in native HTML5 format. This standard format is preferable to other audio support options.

Copy myclip.mp4 and/or myclip.webm and/or myclip.ogg (or myclip.oga) and/or myclip.aac and/or myclip.wav files to the .docs directory for the project. (click here for information about the .docs directory.)

For example to play myclip.mp3 specify the file name and controls in a MESSAGE.

MESSAGE ("@AUDIO:myclip:controls=1:autoplay=yes download = no$")

The parameters are separated by the ':' character, and the first parameter is the name of the audio file.

The value 'yes' can be replaced by '1' or 'true'.

The value 'no' can be replaced by '0' or 'false' or 'none'.

The supported parameters are:

  • autoplay = yes: automaticlly start the clip
  • loop = yes: loop the clip
  • muted = yes: disabling the clip sound
  • controls = yes: displaying clip controls
  • download = no: remove the "download audio" control
  • remoteplayback = no: remove remoteplayback control

Other parameters are interpreted as CSS attributes: for example, "width = 100%" becomes "style =" width: 100%; "'.

video : play a video file

The @VIDEO:myclip$ tag, where myvideo is the name of an video file, can be used to add an video clip in native HTML5 format. This standard format is preferable to other video support options.

Copy myvideo.mp4 and/or myvideo.webm and/or myvideo.ogg (or myvideo.ogv) files to the .docs directory for the project. (click here for information about the .docs directory.) can be used to convert video files.

For example to play myvideo.mp3 specify the file name and controls in a MESSAGE.

MESSAGE ("@VIDEO:myvideo:width=100%:controls=1:autoplay=no:download=no:muted=true:fullscreen=0:poster=gide.png$")

The parameters are separated by the ':' character, and the first parameter is the name of the video.

The value 'yes' can be replaced by '1' or 'true'.

The value 'no' can be replaced by '0' or 'false' or 'none'.

The supported parameters are:

  • autoplay = yes: automatically start the video
  • loop=yes: loop video
  • muted=yes: disable video sound
  • controls=yes: display video controls
  • fullscreen=no: remove the "fullscreen" control
  • download=no: remove the "download video" control
  • remoteplayback=no: remove remoteplayback control
  • poster=mypicture.png: display the image mypicture.png (in folder) before starting the video

Other parameters are interpreted as CSS attributes: for example, "width = 100%" becomes "style =" width: 100%; "'.

Printing individual responses to a pdf file

Respondents can be given the option of downloading a pdf report of their responses when they have completed the survey. The example below shows how the content of this pdf can be controlled.

PRINTING PAGE() BEGINCANVAS(c) ASK(Q1) // NOTE: Use ASK() inside a canvas, not PRINT() ENDCANVAS(c) // Use normal canvas commands - SETBLOCK etc // Example below sets relative column widths, in this case allowing more space for text in the first column. PRINTCANVAS(c,"Q1","ft=430:50:50") PRINT(Q2,"ft=430:50:50") // Start a second page PAGE() PRINT(Q3) PRINT(Q4)

Back to start