Support formation Rapports Power BI

CALCULATE et transition de contexte

En bref

  • Objectifs : décrire ce que fait CALCULATE ; expliquer la transition de contexte ; prévoir le résultat d'une mesure appelée dans un itérateur ou une colonne calculée ; éviter le piège des lignes en double.
  • Prérequis : « Contextes de ligne et de filtre ».
  • Niveau : intermédiaire à avancé.

Pourquoi ?

Deux formules qui semblent identiques donnent des résultats différents : [Total Ventes] et SUM ( Ventes[Montant] ), pourtant le code exact de la mesure, ne renvoient pas le même chiffre dans une colonne calculée ou dans un FILTER. Ce comportement, appelé transition de contexte, est la principale source d'incompréhension en DAX. Le comprendre permet de lire les formules des pages suivantes (itérateurs, classements, nouveaux clients) et d'éviter des erreurs silencieuses.

Notions clés

CALCULATE en bref

CALCULATE ( <expression> [, <filter1> [, <filter2> [, … ] ] ] )

CALCULATE évalue une expression dans un contexte de filtre modifié par ses arguments. Elle fait deux choses, dans cet ordre :

  1. si elle est appelée dans un contexte de ligne, elle transforme la ligne courante en filtre (transition de contexte) ;
  2. elle applique ensuite ses arguments de filtre : un prédicat (Produit[Couleur] = "Rouge"), une table (FILTER (...), VALUES (...)) ou un modificateur (ALL, REMOVEFILTERS, KEEPFILTERS, USERELATIONSHIP...).

Un filtre sur une colonne remplace le filtre existant sur cette même colonne ; les filtres sur les autres colonnes sont conservés (voir « Contextes de ligne et de filtre »).

La transition de contexte

La transition de contexte transforme un contexte de ligne (« je suis sur la ligne d'Alice ») en contexte de filtre (« ne garder que les données d'Alice »). Elle est déclenchée :

  • explicitement par CALCULATE ou CALCULATETABLE ;
  • implicitement, chaque fois qu'une mesure est appelée dans un contexte de ligne, car toute mesure est enveloppée dans un CALCULATE invisible.

Le jeu de données d'exemple

Table Clients (Alice, Bruno, Chloé), reliée à la table Ventes par une relation un-à-plusieurs sur la colonne Client.

ClientMontant
Alice100
Alice50
Bruno200
Chloé30

Alice totalise 150, Bruno 200, Chloé 30, le total général vaut 380.

Total Ventes = SUM ( Ventes[Montant] )

Exemple

Le PBIP TransitionContexte reproduit ce jeu de données (tables Clients, Ventes et VentesDoublon) sur une page de rapport en quatre blocs : colonnes calculées, données sources, mesure avec itérateur, piège des doublons.

Trois colonnes calculées dans Clients

SUM sans CALCULATE = SUM ( Ventes[Montant] )

Avec CALCULATE = CALCULATE ( SUM ( Ventes[Montant] ) )

