Skip to content
2.36.24

Expression functions ​

This page lists every function you can use in an expression: what it does, what it gives back, the arguments it takes, examples, and the mistakes to look out for. How to write an expression, with variables, texts, numbers and dates, is explained in Expressions. How to work with lists is in its section Lists.

GroupFunctions
Comparisoneq, ne, gt, lt
Logicand, or, not, isTrue, isFalse, isEmpty, ifEmpty, ifNull, if
Mathinc, add, subtract, multiply, divide, round, roundUp, roundDown, sum, avg, min, max, parseInteger, parseDecimal, parseAmount
Textconcat, format, length, contains, containsAny, startsWith, endsWith, match, extract, replace, replaceRegex, trim, lower, upper, padLeft, split, toJson
Listscount, any, first, last, elementAt, filter, select, join, distinct, union, values
Dates and timesnow, today, dateTime, date, time, parseDateTime, parseDate, parseTime, daysBetween, addDays, addWorkingDays

Some rules hold for every function:

  • Arguments are checked as you build. An argument of the wrong type, or too many or too few, shows as a problem under the expression. "Any value" below means that every type is taken.
  • An empty value goes through. Most functions give an empty value, not an error, when they can't do their work. See Empty values.
  • Case doesn't matter when texts are compared: eq("paid", "Paid") is true. This holds for every function that compares or searches text.
  • Dates and numbers read as text are always written the same way, whatever the server's language: 2026-10-22, 14:30:00, 2026-10-22 14:30:00, and 12.5 with a period. Use format for any other form.

Comparison ​

The comparison functions compare two values and give a Boolean. The first argument decides how the second is read: eq({ShipmentNumber}, "17") reads 17 as a number when ShipmentNumber is an Integer. So put the variable first. A second argument that can't be read as the type of the first is a problem as you build: eq({Count}, 1.5), for an Integer Count, says Parameter 2 (Decimal) is not convertable to Integer.

eq ​

Tests whether two values are equal. Returns a Boolean.

  • first: any value.
  • second: a value of the same type, or one that can be read as it.
ExpressionResult
eq("Paid", "PAID")true
eq(42, "42")true
eq(date({Mail.ReceivedAt}), today())true when the mail arrived today
  • Two empty values are equal, and an empty value is never equal to a value. An empty value is not an empty text: eq({Name}, "") is false when Name is empty. Use isEmpty.
  • A date compared with a text is read as the date it is, so eq({Invoice.CreatedAt}, "2026-10-09 10:02:59") matches the file's creation time to the second.

ne ​

Tests whether two values are not equal: the opposite of eq. Returns a Boolean.

  • first: any value.
  • second: a value of the same type, or one that can be read as it.
ExpressionResult
ne("Paid", "Open")true
ne(42, "42")false
  • True when exactly one side is empty, false when both are.

gt ​

Tests whether the first value is greater than the second. Returns a Boolean.

  • first: a number, a text, a date or a time.
  • second: a value of the same type, or one that can be read as it.
ExpressionResult
gt(42, 7)true
gt({Amount}, 10000)true for an amount over 10,000
gt({Invoice.CreatedAt}, '2026-10-01 00:00:00')true for a file created after the start of October
  • Equal values give false, and so does an empty value on either side.
  • Two texts are compared as texts, letter by letter: gt("9", "10") is true. To compare numbers that come in as text, read them first: gt(parseDecimal({Total}), 100).
  • Numbers are compared as numbers, an Integer with a Decimal included. Dates and times are compared as dates and times.

lt ​

Tests whether the first value is less than the second. Returns a Boolean.

  • first: a number, a text, a date or a time.
  • second: a value of the same type, or one that can be read as it.
ExpressionResult
lt(7, 42)true
lt({Invoice.DueDate}, today())true when the due date has passed
  • The same rules as gt: equal values and empty values give false, and two texts are compared as texts.

Logic ​

and, or and not combine conditions, and if chooses between two values. isEmpty, ifEmpty and ifNull deal with empty values. isTrue and isFalse read a value that may arrive as the text true or false.

and ​

Tests whether every condition is true. Returns a Boolean.

  • condition, two or more: each a Boolean, such as a comparison.
ExpressionResult
and(gt({Amount}, 0), eq({VatAmount}, 0))true for a positive amount without VAT
and(true, true, false)false
  • It stops at the first false condition: the ones after it aren't worked out. They are still checked as you build.
  • An empty condition, such as a Boolean variable that was never set, counts as false.

or ​

Tests whether at least one condition is true. Returns a Boolean.

  • condition, two or more: each a Boolean.
ExpressionResult
or(eq({Status}, "New"), eq({Status}, "Reopened"))true for either status
  • It stops at the first true condition. An empty condition counts as false.

not ​

Turns a condition around: true becomes false, and false becomes true. Returns a Boolean.

  • condition: a Boolean.
