Logical Expressions Overview


Logical expressions

Logical expressions are used in filter="..." attributes of the <subq>, <section>, <r>, <other>, <info> , <say> and <do> tags, in the if attribute of the <goto> tag and in dependent range lists.
Logical expressions always evaluate to either "TRUE" or "FALSE".
In general they refer to previous responses/answers in the questionnaire.

E.g. if the questionnaire contains a question about "Gender" that looks like this:

an expression like:

\Q1=1

will evaluate to "TRUE" for "Male" respondents and "FALSE" for "Female" respondents.

A logical expression always contains an "=" (equal) sign. On the left handside you refer to an address of a previously asked question (ques-item). An address always starts with "\" (backslash). In QML you refer to a question by its id (label) and not the actual question number. This means that all questions we want to refer to, must have an "id".
On the right hand side of "=" we have a value or value list. If the referred quest-item has an answer equal to this value or list of values, the expression is "TRUE".

The MI Pro system automatically keeps track of which ques-items have been asked and/or answered through the QR-bits.
As surveys are conducted over time, there might also be questions and answers that have not existed for the whole duration. We might therefore also have "not-existed" represented for ques-items and for answers. "Not-existed" is represented internally as the “illegal” combination of the "QR-bits" being not-asked but answered.

This means that the "QR-bits" have the following meaning:

Q R Meaning
0 0 Not asked, not answered
1 0 Asked, not answered
1 1 Asked and answered
0 1
No existence

Value/value lists

The value or value list can be expressed as follows:

Value Explanation
5 Single value
1;5;8 Discrete list (1 or 5 or 8)
2:5 Interval (from 2 through 5)
1;4;7:10 Combination of discrete list and interval
In addition special codes:
¤ Exists (all QR-bit combinations except "01")
? Asked (QR-bit combination "10" or "11")
* Answered (QR-bit combination "11")
- Not answered (QR-bit combination "10")
% The "%" sign is used when we refer to a subq-type N or M question from a subq-type with ques-items in each row (subq-types f/h/rn/rm/a). The significance here is that for each row we exchange the "%" with the corresponding code from the n/m subq in this row. This means that the expression is evaluated once for each row.
# The "#" sign means count the number of responses. E.g. \10=#3 is "TRUE" if question 10 has exactly 3 responses. \10=#2:6 is "TRUE" if question 10 has between 2 and 6 responses. \10=1:12#3:12 is "TRUE" if question 10 codes 1 through 12 has between 3 and 12 responses. Basic logical expressions can be combined with logical operators "|" (or), "&" (and) and "!" (not) and using parentheses.

E.g. a comlex example:

