ExpressionScript examples/en

=Structure=

The first part of the article will describe what Expressions can be used for and where to find/add an Expression. The second part provides examples on how to use Expression.

=Categories of Expressions=

LimeSurvey uses Expressions for the following purposes:
 * Relevance
 * Validation
 * Text output
 * Answers storing

Relevance
Purpose: Hiding question groups/questions

Relevance controls whether a question group or question is shown or hidden. If the result of the Expression is "true" (i.e. 1), the element will be shown. Otherwise (if the result of the Expression is "false" (i.e. 0)), the element will be hidden.

Validation
Purpose: Validate input/actions on questions/subquestions/answers

Validation controls whether the respondent's input into a question or action is valid or not. If the result of the Expression is "true" (i.e. 1), the "good" class will be applied to the element and validation message. Otherwise, if the result of the Expression is "false" (i.e. 0)), the "error" class will be apllied to the element and validation message. You can declare a style for these classes in the template.css.

Text output
Purposes: (Do something) and write out some text

An Expression can be used to write out some text. For example, you can test or calculate something and specify the output depending on the result of the test or calculation. It can also be used to insert the question text, answers, question types, ... of a question used before the Expression is used. Text output can be used everywhere where a text is shown and can return every kind of results.

Answers storing
Purposes: (Do something,) (write out some text) and store something in the database

The Equation Question Type can be used to store something in the database. You can do something with an Expression, show the Equation question (which is similar to a text display) and store the result of the Expression in the database. It stores the answer into the responses table. Then, the result can be used within the statistics feature or it can also be imported into one of the formats provided by the LimeSurvey export functionality.

=Examples for Expressions=

Using hidden equation question to autofill an answer
Problem: Imagine you have two questions Q1 and Q2. Q1 asks respondents for their age. Q2 divides respondents into three groups: age is below 20 years, age is 20, age is greater than 20. So, Q2 should make use of the values "1", "2", "3", which correspond to the above conditions. Also, we should not forget to make Q2 invisible (the question will not be displayed in the survey, but the values will be via the "background process" within the responses table).

To fill in the database using the Equation question type: Q2=if(Q1.NAOK < 20, "1", if(Q1.NAOK > 20, "3", "2"))}
 * First, create a question with code Q1 as a numerical input question.
 * Then create another question with code Q2 as an equation question.
 * In the "Display settings" tab chapter of Q2:
 * set "Always hide this question" field as "On"
 * type in "Equation" field the expression:

Create a summary page using placeholders
This tutorial demonstrates how you can create an overview at the end of the survey, listing all questions and answers via Expression Manager placeholders. It also shows how to limit such an overview to answered questions only.

Our example can be downloaded from here: [[Media:Limesurvey_Expression_Manager_Placeholder_Demo_Survey.lss|Survey placeholders survey example]].

Question types being used here:

1. Single choice questions / single text/numeric questions
 * List (dropdown)
 * List (radio) [L]
 * Yes/No [Y]
 * Long free text [T]
 * Short free text [S]
 * Numerical input [N]
 * Equation [*]

2. Question with subquestions
 * Multiple short text [Q]
 * Multiple choice [M]
 * Array [F]
 * Array (Yes/No/Uncertain) [C]
 * Array (10 point choice) [B]

3. Questions with 2 scales
 * Array dual scale [1]

4. Questions with X and Y scales
 * Array (Numbers) [:]

5. Mask questions
 * Text display [X]

In this simple example, our overview will be a simple list with:

- Question text: User's answer

Single choice questions / single text/numeric questions
For all these question types, Limesurvey will store a single response:


 * List (dropdown)
 * List (radio)
 * List with comment
 * 5 point choice
 * Yes/No
 * Short free text
 * Long free text
 * Huge free text
 * Numerical input
 * Equation
 * Date
 * Gender

Assuming the question code of the question is q1, we can reference the question text and answer using:

- {q1.question}: {q1.shown}

Example:

- How old are you?: 25

If you want to check whether that question was answered you can put an IF statement around your output:

{if(!is_empty(q1),join("- ",q1.question,": ",q1.shown),"")}

