Scripting & More Tab - Formula

  • If you have selected formula as your question type, you will enter your formula in the "Formula" field, located in the Scripting and More tab of the eForm Editor.
  • Formulas are especially useful in scored forms, where the final score for the form is the sum, average, etc. of the points accrued while the patient is completing the form.

Generating a total score:

For example, if you were using the PHQ-9 questionnaire, you could put all of your questions into a section called "phq9q" and then use the following formula to calculate the sum of all of the scores in that section:

ScriptUtil.sum(phq9Q)
Copy Rule

To learn how to round your formula answers to the nearest digit, please refer to: "Limiting the Number of Decimal Places in Formula Calculations".

For more examples of possible score calculations and more advanced scripting articles, please refer to:


Scripting & More Tab - Show this field if

  • The "Show this field if" field in the Scripting and More tab of the eForm Editor can be used to show or hide items (or make a clinical note), depending on answers to previous questions or other patient information.
  • Below you will find some examples of what types of scripts can go into this field.

Display a question, based on demographics:

If you are creating a general health assessment form and you want to ask about the possibility of pregnancy, you can choose to only show this field if the patient is female by entering the following into the "Show this field if" field:

pt.isFemale()
Copy Rule

For a full list of available patient-related functions, please refer to: "ScriptPatient ("Pt) Functions".

Display a question, based on how the patient responds to another question:

To determine if a smoking cessation counseling, you can first create an item that asks the patient whether or not they smoke and has item reference: "smoking".

If the answer is yes, you can show the next question, asking about whether or not they are interested in quitting, with the following in the "Show this field if" field:

smoking.r == 'Y'
Copy Rule

Note: .r refers to that item’s response choice (e.g. “N” for no, “Y” for yes).

Analyze a menu-type item:

If you only want to show a follow-up question if a patient picks a menu choice, use the following ".r" value in combination with Javascript's String.indexOf() function in the "Show this field if" field:

myMenuItem.r.indexOf("myAnswer") >= 0
Copy Rule

Note: In the above string, "myAnswer" is the specific menu choice that you wish to flag.


Basics of JavaScript

Basic Code

Symbol Meaning
== equals
!= not equals
|| or
&& and
> greater than
>= greater than or equal to
< less than
<= less than or equal to
() brackets control order of execution
. a period indicates a property of something
Case JavaScript is case-sensitive (i.e. capitalization matters!)

Answer Variable

Any item that's been completed by a patient has 2 useful properties:

  1. Response value ("r")
  2. Point value ("p")

Example: myPainScale, a numeric scale with point values from 0-5.

myPainScale.r
Returns the value associated with the patient's choice (always in standard language, i.e. English)
myPainScale.p
Returns the point value as a number

Script Variables

Variable Description Example Expressions
pt The ScriptPatient object with age, sex, etc.
pt.isMale() && pt.getAge() >= 55

Refer to "ScriptPatient Functions" for more details about more "pt." expressions.

daysSinceLastCompleted The number of day since the patient last complete this form
daysSinceLastCompleted > 365
firstTime Whether or not the patient has ever completed this form
firstTime
lastCompletedTag A string “remembered” by the form last time it was completed
lastCompletedTag.indexOf('myString') != -1

ScriptUtil Functions

ScriptUtil provides miscellaneous functions that allow you to simplify your scripts and support special use-cases. ScriptUtil is bound to all script session contexts, so you can use these functions in tablet rules or within eForms (show if, make note if, etc.).

Please refer to "ScriptUtil Functions" for examples of common ScriptUtil functions.


ScriptPatient ("pt") Functions

The ScriptPatient functions are available on the "pt" object in any script context, such as a tablet rule or within an eForm Action script.

Function Description Example Expression (boolean)
getAge() Returns age in years
pt.getAge() > 40
getAgeInMonths() Returns age in months
pt.getAgeInMonths() > 18
getAgeInWeeks() Returns age in weeks
pt.getAgeInWeeks() > 6
isFemale() Returns true if female, false if not
pt.isFemale()
isMale() Returns true if male, false if not
pt.isMale()
getReasonForVisit() Returns the patient's reason for visit (not supported for all EMRs)
pt.getReasonForVisit() == 'PHE'
getCppItemKeys(cppListKey) Returns a string array of the patient profile items. Available keys will vary by EMR. See Medication Reconciliation eForm for an example of Rx profile item.
pt.getCppItemKeys('rx').length > 0
getCppItemData(cppListKey) Returns a key-value table for a CPP item with a specified list key and item key.
pt.getCppItemData("immu", "influenza virus vaccine")

 


ScriptUtil Functions

ScriptUtil provides miscellaneous functions that allow you to simplify your scripts and support special use-cases. ScriptUtil is bound to all script session contexts, so you can use these functions in tablet rules or within eForms (show if, make note if, etc.).

Variable(s) Description & Example Expression

sum, max, min

Returns the sum/max/min of point values in the section

ScriptUtil.sum(section1Ref) > 10
Copy Example

countAnswersMatching, countAnswersWithPointsEqualTo

The number of answers matching the value or point value in the specified section

ScriptUtil.countAnswersMatching(mySection,'other') > 0
Copy Example

percentComplete

Returns a number between 0 and 100 representing the number of completed items in a section (including nested sections)

ScriptUtil.percentComplete('nutriSTEPQs') == 100
Copy Example

getKeyword

Provides access to any keyword. Used for CPP access and a ‘catch-all’ for access to patient information.

ScriptUtil.getKeyword('@ptClinicDoc') == 'John Smith'
Copy Example