((\Q10=3)&(\Q11=2:5))|((\Q14=#2:5)&(\Q17=-))

This translates to

Q10=3 AND Q11= 2 or 3 or 5
OR
Q14 has between 2 and 5 answers AND Q17 is not answered

Address

An address to a ques-item consists of up to 3 parts:

  • Question number (always expressed through its ID)
  • Sub question letter (A-Z)
  • Row number (for sub questions with ques-items in each row rn/rm/f/h/a)

An address is always introduced through the "\" (backslash) character. Each component is separated with "." (punctuation mark). When referring within a question, one might skip the question number like this: \.a=2.

One might also combine questions, subqs or rows using ";" or ":" like:
\Q10.a:c=#1:3
Meaning 1 to 3 answers total, in question 10 both subq A, B and C.
When combining questions or subqs (using “;” or “:”the following rules apply:
The questions/subqs must be of the same type.
Only subqtype n/m
Only subqtype rn/rm
Only subqtype f/h
Same number of rows
Same number of codes (rn/rm)

The "%" (percent sign) might be used in place of a row number. In this case the expression is evaluated for each row, and "%" is replaced with the current row number.
The referred question must have at least the same number of rows.

Special addresses

The following special addresses might be used:

\script:NAME(P1,P2...)

This calls an external routine NAME. The parameters provided may be any valid address or a constant. Addresses will be replaced by actual answers, before the routine is called. In this way intricate logic may be implemented. Such scripts must be implemented by MI Pro.

System variables
These variables are described in the section: System Variables


Sample variables
Variables from the sample file, or passed as parameters in the link can also be used directly. These should be preceeded by “\@sms_” .
E.g. If an imported sample has a column labelled “gender”, “\@sms_gender” will refer to this value.

Backward referencing

All expressions in filters etc. have to be backward in the questionnaire. Reference within a block of rotated questions is not allowed (only to other questions guaranteed to come before).

Range expressions (valid answers)

The "range" attribute specifies absolute rules. This means that responses outside of valid ranges are not permitted at all. An example might be a range="15:99" to limit the responses for an age question to ages 15 through 99 years old. Any other value is not possible.

Syntax

Range expressions can be simple or quite complex. The basic part is what we call a "list-part". This consists of a response-value or a list of allowed responses.

List-part Description
4 only 4 is allowed
1:5 responses 1, 2, 3, 4 and 5 are allowed
1;3;8 responses 1, 3 and 8 are allowed
1:3;5;7:9 responses 1, 2, 3, 5, 7, 8 and 9 are allowed
* we must have an answer/response required
- we allow no answer/response
\4 any response from question 4 is allowed
! negates the list
!\4 any response not given to question 4 is allowed
!3:6 3, 4, 5 and 6 are not allowed
rank N The number of type F rows to be ranked
script:NAME(P1, P2..) Call an external routine (NAME). Supply any number of parameters which can be addresses of previous ques-items or constants. The external routine should return the allowable answers. MI Pro must implement such routines.
% Code at current row. Can be used in n/m subqs. Use together with a % for the row part of a conditional construct, meaning evaluate for each row and allow code if condition is "TRUE" Eg. % when \car.%=1:3 The referred question must have at least the same number of rows.
#N or #N:M Number of answers for subq-types m and rm. Sum for subq-type f. N gives number of answers or exact sum. N:M gives an interval. For subq-types m/rm further limitations on which codes to count by prefixing E.g. 1:7#3 meaning 3 answers of codes 1 through 7. For subq-type m, number of asnwers should be checked before moving to next subq. For subq-type rm, check each row. For subq-type f, check the sum of all rows before moving to next subq.

These "range" lists can be combined with logical operators.

E.g.
(1:5)&(\Q3) must be 1, 2, 3, 4, or 5 but also given as response to question 3

(!\Q3.a)|(!\Q5.b) all responses not given to question 3.a or any response given to question 5.b
If a range expression has at least one logical operator then parentheses must be used to group the basic list expressions.
The range list can again be valid under certain circumstances. E.g. One list for “men” and another for “women”.

Conditional Constructs in the Range

There are two conditional constructs:
1. the "when" construct
2. the "try" construct

The "when" construct

This consists of an optional default list followed by one or more "when" lists followed by an optional "else" list (“when” constructs are typically used on single choice questions).

E.g.
(1:5)&(\Q3) must be 1, 2, 3, 4, or 5 but also given as response to question 3

(!\Q3.a)|(!\Q5.b) all responses not given to question 3.a or any response given to question 5.b
If a range expression has at least one logical operator then parentheses must be used to group the basic list expressions.
The range list can again be valid under certain circumstances. E.g. One list for “men” and another for “women”.

The "try" construct

This consists of an optional default list followed by one or more "try" lists (“try” constructs are typically used on multiple choice questions).

E.g.
(1;2) (3) try \3.A=1 (3;5;7) try \3.A=2:4

Default list (1;2) means 1 and 2 are always ok.
3 is ok if response to question 3.A is 1.
3, 5 or 7 is ok if response to question 3.A is 2, 3 or 4.

The "try" construct first inspects the default list if present. Then it will inspect one after the other of the "try" expressions. If the "try" expression evaluates to "TRUE" the list is inspected. If the response is found, everything is ok. If not check the next "try" expression. If a valid response is not found an error message informing the user of an invalid response, should be issued.

System variables

A list of the most relevant system variables is shown below:

Name Description
sys_altid The altid of the interview
sys_computer The computer name (server name)
sys_date The date yyymmdd
sys_dayofweek Day of week 1:Monday
sys_elapsedtime Time in seconds from start
sys_lang Current language
sys_method Method (not relevant anymore, 2 = cawi)
sys_quespos Current question
sys_respguid GUID of interview
sys_random The sys_random variable
sys_rotseed The seed used to generate the random variable
sys_timenowf Current time (servertime) hhmmss
sys_timenowh Current time (servertime) hh/mm
sys_timestartf Start time of interview hhmmss
sys_timestarth Start time of interview hh/mm
sys_week Week number 1-52

fasta cawi-variable:

Name Description
cawi_browser Users browser
cawi_cookies Cookies set in session
cawi_ipaddress IP address of respondent
cawi_language Language of browser
cawi_os OS of respondent
cawi_referer Page refered from
cawi_rspguid
cawi_pagenumcurrent Current page number
cawi_localtimeoffset Time offset respondent vs server
cawi_firstaccesstime Time of first access format YYYY-MM-DD HH:MM:SSZ
cawi_lastaccesstime Time of last access

Scripts:

The following table describes some of the scripts that you can use to create quantitative variables in Research Studio:

VB Script Description
autocode1(filename,text,lookupc,returnc,othercode)
….
autocode4(filename,text1,text2,text3,text4,lookupc,returnc,othercode)
Used to autocode open text based on lookups in an Excel file:
Supply the followiung parameters
  filname - the XLSX file to search, there must be a sheet called Sheet1
  rtext (1..4) - reference to an open question containing one or more rows of text to be coded
  lookupc -vname of column header where to search for text
  return - name of column containing code to be returned
  othercode - code to be assigned category 'other' or '-' to ignore lookups that are not found
codeless1(code) Returns 1:code-1 (typically used in answer control to limit answers to 1 less than the supplied parameter)
codeupton(code) Returns 0:code
codexor(vara, varb) vara and varb is a list of codes. Function returns an XOR between the codes (e.g. returning only the ones that are present in one of the variables.
concat2(a,b)
….
concat8(a,b,c,d,e,f,g,h)
Concatenates the two or more parameters
concat2x(a,b)
….
concat8x(a,b,c,d,e,f,g,h)
Concatenates the two or more parameters, however allows the following character placeholders to be automatically replaced by the proper value:
_AND_SIGN_ "&"
_QUES_SIGN_ "?"
_EQUAL_SIGN_ "=”
_SEMI_SIGN_ ";"
curr_age(born,sysdate) Return current age in years base by subtracting born and sysdate. “born” should be 4 digit year. Systdate should be 8 didgit yyyymmdd format. Typically use \@sys_date as parameter to get todays date.
datetimediff(format,date1,time1,date2,time2) Computs difference in date/time. Formats can be:
"yyyy", "q", "m", "y", "d", "w", "ww", "h", "n" or "s"
Diff(x1,x2,x3) Calculates the difference between two values, x1 and x2. If x1 or x2 is non-numeric, the script alters the value with x3.
Diff0(x1,x2,x3) Calculates the difference between two values, x1 and x2. If x1 or x2 is non-numeric, the script alters the value with x3. If difference is negative, the script returns 0.
Diffneg(x1,x2,x3) Calculates the difference between two values, x1 and x2. If x1 or x2 is non-numeric, the script alters the value with x3. If difference is negative, the script returns the ABSOLUTE VALUE, e.g. positive.
Div2(x1,x2) Divide x1 by x2
echo1(arg1)
echo2(arg1,arg2)
Just returns the value input (used for e.g. testing)
email2(a,b) Concatenate two email addresses with “;” between
EvenOdd(N) Returns 1 if even, 2 if odd number
fromto(fromx,tox) Returns fromx:tox (typically to be used in an answer control to limit min/max value
Hashsum(number) Returns #number (typically to be used in answercontrol to limit number of responses
invitation_qif_altid(qif, altid) Constructs the url: "http://dc.miprocloud.net/dcwebengine/panelsurvey.aspx?qif=" & qif & "&altid=" & altid
invitation_qif_altid_anchor(qif, altid, anchor) Constructs the url above, wrapped in an <a> element with the text set to the “anchor” parameter.
lindex(needle,haystack) Returns the 1 based index of needle found in haystack. Haystack should be a # separated list. “– “returned if not found.
isequal(arg1, arg2) Returns 1 if equal, else 0
lengthOf(istr) Returns length of string
lteq4(p1,p2,p3,p4) Returns 1 if p1<p2<p3<p4 else returns 0
Sum2(x1,x2)
……
Sum12(x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11,x12)
Calculates the sum of two numbers. If any number is non-numeric, it is set to zero.
multiAnswerCount(iStrListe) Returns the number of answers
Mult2(x1,x2)
Mult3(x1,x2,x3)
Multiples the input parameters
Max2(x1,x2)
Max3(x1,x2,x3)
Finds the maximum of two /treenumbers. If any number is non-numeric, it is set to zero.
MaxIndex20 (N1,N2,N3,N4,N5,N6,N7,N8,N9,N10, N11,N12,N13,N14,N15,N16,N17,N18,N19,N20) Finds the index of the maximum number(s) up to 20 parameters. If any number is non-numeric it is set to 0
mktimerandom(xtime,xrandom) Concatenates xtime and xrandom, making sure xrandom is 4 digits (prepends leading 0’s)
Mult2(x1,x2) Multiplies two numbers. If any number is non-numeric, it is set to zero.
quarter(date) Date should be minimum format YYYYMM (typically YYYYMMDD) returns quarter number 1,2,3 or 4.
RandomMulti(lngRangeStart,lngRangeEnd,lngReturnCnt, iSeed) Creates a list of randomly generated codes. Supply start code vale, end code value, number of codes to generate and seed.
redirect_p1(pre,p1n,p1v)
….
redirect_p8(pre,p1n,p1v,p2n,p2v,p3n,p3v,p4n,p4v,p5n,p5v,p6n,p6v,p7n,p7v,p8n,p8v)
Construct redirect links with from 1 to 8 parameters. The redirect links is constructed as follows:
pre&p1n=p1v&p2v=p2n……p8n=p8v
E.g. redirect_p2(‘http://xyz.com/return’,’stat’,’1’,’id’,\id.a.1) will give http://xyz.com/return?stat=1id=1234 (if the id questions contains 1234.
rspidredirect(rspid) Redirects to: http://dc.miprocloud.net/dcwebengine/collect.aspx?rspid=" & rspid
SelectRandomN(x1,x2,x3) Select RANDOM codes from a list:
x1 – Codes to pick from
x2 – Numbers to pick
x3 – A number to initiate the random generator, usually \@sys_random is used to ensure the same sequence the next time around.
selectN(iStrListe,iIntNumberToPick) Select the the n'th codes from a list
SelectFirstN(x1,x2) Select FIRST codes from a list.
x1 – Codes to pick from
x2 – Numbers to pick
select1of5(ind,a,b,c,d,e) Select the element pointed to by “ind”
selectTopXFrom20 (r1,r2,r3,r4,r5,r6,r7,r8,r9,r10, r11,r12,r13,r14,r15,r16,r17,r18,r19,r20 ,topx,maxvalue,random) Find the top X rows from a selection of 20 rows, max value of codes is maxvalue
singleautocode(needle_in, list_in,list_out,not_found) Will look for needle_in, in the # delimted list list_in.
If found it will return the correspondning element from the list_out, else the not_found value is returned
substr(inp, startp, lenp) Return a substring of “inp”
tomax(fromx, maxx) Returns fromx+1:maxx (typically to be used in an answer control to limit min/max value
tomin(tox, minx) Returns minx:tox-1 (typically to be used in an answer control to limit min/max value
TimeDiffSeconds(x1,x2) The TimeDiffSeconds calculates the difference between ANY two timers, e.g. start and end time. Returns time used (in seconds)
x1 = TimeStart
timedifh(fromtimeh, totimeh) Parameters should be in format hhmm, returns difference and accounts for midnight shift (assumes less than 24 hours)