Home Main category Simply CRM Workflow Action Expressions Guide

Simply CRM Workflow Action Expressions Guide

Last updated on Mar 08, 2026

This guide explains the workflow expressions available in Simply CRM for Update fields and related workflow actions that use the same expression engine.

It includes:

  • supported expression syntax

  • available functions

  • practical examples

  • important usage notes


What these expressions are used for

Workflow expressions let a workflow calculate, transform, or retrieve values when it runs.

Typical uses include:

  • filling a field from other fields

  • combining text values

  • calculating dates

  • formatting text

  • applying conditions

  • reading related-record values

  • working with JSON data in advanced workflows


Basic syntax rules

Strings use single quotes

Use:

'Open'

Not:

"Open"

Fields can be referenced directly

Example:

firstname

Expressions can be combined

Example:

concat(firstname, ' ', lastname)

Arithmetic and comparisons are supported

Examples:

amount + 100
quantity * unit_price
amount >= 5000

Conditional logic is supported

Syntax:

if condition then value_if_true else value_if_false end

Example:

if amount > 1000 then 'Large deal' else 'Standard deal' end

Fields from related records can be read directly

Syntax:

(reference_field : (Module) fieldname)

Example:

(account_id : (Accounts) phone)

This reads the phone field from the related Account record referenced by account_id.


Common examples

Use a field value directly

firstname

Returns the value of firstname.


Build a full name

concat(firstname, ' ', lastname)

Example result:

John Smith

Categorize a record by amount

if amount > 1000 then 'Large deal' else 'Standard deal' end

Read a related record field

(account_id : (Accounts) phone)

Returns the related Account phone number.


Supported functions

1. substring(string, start, end)

Returns part of a string.

Example

substring(subject, 0, 10)

Returns the first 10 characters of subject.

Example

substring(accountname, 3, 8)

Returns characters from position 3 to 8.

Note

If used with only 2 parameters, it returns the text from the start position to the end of the string.


2. preg_replace_str_only(pattern, replacement, subject)

Performs a regex replacement on a string.

Example

preg_replace_str_only('/[^0-9]/', '', phone)

Removes all non-numeric characters from a phone number.

Example result

If phone is:

+49 (123) 456-789

Result:

49123456789

3. split(string, separator, index)

Splits a string and returns one part.

Example

split(email, '@', 0)

Returns the part before @.

Example

split(email, '@', 1)

Returns the domain part of the email.

Example result

If email is:

john@example.com

Then:

split(email, '@', 0)

returns:

john

and:

split(email, '@', 1)

returns:

example.com

4. concat(a, b, ...)

Joins multiple values together.

Example

concat(firstname, ' ', lastname)

Result:

John Smith

Example

concat('INV-', invoice_no)

Result:

INV-100045

Note

This function can accept more than two values.

Example:

concat(firstname, ' ', lastname, ' - ', email)

5. time_diff(a, b)

Returns the difference between two date/time values.

Example

time_diff(closingdate, createdtime)

Returns the time difference between closingdate and createdtime.


6. time_diff(a)

Returns the difference between the current date/time and the provided value.

Example

time_diff(duedate)

Useful in advanced date/time calculations.


7. time_diffdays(a, b)

Returns the difference in days between two date/time values.

Example

time_diffdays(closingdate, createdtime)

Returns the number of days between the two dates.


8. time_diffdays(a)

Returns the number of days between now and the provided value.

Example

time_diffdays(duedate)

Useful for overdue or remaining-days logic.


9. add_days(datefield, noofdays)

Adds days to a date.

Example

add_days(closingdate, 7)

Returns a date 7 days after closingdate.

Example

add_days(30)

Returns a date 30 days from today.

Common use

Set a due date 14 days from today:

add_days(14)

10. sub_days(datefield, noofdays)

Subtracts days from a date.

Example

sub_days(closingdate, 3)

Returns a date 3 days before closingdate.

Example

sub_days(10)

Returns the date 10 days before today.


11. add_months(datefield, noofmonths)

Adds months to a date.

Example

add_months(start_date, 1)

Returns a date 1 month after start_date.

Example

add_months(contract_start_date, 12)

Returns the anniversary date one year later.


12. sub_months(datefield, noofmonths)

Subtracts months from a date.

Example

sub_months(contract_end_date, 2)

Returns a date 2 months before contract_end_date.


13. get_date('today')

Returns today’s date.

Example

get_date('today')

14. get_date('tomorrow')

Returns tomorrow’s date.

Example

get_date('tomorrow')

15. get_date('yesterday')

Returns yesterday’s date.

Example

get_date('yesterday')

Common use

Set a field to the current date:

get_date('today')

16. add_time(timefield, minutes)