Avec mesure = [Total Ventes]
ClientSUM sans CALCULATEAvec CALCULATEAvec mesure
Alice380150150
Bruno380200200
Chloé3803030
  • SUM sans CALCULATE : le contexte de ligne existe (on est sur la ligne d'Alice), mais il ne filtre pas la table Ventes. Résultat : le total général, 380, sur chaque ligne.
  • Avec CALCULATE : CALCULATE convertit la ligne courante en filtre Clients[Client] = "Alice", qui se propage à Ventes par la relation. Résultat : 150 pour Alice.
  • Avec mesure : même résultat que CALCULATE, car la mesure contient un CALCULATE implicite. C'est là que la transition devient « invisible ».

[Capture : Power BI Desktop, vue Table, table Clients avec les trois colonnes calculées du PBIP TransitionContexte]

Le même mécanisme dans une mesure

Objectif : compter les clients ayant acheté plus de 100 €.

Nb clients > 100 (avec mesure) = COUNTROWS ( FILTER ( Clients, [Total Ventes] > 100 ) )

Nb clients > 100 (avec SUM) = COUNTROWS ( FILTER ( Clients, SUM ( Ventes[Montant] ) > 100 ) )
  • Avec la mesure : pour chaque client parcouru par FILTER, la mesure déclenche la transition de contexte ; 150, 200 et 30 sont comparés à 100. Résultat : 2 (Alice et Bruno).
  • Avec SUM : sans CALCULATE, SUM renvoie 380 pour chaque client. Résultat : 3.
  • Seule différence entre les deux formules : une mesure à la place d'une expression nue.

[Capture : page de rapport du PBIP TransitionContexte, les deux cartes Nb clients > 100 affichant 2 et 3]

Le diaporama détaille ce raisonnement, avec le schéma de la ligne Alice :

Transition_de_contexte_DAX

Exemple d'usage réel

La transition de contexte est indispensable dès qu'une mesure doit raisonner élément par élément. Dans le PBIP FonctionsGeneration, la mesure ci-dessous compte les couples pays et produit qui n'ont aucune vente : pour chaque couple créé par CROSSJOIN, la mesure [Montant vente] est évaluée avec le pays et le produit du couple comme filtres.

Couples pays-produit sans vente =
COUNTROWS (
    FILTER (
        CROSSJOIN ( VALUES ( Geographie[Pays] ), VALUES ( Produit[ProduitID] ) ),
        ISBLANK ( [Montant vente] )
    )
)

Avec SUM ( Ventes[Montant] ) à la place de la mesure, aucun couple ne serait vide : chaque ligne verrait le montant total.

Pièges et bonnes pratiques

Pourquoi cela paraît complexe

  • C'est invisible : [Total Ventes] ne contient aucun CALCULATE visible, et pourtant se comporte autrement que SUM ( Ventes[Montant] ).
  • Deux contextes coexistent : on « est » sur une ligne sans pour autant « filtrer » sur cette ligne. Cette nuance n'existe pas dans Excel, où une formule de ligne ne voit que sa ligne.
  • Le résultat dépend du lieu d'évaluation : la même mesure donne 380 dans une carte, 150 sur la ligne Alice d'un tableau, et sert de test ligne à ligne dans un FILTER.
  • La propagation passe par les relations : il faut connaître le sens du filtre et la cardinalité pour prévoir le résultat.
  • Le coût en performance : dans un itérateur sur une grande table, la transition est exécutée à chaque ligne et peut ralentir fortement un rapport.

Piège classique : les lignes en double

La transition filtre sur toutes les colonnes de la ligne, pas seulement sur la clé. Dans la table VentesDoublon du PBIP, deux lignes sont strictement identiques (Bruno, 200) :

Avec transition = CALCULATE ( SUM ( VentesDoublon[Montant] ) )

Cette colonne calculée affiche 400 sur chacune des deux lignes Bruno : le filtre Client = "Bruno" ET Montant = 200 laisse passer les deux lignes identiques.

[Capture : vue Table du PBIP TransitionContexte, table VentesDoublon, les deux lignes Bruno affichent 400 dans la colonne Avec transition]

  • Réservez la transition de contexte aux tables qui ont une clé unique : tables de dimension comme Clients, Produits, Calendrier.
  • Évitez d'appeler une mesure dans un itérateur sur une table de faits volumineuse.
  • Dans un itérateur ou une colonne calculée, demandez-vous toujours : « est-ce que j'appelle une mesure ou une expression nue ? ».

À retenir

  • Un contexte de ligne ne filtre pas.
  • CALCULATE le transforme en filtre : c'est la transition de contexte.
  • Une mesure contient toujours un CALCULATE caché.
  • La transition filtre sur toutes les colonnes de la ligne : attention aux tables sans clé unique.

Pour aller plus loin

  • Source (Microsoft Learn, CALCULATE)
  • Source (Microsoft Learn, CALCULATETABLE)
  • Source (Microsoft Learn, contextes)
  • Source (SQLBI, transition de contexte)

Exercice

Mise en pratique DAX, thème 5 | Analyse clients (nouveaux clients, clients perdus, segmentation) et thème 7 | Délais et logistique, questions 7.2 et 7.4 (CALCULATE dans un FILTER sur les commandes).