Calculated variables use responses to survey questions to calculate and store new variables while a participant progresses through the survey. Read this guide to learn more about using calculated variables.
Illume calculations are algorithms that are run within a survey, and persist within the survey data set. Calculations are run on every page, i.e. every time the respondent clicks the Next button, all calculations are re-run. A survey may contain multiple calculations, and calculations can include other calculations. Calculations are processed in the order that they appear in the calculations editor, which is particularly relevant when calculations are based on the results of other calculations.
There are a number of valuable uses for calculations. Calculations can be used to do the following (this list is not all inclusive):
For each calculation, Illume creates a variable with the same name as the calculation. Illume attempts to evaluate all of the calculations in the survey each time a participant moves from one page to the next. Illume relies on piping to grab the value of variables used in the calculation. For example, if a participant entered “200” in response to the question named WEIGHT that asked “What is your weight (in pounds)?”, Illume substitutes 200 for the tag {Value:WEIGHT}.
Illume will perform value substitutions (aka piping) on any variables for which it has data. It does not matter whether that data came from a participant response, from a variable appended to the survey URL, or from data that was pre-loaded from the participant list. If Illume cannot perform the calculation, the value of the calculation will be the default value set for the calculation in the Survey Calculations Editor. If no default value is set, and Illume cannot perform the calculation, the value for the calculation will be null (empty).
There are three conditions under which Illume cannot perform a calculation:
The calculation itself is a JScript.NET expression, or a series of JScript.NET statements. Illume evaluates the JScript.NET using the eval() function and sets the value of the calculated variable to whatever eval() returns.
There are two things to note about eval() in JScript.NET:
EXAMPLE: The following calculation determines the total price for a quantity of some material, then applies a discount of 5%:
var weightInGrams = {Value:KILOGRAMS} * 1000;
var pricePerGram = 0.13;
var totalPrice = weightInGrams * pricePerGram;
var discount = 0.05;
totalPrice * (1 – discount);
Notice that the value to be returned is expressed on the last line as totalPrice * (1 – discount), and that there is no return statement. Because JScript’s eval() returns the value of the last expression, the result of the calculation will be the value of the last expression in the calculation.
The following operators are available for calculated variables:
Arithmetic Operators
Comparison Operators
Logical Operators
To define a calculated variable, follow these steps:
NOTE: Illume uses parentheses to determine precedence when evaluating calculations.
If “Disable this calculation,” is checked the calculation will not be performed. This option is provided to disable a calculation that may need to re-enable later.
If “Run Time Only,” is checked the calculation’s value will not be stored in the data set. You might mark a calculation as run-time only if it is needed only to output a value that is used in another calculation, or in any situation wherein the outputted value of the calculation is not of interest to you in the dataset. For example, if you create a calculation that outputs “he” or “she” based on a gender variable, it is valueable to pipe from the calculation into a question, but it is not valuable to retain the value of “he” or “she” in your data set.
Illume supports complex expressions that use the ?: operator.
This operator tests an expression and returns one of two values, based on whether the expression is true or false. If the expression before the question mark is true, the expression returns the value before the colon. If it is false, it returns the value after the colon.
A simple way to remember this syntax is: Is this true ? “Yes Value” : “No Value”;
Multiple complex expressions can be included within a single calculation:
For example, this calculation which calculates the cost of an order as the number of items times the cost per item, plus a fixed rate of either $20 or $12 or $8, based on the type of shipping: {Value:NumberOfItems} * {Value:CostPerItem} + ({Value:Shipping} == “Overnight” ? 20 : 0) + ({Value:Shipping} == “3-day” ? 12 : 0) + ({Value:Shipping} == “USPS” ? 8 : 0) Assuming that the Shipping question is required and that participants can choose only one shipping option, one of the three complex expressions will be true, and the other two will be false. The true expression will add either 20 or 12 or 8 to the value of the calculation. The two false expressions will both add 0 to the calculation. Complex expressions are especially useful in calculations that must be applied differently to different participants. For example, calculations of lean body weight and blood alcohol content use different constants for men and women.
See Microsoft’s JScript Language Reference for more information about JScript.
+ (Plus Sign) Used for addition.
– (Minus Sign) Used for subtraction.
* (Asterisk) Used for multiplication.
/ (Forward Slash) Used for division.
math.pow({value:VARNAME}, power);
== Is equal.
!= Is not equal.
< Is less than.
> Is greater than
<= Is less than or equal to
>= Is greater than or equal to
&& And
|| Or
?: If/then/else
While the {Value} tag yields a question’s selected response value, the {RScore} tag yields the reverse score.
To get a question’s reverse score, use the {RScore} with the question id. For example, to get the reverse score of the question SATISFACTION, use the tag {RScore:Satisfaction}.
Reverse scoring is generally used on questions that have both negative and positive items in the scale, though Illume permits reverse scoring of any items.
For questions with numeric scales, the reverse score is the score in the same position at the opposite end of the scale. The following tables illustrate reverse scores for items with numeric scales.
Score | Reverse Score |
-1 | 1 |
0 | 0 |
1 | -1 |
Score | Reverse Score |
1 | 4 |
2 | 3 |
3 | 2 |
4 | 1 |
For Check all that apply questions, the {Score} or {Value} tag gives the number of items checked. The {RScore} tag gives the number of items NOT checked.
For individual checkboxes, the {Score} tag yields a value of 1 if the item is checked and 0 if the item is not checked. The {RScore} yields the opposite values.
For non-question items (such as calculations and pre-loaded variables), the {Score} tag yields the item’s value. The {RScore} tag always yields one of the “not set” values described below.
If a question has not been answered, or has no value, the {RScore} will return one of the following values, depending on the item’s data type:
When text is referenced in a calculation, it is put in parenthesis, as in the examples below.
({Value:Q1}==”California”)?1:0
({Value:gender})==1)?”he”:”she”
More complex Jscript objects can be used within these calculations. A good resource for information regarding this can be found at the following URL:
http://msdn.microsoft.com/en-us/library/ye921ye4%28v=VS.80%29.aspx
Though JScript.NET can be used in date object calculations, date and time calculations can be tricky. Calculations that use the current time must take into account the fact that Illume re-calculates calculated variables every time participants move from one page to the next.
Date calculations are tricky because programmers often make incorrect assumptions about units of time. For example, because the JScript date object uses milliseconds as its unit of time, you might think it’s easy to measure a span of years by converting years to milliseconds and performing simple arithmetic on the milliseconds. This may lead to incorrect calculations, since leap years are longer than standard years.
Months are notoriously irregular. They can have 30 days, or 31, or 28, or in some cases, 29. Days irregular as well. In most parts of the US, the first Sunday in April is a 23-hour day, and the last Sunday in October is a 25-hour day.
Below are some examples utilizing Dates. The following JScript calculates a participant’s age on the date of the survey. This calculation assumes that the variable BIRTHDATE is a variable in the survey that asks for the participant’s date of birth, and that variable is of data type Date:
var today = new Date();
var dob = new Date({Value:BIRTHDATE});
var yearDiff = today.getFullYear() – dob.getFullYear(); var monthDiff = today.getMonth() – dob.getMonth();
var dayDiff = today.getDate() – dob.getDate();
if(monthDiff < 0 || (monthDiff == 0 && dayDiff < 0))
yearDiff–;
yearDiff;
If BIRTHDATE were a text variable, not a Date data type variable, and had the format mm/dd/yyyy, the calculation would be as follows:
var today = new Date();
var dob = {Response:BIRTHDATE} + “”;
var dateParts = dob.split(/\D/);
var month = parseInt(dateParts[0], 10);
var day = parseInt(dateParts[1], 10);
var year = parseInt(dateParts[2], 10);
if(year < 100)
year += 1900;
var yearDiff = today.getFullYear() – year;
var monthDiff = today.getMonth() – ( month – 1);
var dayDiff = today.getDate() – day;
if(monthDiff < 0 || (monthDiff == 0 && dayDiff < 0))
yearDiff–;
yearDiff;
NOTE: The value of the value of the calculated variable is set to the value of the last expression evaluated in the JScript. In the examples above, that is the variable yeardiff. Keep in mind that because Illume uses eval() to evaluate the JScript in calculated variables, a return at the end of the script is not needed.
Illume calculations use parentheses to determine which parts of a calculation should be evaluated first. If the calculation uses only addition and subtraction, parentheses do not matter. If the calculation uses multiplication or division, parentheses matter very much.
Illume will scan a calculation from right to left, evaluating all expressions in parentheses, followed by all multiplication operations, then all division operations, then all addition operations, and finally all subtraction operations.
Note the following examples:
40000 + (2000 * 0.28) = 40000 + 560 = 40560
The correct calculation uses parentheses to add salary and bonus before applying the tax rate.
(({Value:SALARY} + {Value:BONUS}) * {Value:TAXRATE})
Which works out as follows:
(40000 + 2000) * 0.28 = 42000 * 0.28 = 11760
Calculations can be used to test and assemble text values. The following expression tests whether someone typed “California” in response to question Q2:
{Value:Q2} == “California”?1:0
This expression returns a whole number: 1 if the value does equal “California” and 0 if the value does not equal California. Text calculations are not case sensitive. This means the calculation above will be true whether the participant typed California, california, or CALIFORNIA.
The expression below creates an email address by adding @company.com to whatever the user typed in response to the LASTNAME question:
({Value:LASTNAME} + “@company.com”)
The survey calculation DatStat Object consists of many very useful methods that can be called from survey calculations. These methods allow for more capability and flexibility within a survey calculation. Note: The survey calculation editor does not currently color code any of the DatStat object methods. Variable name references used in the DatStat object methods will not be updated when using the survey rename capability unlike the tags (e.g. {Value:GENDER}).
Almost all of the DatStat object methods share the same signatures as those used by our runtime SDK. To make a call just prefix the method or property with “DatStat.” (case sensitive). The methods are also data-type aware so make sure to pass variables of the proper type to them (eg if the method is expecting an integer, do not pass a string to it).
Method Name | Returns | Description |
GetHttpFormElement(name : String) | String | This method retrieves the name of an Http form element. |
var val = DatStat.GetHttpFormElement(‘MYHIDDEN’); | ||
GetParameter(parameterName : String) | String | This method signature is equivalent to the HookContext.GetParameter() method. It retrieves a survey parameter string value. |
var parameter_text = DatStat.GetParameter(‘MYPARAM’); | ||
GetRandomizationMap(variableName : String) | String | This method retrieves the randomization map for a specific variable that is randomized. The value returned is a comma delimited list of ordinals (e.g. 3,1,0,2). |
var order = DatStat.GetRandomizationMap(‘CUSTOMER_EVAL’); | ||
GetResponse(variableName : String) | Object | This method signature is equivalent to the HookContext.GetResponse() method. This method retrieves the response code and is equivalent to using a {Value} tag. |
var val = DatStat.GetResponse(‘Q55’); | ||
GetResponseLabel(variableName : String) | String | This method signature is equivalent to the HookContext.GetResponseLabel() method. This method retrieves the response label. |
var theResponse = DatStat.GetResponseLabel(‘Q55’); | ||
GetUserData(dataName : String) | String | This method signature is equivalent to the HookContext.GetUserData() method. It will return the value for the specified piece of User Data from a participant list. |
var userData= DatStat.GetUserData(‘LOCATION’); | ||
IsOnPage(variableName : String) | Boolean | This method will return true if the item identified by the variableName parameter appears on the page of the set of responses that are being currently processed. |
if(DatStat.IsOnPage(‘Q55’)) { // do something } | ||
PageItemNames() | String[] | This method returns an array of variable names that appear on the page of the set of responses that are currently being processed. |
var items : String[] = DatStat.PageItemNames(); | ||
QuotaCountGet(quotaName : String) | int | This method returns the current count for the specified quota. |
var count = DatStat.QuotaCountGet(‘MALE’); | ||
QuotaLimitGet(quotaName : String) | int | This method returns the quota limit defined for the specified quota. If the current survey session happens to be a test participant then the test data quota limit is returned. |
var limit = DatStat.QuotaLimitGet(‘MALE’); | ||
QuotaStatusGet(quotaName : String) | int | This method returns a ‘0’ or ‘1’ that designates the quota status for the sepecified quota. A value of ‘0’ means that the specified quota hasn’t yet met the limit. A value of ‘1’ means that the specified quota has met or exceeded the quota limit. |
var status = DatStat.QuotaStatusGet(‘MALE’); | ||
ResponseReplacement(input : String) | String | This method signature is equivalent to the HookContext.ResponseReplacement() method. This method replaces all tags to their proper values. |
var surveyName = DatStat.ResponseReplacement(‘{SurveyName}’); | ||
SetResponseData(variableName : String, responseValue : Object) | Boolean | This method signature is equivalent to the HookContext.SetResponseData() method. This method sets a specific variable to a particular value. A value of true is returned if the variable was set properly, otherwise a value of false is returned. Setting a value to ‘blank’ is equivalent to clearing the value. (i.e. DatStat.SetResponse(“Q1”,) ) |
DatStat.SetResponseData(‘Q1’, myvar); | ||
SetUserData(dataName : String, dataValue : String) | void | This method signature is equivalent to the HookContext.SetUserData() method. This method sets a user data field to a particular string value. |
if ( DatStat.GetResponse(‘GENDER’) == 1 ) DatStat.SetUserData(‘PRONOUN’, ‘his’); else DatStat.SetUserData(‘PRONOUN’, ‘her’); |
The problem: You want to know how long it takes participants to complete a specific section of your survey. The solution: Use calculated variables to create timestamps at selected points in the survey. This solution is fairly detailed, and a knowledge of JavaScript or JScript is helpful.
NOTE: Illume automatically records the elapsed time for all surveys. This value is stored in the variable DATSTAT.ELAPSEDTIME and appears in the data dictionary for all surveys in a collection called DATSTAT.INTERNAL. The variable does not show up in the Survey Designer, but it does show up in the Data Manager, where you can easily run queries on it. DATSTAT.ELAPSEDTIME shows the elapsed time for the entire survey, not for individual components of the survey.
You should also keep in mind that the elapsed time may not always be accurate, because participants may stop work on a survey for 10 or 20 minutes at a time. They may even start a survey one day and then log back in three days later to complete it. In this case, the elapsed time will be three days!
Assume your survey contains three collections of questions called SECTION_ONE, SECTION_TWO and SECTION_THREE. You want to know how long it takes participants to complete SECTION_TWO. You can measure the time interval by creating three calculated variables. The first records the time at which Illume received a response to the last question in SECTION_ONE. The second records the time at which Illume received a response to the last question in SECTION_TWO. The third calculates the difference between the first two variables. In order for this work, the last questions in sections one and two must be required, and there must be at least one page break between the two questions to ensure that Illume does not receive both responses at the same time.
To create a timestamp that records when a question was answered, follow these steps:
The formula here (for cutting and pasting) is: ({Value:GENDER} != null && {Value:SECTION_ONE_END} ==
0) ? new Date().getTime() : {Value:SECTION_ONE_END};
Repeat steps 2-7 to create a second calculated variable to record the timestamp at the next milestone question.
You now have two timestamps: one showing when Illume received the answer to the last question in SECTION_ONE and another showing when Illume received the answer to the last question in SECTION_TWO. Follow these steps to create a third variable that calculates the difference between the two.
The formula used to generate the timestamps above does the following:
The formula used to calculate the difference between the two timestamps simply subtracts the earlier time from the later time and divides by 60000. Because the times are measured in milliseconds, the difference between the two times will be in milliseconds. To get the number of minutes, divide the number of milliseconds by 60000.