This "translates" to: IF question with code q1 is not empty, output "- " AND the question text AND ": " AND the answer text (the join function joins elements as a new string; ELSE: output nothing ("" means empty string).

Question with subquestions
For all these question types LimeSurvey uses subquestions:


 * Multiple short text
 * Multiple choice
 * Multiple choice with comments
 * Array
 * Array (5 point choice)
 * Array (10 point choice)
 * Array (Yes/No/Uncertain)
 * Array (Increase/Same/Decrease)
 * Array by column

Assuming the question code of the question is q2 and the subquestions are numbered SQ001, SQ002, (auto-numbering done by LimeSurvey), we can reference the question text and answer using:

- {q2_SQ001.question}: {q2_SQ001.shown}

- {q2_SQ002.question}: {q2_SQ002.shown}

For multiple choice questions it makes sense to now show the text of the ticked subquestion but to show a Y for each selected option:

- {q2_SQ001.question}: {q2_SQ001}

- {q2_SQ002.question}: {q2_SQ002}

...

Note that currently it is not possible to output the question text of questions with subquestions, see this feature request.

Example 1 (assuming question type is multiple choice)
- Do you know these car brands?

-- Mercedes: Y

-- Audi: N

-- Volvo: Y

If you want to output checked items only you can put an IF statement around your output and check for the checkbox value:

{ if( q2_SQ001=="Y", join( "- ", q2_SQ001.question, ": ", q2_SQ001.shown ), "" ) }

Use the listifop function if you want to output a list of only the selected items, eg: Mercedes, Volvo

{ listifop( 'value', '==', 'Y', 'question', ', ', that.q2.sgqa ) }

Where that.q2  expands to all of q2's subquestions. See self, this and that for more detail.

Example 2 (assuming question type is Array (10 point choice))
- Please rate the quality of the car brands below on a scale from 1=very bad to 10=very good?

-- Mercedes: 7

-- Audi: 9

-- Volvo: 9

If you want to output rated items only you can put an IF statement around your output and check if the current sub question was answered by using:

{ if( ! is_empty( q3_SQ001 ), join( "- ", q3_SQ001.question, ": ", q3_SQ001.shown ), "" ) }

Use the listifop function if for example you want to only output a list of the selected items greater than eight, eg: Audi / Volvo

{ listifop( 'value', '>', 8, 'question', ' / ', that.q3.sgqa ) }

Question with two scales
Let's assume that the following codes are being used:
 * Question code: q4
 * Subquestion codes: SQ001, SQ002, ...
 * Answer codes scale 1: A1, A2, ...
 * Answer codes scale 2: B1, B2, ...

Let's output the results for both scales and the first two subquestions:

- {q4_SQ001_0.question}: {q4_SQ001_0.shown} / {q4_SQ001_1.shown}

- {q4_SQ002_0.question}: {q4_SQ002_0.shown} / {q4_SQ002_1.shown}

To output the subquestion text, you need to add the scale ID to the placeholder (though the texts are the same for both scales). So instead of {q4_SQ001.question} we have to use {q4_SQ001_0.question} or {q4_SQ001_1.question}.

If you want to export/display the results of subquestions with at least one answer only, use this syntax for each subquestion:

{if(count(q4_SQ001_0,q4_SQ001_1)>0,join("- ",q4_SQ001_0.question,": ",q4_SQ001_0.shown," / ",q4_SQ001_1.shown),"")}

Question with X and Y scales
This applies to all matrix questions which allow an answer for every cell (not just every row as shown previously):
 * Array Texts
 * Array Numbers

Assumed codes used:
 * Question code: q5
 * Subquestion codes: SQ001, SQ002, ...
 * Answer codes: A1, A2, ...

To refer to the result of a certain subquestion from a certain column, you need to use QuestionCode. '_' . SubQuestionCode. '_' . AnswerCode. Example for referring to the answer of the third subquestion and second column: q5_SQ003_A2.

Let's output the results for columns 1-3 of the first two subquestions:

- {q5_SQ001_A1.question}: {q5_SQ001_A1.shown} | {q5_SQ001_A2.shown} | {q5_SQ001_A3.shown}

- {q5_SQ002_A1.question}: {q5_SQ002_A1.shown} | {q5_SQ002_A2.shown} | {q5_SQ002_A3.shown}

Since for these question types each cell (combination of X axes and Y axes) equals one answer option, a test for existing data needs to be done for each cell. Example:

{if(!is_empty(q5_SQ001_A1),join("- ",q5_SQ001_A1.question,": ",q5_SQ001_A1.shown),"")}

Using Expression Manager for Assessments
Here comes another example on how to use the Expression Manager with Array type questions and assessments:

Let's say you have 2 array questions and you want to save the results of the calculation data to your database. It is actually simple, you will need to create and test your arrays and submit a dummy response to see if it works and gives you the results in the completed page.

Implementation details:
 * add a question of type equation
 * add the following line assuming that Q1 is your array question code while Q2 is the second one:
 * {sum(Q1_SQ001.value,Q2_SQ001.value)}

Note that SQ001 is the default code for any subquestion. If you change the subquestion code, adjust the equation above accordingly.

Using em_validation_q in array
You can use the question validation equation to control an array with any condition.

Implementation details:
 * for the first array : array of single choice
 * Question code is ARRAY
 * Sub question code are SQ01,SQ02,SQ03 and SQ04
 * update the Whole question validation equation and put !is_empty(ARRAY_SQ01) and !is_empty(ARRAY_SQ03)
 * for the second array : array of text
 * Question code is ARRAYTEXT
 * Sub question at Y axis code are SY01,SY02,SY03, and SY04
 * Update the Whole question validation equation and put count(self.sq_SY01 >= 1) and count(self.sq_SY03 >= 3)