Adds minutes to a time value.

Example

add_time(time_start, 30)

Returns a time 30 minutes after time_start.

Example

add_time(15)

Returns the current time plus 15 minutes.


17. sub_time(timefield, minutes)

Subtracts minutes from a time value.

Example

sub_time(time_end, 45)

Returns a time 45 minutes before time_end.


18. power(base, exponential)

Raises a number to a power.

Example

power(2, 3)

Returns:

8

Example

power(quantity, 2)

Returns the square of quantity.


19. getDateValue(dateValue, format)

Formats a date/time value.

Example

getDateValue(createdtime, 'd/m/Y')

Formats createdtime as day/month/year.

Example

getDateValue(createdtime, 'l j \of F Y h:i:s A')

Could produce something like:

Monday 4 of March 2026 09:15:22 AM

Example

getDateValue('d/m/Y')

Formats the current date/time using the given format.

Common use

Store a user-friendly date string:

getDateValue(closingdate, 'd.m.Y')

20. str_contains(a, b)

Checks whether two |##|-separated multi-value strings share at least one common value.

Example

str_contains(cf_1234, 'Blue|##|Green')

Returns true if cf_1234 contains either Blue or Green.

Important note

This is not a normal substring search. It is mainly useful for multi-select picklist style values.

Example

If cf_1234 contains:

Red|##|Blue|##|Yellow

then:

str_contains(cf_1234, 'Blue|##|Green')

returns true.


21. RecurrenceRuleAsDates(sourcefield, format, endDate, startDate)

Creates a comma-separated list of dates from a recurrence rule field.

Example

RecurrenceRuleAsDates(recurrence_rule, 'd/m/Y', '31/12/2026', '01/01/2026')

Useful in advanced scheduling or recurrence-based workflows.


22. GetFieldValue(sourcefield)

Returns a field value.

Example

GetFieldValue(firstname)

Returns the value of firstname.

Example with related field

GetFieldValue((account_id : (Accounts) phone))

Returns the phone number from the related Account.

Note

In many simple cases, the field can be used directly without wrapping it in GetFieldValue().


23. GetTime(sourcefield)

Converts a decimal hour value into HH:MM.

Example

GetTime(1.5)

Returns:

01:30

Example

GetTime(hours_worked)

If hours_worked is 2.75, the result would be:

02:45

24. UrlDecode(sourcefield)

URL-decodes a string.

Example

UrlDecode(cf_encoded_text)

If the field contains:

Hello%20World

it returns:

Hello World

25. changeCase(sourcefield, operation)

Changes the letter case of text.

Supported operations:

  • 'upper'

  • 'lower'

  • 'ucfirst'

  • 'ucwords'

Example

changeCase(lastname, 'upper')

Result:

SMITH

Example

changeCase(firstname, 'ucfirst')

Result:

John

Example

changeCase(accountname, 'ucwords')

If the value is:

big blue systems

the result is:

Big Blue Systems

Common use

Normalize all-uppercase imports:

changeCase(firstname, 'ucfirst')

26. searchModule(module, field, operator, value, returnFields)

Searches another module and returns matching records as JSON.

Supported operators:

  • 'equal'

  • 'contains'

  • 'notequal'

Example

searchModule('Contacts', 'email', 'equal', email, '[firstname,lastname,email]')

Searches Contacts where email exactly matches the current record email.

Example

searchModule('Accounts', 'accountname', 'contains', accountname, '[id,accountname,phone]')

Searches Accounts whose account name contains the current record account name.

Note

This is an advanced function, mainly useful for integrations and automation logic.


27. jsonArrayMerge(param1, param2)

Merges two JSON arrays or JSON objects.

Example

jsonArrayMerge('{"a":1}', '{"b":2}')

Result:

{"a":1,"b":2}

Example

jsonArrayMerge(cf_json_part1, cf_json_part2)

Combines two JSON values from fields.


28. json_get(fieldname, key)

Reads a value from JSON using a key path.

Example

json_get(cf_json_payload, 'customer.name')

Returns the nested value of customer.name.

Example

json_get(cf_json_payload, 'items[0].sku')

Returns the sku of the first item in the items array.

Example

If cf_json_payload contains:

{"customer":{"name":"John"}}

then:

json_get(cf_json_payload, 'customer.name')

returns:

John

29. json_set(fieldname, key, value)

Sets or updates a value in JSON.

Example

json_set(cf_json_payload, 'customer.name', firstname)

Updates customer.name using the current record firstname.

Example

json_set(cf_json_payload, 'status', 'Processed')

Sets the top-level status value to Processed.

Example

If cf_json_payload contains:

{"status":"New"}

then:

json_set(cf_json_payload, 'status', 'Processed')