ExpressionResult
not(isEmpty({OrderNumber}))true when OrderNumber is filled in
not({IsInternal})true when IsInternal is false
  • It takes a Boolean only. For a value that may be a text, such as false, use isFalse.
  • An empty condition gives false, not true.

isTrue ​

Tests whether a value is true, or the text true. Returns a Boolean.

  • value: any value.
ExpressionResult
isTrue({IsInternal})true when IsInternal is true
isTrue("TRUE")true
isTrue("yes")false
  • Only true and the text true, in any case, count. Everything else gives false, an empty value included.
  • isTrue and isFalse are not opposites: both are false for an empty value, or for a text such as yes.

isFalse ​

Tests whether a value is false, or the text false. Returns a Boolean.

  • value: any value.
ExpressionResult
isFalse({IsInternal})true when IsInternal is false
isFalse(contains({Mail.Subject}, "reminder"))true when the subject doesn't contain reminder
  • Unlike not, it takes a value of any type. An empty value gives false.

isEmpty ​

Tests whether a value holds nothing. Returns a Boolean.

  • value: any value, a list included.
ExpressionResult
isEmpty({Comment})true when Comment was never set, or is an empty text
isEmpty(" ")true
isEmpty({Mail.Attachments})true when the mail has no attachments
  • True for an empty value, an empty text, a text of only spaces, and an empty list. 0 and false are values, so they aren't empty.

ifEmpty ​

Gives a value, or a fallback when the value holds nothing. Returns the type of the first argument.

  • value: any value but a list.
  • fallback: a value of the same type, or one that can be read as it.
ExpressionResult
ifEmpty({Reference}, "unknown")unknown when Reference is empty or only spaces
ifEmpty(" ", "Nidaros")Nidaros
ifEmpty(0, 42)0
  • "Holds nothing" means what isEmpty tests. Neither argument may be a list.

ifNull ​

Gives a value, or a fallback when the value was never set. Returns the type of the first argument.

  • value: any value but a list.
  • fallback: a value of the same type, or one that can be read as it.
ExpressionResult
ifNull({Reference}, "unknown")unknown when Reference was never set
ifNull("", "Nidaros")an empty text
ifNull(parseInteger({Quantity}), 0)0 when Quantity doesn't hold a whole number
  • It keeps an empty text, because someone set it. Use ifEmpty to replace that too.
  • The parse… functions and extract give an empty value when they find nothing, so ifNull can supply a default.

if ​

Chooses between two values by a condition. Returns the type of then.

  • condition: a Boolean.
  • then: the value when the condition is true.
  • else (optional): the value when it is false, of the same type as then, or one that can be read as it.
ExpressionResult
if(gt({Amount}, 10000), "Large", "Small")Large for an amount of 12,500
if(isEmpty({Reference}), {Description}, {Reference})Reference, or Description when there is none
if(eq({Pages}, 1), "1 page", concat({Pages}, " pages"))3 pages for 3
  • Without else, a false condition gives an empty value. In a mapping row, that leaves the property out.
  • else must fit the type of then. if({Urgent}, 1.5, 2) works, but if({Urgent}, 2, 1.5) doesn't: a Decimal can't be read as an Integer. Put the Decimal first.
  • then and else are both lists, or neither is. Only the value chosen is worked out.

Math ​

add, subtract, multiply, divide, the rounding functions, sum and avg take Integers and Decimals in any mix, and give a Decimal, also for two whole numbers. An input that takes an Integer needs a whole number back: parseInteger(round(divide({Total}, 3))). An empty argument gives an empty result.

inc ​

Counts an Integer up, by one or by a step. Returns an Integer.

  • value: an Integer.
  • step (optional): an Integer; 1 when left out.
ExpressionResult
inc(41)42
inc(40, 2)42
inc(ifNull({Attempt}, 0))1 the first time, when Attempt was never set
  • An empty value gives 0, not 1: inc({Attempt}) stays at 0 while Attempt is empty. Start it with ifNull, as above.

add ​

Adds two numbers. Returns a Decimal.

  • value, addend: Integers or Decimals.
ExpressionResult
add(40, 2)42
add({Amount}, {ShippingCosts})the amount with shipping
  • To add a number of days to a date, use addDays.

subtract ​

Subtracts the second number from the first. Returns a Decimal.

  • value, subtrahend: Integers or Decimals.
ExpressionResult
subtract(44, 2)42
subtract({Amount}, {Discount})the amount after the discount

multiply ​

Multiplies two numbers. Returns a Decimal.

  • value, factor: Integers or Decimals.
ExpressionResult
multiply(6, 7)42
multiply({Amount}, 1.21)the amount with 21% VAT

divide ​

Divides the first number by the second. Returns a Decimal, so a division that doesn't come out even keeps its fraction.

  • dividend, divisor: Integers or Decimals.
ExpressionResult
divide(10, 4)2.5
divide({Amount}, 1.21)the amount without 21% VAT
divide({Total}, 0)empty
  • Dividing by 0 gives an empty value, not an error.

round ​