getResponse

Provides access to an answer provided on a previous EForm in the same session.

ScriptUtil.getResponse('mySmokingScreenForm','isCurrentSmoker') == 'Y'
Copy Example

queueContains

(supported on Ocean Tablet only)

Returns true if the form queue (or completed forms) contains the ref passed in.

ScriptUtil.queueContains('phq9')
Copy Example

queueSize

(supported on Ocean Tablet only)

Returns the number of forms in the queue plus any forms that have already been completed.

ScriptUtil.queueSize() == 0
Copy Example

parseDate

Accepts a date string in "yyyy-mm-dd" format and returns a Javascript Date (tablet v127+)

ScriptUtil.parseDate("2015-3-5")
Copy Example

webQ

Displays sections or items for web questionnaires only, not tablets.

ScriptUtil.isWebQ()
Copy Example

 


Using Formula Scripting to Calculate an Average

A hidden formula item can be added to an eForm to calculate the average of certain values collected from the eForm questions.

Generating a simple average is straightforward if you can always assume a fixed number of answered questions (i.e. if you require a response to all questions).

For example, for five questions with refs 'q1', 'q2', 'q3', 'q4', and 'q5', your formula would look like this:

(q1.p + q2.p + q3.p + q4.p + q5.p) / 5
Copy Formula

However, it gets a bit trickier if you only want to count a question when it’s answered. Using the above example, if q3 was left blank, you would only want to divide by 4 when generating the average. That means you need to calculate the denominator by adding 1 for each answered question.

This is what your new formula would look like:

(q1.p + q2.p + q3.p + q4.p + q5.p) / ((q1.r != '' ? 1 : 0) + (q2.r != '' ? 1 : 0) + (q3.r != '' ? 1 : 0) + (q4.r != '' ? 1 : 0) + (q5.r != '' ? 1 : 0))
Copy Formula

The '.r' is the literal response, so:

  • q1.r == '' means the answer is blank.
  • q1.r == 'N' means the answer is 'No'.
  • q1.r == 'Y' means the answer is 'Yes'.

The statements (q1.r != '' ? 1 : 0) are JavaScript shorthand for saying "use 1 if q1.r isn’t empty; otherwise use 0".


Limiting the Number of Decimal Places in Formula Calculations

When developing complex formulas in Ocean eForms, you may find yourself with a large number of decimal places (e.g., 2.342456677543). In order to limit the number of decimal places, simply add '.toFixed(#)' to the end of your formula, where # is the desired number of decimal places.

For example:

Original formula:
(( (6 - q1.p) + (6 - q2.p) + (q3.p) ) / 3)
Copy Formula

This formula would result in an answer such a 2.666667

Revised formula:
(( (6 - q1.p) + (6 - q2.p) + (q3.p) ) / 3).toFixed(2)
Copy Formula

This formula would result in an answer such as 2.67


Advanced JavaScript in Forms ("Fancy Stuff")

Inline Functions

Sometimes, you want a formula or "show if" expression to do really fancy stuff. Perhaps you want to do an "if/then/else" type of expression to decide whether a section of questions resolves to level 1 or level 2. It could be a lot more complicated than that (see the probability of readmission score for an example).

You will find that adding a simple if (x) { return y; } won't work. For example, the following will not work:

(ScriptUtil.sum(mySection) > 5) return 2; else return 1;

The trick is that you need to define and execute a function inline, like this:

function() { if (ScriptUtil.sum(mySection) > 5) return 2; else return 1; }() 
Copy Rule

Technical details

To break this down, this part defines the function:

function() { if (ScriptUtil.sum(mySection) > 5) return 2; else return 1;}

The "()" at the end simply runs the newly defined function.

Date Manipulations

You can create a new Date in Javascript using the "new Date()" call, which returns the current date/time instant. You can use "new Date(2020,2,10)" to create a date for March 10, 2020 (yes, March; the month is confusingly 0-indexed, so January is month 0).

You can call (new Date().getMonth()) to get the current month (0-indexed again, so March == 2).

To compare dates, simply subtract them to obtain the number of milliseconds in between, then divide that difference by (1000*60*60*24) to get the difference in days.

Google "Javascript date reference" for more information.

Advanced Javascript

As long your script evaluates to a single expression, you can do pretty much anything that you can do with Javascript. Some advanced scripting functionality uses an inline function as described above to have a complicated multi-line algorithm wrapped in a single expression.

You can learn more about Javascript using Google (e.g. "how do I compare dates in Javascript?") or by reading a good reference book (e.g. "Javascript: The Good Parts").


Reverse Coding in Ocean eForms

Occasionally, when developing scales using Likert-type questions, you will find yourself needing to reverse code some of the items.

For example, an item such as "I don't like working with computers" scored from 1-5 (where 1 is "strongly disagree" and 5 is "strongly agree"), should be re-coded so that the negative answer is associated with the lower score. Re-coding is especially important if the item is being used in a formula to compute a scale score.

In Ocean, your reverse coding formula would be as follows:

New score = (max + min) - response

For example:

You have provided your patient with a 3-question survey scored on a 5 point-scale. Questions 1 and 2 are reverse coded. You would like to calculate a mean score for the survey.

Survey responses:
  • q1. 5
  • q2. 4
  • q3. 1
Ocean formula:
((6 - q1.p) + (6 - q2.p) + (q3.p)) / 3
Copy Formula

Mean score: ( ( 6 - 5 ) + ( 6 - 4 ) + 1 ) / 3 = 1.33