Overview

The expression language is used to define dynamic values for component properties and expression Tags. Expressions often involve one or more other values that are used to calculate a final value. In most cases, expressions only return a value.

The classic example for an expression is to change a temperature that is stored in Celsius to Fahrenheit in order to display it. Suppose you had a Tag,Tank 6/Temp, that was in Celsius. If you wanted to display that Tag in Fahrenheit on a Label, you would use an Expression Binding on the label's text property using the following expression:

1.8 * {Tank 6/Temp} + 32

Every time that the temperature Tag changes, the expression will re-calculate the value and push it into the Label's text property. Now lets say that you wanted to append a "°F" to the end of the label so that the user knew the units of the temperature. You could simply use some string concatenation in your expression, like this:

(1.8 * {Tank 6/Temp} + 32) + " °F"

Lets suppose that you wanted to give the user an option to display the value in Celsius or Fahrenheit, based on checking a checkbox. You could add a Check Box component to the screen called DisplayFahrenheit. Then you could use this expression to dynamically display either unit, based upon the user's selection:

if({Root Container.DisplayFahrenheit.selected}, (1.8 * {Tank 6/Temp} + 32) + " °F", {Tankf/Temp} +  " °C")






Syntax

As its name suggests, everything in the expression language is an "expression". This means that everything returns a value5 is an expression. So is 5+1. So are {MyTags/TankLevel} and {MyTags/TankLevel}+1. Expressions can be combined in many powerful ways. Lets take a look at how expressions are written.

More formally, an expression is any one of the following:

  • Number
  • Boolean
  • String
  • Bound Tag
  • Bound property
  • Function call
  • Dataset access
  • Equation involving any of these

Literal Values

Literal values are things like numbers, booleans, and strings that are represented directly in the language. In the expression language, numbers can by typed in directly as integers, floating point values, or using hexadecimal notation with a 0x prefix. Examples:

42
8.456
0xFFC2


Strings are represented by surrounding them with double or single quotes. You can use the backslash character to escape quotes that you want to be included in the string. Examples:

"This is a regular string"
'This one uses single quotes'
"This string uses \"escaping\" to include quotes inside the string"

In addition, the following escape characters are available:

CharacterDescription
\n
New line
\r
Tab
\t
Carriage return


// The words "Hello" and "User" will be placed on separate lines
"Hello\nUser"

// Each "\t" will inject a tab
"Lots\tOf\tSpace"

Operators

You can use these arithmetic, logical, and bit-shifting operators to combine expressions.

OperatorNameDescription
//CommentsAllows for comments following this operator.
-Unary Minus or Subtraction

If both preceeded by a number, then returns a value by subtracting the operand right from the operand on the left of the operator:

If preceded by anything else (or nothing, such as the start of the expression) and is followed by a number, this operator will negate the number.

// This will return 6
10 - 4

// This will return -10
- (15 - 5)


!

Not

Logical opposite of a boolean.
^PowerRaises a number to the power of another number. 
%ModulusModulus or remainder of two numbers. a%b is the remainder of a÷b.
*MultiplyMultiplies the number on the left of the operator by the number on the right of the operator.
/DivideDivides the number on the left of the operator by the number on the right of the operator. 
+Add or Concatenation

If both operands are numbers, this will add them together.

Otherwise treats arguments as strings and performs concatenation.

// This will return 10
4 + 6

// This will return 'FirstSecond'
'First' + 'Second'

// This will return '2Alarms'
2 + 'Alarms'


-SubtractionSubtracts the number on the right of the operator from the number on the left of the operator.  
~Bitwise NOTExamples the bits of an operand, and performs performs logical negation: bits with a value of 0 become 1, and vice versa.
&Bitwise AND

Examines the bits of two operands, and performs a logical AND to each set, comparing the bits in each position from both sets. Returns true for any position where the bits being compared are true.

//		0101
//	AND 0011
//	=	0001


// Performs the bitwise operation above, resulting in the decimal 1
5 & 3


|Bitwise OR

Examines the bits of two operands, and performs a logical OR to each set, comparing the bits in each position from both sets. Returns true for any position where either bit being compared is true. 

//		0101
//	OR	0011
//	=	0111


// Performs the bitwise operation above, resulting in the decimal 7
5 | 3


xorBitwise XOR

Examines the bits of two operands, and performs a logical exclusive OR to each set, comparing the bits in each position from both sets. Returns true for any position where only one of the bits are true.

//		0101
//	XOR	0011
//	=	0110


// Performs the bitwise operation above, resulting in the decimal 6
5 xor 3


<<Left ShiftA signed bitwise left shift.
>>Right ShiftA signed bitwise right shift.
>Greater ThanLogical greater-than test between two numbers. Returns a boolean.
<Less ThanLogical less-than test between two numbers. Returns a boolean.
>=Greater Than or Equal ToTests if the operand on the left is greater or equal to the operand on the right. Returns a boolean.
<=Less Than or Equal ToTests if the operand on the left is less than or equal to the operand on the right. Returns a boolean.
=EqualTests for equality between two operands.
!=Not EqualTests for equality, returning true when not equal.
&&Logical ANDReturns true when both operands are true. Anything non-zero is considered true.
||Logical ORReturns true when either operand is true. Anything non-zero is considered true.
likeFuzzy String MatchingCompares the left-hand value with the pattern on the right side. The pattern may consist of %,*, and ? wildcards.

Bound Values

Bound values are paths to other values enclosed in braces. These will appear red in the expression editor. When you are writing an expression for a Expression Binding in Vision, you can reference Tag values and property values using the brace notation. When you are writing an expression for an Expression Tag, you can only reference other Tag values. You can use the Insert Property icon and Insert Tag  icon to build these references for you.