returns updated JSON similar to:

{"status":"Processed"}

30. json_get_line_items(recordId)

Returns line items from an inventory record as JSON.

Example

json_get_line_items(id)

Useful in modules such as:

  • Quotes

  • Sales Orders

  • Purchase Orders

  • Invoices

This is mainly for advanced integrations or JSON transformations.


31. getfieldOptions(Module.fieldname)

Returns the available picklist options for a field as JSON.

Example

getfieldOptions('HelpDesk.ticketstatus')

Returns the available values for the ticketstatus field in HelpDesk.

Note

This is mostly useful in advanced workflows or integrations.


Arithmetic operators

These operators can be used directly in expressions.

Addition

amount + 100

Adds 100 to amount.


Subtraction

amount - discount_amount

Subtracts discount_amount from amount.


Multiplication

quantity * unit_price

Calculates the total from quantity and unit price.


Division

amount / 2

Divides amount by 2.


Comparison operators

These operators can be used inside conditions.

Equal

amount == 1000

Greater than

amount > 0

Less than

amount < 0

Greater than or equal

amount >= 500

Less than or equal

amount <= 2000

Conditional expressions

The expression engine supports if / then / else / end.

Basic example

if bill_country == 'Denmark' then 'DK' else 'Other' end

Another example

if amount >= 10000 then 'Enterprise' else 'SMB' end

Nested example

if amount > 10000 then 'Large' else if amount > 5000 then 'Medium' else 'Small' end

Use nested conditions carefully to keep expressions readable.


Related field syntax

A field from a related record can be read using:

(reference_field : (Module) fieldname)

Example

(contact_id : (Contacts) email)

Returns the email of the related Contact.

Example

(account_id : (Accounts) phone)

Returns the phone number of the related Account.

Practical use

Fill a field on the current record with a value from a linked Account:

(account_id : (Accounts) website)

Practical examples

1. Build a full name

concat(firstname, ' ', lastname)

2. Create a due date 14 days from today

add_days(14)

3. Create a due date 7 days after another date

add_days(closingdate, 7)

4. Convert text to uppercase

changeCase(lastname, 'upper')

5. Capitalize a first name

changeCase(firstname, 'ucfirst')

6. Extract an email domain

split(email, '@', 1)

If email is john@example.com, the result is:

example.com

7. Strip formatting from a phone number

preg_replace_str_only('/[^0-9]/', '', phone)

8. Categorize a deal by amount

if amount >= 10000 then 'Enterprise' else 'SMB' end

9. Pull a related Account phone number

(account_id : (Accounts) phone)

10. Read a value from JSON

json_get(cf_api_response, 'data.customer_id')

11. Format a date for display

getDateValue(closingdate, 'd.m.Y')

12. Prefix a reference number

concat('CASE-', ticket_no)

Important notes

1. Always use single quotes for text

Correct:

'Closed Won'

Incorrect:

"Closed Won"

2. concat() can take multiple parts

Example:

concat(firstname, ' ', lastname, ' (', email, ')')

3. str_contains() is for multi-value strings

It checks overlap in values separated by |##|, not ordinary text search.


4. Some functions are advanced

These are typically used in more advanced workflows or integrations:

  • searchModule()

  • jsonArrayMerge()

  • json_get()

  • json_set()

  • json_get_line_items()

  • getfieldOptions()

  • RecurrenceRuleAsDates()


5. Related-record syntax is especially useful

Example:

(account_id : (Accounts) phone)

This makes it possible to pull values directly from linked records without custom code.


Quick reference

Text functions

  • substring()

  • preg_replace_str_only()

  • split()

  • concat()

  • UrlDecode()

  • changeCase()

Date and time functions

  • time_diff()

  • time_diffdays()

  • add_days()

  • sub_days()

  • add_months()

  • sub_months()

  • get_date()

  • add_time()

  • sub_time()

  • getDateValue()

  • GetTime()

Logic and numeric functions

  • power()

  • if / then / else / end

  • arithmetic operators

  • comparison operators

Related-record access

  • (reference_field : (Module) fieldname)

  • GetFieldValue()

JSON and advanced functions

  • searchModule()

  • jsonArrayMerge()

  • json_get()

  • json_set()

  • json_get_line_items()

  • getfieldOptions()

  • RecurrenceRuleAsDates()


Summary

These workflow expressions support:

  • field-based calculations

  • text formatting

  • date arithmetic

  • conditional logic

  • related-record lookups

  • JSON transformation

  • module search functions

Most commonly used expressions include:

  • concat()

  • changeCase()

  • split()

  • add_days()

  • get_date()

  • if ... then ... else ... end

  • related-record syntax such as (account_id : (Accounts) phone)