Functions

Modified on Thu, 11 Jun at 2:15 AM

Functions can be used to validate syntax, calculate values, transform data, and control workflow. 


Much of the content below is borrowed and adapted under the Creative Commons license from Get ODK. Note: OpenClinica does not support every function listed on the Get ODK website. Review the full list of functions that have been validated and tested in OpenClinica in the OpenClinica Validated Functions Index.


General Functions

Conditional (if statements)

Description:Evaluates expression, if the expression is true it returns or executes the then statement, if the expression evaluates to false it returns/executes the else statement.
Syntax:if(expression, then, else)
Example:if(${ae_death} = ‘yes’, ‘SAE’, if(${ae_hospital} = 'yes', 'SAE', if(...))) 

This nested if statement will eventually cascade through the entire SAE criteria list to see if any were answered 'Yes', and if so it will return 'SAE', if not then it will move to the next criteria and so-on. The last statement should return 'false' or similar negative value.


Once (run something once)

Description:Returns the value defined by expressionif the question's value is empty. Otherwise, returns the current value of the question.

This can be used to ensure that a random number is only generated once, or to store the first value entered for a question in a way that is retrievable even if the response is changed later.

Syntax:once(expression)
Example:once(today())
When used in a calculation, returns the current date on form loadIf an expression is in a calculation, constraint, or required condition, it is evaluated when the item becomes relevant and the item is not empty. Typically used in calculations.Could also be used in relevant conditions or constraints, but in these cases its usually more clear to use as if() statement. For example:

Instead of using once(), you could also if(. !='', today(), .). If it's not empty, do expression. Otherwise, leave unchanged.


Selected (see if something was selected)

Description:Checks whether string2 appears in string1, where string1 is a space-separated list of values. Either or both could be item references instead of hard-coded string literals.
Syntax:selected(string1, string2)
Example:selected(${diagnoses}, 'cancer')
Returns true if “cancer” was selected from a set of diagnoses. Otherwise, returns false.

not(selected(., 'c') or selected(., 'd'))
Returns true if the user did not choose c or d from the current item.

Note: Can be used as a shortcut for writing many or clauses. For example, selected('a b c d e', .) is a shortcut for ". = 'a' or . = 'b' or ' = 'c' or . = 'd' or . = 'e'." This could be useful in if() statements, relevant logic, etc.


Count Selected (count number of selected choices)

Description:Returns the number of choices selected in a multiple choice question.
Syntax:count-selected(select_multiple_item_name)
Example:count-selected(${days_sick})
Returns the number of days the subject was sick (e.g. from a set of choices ${days_sick} such as Mon, Tue, Wed, etc.).  Taking a space separated string and telling you how many of a given value exist. Can also be used to count the total number of selection choices in a space separated lists. If you concatenate strings together with a space, or join repeating data with a space, in a calculate item, this function would return the total number of items in that string.



Functions for Repeating Data Structures


Max

Description:Returns the largest member of nodeset.

Only works on sets of numbers. Empty values (that is, variables referencing unanswered questions) are actually empty strings, and will not be automatically converted to zero (0). Learn more about Null Values in Form Logic.

Syntax:max(nodeset)
Example:In the below example form definition, the calculation max(${child_age})would return the largest age of all the ages in the repeating item group.

If you wanted to see if one of the children was, say 5 years old, you could use the join or concat function to produce a string of all the responses, then use this string as the argument for the selected function.

For use with repeating item data from a different form, the max function can be used directly as part of the cross-form data pull. In this example, the largest value of the item from all repeats would be returned:

max(instance('clinicaldata')/ODM/ClinicalData/SubjectData/StudyEventData[@StudyEventOID='Event OID Here']/FormData[@FormOID='Form OID Here']/ItemGroupData[@OpenClinica:ItemGroupName='Item Group Name Here']/ItemData[@OpenClinica:ItemName='Item Name Here']/@Value)


typenamelabelcalculation
begin_repeatchild_questionsQuestions about child
textchild_nameChild's name
integerchild_ageChild's age
end_repeat