Dataset Access

If you have an expression that returns a dataset, you can pull a value out of the datatset using the dataset access notation, which takes one of these forms:

Dataset_Expression ["Column_Name"]    //returns the value from the first row at the given column name
Dataset_Expression [Column_Index] //returns the value from the given column at the first row
Dataset_Expression [Row_Index, "Column_Name"] //returns the value from the given row at the given column name
Dataset_Expression [Row_Index, Column_Index] //returns the value from the given row at the given column index


For example, this expression would pull a value out of a Table at row 6 for column "ProductCode":

{Root Container.Table.data}[6, "ProductCode"]


Note that you'll often have to convince the expression system that what you're doing is safe. The expression language can't tell what the datatype will be for a given column, so you may have to use a type-casting function to convince the expression language to accept your expression, like this:

toInt({Root Container.Table.data}[6, "ProductCode"])

Expression Functions

The expression language's functions are where much of the real power lies. A function may take various arguments, all of which can themselves be any arbitrary expression. This means that you can use the results of one function as the argument to another function. In general, the syntax for a function call is:

functionName(expression1, expression2, ...)

Whitespace and Comments

Whitespace, such as spaces, tabs and newlines, are largely ignored in the expression language. It is often helpful to break your expression up onto multiple lines for clarity. Comments are delimited by two forward slashes. This will make the rest of that line be ignored. This example shows an if function spread over 4 lines with comments annotating the arguments.

if( {Root Container.UseTagValueOption.selected},
    {MyTags/SomeValue}, // Use the tag value
    "Not Selected"     // Use default value if the user doesn't check the box
)

Tag Paths

While referencing a tag path in expressions, you may see some special notation, such as "~" and "[.]". More information on this notation can be found on the Understanding Tags page. 


Additional Examples

The following headings demonstrate many simple examples that better demonstrate the Expression Language's syntax. 

String Concatenation

You can use an expression binding to concatenate strings resulting in a new string that reflects the concatenation of different strings.

The function starts with CONCAT() and inside the function is a list of strings. They can be manually typed like "42" or they can come from Tags or properties.

Example 1

concat("The answer is: ", "42") //returns "The answer is: 42"

Example 2

You have a Date, and need to extract the year, and concatenate the word "Vintage" to the end for a label display. Bind a label's text property to: 

 dateExtract({Root Container.VintageDate}, 'year') + ' Vintage'








Celsius to Fahrenheit

Use an expression binding to convert a temperature from Celsius to Fahrenheit. This is an example of how an expression binding can handle calculations.

{celsiusTemp} * 9/5 + 32

The reference to the Celsius temperature can come from a property or a Tag. As the property or the Tag changes, so does the expression binding.







Format Date

You can format a date in an expression binding by using the dateFormat and now functions.

To make a label that updates to show the current time:

  1. Drag a Label component onto the window.
     
  2. Select the label's Text property binding icon and select Expression binding.
     
  3. Enter the following code into the expression, and click OK.

    dateFormat(now(1000), "MMM d, yyyy hh:mm:s a") 

    The dateFormat function takes two arguments. The first argument is any date type variable. This can include another function (like now) that returns a date type. The second argument refers to the date format that you want returned. The now function returns the current time and in this case it will update every second. 
    For more information on the date formatting expression, see the Appendix.








Date Manipulations

You can manipulate dates in expression bindings such as a date addition/subtraction with the dateArithmetic function. This is important when you want to use the expression bindings to select a date that is offset by a certain amount.

The following example will return the time 15 minutes ago by using the dateArithmetic expression function:

 dateArithmetic(now(), -15, "minute")









Bit Functions

You can use various bit functions in expression bindings like getBit to return individual bits of a word.

Example 1

Assuming a tag path 'Folder/BitTag', the following would return the binary representation of the Tag's value at the 0 position

getBit({Folder/BitTag}, 0)

For more details on the getBit function, please see the getBit page in the Appendix. 

Example 2

You have 3 bits in a PLC, only one of which will be on at a time. You want to turn these 3 bits into a single integer (0,1,2) to drive a component's Styles. Bind a custom integer property to:

binEnum({MyTags/Bit1}, {MyTags/Bit2}, {MyTags/Bit3})









Switch

You can use the switch function in expression bindings to evaluate conditional statements. This function acts like the switch statement in C-like programming languages. It takes the value argument and compares it to each of the case1 through caseN expressions.

The following example returns the string "Running" when it is given the value of 1. Its options are 0,1, and 2. And when comparing the value to the options the switch statement returns one of the corresponding results. If a result cannot be found, a fail-over option is returned.

switch(
1,
0, 1, 2,
"Off","Running","Fault",
forceQuality("!BAD STATE!",0))









Checking Conditions

You can use expression bindings to return true or false based on different conditions.

Example 1

Consider the following expression that references the Tag with a path of 'Folder/Machine State':

{Folder/Machine State} = 0

The above expression simply tests the value of the Machine State Tag. If the value of the Machine State Tag is ever equal to 0 then the above expression would return true. In every case where Machine State is not equal to 0, then the expression would return false.  

Example 2

It is possible to check for multiple conditions in the same expression. If you have two boolean Tags and you only want the expression to return true if both Tags are true then the binding would look like:

{boolTag1}=True && {boolTag2}=True 

Example 3

Consider the following expression that references the Tag with a path of 'Folder/Machine State':

if({Folder/Machine State} = 0, 1, 0)

This also finds the opposite of the Machine State if it's a boolean. It returns whether or not the Machine State is 0.