When customizing your surveys, you typically need a way to specify the following:
Expression Manager (EM) provides an intuitive way to specifying the logic for each of those features. Nearly anything that you can write as a standard mathematical equation is a valid expression, even if you are calling functions. EM currently provides access to 70 functions, and can be easily extended to support more. It also lets you access your variables using human-readable variable names (the question and answer codes).
Some surveys use "Goto Logic", such that if you answer Question 1 with option C, then jump to Question 5. This approach is very limiting, since is hard to validate, and easily breaks when you have to re-order questions. EM uses a Boolean relevance equation to specify all of the conditions under which a question might be valid. If the question is relevant, then the question is shown, otherwise it is Not Applicable, and the value NULL (basically, "blank") is stored in the database. This is similar to what can be done via the Conditions editor (Set conditions), but EM lets you easily specify much more complex and powerful criteria using the question or answer code.
The following functions are currently available (functions with links mean they are based on the PHP programming language -- and you can read more about functionality by following the link.
In the syntax column the first word describes what data type is returned by the function (so in the first case, abs(number) will return a number/numeric value).
Note: Functions must be wrapped in curly braces ({ } like {abs(number)}
Function | Meaning | Syntax |
---|---|---|
abs | Absolute value | number abs(number) |
acos | Arc cosine | number acos(number) |
addslashes | Quote string with slashes | string addslashes(string) |
asin | Arc sine | number asin(number) |
atan | Arc tangent | number atan(number) |
atan2 | Arc tangent of two variables | number atan2(number, number) |
ceil | Round fractions up | number ceil(number) |
checkdate | Returns true(1) if it is a valid date in gregorian calendar | bool checkdate(month,day,year) |
convert_value | Convert a numerical value using a inputTable and outputTable of numerical values | number convert_value(fValue, iStrict, sTranslateFromList, sTranslateToList) |
cos | Cosine | number cos(number) |
count | count the number of answered (non-blank)questions in the list | number count(arg1, arg12, ..., argN) |
countif | Count the number of answered questions in the list equal the first argument | number countif(matches, arg1, arg2, ... argN) |
countifop | Count the number of answered questions in the list which pass the criteria (arg op value) | number countifop(op, value, arg1, arg2, ... argN) |
date | Format a local date/time | string date(format [, timestamp=time()]) |
exp | Calculates the exponent of e | number exp(number) |
fixnum | Display numbers with comma as radix separator, if needed | string fixnum(number) |
floor | Round fractions down | number floor(number) |
gmdate | Format a GMT date/time | string gmdate(format [, timestamp=time()]) |
html_entity_decode | Convert all HTML entities to their applicable characters (always uses ENT_QUOTES and UTF-8) | string html_entity_decode(string) |
htmlentities | Convert all applicable characters to HTML entities (always uses ENT_QUOTES and UTF-8) | string htmlentities(string) |
expr_mgr_htmlspecialchars | Convert special characters to HTML entities (always uses ENT_QUOTES and UTF-8) | string htmlspecialchars(string) |
expr_mgr_htmlspecialchars_decode | Convert special HTML entities back to characters (always uses ENT_QUOTES and UTF-8) | string htmlspecialchars_decode(string) |
idate | Format a local time/date as integer | string idate(string [, timestamp=time()]) |
if | Excel-style if(test,result_if_true,result_if_false) | if(test,result_if_true,result_if_false) |
implode | Join array elements with a string | string implode(glue,arg1,arg2,...,argN) |
intval | Get the integer value of a variable | int intval(number [, base=10]) |
is_empty | Determine whether a variable is considered to be empty | bool is_empty(var) |
is_float | Finds whether the type of a variable is float | bool is_float(var) |
is_int | Find whether the type of a variable is integer | bool is_int(var) |
is_nan | Finds whether a value is not a number | bool is_nan(var) |
is_null | Finds whether a variable is NULL | bool is_null(var) |
is_numeric | Finds whether a variable is a number or a numeric string | bool is_numeric(var) |
is_string | Find whether the type of a variable is string | bool is_string(var) |
join (New in 2.0 build 130129) | Join elements as a new string | join(arg1, arg2, ... argN) |
list | Return comma-separated list of non-blank values | string list(arg1, arg2, ... argN) |
log | The logarithm of number to base, if given, or the natural logarithm. | number log(number,base=e) |
ltrim | Strip whitespace (or other characters) from the beginning of a string | string ltrim(string [, charlist]) |
max | Find highest value | number max(arg1, arg2, ... argN) |
min | Find lowest value | number min(arg1, arg2, ... argN) |
mktime | Get UNIX timestamp for a date (each of the 6 arguments are optional) | number mktime([hour [, minute [, second [, month [, day [, year ]]]]]]) |
modulo-function | The modulo function is not supported yet. You can use the floor() function instead | floor(x/y)==(x/y) |
nl2br | Inserts HTML line breaks before all newlines in a string | string nl2br(string) |
number_format | Format a number with grouped thousands | string number_format(number) |
pi | Get value of pi | number pi() |
pow | Exponential expression | number pow(base, exp) |
quoted_printable_decode | Convert a quoted-printable string to an 8 bit string | string quoted_printable_decode(string) |
quoted_printable_encode | Convert a 8 bit string to a quoted-printable string | string quoted_printable_encode(string) |
quotemeta | Quote meta characters | string quotemeta(string) |
rand | Generate a random integer | int rand() OR int rand(min, max) |
regexMatch | compare a string to a regular expression | bool regexMatch(pattern,input) |
round | Rounds a number to an optional precision | number round(val [, precision]) |
rtrim | Strip whitespace (or other characters) from the end of a string | string rtrim(string [, charlist]) |
sin | Sine | number sin(arg) |
sprintf | Return a formatted string | string sprintf(format, arg1, arg2, ... argN) |
sqrt | Square root | number sqrt(arg) |
stddev | Calculate the Sample Standard Deviation for the list of numbers | number stddev(arg1, arg2, ... argN) |
str_pad | Pad a string to a certain length with another string | string str_pad(input, pad_length [, pad_string]) |
str_repeat | Repeat a string | string str_repeat(input, multiplier) |
str_replace | Replace all occurrences of the search string with the replacement string | string str_replace(search, replace, subject) |
strcasecmp | Binary safe case-insensitive string comparison | int strcasecmp(str1, str2) |
strcmp | Binary safe string comparison | int strcmp(str1, str2) |
strip_tags | Strip HTML and PHP tags from a string | string strip_tags(str, allowable_tags) |
stripos | Find position of first occurrence of a case-insensitive unicode string (starting by 0, return false if not found) | int stripos(haystack, needle [, offset=0]) |
stripslashes | Un-quotes a quoted string | string stripslashes(string) |
stristr | Case-insensitive strstr | string stristr(haystack, needle [, before_needle=false]) |
strlen | Get string length | int strlen(string) |
strpos | Find position of first occurrence of an unicode string (starting by 0, return false if not found) | int strpos(haystack, needle [ offset=0]) |
strrev | Reverse a string | string strrev(string) |
strstr | Find first occurrence of a string | string strstr(haystack, needle[, before_needle=false]) |
strtolower | Make a string lowercase | string strtolower(string) |
strtotime | Parse about any English textual datetime description into a Unix timestamp | int strtotime(string) |
strtoupper | Make a string uppercase | string strtoupper(string) |
substr | Return part of an unicode string | string substr(string, start [, length]) |
sum | Calculate the sum of values in an array | number sum(arg1, arg2, ... argN) |
sumifop | Sum the values of answered questions in the list which pass the criteria (arg op value) | number sumifop(op, value, arg1, arg2, ... argN) |
tan | Tangent | number tan(arg) |
time | Return current UNIX timestamp | number time() |
trim | Strip whitespace (or other characters) from the beginning and end of a string | string trim(string [, charlist]) |
ucwords | Uppercase the first character of each word in a string | string ucwords(string) |
unique | Returns true if all non-empty responses are unique | boolean unique(arg1, ..., argN) |
Syntax follows normal operator precedence:
Level | Operator(s) | Description |
---|---|---|
1 | () | parentheses for grouping or calling functions |
2 | ! - + | unary operators: not, negation, unary-plus |
3 | * / | times, divide |
4 | + - | plus, minus |
5 | < <= > >= lt le gt ge | relative comparisons |
6 | == != eq ne | equality comparisons |
7 | and | logical AND |
8 | or | logical OR |
9 | = | assignment operator |
10 | , | comma operator |
EM provides read-only access to whichever variables we might need. For backwards compatibility, it provides access to the following:
In addition, EM lets you refer to variables by the Question Code. This is also the variable label used when you export your data to SPSS, R, or SAS. This makes equations easy for everyone to read and validate the logic.
Important: It is only safe to refer to variables that occur in preceding pages or questions.
Furthermore, EM lets you access many properties of the Question:
Syntax | Meaning | Example | Example Result |
---|---|---|---|
Qcode | an alias for Qcode.code (see below) | {implode(',',name,gender)} | 'Tom','M' |
Qcode.code | the selected response code for the question if it is relevant (otherwise blank), or the text value if it is not a coded question | {implode(',',name.code,gender.code)} | 'Tom','M' |
Qcode.NAOK | same as Qcode - Using NAOK means that all or some of the variables are irrelevant (e.g. "Not Applicable" (NA) is alright (OK)). | {gender.NAOK} | 'M' |
Qcode.value | the assessment value for the question if it is relevant (otherwise blank), or the text value if it is not a coded question | {gender.value} | '1' |
Qcode.valueNAOK | same as Qcode.value - see Qcode.NAOK above | {gender.valueNAOK} | '1' |
Qcode.shown | the display value for the question | {implode(',',name.shown,gender.shown)} | 'Tom','Male' |
Qcode.question | the text of the question | {gender.question} | 'What is your gender?' |
Qcode.mandatory | whether the question is mandatory (Y/N) | {gender.mandatory} | 'N' |
Qcode.qid | the internal question number (not the sequential number) | {gender.qid} | 337 |
Qcode.type | the question type | {gender.type} | 'G' |
Qcode.jsName | the correct javascript name for the question, regardless whether declared on or off this page | {gender.jsName} | 'java1827X3X337' |
Qcode.gid | the internal group number (not the sequential number) | {gender.gid} | 3 |
Qcode.qseq | the sequential number of the question, starting from 0 | {gender.qseq} | 5 |
Qcode.gseq | the sequential number of the group, starting from 0 | {gender.gseq} | 1 |
Qcode.relevanceStatus | whether the question is currently relevant (0 or 1) | {gender.relevanceStatus} | 1 |
Qcode.relevance | the question-level relevance equation | {gender.relevance} | '!is_empty(name)' |
Qcode.grelevance | the group-level relevance equation | {gender.grelevance} | 'num_children >= 5' |
Qcode.sgqa | the SGQA value for this question | {gender.sgqa} | '1827X3X337' |