calculateage_of_oldest_child
max(${child_age})


Min

Description:Returns the smallest member of nodeset. 

Only works on sets of numbers. Empty values (that is, variables referencing unanswered questions) are actually empty strings, and will not be automatically converted to zero (0). Learn more about Null Values in Form Logic.

Syntax:min(nodeset)
Example:In the below example, the calculation min(${child_age}) would return the lowest age of all the ages in the repeating item group.


typenamelabelcalculation
begin_repeatchild_questionsQuestions about child
textchild_nameChild's name
integerchild_ageChild's age
end_repeat


calculateage_of_oldest_child
max(${child_age})


Sum repeats

Description:Returns the sum of the members of nodeset. Can be used to tally responses to a repeated select question.
Syntax:sum(nodeset)
Example:The below example uses this function to tally the number of meal preference.


typenamelabelcalculation
begin_repeatguest_detailsGuest details
textguest_nameGuest name
select_one_meal_optionsmeal_preferenceMeal preference
calculatechkn
if(${meal_preference} = 'chicken', 1, 0 )
calculatefsh
if(${meal_preference} = 'fish', 1, 0 )
calculateveg
if(${meal_preference} = 'vegetarian', 1, 0 )
end_repeat


calculatechkn_count
sum(${chkn})
calculatefsh_count
sum(${fsh})
calculateveg_count
sum(${veg})


Count repeats

Description:Returns the sum of the members of nodeset. Can be used to tally responses to a repeated select question.
Syntax:count(nodeset)
Example:The below example asks the user for the number of family members, then uses the count function to ensure follow-up questions are asked once per each family member.


typenamelabelrepeat_countcalculation
noteperson_list_notePlease list the names of the people in your household.  
begin_repeatpersonMember of household  
textnameName  
end_repeat    
begin_repeatperson_detailsDetailscount(${person}) 
calculatecurrent_name  indexed-repeat(${name}, ${person}, position(..))
datemember_bdayBirthday of ${current_name}  
end_repeat    


Count non-empty repeats

Description:Returns the number of non-empty members of nodeset.
Syntax:count-non-empty(nodeset)
Example:count-non-empty(${bp_sys})
Returns the number of times systolic blood pressure was blank, where ${bp_sys} captures systolic blood pressure inside a repeating group.

If a user adds a repeating group occurrence but does not put data into any of its fields, the count() function would increase by 1, but the count-non-empty() function would not increase.


Indexed Repeat

Description:Returns a particular iteration of a repeating value. 
Syntax:indexed-repeat(item_name, repeating_group_name, iteration)

item_name is the variable you want to retrieve
repeating_group is the name of the repeating group containing the item_name
iteration is the repetition number for the item_name

Example:indexed-repeat(${bp_diastolic}, ${bp_rg}, ${bp_number})

When used as a calculation, returns the diastolic pressure from a specific repeat instance, where:

  • ${bp_diastolic} is the value by the diastolic pressure captured across one or more repetitions
  • ${bp_rg} is the name of the repeating group that collects multiple blood pressure values
  • ${bp_number} is an integer indicating which repetition of the blood pressure to return


Position

Description:Returns an integer equal to the position of the current node within the node defined by xpath. The first entry has a position of 1, second entry 2, and so on. 

Most often this is used in the form position(..) to identify the current iteration within a repeating group.

Syntax:position(xpath)
Example:position(..)
When used as a calculation inside a repeating group, will return the current repeat iteration. Could be used to assign a number for each repetition. In the example below, the first repeating group captures the names of each household member. The second repeating group asks for the birthdate for each household member entered in the first group. This shows how position() can be used with indexed-repeat().


typenamelabelrepeat_countcalculation
begin_repeat  
calculatemed_num  position(..)
textnamePlease enter the name of medication # ${med_num)  
end_repeat    



String functions

Concatenate (combine values)

Description:Concatenates one or more arguments into a single string.

If any arg is a nodeset, the values within the set are concatenated into a string.