Rounds a number to a number of decimals. Returns a Decimal.

  • value: an Integer or a Decimal.
  • digits (optional): an Integer, the number of decimals; 0 when left out.
ExpressionResult
round(3.14159, 2)3.14
round(multiply({Amount}, 1.21), 2)the amount with VAT, to the cent
  • A half rounds away from zero: round(2.5) is 3 and round(-2.5) is -3.
  • A negative digits gives an empty value.

roundUp ​

Rounds a number away from zero, whatever the digits that are dropped, as a spreadsheet's ROUNDUP does. Returns a Decimal.

  • value: an Integer or a Decimal.
  • digits (optional): an Integer; 0 when left out.
ExpressionResult
roundUp(2.01)3
roundUp(3.14159, 2)3.15
roundUp(-2.01)-3

roundDown ​

Rounds a number towards zero, dropping the digits past digits, as a spreadsheet's ROUNDDOWN does. Returns a Decimal.

  • value: an Integer or a Decimal.
  • digits (optional): an Integer; 0 when left out.
ExpressionResult
roundDown(2.99)2
roundDown(3.14159, 2)3.14
roundDown(-2.99)-2

sum ​

Adds up the numbers in a list, or one property of every item. Returns a Decimal.

  • list: a list of numbers, or of items with a number in them.
  • path (optional): the property to add up, as a text, such as "Weight". Needed for a list of items.
ExpressionResult
sum({Amounts})the total of the amounts
sum({Deliveries}, "Weight")the total weight
sum(filter({Lines}, "VatRate", 21), "Amount")the total of the lines at 21% VAT
  • An item without the property, or without a number in it, adds nothing. An empty list gives 0.

avg ​

Works out the average of the numbers in a list, or of one property of every item. Returns a Decimal.

  • list: a list of numbers, or of items with a number in them.
  • path (optional): the property to average, as a text.
ExpressionResult
avg({OrderLines}, "SalesPrice")9.875 for prices of 12.50 and 7.25
  • An item without a number is left out of the average altogether. With no number at all, the result is empty.

min ​

Gives the smallest value in a list, or of one property of every item. Returns the type of the items, or of the property.

  • list: a list.
  • path (optional): the property to compare, as a text. Needed for a list of items.
ExpressionResult
min({Deliveries}, "Weight")the lowest weight
min({OrderLines}, "DeliveryDate")the earliest delivery date
  • The values are compared as numbers when they all are, texts holding a number included ("9" is less than "21"); otherwise as dates when they all are; otherwise as texts.
  • Empty values are left out. An empty list gives an empty value.

max ​

Gives the largest value in a list, or of one property of every item. Returns the type of the items, or of the property.

  • list: a list.
  • path (optional): the property to compare, as a text. Needed for a list of items.
ExpressionResult
max({Lines}, "Quantity")the largest quantity
max({Mail.Attachments}, "CreatedAt")when the newest attachment was created, as a DateTime
  • The same rules as min.

parseInteger ​

Reads a value as a whole number. Returns an Integer, or an empty value when the value isn't a whole number.

  • value: any value but a list.
ExpressionResult
parseInteger(" 007 ")7
parseInteger("42.5")empty
ifNull(parseInteger({Quantity}), 0)0 when Quantity holds no whole number
  • Spaces around a text are ignored. A Decimal without a fraction, such as 42.0, counts.
  • A number with a fraction is not rounded: it gives an empty value. Round it first with round.

parseDecimal ​

Reads a value as a number written with a period. Returns a Decimal, or an empty value when the value isn't a number.

  • value: any value but a list.
ExpressionResult
parseDecimal("8.5")8.5
parseDecimal(42)42
parseDecimal("8,5")empty
  • Only a period separates the decimals, and there is no thousands separator. For an amount written the Dutch way, such as 8,50, use parseAmount.

parseAmount ​

Reads an amount as people write it, the Dutch or the English way. Returns a Decimal, or an empty value when the value isn't an amount.

  • value: any value but a list.
ExpressionResult
parseAmount("12,50")12.50
parseAmount("1.250,00")1250.00
parseAmount("1,250.00")1250.00
  • A separator followed by exactly three digits is a thousands separator: 2.500 and 2,500 are both two thousand five hundred.
  • Thousands must be grouped in threes: 12.3456 is not an amount. 500, is 500, and ,50 is 0.50.
  • A value that already is a number passes through as it is: parseAmount(1.234) is 1.234, not 1234.

Text ​

The text functions read their arguments as text: a number as 12.5, a date as 2026-10-22. Searching and comparing ignores case.

contains, containsAny, startsWith and endsWith don't search a single date, time or date and time: that is a problem as you build. Compare it as a date, or write it as text with format first: startsWith(format({Invoice.CreatedAt}, "yyyy-MM"), "2026-10").

Regular expressions. match, extract and replaceRegex take a pattern, a regular expression in the .NET style. The pattern is found anywhere in the text, ignoring case, unless it starts with ^ or ends with $. Some of its building blocks:

