Expression
Evaluate formulas through Apex code.
Install / Use
/learn @cesarParra/ExpressionREADME
Powerful formula-syntax evaluator for Apex and LWC.
</div>Features
- Supports all the most important operators and functions available in Salesforce formulas
- Support for lists and maps, including spread operator (
...) support. - Automatically understands relationships and can extract data from child records
- Comment support
- String interpolations
- Pre-built LWC component to evaluate Expressions in record pages and Experience Builder sites
- And much more!
Examples
Basic Math Operations
Object simpleMath = expression.Evaluator.run('(1 + 1) * 10');
System.debug(simpleMath); // 20
Object respectsPemdas = expression.Evaluator.run('1 + 1 * 10 + 50 * 20 / 100 + (20 * 20 /10)');
System.debug(respectsPemdas); // 61
String Operations
Object simpleConcat = expression.Evaluator.run('"👋 hello " + "there!"');
System.debug(simpleConcat); // 👋 hello there!
Id recordId = '001Oy00000GkWjfIAF';
Object interpolation = expression.Evaluator.run('"👋 hello ${Name}"', recordId);
System.debug(interpolation); // 👋 hello Acme Inc.
Advanced Operations
// Calculating if a year is a leap year
Id recordId = '001Oy00000GkWjfIAF';
Object result = expression.Evaluator.run('OR(\n' +
' MOD( YEAR( DATEVALUE(CreatedDate) ), 400 ) = 0, \n' +
' AND( \n' +
' MOD( YEAR( DATEVALUE(CreatedDate) ), 4 ) = 0,\n' +
' MOD( YEAR( DATEVALUE(CreatedDate) ), 100 ) != 0\n' +
' )\n' +
')', recordId);
System.debug(result); // true
// Determining the the region of an address
Id recordId = '001Oy00000GkWjfIAF';
Object result = expression.Evaluator.run('IF(ISBLANK(BillingState), "None",\n' +
'IF(CONTAINS("AK:AZ:CA:HA:NV:NM:OR:UT:WA", BillingState), "West",\n' +
'IF(CONTAINS("CO:ID:MT:KS:OK:TX:WY", BillingState), "Central",\n' +
'IF(CONTAINS("CT:ME:MA:NH:NY:PA:RI:VT", BillingState), "East",\n' +
'IF(CONTAINS("AL:AR:DC:DE:FL:GA:KY:LA:MD:MS:NC:NJ:SC:TN:VA:WV", BillingState), "South",\n' +
'IF(CONTAINS("IL:IN:IA:MI:MN:MO:NE:ND:OH:SD:WI", BillingState), "North", "Other"))))))', recordId);
System.debug(result); // South
Using Lists and Maps
Object listExample = expression.Evaluator.run('[1, 2, 3]');
System.debug(listExample); // (1 2 3)
Object mapExample = expression.Evaluator.run('{"key": "value"}');
System.debug(mapExample); // {key=value}
Piping Complex Operations
Id recordId = '001Oy00000GkWjfIAF';
Object result = expression.Evaluator.run(
'ChildAccounts ' +
'-> WHERE(AnnualRevenue > 200) ' +
'-> WHERE(NumberOfEmployees > 10) ' +
'-> MAP(Name)',
recordId);
System.debug(result); // (Acme Inc. Acme Subsidiary)
Declaring Custom Functions
String expr = 'fun factorial(n) => IF(n = 0 || n = 1, 1, n * factorial(n - 1));\n' +
'\n' +
'factorial(5)';
Object result = Evaluator.run(expr);
System.debug(result); // 120
Documentation
Table of Contents
- Introduction
- Usage
- Language Features
- Standard Library
- Advanced Usage
- Components
For the full Expression language documentation, please visit cesarparra.github.io/expression/.
Contributing
Contributions are welcome! Feel free to open an issue or submit a pull request.
Setup
Create a scratch org by running:
sf org create scratch -f config/dev.json -a Expression --set-default
Push the source to the scratch org:
sf project deploy start
Assign the Expression Admin permission set to the default user:
sf org assign permset -n Expression_Admin
Debugging
While debugging, you might find it helpful to see the generated AST for a given expression.
The source code includes a Visitor implementation
whose sole purpose is to do this, AstPrinter. When enabled, it will
print the AST to the logs.
You can enable it by passing an expression.Configuration option to the run
method with the printAst option enabled :
expression.Configuration config = new expression.Configuration().printAst();
Object value = expression.Evaluator.run('AND(true, false, 1=1)', config);
// Outputs to the logs:
// (AND true false (= 1 1))
Running tests
Run the tests with:
sf apex test run
