How to Use the RecalculateFormulas Method of the Formula Class to Update Formula Fields Values at Runtime

ליאור נכתב על ידי ליאור לביא, עודכן בתאריך 20/11/2023

Sometimes when writing code, we may want to refer to the value coming from a formula field. However, when we attempt to access this field to retrieve the value, we discover that it is not up-to-date. This is because formula fields are calculated at the time of accessing the record through the UI, and not during the runtime of our code on the server side.

Example

To understand the issue, let's take a look at the following example for creating a record with a formula field based on a Lookup field.

Account shire = new Account(Name = 'The Shire', Site='Middle-Earth');
insert shire;

Contact bilboBaggins = new Contact(email = 'bbaggins@shire.com', firstName='Bilbo', lastName='Baggins', AccountId=shire.id);

System.debug('Account Site BEFORE Recalculation: ' + bilboBaggins.Account_Site__c); //Will output 'Account Site BEFORE Recalculation: null'

Formula.recalculateFormulas(new List<Contact>{bilboBaggins});

System.debug('Account Site AFTER Recalculation: ' + bilboBaggins.Account_Site__c); //Will output 'Account Site AFTER Recalculation: Middle-Earth'

Explanation

In the above example, we performed the following steps:

  1. Created a new formula field using the UI named "Account Site" on the Contact object, and its value displays the Site of the account from the Account field on the Contact object. Account Site Formula
  2. In the code, we created a new Account with the Name set to 'The Shire' and the Site set to 'Middle-Earth', and inserted it into our database.
    Account shire = new Account(Name = 'The Shire', Site='Middle-Earth');
    insert shire;
  3. Created a Contact record without inserting it into the database.
    Contact bilboBaggins = new Contact(email = 'bbaggins@shire.com', firstName='Bilbo', lastName='Baggins', AccountId=shire.id);
  4. At this point, things are starting to get interesting! In line 6, we ran the System.debug command to print the value that the formula field "Account Site" returns. As you can see, the returned value is Null, even though we populated the AccountId field on our Contact with an account that has a value in the Site field, which is 'Middle-Earth'.
    System.debug('Account Site BEFORE Recalculation: ' + bilboBaggins.Account_Site__c); //Will output 'Account Site BEFORE Recalculation: null'
  5. In line 8, we executed the static method Formula.recalculateFormulas, passing a new list of SObject records, in our case Contacts, with one item in it, the Contact we created for Bilbo Baggins. The recalculateFormulas method takes a list of SObjects as an argument, and Contact is a Sub-Class of SObject.
    Formula.recalculateFormulas(new List<Contact>{bilboBaggins});
  6. In line 10, we ran the System.debug method again, and this time we did receive the value 'Middle-Earth', as the formula field value is recalculated based on the value of the AccountId field.
    System.debug('Account Site AFTER Recalculation: ' + bilboBaggins.Account_Site__c); //Will output 'Account Site AFTER Recalculation: Middle-Earth'

In summary, if your code is using the value of a formula field that is based on other fields that you updated during its execution, make sure to recalculate the formula field value before relying on it for additional logic! 😊