PatternMatches
\d, \d+, \d{4}a digit, one or more digits, exactly four digits
\s*any number of spaces
.any character; \. is a period
^, $the start, the end of the text
[A-Z]one letter
(…)a group, which extract and replaceRegex can refer to

a|b matches either a or b. A pattern typed in that isn't a valid regular expression is a problem as you build.

concat ​

Joins values into one text. Returns a text (String).

  • value, any number: any values.
ExpressionResult
concat("Hello, ", {Name}, "!")Hello, Anna!
concat({OrderId}, ".", {OrderLineId})50.550
  • Empty values add nothing. A complex value, such as a whole Shipment, is skipped: use its properties.
  • concat({Days}) is the simple way to turn a number into a text.

format ​

Writes a value as text in a .NET format. Returns a text (String).

  • value: any value.
  • format: a text: a format such as "0.00", or a pattern in which {0} stands for the value, such as "Invoice {0}" or "{0:D5}".
FormatValueResult
"0.00"2450.52450.50
"N2"2450.52,450.50
"D5"4200042
"dd-MM-yyyy"'2026-10-22'22-10-2026
"yyyy-MM-dd HH:mm"'2026-10-22 14:30:00'2026-10-22 14:30
"Invoice {0}"42Invoice 42

So format({Amount}, "0.00") gives 12.50 for 12.5, and format(today(), "dd-MM-yyyy") gives 22-10-2026.

  • The result is the same on every server: a period for the decimals and a comma between thousands, and day and month names in English. For an amount the Dutch way, replace the period: replace(format({Amount}, "0.00"), ".", ",") gives 12,50.
  • A format that doesn't fit the value, such as D5 for a Decimal, gives the value as plain text.
  • The result is a text, so it can't be compared as a date. Use date for that.

length ​

Counts the characters in a text. Returns an Integer.

  • text: a String, not a list.
ExpressionResult
length("Nidaros")7
length({PostalCode})6 for 1234AB
  • It takes only a text. A number, a date or a list is a problem as you build. To count the items of a list, use count. To test whether a value is filled in, use isEmpty.
  • An empty value gives 0. Spaces count: length(" ") is 2.

contains ​

Tests whether a text contains another, or whether a list holds a value. Returns a Boolean.

  • haystack: any value, or a list.
  • needle: the text to look for.
ExpressionResult
contains({Mail.Subject}, "reminder")true for Second REMINDER
contains({Tags}, "Spider")true when Tags is Nidaros, Spider
contains({Tags}, "Spi")false: in a list, the whole item must match
  • An empty needle never matches. A test against a keyword that isn't filled in doesn't fire.
  • When the first argument is a list, it tests whether one of its items equals the needle, not whether one contains it. To search inside the items, use any with "contains".

containsAny ​

Tests whether a text contains any of a list of texts. Returns a Boolean.

  • haystack: any value, or a list.
  • list: a list of the texts to look for.
ExpressionResult
containsAny({Mail.Subject}, {SkipKeywords})true for a subject with any of the keywords
containsAny({Mail.Subject}, split("urgent;asap", ";"))true for ASAP: invoice 42
  • The second argument must be a list. Empty items in it never match, so a list from split with a separator at the end doesn't match everything.
  • When the first argument is a list too, it tests whether the two lists share an item. See E-mail values for an example.

startsWith ​

Tests whether a value begins with a text. Returns a Boolean.

  • value: any value but a date or a time, read as text.
  • prefix: a text.
ExpressionResult
startsWith({Mail.Subject}, "RE:")true for Re: invoice 42
startsWith(format({Invoice.CreatedAt}, "yyyy-MM"), "2026-10")true for a file created in October 2026
  • An empty prefix never matches.

endsWith ​

Tests whether a value ends with a text. Returns a Boolean.

  • value: any value but a date or a time, read as text.
  • suffix: a text.
ExpressionResult
endsWith({Mail.From.Address}, "@nidaros.nl")true for a sender in that domain
  • An empty suffix never matches.

match ​

Tests whether a value matches a regular expression. Returns a Boolean.

  • value: any value, read as text.
  • pattern: a text, the regular expression.
ExpressionResult
match({Mail.Subject}, "^RE:")true for a subject that starts with RE:
match({Iban}, "^NL\d{2}[A-Z]{4}\d{10}$")true for a well-formed Dutch IBAN
  • Without ^ and $, the pattern may be anywhere: match({Code}, "\d{4}") is true for AB12345.
  • An empty pattern never matches. A pattern from a variable that isn't valid gives false.

extract ​

Gives the part of a value that a regular expression finds. Returns a text (String), or an empty value when nothing is found.

  • value: any value, read as text, or a list.
  • pattern: a text, the regular expression.
  • group (optional): the number of a group in the pattern, counting from 1, or the name of a named group. The whole match when left out.
