20 mai 2025 · Alex Badiu
Quel contenu inclure dans un Design Document – Modèle
Quelles caractéristiques du modèle doivent être décrites dans un Design Document ?
Le modèle de données est le cœur de tout rapport Power BI. Ce « back-end » ne reçoit souvent pas l’attention qu’il mérite, car consacrer du temps à des portions de la solution invisibles pour les consommateurs peut sembler un effort gaspillé : rien n’est plus faux. Vous serez récompensé de bien des façons si vous prenez soin de préparer votre modèle de données, notamment par :
- De meilleures performances
- Des calculs plus simples
- Des mises à niveau plus faciles (grâce à une meilleure compréhension du modèle existant et à une évaluation plus réaliste de l’impact et de l’effort requis pour les changements)
L’intention de la conception du modèle sémantique a été explorée dans des numéros précédents (#7 et #9).
Ce numéro traite plutôt de la conception réelle telle qu’implémentée dans le fichier Power BI.
[!NOTE] Alors que les sections du design document présentées jusqu’à présent reflètent l’intention de conception, le modèle implémenté (réel) est souvent présenté en annexes.
Général
Staging
Avant d’entrer dans les détails du modèle, il convient de décrire la logique d’extraction et de transformation des données.
Les données doivent être extraites telles quelles (c’est-à-dire sans transformation) dans des tables de staging. Les tables de staging doivent en outre être clairement nommées comme telles, par exemple en ajoutant un préfixe « RAW ». Lorsque nécessaire, les tables de staging peuvent être fusionnées pour produire une table du modèle (par exemple, RAW Customers + RAW Addresses 🡪 Customers, etc.).
Table de staging : RAW Customers
| ID | Name | Type | Sample | Notes |
|---|---|---|---|---|
| 1 | Customer ID | Integer | 1 | Clé primaire |
| 2 | Customer | Text | Dave | |
| 3 | Address ID | Integer | 1 | Clé étrangère |
Table de staging : RAW Addresses
| ID | Name | Type | Sample | Notes |
|---|---|---|---|---|
| 1 | Address ID | Integer | 1 | Clé primaire |
| 3 | City | Text | Ottawa | |
| 4 | Country | Text | Canada |
Opération de transformation : fusionner les tables RAW Customers et RAW Addresses via Address ID (jointure externe gauche)
Table du modèle : Customers
| ID | Name | Type | Sample | Notes |
|---|---|---|---|---|
| 1 | Customer ID | Integer | 1 | Clé primaire |
| 2 | Customer | Text | Dave | |
| 3 | City | Text | Ottawa | |
| 4 | Country | Text | Canada |
Fonctions INFO VIEW
Les fonctions INFO VIEW peuvent être facilement exploitées pour extraire la conception implémentée. Une fois cette information consolidée en un seul endroit (oui, je sais que Power BI Desktop est déjà un seul endroit, mais l’information y est quelque peu dispersée et une vue « à 10 000 pieds » peut être difficile à obtenir), une vision « à vol d’oiseau » permet de repérer plus facilement les écarts.
À cette fin, les tables et colonnes, les relations et les mesures tels qu’implémentés doivent être rassemblés dans des tables de documentation.
REMARQUE : la procédure utilisée pour exporter les données des tableaux suivants depuis Power BI Desktop a été la suivante :
- Ouvrir DAX Query View et saisir la requête souhaitée
- Cliquer sur le bouton « Run »
- Cliquer sur le bouton « Copy » et sélectionner « Entire table »
- Sélectionner plus de lignes que nécessaire dans la table du design document souhaitée et utiliser CTRL-V pour coller les données exportées
- Supprimer la ligne d’en-tête ainsi que toute ligne vide ou dupliquée
- Modifier les colonnes « ID » et « Notes » selon les besoins
- Ajouter les données de la colonne « Sample » selon les besoins
Tables et colonnes
Lister toutes les tables du modèle ; la requête suivante peut être utilisée dans DAX Query View depuis Power BI Desktop pour récupérer les données des tables :
EVALUATE
VAR _Result =
SELECTCOLUMNS(
INFO.VIEW.TABLES(),
"ID", [ID],
"Name", [Name],
"Category", [DataCategory],
"Type", IF( ISBLANK([Expression]), "Normal", "Calculated" ),
"Expression", [Expression],
"Is Hidden", [IsHidden]
)
RETURN
_Result
| ID | Name | Category | Type | Expression | Is Hidden |
|---|---|---|---|---|---|
| 1 | Key Measures | Regular | Normal | false | |
| 2 | Dates | Time | Normal | false | |
| 3 | Invoices | Regular | Normal | false | |
| 4 | Customers | Regular | Normal | false | |
| 5 | Last Refresh | Regular | Normal | true | |
| 6 | Orders | Regular | Normal | false | |
| 7 | Products | Regular | Normal | false | |
| 8 | Regions | Regular | Normal | false | |
| 9 | Aging | Regular | Calculated | SELECTCOLUMNS ( GENERATESERIES ( 1, 6, 1 ), “Aging ID”, [Value] ) |
true |
Lister toutes les colonnes de chaque table ; la requête suivante peut être utilisée dans DAX Query View depuis Power BI Desktop pour récupérer les données des colonnes (ajuster la variable [_Table] selon les besoins) :
EVALUATE
VAR _Table = "Dates"
VAR _Result =
SELECTCOLUMNS(
FILTER( INFO.VIEW.COLUMNS(), [Table] = _Table && [Type] IN {"Data", "Calculated"} ),
"ID", [ID],
"Name", [Name],
"Type", IF( [DataType] = "True/False" , "Boolean", [DataType] ),
// "Nulls", IF( [IsNullable] = TRUE(), "Yes", "No" ),
"Sample", BLANK(),
"Notes", COMBINEVALUES( " | ", IF( [IsKey] = TRUE(), "Primary Key", BLANK() ),
IF( OR( [FormatString] = "0", [DataType] = "True/False" ), BLANK(), [FormatString] ), [Expression] )
)
RETURN
_Result
Fait
Invoices
| ID | Name | Type | Sample | Notes |
|---|---|---|---|---|
| 1 | Invoice ID | Integer | 2401 | Clé primaire |
| 2 | Invoice Date | Date | January 31, 2024 | Long Date |
| 3 | Amount | Number | 371900 | |
| 4 | Customer ID | Integer | 1 | Clé étrangère |
| 5 | Region ID | Integer | 1 | Clé étrangère |
Orders
| ID | Name | Type | Sample | Notes |
|---|---|---|---|---|
| 1 | Order ID | Integer | 2407 | Clé primaire |
| 2 | Order Date | Date | July 17, 2024 | Long Date |
| 3 | Product ID | Integer | 5 | Clé étrangère |
| 4 | Quantity | Integer | 16 | |
| 5 | Customer ID | Integer | 4 | Clé étrangère |
| 6 | Region ID | Integer | 6 | Clé étrangère |
Dimension
Customers
| ID | Name | Type | Sample | Notes |
|---|---|---|---|---|
| 1 | Customer ID | Integer | 1 | Clé primaire |
| 2 | Customer | Text | Dave | |
| 3 | City | Text | Ottawa | |
| 4 | Country | Text | Canada |
Products
| ID | Name | Type | Sample | Notes |
|---|---|---|---|---|
| 1 | Product ID | Integer | 4 | Clé primaire |
| 2 | Product | Text | Shoes | |
| 3 | Unit Price | Integer | 120 | |
| 4 | Unit Cost | Integer | 110 |
Regions
| ID | Name | Type | Sample | Notes |
|---|---|---|---|---|
| 1 | Region ID | Integer | 1 | Clé primaire |
| 2 | Region | Text | Canada |
Dates
Une table de dates sera créée directement en code M dans Power BI. La table de dates doit couvrir toute la période d’intérêt avec des années civiles complètes et sera initialement créée pour une période de trois ans (soit du 2023-01-01 au 2025-12-31).
La table [Dates] a été générée à l’aide de code Power Query/M provenant de l’Extended Date Table, conçue par Melissa de Korte, experte Enterprise DNA, l’une des (sinon la) meilleures tables de dates disponibles pour Power BI.
https://forum.enterprisedna.co/t/extended-date-table-power-query-m-function/6390.
| ID | Name | Type | Sample | Notes |
|---|---|---|---|---|
| 1 | Date | Date | 05-Feb-2025 | Clé primaire dd-mmm-yyyy |
| 2 | Year | Integer | 2025 | |
| 3 | Quarter Number | Integer | 1 | |
| 4 | Quarter | Text | Q1 | |
| 5 | Month | Integer | 2 | |
| 6 | Month & Year | Text | Feb 2025 | |
| 7 | MonthnYear | Integer | 202502 | |
| 8 | Month Name | Text | February | |
| 9 | Month Short | Text | Feb | |
| 10 | Month Initial | Text | F | |
| 11 | Day of Month | Integer | 5 | |
| 12 | Day of Week Number | Integer | 2 | |
| 13 | Day of Week Name | Text | Wednesday | |
| 14 | Day of Week Initial | Text | W | |
| 15 | DateInt | Integer | 20250205 | |
| 16 | IsAfterToday | Boolean | True | |
| 17 | IsWeekDay | Boolean | True | |
| 18 | Day Type | Text | Weekday | |
| 19 | Fiscal Year | Text | FY2025 | |
| 20 | Fiscal Quarter | Text | FQ4 2025 | |
| 21 | FQuarternYear | Integer | 20254 | |
| 22 | Fiscal Period | Text | FP11 2025 | |
| 23 | FPeriodnYear | Integer | 202511 | |
| 24 | IsCurrentFY | Boolean | True | |
| 25 | IsCurrentFQ | Boolean | True | |
| 26 | IsCurrentFP | Boolean | False | |
| 27 | IsPYTD | Boolean | False | |
| 28 | IsPFYTD | Boolean | False |
Support
Aging
Il s’agit d’une table calculée qui reflète les tranches d’ancienneté des factures utilisées par l’organisation.
Aging = SELECTCOLUMNS ( GENERATESERIES ( 1, 6, 1 ), "Aging ID", [Value] )
| ID | Name | Type | DAX Expression | Notes |
|---|---|---|---|---|
| 1 | Aging ID | Integer | (voir l’expression de création de table ci-dessus) | Clé primaire |
| 2 | Aging | Text | SWITCH(TRUE(), [Aging ID] = 1, “0-30 days”, [Aging ID] = 2, “31-60 days”, [Aging ID] = 3, “61-90 days”, [Aging ID] = 4, “91-120 days”, [Aging ID] = 5, “121-180 days”, [Aging ID] = 6, “over 180 days”, “ERROR”) |
|
| 3 | Min | Integer | SWITCH(TRUE(), [Aging ID] = 1, 0, [Aging ID] = 2, 31, [Aging ID] = 3, 61, [Aging ID] = 4, 91, [Aging ID] = 5, 121, [Aging ID] = 6, 181, -1) |
|
| 4 | Max | Integer | SWITCH(TRUE(), [Aging ID] = 1, 30, [Aging ID] = 2, 60, [Aging ID] = 3, 90, [Aging ID] = 4, 120, [Aging ID] = 5, 180, [Aging ID] = 6, 9999, -1) |
Tiers
| ID | Name | Type | Sample | Notes |
|---|---|---|---|---|
| 1 | Tier ID | Integer | 1 | Clé primaire |
| 2 | Tier | Text | Gold | |
| 3 | Lower Bound | Integer | 10,000,000 | |
| 4 | Upper Bound | Integer | 9,999,999,999 |
Last Refresh
Il n’y a pas de source de données pour cette table ; elle a plutôt été générée à l’aide de code Power Query/M par Melissa de Korte, experte Enterprise DNA : https://forum.enterprisedna.co/t/adding-a-last-refresh-date-to-your-report/6485
Cette table est une table de support utilisée par la mesure [Last Refresh].
let
Source = DateTime.FixedLocalNow(),
#"Converted to Table" = #table(1, {{Source}}),
#"Renamed Columns" = Table.RenameColumns(#"Converted to Table", {{"Column1", "Last Refresh"}}),
#"Changed Type" = Table.TransformColumnTypes(#"Renamed Columns", {{"Last Refresh", type datetime}}),
#"Inserted Date" = Table.AddColumn(#"Changed Type", "Date", each DateTime.Date([Last Refresh]), type date),
#"Insert Time" = Table.AddColumn(#"Inserted Date", "Time", each DateTime.Time([Last Refresh]), type time)
in
#"Insert Time"
| ID | Name | Type | Sample | Notes |
|---|---|---|---|---|
| 1 | Last Refresh | Date | 2024-12-05 1:19.22 | General Date |
| 2 | Date | Date | December 5, 2024 | Long Date |
| 3 | Time | Date | 1:19.22 PM | Long Time |
Relations
Lister toutes les relations du modèle ; la requête suivante peut être utilisée dans DAX Query View depuis Power BI pour récupérer le détail des relations :
EVALUATE
VAR _Result =
SELECTCOLUMNS(
INFO.VIEW.RELATIONSHIPS(),
"ID", [ID],
// "Relationship", [Relationship],
"From", [FromTable] & "[" & [FromColumn] & "]",
"To", [ToTable] & "[" & [ToColumn] & "]",
"Cardinality", [FromCardinality] & "-to-" & [ToCardinality],
"Cross-filter Direction", SWITCH( TRUE(),
[CrossFilteringBehavior] = "OneDirection", "Single",
[CrossFilteringBehavior] = "BothDirections", "Both",
[CrossFilteringBehavior] ),
"Status", IF( [IsActive] = TRUE(), "Active", "Inactive" )
)
RETURN
_Result
| ID | From | To | Cardinality | Cross-Filter Direction | Status |
|---|---|---|---|---|---|
| 1 | Invoices[Customer ID] | Customers[Customer ID] | Many-to-One | Single | Active |
| 2 | Invoices[Invoice Date] | Dates[Date] | Many-to-One | Single | Active |
| 3 | Orders[Order Date] | Dates[Date] | Many-to-One | Single | Active |
| 4 | Orders[Product ID] | Products[Product ID] | Many-to-One | Single | Active |
| 5 | Orders[Region ID] | Regions[Region ID] | Many-to-One | Single | Active |
| 6 | Orders[Customer ID] | Customers[Customer ID] | Many-to-One | Single | Active |
Mesures
Une table Key Measures saisie manuellement a été ajoutée, ainsi que diverses mesures.
Pour formater toutes les mesures d’un modèle Power BI :
- Ouvrir [Power BI Desktop] et le fichier PBIX concerné
- Ouvrir l’outil externe [Tabular Editor V2] (version 2.13 ou supérieure)
- Sélectionner l’onglet [C# Script]
- Saisir ce qui suit dans la fenêtre C# Script, puis cliquer sur le bouton [Run]
bool shortFormat = false;
bool skipSpaceAfterFunctionName = true;
FormatDax(Model.AllMeasures, shortFormat, skipSpaceAfterFunctionName);
Méthode :
Lister toutes les mesures du modèle ; la requête suivante peut être utilisée dans DAX Query View depuis Power BI pour récupérer les noms et expressions des mesures :
EVALUATE
VAR _Result =
SELECTCOLUMNS(
INFO.VIEW.MEASURES(),
"Documentation", [Name] & " = " & [Expression]
)
RETURN
_Result
Méthode alternative 1 (DAX Studio) : pour lister toutes les mesures d’un modèle Power BI :
- Ouvrir [Power BI Desktop] et le fichier PBIX concerné
- Ouvrir l’outil externe [DAX Studio]
- Faire un clic droit sur n’importe quelle table dans l’onglet [Metadata] du panneau [Query] et sélectionner [Define All Measures (All Tables)]
Méthode alternative 2 (TMDL) : pour lister toutes les mesures d’un modèle Power BI (y compris les format strings) :
- Ouvrir [Power BI Desktop] et le fichier PBIX concerné
- Dans la barre latérale gauche, sélectionner [TMDL View]
- Glisser la table souhaitée (contenant les mesures) dans la fenêtre TMDL
- Supprimer les lignes non désirées (createOrReplace, table, lineageTag, partition, annotation)
Total Sales = SUMX( Orders, Orders[Quantity] * RELATED( Products[Unit Price] ) )
Total Costs = SUMX( Orders, Orders[Quantity] * RELATED( Products[Unit Cost] ) )
Total Profit = [Total Sales] - [Total Costs]
Profit % = DIVIDE( [Total Profit], [Total Sales], 0 )
Ressources
Publications LinkedIn
Les publications LinkedIn couvrant le design document sont listées ci-dessous :
1. Général et périmètre
2. Flux de travail, enjeux et règles métier
3. Data
4. Reports
5. Validation
6. Déploiement
7. Modèle
Exemples
Des fragments de documents exemples couvrant des sections spécifiques sont disponibles dans le dépôt GitHub :
1. Design Document - Sample Fragment 01 - General and Scope
2. Design Document - Sample Fragment 02 - Workflow, Issues, and Business Rules
3. Design Document - Sample Fragment 03 - Data
4. Design Document - Sample Fragment 04 - Reports
5a. Design Document - Sample Fragment 05 - Validation
5b. Design Document - Sample Validation Spreadsheet
6. Design Document - Sample Fragment 06 - Deployment
7a. Design Document - Sample Fragment 07 - Model
7b. Design Document - Sample Power BI File