Skip to main content

Operators

Table of contents


Basic operators

Arithmetic operators

The Expression Language supports the basic arithmetic operators for integer and double values. Integer values are converted to doubles automatically:

  • Plus: +
  • Minus:
  • Multiply: *
  • Divide: /
  • Modulo: mod

The mod operator returns the remainder of a division. It works with integer and double values and is commonly used to check divisibility, alternating values (e.g. even/odd), or repeating patterns. It is evaluated with the same precedence as multiplication and division.

Example:

shape.right - shape.left    // equals to shape.width

17 mod 3          // equals 2
7.5 mod 2.0       // equals 1.5

// Even / odd check
10 mod 2          // equals 0
11 mod 2          // equals 1
index mod 2 = 0   // true for even index values

Comparison operators

Comparison operators compare values and return a boolean.

  • Equals: =
  • Not equals: !=
  • Greater than: >
  • Greater than or equals: >=
  • Smaller than: <
  • Smaller than or equals: <=

Example:

shape.bottom >= 200.0

Logical operators

Logical operators work on boolean expressions. They combine conditions or negate their result and always return true or false.

and

The and operator returns true if both operands evaluate to true.

Example:

shape.left > 30.0 and shape.top < 500.0
// true only if both conditions are fulfilled

or

The or operator returns true if at least one operand evaluates to true.

Example:

shape.right >= 200.0 or shape.bottom < 100.0

You can combine multiple logical operators in a single expression. Parentheses can be used to control evaluation order.

Example:

(shape.left > 30.0 and shape.top < 500.0) or shape.right >= 200.0

not

The not operator negates a boolean expression. It can be used to invert the result of the operators in, inside, and intersects.

Examples:

5 not inside 4..6   // false
10 not in [1,2,3]  // true
Rectangle(0.0,0.0,10.0,10.0) not intersects Rectangle(20.0,20.0,30.0,30.0)  // true

Ternary operator

The ternary operator uses the expression ? :.

It acts as a logical if .. then .. else. The expression before the question mark stands for if, the question mark ? stands for then and the colon : for else.

Example:

reference.text = "Datum:" ? "de" : "en"  // If reference.text equals "Datum:"
                                         // then use "de", else use "en" 

You can concatenate ternary operators. 

Example:

reference.text = "Datum:" ? "de" : reference.text = "Fecha" ? "es" : "en"
// If reference.text = "Datum", use "de"
// Else if reference.text = "Fecha", use "es"
// Else use "en"

Coalescence operator

The coalescence operator deals with missing values and uses the ?? sign.

It checks if the previous value is null and acts as a shortcut for if a = null then b else a.

Examples:

prev.left ?? 0.0        // If there is no previous item, prev.left is null.
                        // In this case, use 0.0 instead of null.
                        // If there is a previous item, prev.left is not null.
                        // In this case, use prev.left.
                  
shape.font.size ?? 9.0  // If shape is a path shape, it has no font; shape.font.size is 
                        // therefore null. In this case, use 9.0 as the font size.

Note

The Expression Language has built-in support for null values and handles such cases automatically. Most likely you will not need the coalescence operator in your templates.


Numeric and interval operators

The Expression Language supports several operators that work on numbers and numeric intervals.

Range operator

The range operator uses the .. sign and works with integer or double values.

It creates a range from the first number to the second number, inclusive.

Examples:

1..5      // integer values 1,2,3,4,5
1.0..5.0  // all floating point values from 1.0 to 5.0

Use the inside operator to check whether a value is within a range.

Tolerance operator

The tolerance operator uses the ~ sign and works with double values.

It creates a numeric tolerance range around a base value. The result is an inclusive range that extends the given value by a specified amount, either on both sides or on one side only:

  • ~ spreads the value both below and above 
  • ~+ spreads the value only upwards
  • ~- spreads the value only downwards

This operator is especially useful for handling rounding differences, measurement inaccuracies, or layout tolerances.