ExpressionResult
extract("Invoice 2026-0042", "\d{4}-\d{4}")2026-0042
extract("Invoice 2026-0042", "(\d{4})-(\d{4})", 2)0042
ifNull(extract({Mail.Subject}, "order (\d+)", 1), "unknown")unknown when the subject holds no order number
  • The first match counts. Nothing found gives an empty value, so ifNull can supply a default.
  • For a list, the items are tried in order, and the first one that holds a match answers: extract(select({OrderLines}, "Reference"), "PRID:(\d+)", 1).

replace ​

Replaces every occurrence of a text by another. Returns a text (String).

  • value: any value, read as text.
  • search: the text to find, as it is: not a pattern.
  • replacement: the text to put in its place.
ExpressionResult
replace({Description}, "[StudentName]", {StudentName})Contribution Zoë de Vries for Contribution [StudentName]
replace(format({Amount}, "0.00"), ".", ",")12,50
  • The search ignores case, so [studentname] is replaced too.
  • An empty search changes nothing. An empty replacement removes what is found.
  • To fill in more than one placeholder, nest it: replace(replace({Text}, "[Name]", {Name}), "[Number]", {Number}). Or use a template.

replaceRegex ​

Replaces every match of a regular expression by a text. Returns a text (String).

  • value: any value but a list, read as text.
  • pattern: a text, the regular expression.
  • replacement: the text to put in its place. $0 stands for the whole match, $1 for the first group, ${name} for a named group, and $$ for a dollar sign.
