Recalcul des champs de formule Salesforce en Apex
Tags: salesforce, database, french
Published: 2019-09-10 18:16:32

---
title: Recalcul des champs de formule Salesforce en Apex
description: Édition hiver 20
published: true
tags: salesforce,database,french
canonical_url: https://katiekodes.com/apex-recalcul-formules-salesforce/
---

L’édition hiver ‘20 de Salesforce inclue une nouvelle classe Apex `Formule` – regardez ici un exemple de ses capacités.

[James Hou](https://github.com/tsalb) a annoncé, dans [l’excellent résumé de l’édition hiver ‘20 de Salesforce sur Reddit](https://old.reddit.com/r/salesforce/comments/d1qc3r/winter_20_release_notes_abridged_edition/), traduit par [Windyo](https://github.com/Windyo) :

> [Recalcul des formules en Apex](http://releasenotes.docs.salesforce.com/en-us/winter20/release-notes/rn_apex_new_classes_methods.htm#rn_apex_new_classes_methods_new_classes) : c’est ENORME.
> 
> Cette release permet de calculer les formules, en batch, sans opération DML.
> 
> De fait, ça permet donc de laisser les champs formules gérer les calculs un peu complexes, et d’en utiliser les résultats en Apex **_sans sauvegarder_**.

Et c’est vrai !

Voyons un petit exemple :

```java
@isTest
public class UnTest {
	static testMethod void executerTest() {
		ObjetParent __c parent = new ObjetParent__ c(
			Name = 'Un parent',
			Code__c = 'ABAB'
		);
		INSERT parent;
		ObjetEnfant __c enfant = new ObjetEnfant__ c(
			Name = 'Un enfant',
			Code__c = 'XYXY',
			Parent__c = parent.Id
		);
		System.assertEquals(NULL, enfant.Formule_Code_Concatene__c);
		Test.startTest();
		Formula.recalculateFormulas(new List<ObjetEnfant__c>{enfant});
		Test.stopTest();
		System.assertEquals('ABAB|XYXY', enfant.Formule_Code_Concatene__c);
	}
}

```

Notez que l’objet dit «`enfant`» _**n’existe pas**_ dans la base de données.

Je ne l’ai pas encore enregistré avec une commande `INSERT`.

Et quand même, après la commande `Formula.recalculateFormulas()`, le valeur de son champ `Formule_Code_Concatene__c` est `ABAB|XYXY`.

_Notez: Dans ce cas, la formule est:_

```
Parent__r.Code__c & "|" & Code__c

```

---

## Erreur connu

Si vous essayez dans un contexte de déclencheur `BEFORE`, vous verrez peut-être une erreur `System.DmlException` qui annonce `UNKNOWN_EXCEPTION` et `Cannot set the value of a calculated field`.

Jusqu'ici, il me paraî qu'il faut éviter d'exécuter `Formula.recalculateFormulas()` avec les objets `SObject` que vous désirez mettre à jour.

S'il faut lire les contenus du champ de formule `Contact.Formule_1__c` pour décider s'il faut mettre à jour le champs `Contact.Champs_Personnalise__c`, faîtes ainsi :

```java
private void xyzzy(List<Contact> contacts) {
	Map<Contact, Contact> contactsEtLeursCopies = new Map<Contact, Contact>();
	for ( Contact c : contacts ) { contactsEtLeursCopies.put(c, c.clone()); }
	Formula.recalculateFormulas(contactsEtLeursCopies.values());
	for ( Contact c : contacts ) {
		Contact cCopie = contactsEtLeursCopies.get(c);
		if ( cCopie.Formule_1__c == 'Bonjour' ) {
			c.Champs_Personnalise__c = 'le monde';
		}
	}
}
```

Je ne sais pas lequel est plus performant :  une petite requête SOQL ou cet approche-ci de faire des copies des `SObject`.  Qu'en pensez-vous ?