Examples:

16.0 ~ 0.5    // equal to 15.5..16.5
16.0 ~+ 0.5   // equal to 16.0..16.5
16.0 ~- 0.5   // equal to 15.5..16.0

Use the inside operator to check whether a value falls within a tolerance range.

Distance operator

The distance operator uses the _ sign and works with integer or double values.

It returns the distance between two integer or double values. Mathematically, the distance operator is equivalent to the absolute value of the difference between a and b: |a-b|.

Examples:

3 _ 5 = 2                        // returns true
this.bottom _ next.top > 2.0     // In a Find sequence node, 
                                 // find paragraphs with a spacing of more than 2 points

Containment and intersection operators

in

The in operator checks whether an element exists within a sequence or a string.

Examples:

1 in [1,2,3]                                       // true
[1,2] in [0,1,2,3]                                 // true
"hello" in "hello world"                           // true
font.name in ["Verdana", "Verdana Bold"]

inside

The inside operator checks whether a value or object lies within an inclusive range or a geometric shape. Inclusive means that the lower and upper bounds of the range are included as well.

Examples:

5 inside 4..6                                     // true
4 inside 4..6                                     // true
6 inside 4..6                                     // true
4.893 inside 4..6                                 // true
4.893 inside 5.0 ~ 1.0                            // true
Point(5,5) inside Rectangle(0,0,10,10)            // true
Rectangle(2,2,5,5) inside Rectangle(0,0,10,10)    // true

intersects

The intersects operator checks whether two rectangles or two ranges overlap. It returns true if there is at least one shared value or area between the operands. Intersection checks are inclusive; shared boundaries count as intersection.

Examples:

Rectangle(10, 10, 100, 40) intersects Rectangle(80, 30, 150, 70)
// true (overlapping area)

Rectangle(0, 0, 50, 50) intersects Rectangle(50, 0, 100, 50)
// true (shared vertical border)

Rectangle(0, 0, 50, 50) intersects Rectangle(0, 60, 50, 100)
// false (gap between rectangles)

10..20 intersects 15..25      // true (common values: 15–20)
1..5 intersects 5..10         // true (shared boundary value: 5)
1..4 intersects 5..10         // false
9.5..10.5 intersects 10..12   // true (10–10.5 overlaps)

Use the inside operator to check whether a point is inside a rectangle.


Sequence and string operators

find

The find operator returns the position of the first occurrence of a subsequence in a sequence as an integer value (zero-based). Since strings are considered sequences of characters, find can also find the first occurrence of one string within another string.

If a subsequence is not found in the sequence, find returns null.

Examples:

[1,2,3,4,5] find [3,4]             // returns 2
"hello world" find "world"         // returns 6
"hello world" find ""              // returns 0
"hello world" find "space"         // returns null

concat

The concat operator concatenates two strings.

Examples:

"hello " concat "world"              // returns "hello world"
"Bill No. " concat reference.text    // Use "Bill No. " as a static text and add a dynamic
                                     // text from the document (reference.text)

slice

The slice operator extracts a substring or subsequence from a string or sequence, based on a range (zero-based).

Examples:

[1, 2, 3, 4, 5, 6] slice 2..4    // returns [3, 4, 5]
"hello world" slice 6..10        // returns "world"

match

The match operator checks whether a string matches a regular expression pattern.

Example:

shape.text match "^Invoice|^Reminder"  // Find all text shapes in the document 
                                       // that start with "Invoice" or "Reminder"

Warning

The match operator can significantly slow down the performance. Only use it if there are no alternative selection options.

We recommend using the in or find operators instead:

"Invoice" in shape.text               // shape.text contains "Invoice" anywhere
shape.text find "Invoice" = 0         // shape.text starts with "Invoice"

// Replace the slow regex match operator of the previous example with this expression:
(shape.text find "Invoice" = 0) or (shape.text find "Reminder" = 0)