ExpressionResult
replaceRegex("Invoice 2026-0042", "\d{4}-(\d{4})", "no. $1")Invoice no. 0042
replaceRegex({Phone}, "\s", "")0612345678 for 06 1234 5678
  • A replacement that holds a $ from a variable is still read as one of the substitutions. Double its dollar signs first: replace({Name}, "$", "$$").
  • A pattern built from a list of terms, such as concat("\b(", join({Terms}, "|"), ")\b"), finds any of them. Characters such as ., ( and + in a term then mean something to the pattern.
  • An empty pattern, or one from a variable that isn't valid, leaves the value as it is.

trim ​

Removes the spaces at the start and the end of a value. Returns a text (String).

  • value: any value, read as text.
ExpressionResult
trim(" Jansen BV ")Jansen BV
eq(trim({Invoice.Name}), trim({Customer.CompanyName}))true when only the spaces differ
  • An empty value gives an empty text.

lower ​

Writes a value in lower case. Returns a text (String).

  • value: any value, read as text.
ExpressionResult
lower("NIDAROS")nidaros
  • Comparisons already ignore case, so lower is for producing a value, not for comparing one. An empty value gives an empty text.

upper ​

Writes a value in upper case. Returns a text (String).

  • value: any value, read as text.
ExpressionResult
upper(trim({Code}))AB12 for ab12 with a space before it
concat(upper({Administration}), " - ", {InvoiceNumber})NIDAROS - 42

padLeft ​

Fills a value up on the left to a length. Returns a text (String).

  • value: any value, read as text.
  • width: an Integer, the length to reach.
  • character (optional): the character to fill with; a space when left out. Only its first character is used.
ExpressionResult
padLeft("42", 5, "0")00042
padLeft({Code}, 4, "0")0007 for 7
  • A value that is already as long as width stays as it is. A width below 0 or above 1000 changes nothing.
  • For a number, format({Number}, "D5") does the same.

split ​

Splits a text into a list at a separator. Returns a list of texts (String).

  • value: any value, read as text.
  • separator: a text.
ExpressionResult
split("Nidaros;Spider", ";")a list of Nidaros and Spider
split("Nidaros ; Spider", ";")the same list: each item is trimmed
count(split("Nidaros;Spider;", ";"))3
  • Empty items are kept, so a separator at the end gives an empty last item.
  • An empty separator gives a list of one item, the whole value.

toJson ​

Writes a value as JSON text, for an HTTP body, a file or a message. Returns a text (String).

  • value: any value, a list or a complex value included.
  • nameCase (optional): how property names are written, typed in as a text: "asIs" (when left out), "camelCase", "pascalCase", "snakeCase" or "kebabCase". It can't be a variable.
nameCaseVATNumberorderLine
asIsVATNumberorderLine
camelCasevatNumberorderLine
pascalCaseVATNumberOrderLine
snakeCasevat_numberorder_line
kebabCasevat-numberorder-line
ExpressionResult
toJson({Order}){"OrderNumber":"SO-1001","Total":12.50}
toJson({Order}, "camelCase"){"orderNumber":"SO-1001","total":12.50}
toJson({Tags})["urgent","reminder"]
  • nameCase applies to every property name, at every depth.
  • Dates are written as "2026-10-22", "14:30:00", and "2026-10-22T14:30:00+02:00". An empty value gives null.
  • The JSON is on one line. Characters such as < and & are written as they are, so don't put the text into an HTML page as it is.

Lists ​

These functions work on a list: a variable marked as a list, a list property such as {Mail.To}, or a function that gives a list, such as filter, select or split. The aggregates sum, avg, min and max are under Math, and contains and containsAny under Text. See also Lists in the chapter on expressions.

  • A path inside these functions is a text in quotes, read from each item: "Weight", "Address.Country". "" is the item itself, for a list of plain values such as texts. A path can't go into a list of its own, and there is no [0].
  • A comparison in any, count and filter is one of "eq", "ne", "gt", "lt", "contains", "startsWith", "endsWith" and "match", typed in as a text. Each means what the function of that name means. Without one, the comparison is eq.
  • An item without the property never matches, whatever the comparison, except "ne", for which it matches. eq against "" doesn't match it either.
  • A function that requires a list says so as you build when it gets one value.

count ​

Counts the items of a list, or the items that match. Returns an Integer.

  • list: a list.
  • path, comparison, value (optional): the property to test, the comparison, and the value to compare with. Give path and value together, with or without comparison.
ExpressionResult
count({Deliveries})how many deliveries there are
count({Deliveries}, "Address.Country", "NL")how many go to the Netherlands
gt(count({Mail.Attachments}, "Extension", "endsWith", "ml"), 0)true for at least one XML or HTML attachment
  • Use count for a list: length counts the characters of a text, and doesn't take a list.
  • A value that isn't a list gives 0.

any ​

Tests whether a list has any items, or any items that match. Returns a Boolean.

  • list: a list.
  • path, comparison, value (optional): as for count.
ExpressionResult
any({Mail.Attachments})true when there is at least one attachment
any({Deliveries}, "Weight", "gt", 100)true when a delivery weighs over 100
any({Tags}, "", "urgent")true when Tags holds urgent
  • any({List}) means the same as gt(count({List}), 0).
  • A path without a value, two arguments in all, is a problem as you build.

first ​

Gives the first item of a list, or the first value of a property. Returns the type of the items, or of the property.

  • list: a list.
  • path (optional): the property to read, as a text.
ExpressionResult
first({Deliveries})the first delivery
first({Mail.To}, "Address")the first recipient's address
first(filter({OrderLines}, "OrderLineId", {Line.OrderLineId}))the order line with that id
  • Empty items, and items without the property, are skipped. An empty list gives an empty value.
  • A single value counts as a list of one. Data converted from XML holds a list of one as the item itself, so first({OrderLine.Products}) reads one product and a list of them alike.

last ​

Gives the last item of a list, or the last value of a property. Returns the type of the items, or of the property.

  • list: a list.
  • path (optional): the property to read, as a text.
ExpressionResult
last({Deliveries})the last delivery
last(split({File.Url}, "/"))the file name at the end of a URL

elementAt ​

Gives the item of a list at a position, counting from 0. Returns Any.

  • list: a list.
  • index: an Integer; 0 is the first item.
ExpressionResult
elementAt({Tags}, 0)Nidaros when Tags is Nidaros, Spider
elementAt(split("A;B;C", ";"), 2)C
  • A position past the end, or below 0, gives an empty value.
  • The result is Any, so the designer doesn't check what it is, and a path can't go on from it: elementAt({Mail.Attachments}, 0).FileName is an error. Select the property first: elementAt(select({Mail.Attachments}, "FileName"), 0). For the first or last item, first and last keep the type.

filter ​

Gives the items of a list that match. Returns a list of the same type as the list.

  • list: a list.
  • path: the property to test, as a text.
  • comparison (optional): the comparison; "eq" when left out.
  • value: the value to compare with.
ExpressionResult
filter({Deliveries}, "Address.Country", "NL")the deliveries to the Netherlands
filter({Mail.Attachments}, "Extension", ".pdf")the PDF attachments, as a list of File
filter(filter({Mail.Attachments}, "Extension", ".pdf"), "Name", "startsWith", "invoice")the PDF attachments whose name starts with invoice
  • The result is a list again, so it can go into count, select, first or another filter.
  • A value that isn't a list gives an empty list.

select ​

Gives one property of every item, as a list of its own. Returns a list of the property's type.

  • list: a list.
  • path: the property to take, as a text, such as "Address" or "Sender.Country".
ExpressionResult
select({Deliveries}, "Recipient")the recipients, as a list of texts
join(select({Mail.To}, "Address"), "; ")orders@nidaros.nl; finance@nidaros.nl
contains(select({Mail.Attachments}, "Name"), "invoice")true when an attachment is named invoice
  • This is how to read through a list, where a path can't: {Mail.To.Address} is an error, select({Mail.To}, "Address") the list of addresses.
  • Items without the property are left out, so count(select(…)) counts values, where count(…) counts items.
  • A path that names a list property, such as select({Mails}, "To"), gives Any.

join ​

Joins the items of a list into one text, with a separator between them. Returns a text (String).

  • list: a list of texts, numbers or Booleans.
  • separator: a text.
ExpressionResult
join({Tags}, ", ")Nidaros, Spider
join(select({Mail.To}, "Address"), "; ")the recipients on one line
  • Items that are complex values, such as e-mail addresses, are skipped without a word: join({Mail.To}, "; ") gives an empty text. Use select first, as in the second example.

distinct ​

Gives a list without repeats, or the different values of one property. Returns a list of the type of the items, or of the property.

  • list: a list.
  • path (optional): the property to take, as a text.
ExpressionResult
distinct({OrderLines}, "VatRate")each VAT rate once
join(distinct({FileNames}), ", ")each file name once, on one line
  • The first of each value is kept, in order. Texts are compared ignoring case, and numbers by their value: 1 and 1.0 are the same.
  • Empty values are left out.

union ​

Puts the items of several lists together, each once. Returns a list of the lists' type, or of Any where they differ.

  • list, one or more: lists.
ExpressionResult
union({Settings.ResultsCc}, {School.ResultsCc})every address in either list, once
union({Tags})Tags without repeats or blanks
  • Repeats are found as by distinct: X@school.nl and x@school.nl are one.
  • Texts are trimmed, and empty items and blank texts are left out. A list that isn't set adds nothing.

values ​

Gives the values of an object's properties, as a list. Returns a list of Any.

  • object: one value, not a list.
ExpressionResult
values({OrderLine.DeliveryAddresses})the delivery addresses, as a list
count(values({OrderLine.DeliveryAddresses}))how many addresses there are
  • For data that names each item, such as XML converted to JSON, where DeliveryAddresses holds a DeliveryAddress1 and a DeliveryAddress2.
  • Anything other than an object, an empty value included, gives an empty list.

Dates and times ​

Now and today are on the clock of the server, or of the organization's time zone where it has one. A date and time that comes in with a time zone, such as 2026-10-09T08:02:59Z, is read as that moment on the same clock.

Text is read as a date in these forms only. A form such as 10/9/2026 is not read, because it could be either day.

KindForms
DateTime2026-10-22 14:30:00, 2026-10-22T14:30:00, 22-10-2026 14:30:00, and ISO 8601 with a time zone
Date2026-10-22, 22-10-2026
Time14:30:00, 14:30

A date with the day first is read day first: 01-02-2026 is 1 February. For other forms, give dateTime, date or time a format.

Two ways to read a date. dateTime, date and time take a text or a date, can use a format, and give the current value without an argument. parseDateTime, parseDate and parseTime take any value, such as a spreadsheet cell or an Any output, and give an empty value for anything that isn't exactly that kind of value, so ifNull can supply a default.

dateTime, date, timeparseDateTime, parseDate, parseTime
Takesa text, a date or a timeany value but a list
Without an argumentthe current valuea problem as you build
A DateTime, for a Date or a Timeits date or time partempty
A formatoptionalnot taken
Spaces around the textpart of the textignored
A text it can't reademptyempty

now ​

Gives the current date and time. It takes no arguments. Returns a DateTime.

ExpressionResult
now()2026-10-22 14:30:00
format(now(), "HH:mm")14:30
  • The same as dateTime().

today ​

Gives the current date. It takes no arguments. Returns a Date.

ExpressionResult
today()2026-10-22
addWorkingDays(today(), 2)2026-10-26, when today is Thursday 22 October 2026
  • The same as date().

dateTime ​

Gives the current date and time, or reads a value as one. Returns a DateTime.

  • value (optional): a text or a DateTime.
  • format (optional): a text, the .NET format the text is in.
ExpressionResult
dateTime("22-10-2026 14:30:00")2026-10-22 14:30:00
dateTime("20261022 143000", "yyyyMMdd HHmmss")2026-10-22 14:30:00
  • A Date isn't taken: it has no time.
  • A format only goes with a text. A text it can't read gives an empty value.

date ​

Gives the current date, reads a value as a date, or takes the date of a DateTime. Returns a Date.

  • value (optional): a text, a Date or a DateTime.
  • format (optional): a text, the .NET format the text is in.
ExpressionResult
date("20261022", "yyyyMMdd")2026-10-22
date('2026-10-22 14:30:00')2026-10-22
eq(date({Mail.ReceivedAt}), today())true when the mail arrived today
  • The result is a Date, which can be compared. format gives a text, which can't be compared as a date.

time ​

Gives the current time, reads a value as a time, or takes the time of a DateTime. Returns a Time.

  • value (optional): a text, a Time or a DateTime.
  • format (optional): a text, the .NET format the text is in.
ExpressionResult
time("14:05")14:05:00
gt(time({Mail.ReceivedAt}), '17:00:00')true for mail that arrived after five

parseDateTime ​

Reads a value as a date and time. Returns a DateTime, or an empty value when the value isn't one.

  • value: any value but a list.
ExpressionResult
parseDateTime("22-10-2026 14:30:00")2026-10-22 14:30:00
parseDateTime("2026-10-22")empty: a date without a time
  • A Date isn't taken for midnight: it gives an empty value.

parseDate ​

Reads a value as a date. Returns a Date, or an empty value when the value isn't one.

  • value: any value but a list.
ExpressionResult
parseDate("9-7-2026")2026-07-09
ifNull(parseDate({Row.Date}), today())today, when the cell holds no date
  • A DateTime, or a text that holds one, gives an empty value. To take the date of a DateTime, use date.

parseTime ​

Reads a value as a time of day. Returns a Time, or an empty value when the value isn't one.

  • value: any value but a list.
ExpressionResult
parseTime("9:30")09:30:00
parseTime("25:00")empty
  • A DateTime gives an empty value. To take the time of a DateTime, use time.

daysBetween ​

Counts the calendar days from one date to another. Returns an Integer.

  • from: a Date or a DateTime.
  • to: a Date or a DateTime.
ExpressionResult
daysBetween('2026-07-01', '2026-07-09')8
daysBetween('2026-07-09', '2026-07-01')-8
gt(daysBetween({LastReminder}, today()), 7)true more than a week after the last reminder
  • The times are dropped first, so the hour of the day never matters, and a Date and a DateTime can be mixed.

addDays ​

Moves a date a number of days forward or back. Returns a Date or a DateTime: the type of date.

  • date: a Date or a DateTime.
  • count: an Integer; negative to go back.
ExpressionResult
addDays('2026-10-22', 14)2026-11-05
addDays(today(), -7)a week ago
lt({Invoice.DueDate}, addDays(today(), 14))true when the invoice is due within two weeks
  • A DateTime keeps its time of day.

addWorkingDays ​

Moves a date a number of working days, Monday to Friday, forward or back. Returns a Date or a DateTime: the type of date.

  • date: a Date or a DateTime.
  • count: an Integer; negative to go back.
ExpressionResult
addWorkingDays('2026-10-22', 2)2026-10-26: Thursday to Monday
addWorkingDays('2026-10-24', 1)2026-10-26: Saturday to Monday
addWorkingDays('2026-10-24', -1)2026-10-23: Saturday to Friday
  • Public holidays aren't known: they count as working days.
  • 0 gives the date itself, even on a Saturday or a Sunday. A DateTime keeps its time of day.

E-mail values ​

An Email variable, such as the one a mail trigger starts a run with, holds a whole message. Its parts are read with a path, such as {Mail.Subject}, and its attachments are files that any activity that takes a File accepts. Below, Mail is an Email variable. Property names aren't case-sensitive: {Mail.Subject} is {mail.subject}.

Email propertyType
Subject, TextBody, HtmlBodyString
FromEmailAddress
To, Cc, Bcc, ReplyToa list of EmailAddress
Attachmentsa list of File
SentAt, ReceivedAtDateTime
IsReadBoolean
Importance, MessageId, Reference, Protocol, FolderString
EmailAddress propertyHolds
Addressjane@contoso.com
NameJane Doe
DisplayJane Doe <jane@contoso.com>, or the address alone when there is no name
File propertyHolds
FileNameinvoice.pdf
Nameinvoice: the file name without its extension
Extension.pdf
ContentType, Keytexts
Sizethe size in bytes, an Integer
CreatedAtwhen the file was downloaded, received or made, a DateTime. Empty for a file stored before Spider recorded it, so use ifNull({Invoice.CreatedAt}, now()).

What works:

ExpressionResult
{Mail.From.Address}jane@contoso.com
{Mail.From.Display}Jane Doe <jane@contoso.com>
any({Mail.To}, "Address", "orders@nidaros.nl")true when that mailbox is a recipient
any({Mail.Cc}, "Name", "Finance")true when Finance is copied
count({Mail.Attachments})how many attachments it has
any({Mail.Attachments}, "Extension", ".pdf")true when a PDF is attached
containsAny(select(filter({Mail.Attachments}, "Extension", ".pdf"), "Name"), select(filter({Mail.Attachments}, "Extension", ".xml"), "Name"))true when a PDF has an XML of the same name
join(select({Mail.To}, "Address"), "; ")the recipients on one line
gt(daysBetween({Mail.ReceivedAt}, today()), 7)true more than a week after it arrived

What doesn't work:

  • {Mail.To.Address} and {Mail.Attachments.FileName}: a path can't go through a list. Use select({Mail.To}, "Address") for the addresses, or any and count to ask whether, or how many: any({Mail.To}, "Address", "orders@nidaros.nl").
  • join({Mail.To}, "; "): this gives an empty text, because an address is not a text but has properties. Select them first: join(select({Mail.To}, "Address"), "; ").
  • elementAt({Mail.Attachments}, 0).FileName: a path can't go on from a function. Use first({Mail.Attachments}, "FileName").
  • contains({Mail.ReceivedAt}, "23:30"): SentAt and ReceivedAt are DateTimes, which the text functions don't search. Compare them as dates, gt({Mail.ReceivedAt}, '2026-10-01 00:00:00'), or write them as text with format first.
  • Expressions: how to write an expression, and the builder.
  • Types: the types, and which value fits where.

Version 2.36.24