Syntax:concat(arg1, arg2, arg3...)
Example:concat(${yyyy},'-',${mm},'-',${dd})
Combines year, month, and day (each captured separately) into a single item formatted YYYY-MM-DD.

concat(${temp},' ⁰C')
Combines temperature value with units label (e.g. to display "37 ⁰C").


Convert to String (transform data type)

Description:Converts arg to a string.
Syntax:string(arg)
string references the item for which you wish to count characters


Regular Expression (validate syntax)

Description:Returns True if the string is an exact and complete match for the expression. Regular expressions provide a standardized way of validating the syntax of data entered.
Syntax:regex(string, expression)

string is the value you want to which you want to apply the regular expression
expression is the regular expression

Example:regex(., '([01][0-9]|2[0-3]):[0-5][0-9]') and string-length(.) = 5
When used as a constraint, ensures the user enters time in 24-hour format (HH:MM)

regex(., '[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}')
When used as a constraint, ensures the user enters an email address in the format xxxx@xxxx.xxxxLearn more about how to construct regular expressions.


Substring (parse a string)

Description:Returns the substring of string beginning at the index start and extending to (but not including) index end (or to the termination of string, if end is not provided).
Syntax:substr(string, start, end)
string references the data item you wish to parse
start is the index number of the beginning character you want to include
end is the index number of the first character after startthat you do NOT want to include

Members of string are zero-indexed, so the first character of the string has index value of 0, the second character an index value of 1, etc.

Example:substr(${date}, 0, 4)
Returns just the 4-digit year from a date field which has a format such as YYYY-MM-DD.


Substring Before (parse a string)

Description:Returns the substring of string before the first occurrence of the target substring.

If the target is not found, or string begins with the target substring, then this will return an empty string.

Syntax:substring-before(string, target)
string references the data item you wish to parse
target is the stopping point (up to which the system will return the partial string)
Example:substr-before(${kit_num}, ‘-’)
If the value of ${kit_num} is "123-ABC-XYZ", the function would return 123. Returns the string value before the first occurrence of the target.


Substring After (parse a string)

Description:Returns the substring of stringafter the first occurrence of the target substring. If the target is not found this will return an empty string.
Syntax:substring-after(string, target)
string references the data item you wish to parse
target is the starting point, beyond which you want the system will return the remaining string
Example:substr-after(${kit_num}, ‘-’)
If the value of ${kit_num} is "112-ABC-XYZ", the function would return ABC-XYZ. Returns the string value after the first occurrence of the target. To return just XYZ, you could run this function two times, nested together. 


String Length (count characters in a string)

Description:Returns the number of characters in string.

If no value is passed in, returns the number of characters in the value of the question that this function call is tied to which can be useful in a constraint expression.

Syntax:string-length(string)
string references the item for which you wish to count characters
Example:substr(., string-length(.) - 4, string-length(.)) = ".pdf" or substr(., string-length(.) - 4, string-length(.)) = ".PDF"

Ensures only PDF files are uploaded when used as a constraint on a file field.

The substing function first gets the last 4 characters of the file name. Then it checks to see if the PDF file extension is all lowercase or uppercase.


Translate

Description:Returns a copy of a string where every occurrence of a specified character is replaced by a new character.
Syntax:translate(string, fromchars, tochars)

string is the item you want to translate
fromchars are the characters, if found within the string, you want to translate
tochars are the characters you want to translate to

If fromchars is longer than tochars then every occurrence of a character in fromchars that does not have a corresponding character in tochars will be removed from the string.

Example:translate(substr(., string-length(.) - 4, string-length(.)), 'pdf', 'PDF') = '.PDF'

When used as a constraint on a file field, ensures the files with a PDF extension are uploaded, regardless of the case in which the file extension is written.

The substing function first gets the last 4 characters of the file name. Then it checks to see if the PDF file extension is all lowercase or uppercase.

