Tweet |
Image generated by ChatGPT o3 in response to a prompt by Bob Buzzard
Proving yet again AI isn't good at putting text in images!
Introduction
The ability to
evaluate dynamic formulas in Apex, which went GA in the Spring '25 Salesforce release, gets a minor but
very useful improvement in the Summer '25 release - template mode. In this
mode you can use merge syntax to refer to record fields, making formulas that
concatenate strings much easier to specify. Using the example from the
release notes, rather than writing the formula to combine an account
name and website as a clunky concatenation :
name & " (" & website & ")"
we can write:
{!name} ({!website})
and tell the formula builder to evaluate it as a template. This felt like a good addition to my formula tester page, that I created to demonstrate the Spring '25 functionality, and it also uncovered some unexpected behaviour.
The Sample
My formula tester page is updated to allow the user to specify whether the formula should be evaluated as a template or not via a simple checkbox under the text area to input the formula:
I've also tried to make the page helpful and added an onchange handler to the text area that toggles the Formula is template checkbox based on whether the entered text contains the patter {! - note that the user can override this if they need that string literal for some other reason:
There will be code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | @AuraEnabled public static String CheckFormula(String formulaStr, String sobjectType, String returnTypeStr, Id recordId, Boolean formulaIsTemplate) { FormulaEval.FormulaReturnType returnType = FormulaEval.FormulaReturnType.valueof(returnTypeStr); FormulaEval.FormulaInstance formulaInstance = Formula.builder() .withType(Type.forName(sobjectType)) .withReturnType(returnType) .withFormula(formulaStr) .parseAsTemplate(formulaIsTemplate) .build(); //Use the list of field names returned by the getReferenced method to generate dynamic soql Set<String> fieldNames = formulaInstance.getReferencedFields(); Set<String> lcFieldNames= new Set<String>(); for (String fieldName : fieldNames) { lcFieldNames.add(fieldName.toLowerCase()); } if (lcFieldNames.isEmpty()) { lcFieldNames.add( 'id' ); } String fieldNameList = String.join(lcFieldNames, ',' ); String queryStr = 'select ' + fieldNameList + ' from ' + sobjectType + ' where id=:recordId LIMIT 1' ; //select name, website from Account SObject s = Database.query(queryStr); Object formulaResult=formulaInstance.evaluate(s); system.debug(formulaResult); return formulaResult.toString(); } |
1 2 3 4 5 6 7 8 9 | FormulaEval.FormulaInstance formulaInstance = Formula.builder() .withType(Schema.Account. class ) .withReturnType(FormulaEval.FormulaReturnType.STRING) .withFormula( '{!name} {!Name} {!NaMe} {!NAME}' ) .parseAsTemplate( true ) .build(); String fieldNameList = String.join(formulaInstance.getReferencedFields(), ',' ); System.debug( 'Field name list = ' + fieldNameList); |
So I had to add some extra code to iterate the field names, lower case them and add them to a new Set to remove any duplicates. Then I could check if it was empty and if it was add the id field.
You can find the updated code in my Summer 25 samples repository - note that this needs a Salesforce instance on the Summer '25 which, at the time of writing (April 25th), is pre-release orgs. Sandboxes are available on May 9th and scratch orgs on May 11th, assuming Salesforce hit their dates.
More Information
- Repo with sample code
- Evaluate Dynamic Formulas in Apex GA
- Salesforce release notes for this feature