translate(${input_item}, 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ') 
Would translate any lowercase letter into an uppercase letter for the string input_item.

OpenClinica reads in cross form data from a select_multiple item as a comma separated list. However, if you want to treat this as a select_multiple value on the form you read it into, it must be treated as a space separated list. For example, the following expression would convert these values into a space separated string upon reading it into the form:

translate(instance('clinicaldata')/ODM/ClinicalData/SubjectData/StudyEventData[@StudyEventOID='Event OID Here']/FormData[@FormOID='Form OID Here']/ItemGroupData[@OpenClinica:ItemGroupName='Item Group Name Here']/ItemData[@OpenClinica:ItemName='Item Name Here']/@Value, ',', ' ') 



Math functions and number handling

Negation

Description:
Syntax:not(expression)
Example:


Truncate decimal

Description:Truncates the fractional portion of a decimal number to return an integer.
Syntax:int(number)
Example:int(${age)

If ${age} = 24.6, would return the value 24.


Convert to Number

Description:Converts argto number value.

If arg is a string of digits, returns the number value.

If arg is True, returns 1. If arg is False, returns 0.

If arg cannot be converted, returns NaN (not a number).

Syntax:number(arg)
Example:number(${year})

if ${year} = "1995", then number(${year}) would return 1995


Round

Description:Rounds a decimal number to some number of decimal places.
Syntax:round(number, # places)
Example:round(${pi}, 4)

If ${pi} = “3.14159”, then round(${pi}, 4) would return 3.1416


Random Number

Description:Returns a random number between 0.0 (inclusive) and 1.0 (exclusive).
Syntax:random()
Example:once(round(random()*3+1,0))

The above expression would return and integer of either 1, 2, or 3, and could thus be used to randomly assign participants to one of three groups.

The following logic could then be used to map the output of the above function to one of the three groups:

if(${rndm} = 1,'A', if(${rndm} = 2,'B', 'C'))



Date and Time

Current Date

Description:Returns the current date without a time component.
Syntax:today()
Example:The expression . <= today() could be used in a constraint to ensure the date entered is not a future date.


Current Date and Time

Description:Returns the current date and time with the timezone.
Syntax:now()
Example:For example, this can be used to set the current date and time as default.


Decimal Time

Description:Converts time to a number representing a fractional day.
Syntax:decimal-time(time)
Example:For example,

decimal-time(12:00)

noon is 0.5 and 6:00 PM is 0.75.


Formatting Dates

Description:Returns date as a string formatted as defined by format.
Syntax:format-date(date, format)
Example:format-date(${date},‘%d-%b-%Y’)

If ${date} = 2028-11-06 would return 06-Nov-2028

Month and day abbreviations are language and locale specific. If form locale can be determined, that locale will be used. Otherwise, the device locale will be used.


%Y4-digit year
%y2-digit year
%m0-padded month
%nnumeric month
%bshort text month (Jan, Feb, Mar…)
%d0-padded day of month
%eday of month
%ashort text day (Sun, Mon, Tue…).


Formatting Date + Time

Description:Returns dateTime as a string formatted as defined by format.
Syntax:format-date-time(dateTime, format)
Example:

 

The identifiers list in format-date() are available, plus the following:

%H0-padded hour (24-hr time)
%hhour (24-hr time)
%M0-padded minute
%S0-padded second
%30-padded millisecond ticks.



Calculations

Power/Exponent

Description:Raises number to a power
Syntax:pow(number, power)
Example:pow(2,3) 

Returns the value 8.


Log

Description:Returns the natural log of number.
Syntax:log(number)
Example:log(30) 

Returns 3.4011973816621555, the natural log of 30.


Log Base-10

Description:Returns the base-10 log of number.
Syntax:log10(number)
Example:log10(30) 

Returns 1.4771212547196624, the base-10 log of 30.


Absolute Value

Description:Returns the absolute value of number.
Syntax:abs(number)
Example:abs(-5.23) 

Returns 5.23.


Was this article helpful?

That’s Great!

Thank you for your feedback

Sorry! We couldn't be helpful

Thank you for your feedback

Let us know how can we improve this article!

Select at least one of the reasons
CAPTCHA verification is required.

Feedback sent

We appreciate your effort and will try to fix the article