Skip to main content

dax-development

Use when the task involves writing, modifying, or reviewing DAX measures in a Power BI semantic model. Triggers: "write a DAX measure", "add YTD measure", "create time intelligence", "DAX formula", "FYTD calculation", "variance measure", "percentage measure", "fix DAX error", "DAX performance", "DIVIDE safety", "VAR/RETURN pattern", "display folder", "formatString for measure", "conditional formatting measure", "budget vs actuals".

Zur Installation springen

Quellinformationen

Repository
natalinio/agentic-powerbi-squad
Letzte Quellaktivität
2. April 2026 um 15:38
Erkannte Sprache von SKILL.md
Englisch
Sterne
0
Forks
1

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

Datei-Explorer
4 Dateien

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
dax-development
description
Use when the task involves writing, modifying, or reviewing DAX measures in a Power BI semantic model. Triggers: "write a DAX measure", "add YTD measure", "create time intelligence", "DAX formula", "FYTD calculation", "variance measure", "percentage measure", "fix DAX error", "DAX performance", "DIVIDE safety", "VAR/RETURN pattern", "display folder", "formatString for measure", "conditional formatting measure", "budget vs actuals".
user-invocable
true
# Skill: DAX KPIs and Measures Development ## Prerequisites — MANDATORY Before writing ANY DAX code: 1. **Read** `.github/skills/dax-development/references/dax-patterns.md` for validated DAX patterns. 2. **Read** `.github/skills/dax-development/references/dax-pitfalls.md` — anti-hallucination guard for deprecated, non-existent, and commonly confused DAX functions. 3. **Read** `.github/references/naming-conventions.md` for measure naming rules. 4. **Search** Microsoft documentation with `microsoft_docs_search` for any DAX function you are uncertain about. 5. **Search** for code examples with `microsoft_code_sample_search` when implementing time intelligence or complex calculations. ## Input / Output | | | |---|---| | **Input** | TMDL table files, `<ProjectName>/spec/requirements_summary.md` | | **Output** | `<ProjectName>/PBIP/<ProjectName>.SemanticModel/definition/tables/_Measures.tmdl` | ## Measures Table - ALL DAX measures MUST be created inside a **disconnected table** named `_Measures`. - This table has NO data relationships — it is purely a container for measures. - The `_Measures` table TMDL is defined in `tables/_Measures.tmdl`. ## DAX Coding Standards ### Formatting - ALL DAX code MUST be formatted across **multiple lines** for readability. - Use **VAR / RETURN** pattern for all non-trivial measures. - One expression per line. - Indent consistently with tabs. ### VAR Naming — Reserved Keywords (ZERO TOLERANCE) **NEVER** use DAX reserved keywords or function names as VAR names. Power BI Desktop will report *"'<Name>' is a reserved word"* compile errors. **Forbidden VAR names** (non-exhaustive): `Variance`, `Status`, `Value`, `Date`, `Time`, `Year`, `Month`, `Day`, `Table`, `Column`, `Currency`, `Number`, `Text`, `Boolean`, `True`, `False`, `Blank`, `Error`, `Order`, `Rank`, `Index`, `Format`, `Type`, `Result`, `None`, `All`, `Filter`. **Rule**: Always use descriptive, business-context prefixed names: - `Variance` → `SalesBudgetVariance` - `Status` → `BudgetStatusValue` - `Value` → `MetricValue` - `Result` → `CalcResult` ### DAX Comments (Allowed) - **DAX expressions support comments**: `//` for single-line, `/* */` for multi-line. - Use comments to explain complex business logic, time intelligence parameters, or non-obvious calculations. ### TMDL Descriptions (`///`) - Use `///` (triple-slash) before a measure declaration to set its `Description` property. - `///` must be immediately followed by the `measure` keyword — no blank line between. - This is a TMDL feature, not a comment. It populates the measure description visible in Power BI. **Example**: ```tmdl measure 'Sales Amount FYTD' = // Calculate fiscal year-to-date sales using dynamic fiscal year parameter VAR FiscalYearEndMonth = VAR FYStartMonth = SELECTEDVALUE(Parameters[ParameterValue], "1") VAR StartMonthNum = VALUE(FYStartMonth) VAR EndMonth = IF(StartMonthNum = 1, 12, StartMonthNum - 1) RETURN FORMAT(EndMonth, "0") & "/30" // Format as MM/DD VAR FYTDSales = CALCULATE( [Sales Amount], DATESYTD(Dim_Date[Date], FiscalYearEndMonth) ) RETURN FYTDSales formatString: "#,##0.00" displayFolder: "Time Intelligence" ``` ### Example: ```tmdl measure 'Sales Amount FYTD' = VAR CurrentDate = MAX(Dim_Date[Date]) VAR FYTDSales = CALCULATE( [Sales Amount], DATESYTD(Dim_Date[Date], "6/30") ) RETURN FYTDSales formatString: #,##0.00 displayFolder: Sales lineageTag: <generate-guid> ``` ### Division Safety - **ALWAYS** use `DIVIDE(numerator, denominator, 0)` instead of `/` operator. - This prevents division-by-zero errors. ### Time Intelligence - Assume the dedicated date dimension will be marked as the official **Date Table** in the model before final Desktop validation. - That marking must be done only after the date table data has been loaded and validated as contiguous in Power BI Desktop. - Use standard time intelligence functions: - **YTD**: `TOTALYTD([Measure], Dim_Date[Date])` or `DATESYTD(Dim_Date[Date])` for fiscal year: `DATESYTD(Dim_Date[Date], "6/30")` - **Previous Year**: `CALCULATE([Measure], SAMEPERIODLASTYEAR(Dim_Date[Date]))` - **Month-over-Month**: `CALCULATE([Measure], DATEADD(Dim_Date[Date], -1, MONTH))` - **YoY Variance**: Use VAR pattern to calculate both periods, then subtract. ### ⚠️ Time Intelligence with Dynamic Parameters (CRITICAL) **WARNING**: Functions like `DATESYTD`, `TOTALYTD`, `DATESMTD`, `TOTALMTD` require **constant literal values** for year-end date parameters. They do NOT accept variables or dynamic expressions. **Example of ERROR**: ```dax ❌ WRONG (causes warning: "Only constant date value is allowed"): VAR FiscalYearEndMonth = ... // Dynamic calculation RETURN CALCULATE([Sales Amount], DATESYTD(Dim_Date[Date], FiscalYearEndMonth)) ``` **Solution**: Use manual filtering logic when parameters must be dynamic: ```dax ✅ CORRECT (supports dynamic fiscal year parameters): measure 'Sales Amount FYTD' = // Manual fiscal YTD calculation with dynamic parameter support VAR CurrentDate = MAX(Dim_Date[Date]) VAR FYStartMonth = VALUE(SELECTEDVALUE(Parameters[ParameterValue], "1")) VAR CurrentYear = YEAR(CurrentDate) VAR CurrentMonth = MONTH(CurrentDate) // Calculate current fiscal year VAR FiscalYear = IF( CurrentMonth >= FYStartMonth, CurrentYear, CurrentYear - 1 ) VAR FYStartDate = DATE(FiscalYear, FYStartMonth, 1) VAR Result = CALCULATE( [Sales Amount], FILTER( ALL(Dim_Date[Date]), Dim_Date[Date] >= FYStartDate && Dim_Date[Date] <= CurrentDate ) ) RETURN Result ``` **Functions Requiring Constant Parameters**: - `DATESYTD(dates, [year_end_date])` → year_end_date must be literal like `"6/30"` - `TOTALYTD(expression, dates, [year_end_date])` → year_end_date must be literal - `DATESMTD`, `TOTALMTD`, `DATESQTD`, `TOTALQTD` → No year-end parameter, but similar optimization constraints **When to Use Manual Logic**: - Fiscal year start month is user-selectable (parameter table) - Multiple fiscal year scenarios in same model - Dynamic calendar logic based on business rules **When `DATESYTD` is OK**: - Fixed fiscal year end (e.g., always June 30): `DATESYTD(Dim_Date[Date], "6/30")` - Calendar year only: `DATESYTD(Dim_Date[Date])` (defaults to Dec 31) ### Filter Context - Use `CALCULATE()` with explicit filter modifications. - Use `REMOVEFILTERS()` instead of `ALL()` when clearing filters on a table. - Use `KEEPFILTERS()` when you need to intersect with existing filters. - NEVER use `FILTER(ALL(...))` when `REMOVEFILTERS` + `VALUES` achieves the same result more efficiently. ### Measure Dependencies - Base measures should be defined FIRST, then composite measures reference them. - Example order: 1. `Sales Amount` (base) 2. `Sales Amount FYTD` (time intelligence on base) 3. `Sales vs Budget` (comparison using two bases) 4. `Sales vs Budget %` (percentage using DIVIDE) ## Measure Naming Conventions Follow `.github/references/naming-conventions.md`. Summary: - **Base measures**: Descriptive name — `'Sales Amount'`, `'Total Quantity'` - **Time intelligence**: Suffix with period — `'Sales Amount FYTD'`, `'Sales Amount PY'` - **Percentages**: Suffix with `%` — `'Adjusted Profit %'` - **Variance**: Suffix with `vs` — `'Sales vs Budget'`, `'Sales vs Budget %'` - **Count measures**: Prefix with `#` or `Count of` — `'# Customers'`, `'Count of Transactions'` ## Display Folders Organize measures into `displayFolder` categories: - `Sales` — revenue and volume measures - `Budget` — budget comparison measures - `Profitability` — margin and profit measures - `Time Intelligence` — YTD, PY, MoM variants ## Conditional Formatting Support For KPIs with status indicators (above/below target), create helper measures: ```dax measure 'Budget Status' = VAR SalesVal = [Sales Amount FYTD] VAR BudgetVal = [Budget Amount FYTD] VAR Ratio = DIVIDE(SalesVal, BudgetVal, 0) RETURN SWITCH( TRUE(), Ratio >= 1, "Above Target", Ratio >= 0.9, "Close to Target", "Below Target" ) lineageTag: <generate-guid> ``` ## BPA Compliance Checklist (Preventive) **CRITICAL**: Before writing ANY DAX code, review the following Best Practice Analyzer rules from `.github/skills/code-review/references/bpa-rules-reference.md`. These guidelines ensure production-quality measures. ### DAX Expression Rules (Error/Warning Severity) 1. **DAX_FULLY_QUALIFIED_COLUMNS** (Error): Column references MUST be fully qualified with table name. Unqualified columns cause ambiguity errors. ```dax ✅ DO: measure 'Total Sales' = SUM(Fact_Sales[SalesAmount]) // Fully qualified ❌ DON'T: measure 'Total Sales' = SUM([SalesAmount]) // Ambiguous if multiple tables have SalesAmount ``` 2. **DAX_DIVISION_COLUMNS** (Error): Division operations MUST use `DIVIDE()` function, NEVER `/` operator. `DIVIDE()` handles division-by-zero gracefully. ```dax ✅ DO: measure 'Profit Margin' = VAR TotalProfit = SUM(Fact_Sales[Profit]) VAR TotalRevenue = SUM(Fact_Sales[Revenue]) RETURN DIVIDE(TotalProfit, TotalRevenue, 0) // Safe with default ❌ DON'T: measure 'Profit Margin' = SUM(Fact_Sales[Profit]) / SUM(Fact_Sales[Revenue]) // Throws error if denominator = 0 ``` 3. **DAX_UNQUALIFIED_MEASURES** (Warning): Measure references SHOULD be unqualified (no table prefix). Measures are model-level objects. ```dax ✅ DO: measure 'Sales YTD' = CALCULATE([Total Sales], DATESYTD(Dim_Date[Date])) // Unqualified measure ❌ DON'T: measure 'Sales YTD' = CALCULATE([_Measures].[Total Sales], DATESYTD(Dim_Date[Date])) // Unnecessary table prefix ``` 4. **DAX_TODO_COMMENTS** (Warning): DAX expressions SHOULD NOT contain TODO/FIXME comments in production. All measures must be production-ready. ```dax ❌ DON'T: measure 'Sales Forecast' = // TODO: Implement forecasting algorithm SUM(Fact_Sales[SalesAmount]) ✅ DO: measure 'Sales Forecast' = VAR HistoricalSales = CALCULATE( SUM(Fact_Sales[SalesAmount]), DATESINPERIOD(Dim_Date[Date], MAX(Dim_Date[Date]), -12, MONTH) ) VAR GrowthRate = 0.15 RETURN HistoricalSales * (1 + GrowthRate) ``` ### Formatting Rules (Warning Severity) 5. **OBJECTS_WITH_NO_FORMAT_STRING_MEASURES** (Warning): ALL measures MUST have `formatString` property. Critical for usability in Power BI visuals. ```tmdl ✅ DO: measure 'Total Sales' = expression: ```SUM(Fact_Sales[SalesAmount])``` formatString: "$#,##0.00" // Currency format displayFolder: "Sales Metrics" ❌ DON'T: measure 'Total Sales' = expression: ```SUM(Fact_Sales[SalesAmount])``` // Missing formatString ``` **Common Format Strings**: - Currency: `"$#,##0.00"` or `"€#,##0.00"` - Percentage: `"0.00%"` - Integer count: `"#,##0"` - Decimal: `"#,##0.00"` - No decimal: `"#,##0"` ### Layout Rules (Info Severity) 6. **ORGANIZE_MEASURES_IN_DISPLAY_FOLDERS** (Info): Measures SHOULD have `displayFolder` property for logical grouping. ```tmdl ✅ DO: measure 'Total Sales' = expression: ```SUM(Fact_Sales[SalesAmount])``` formatString: "$#,##0.00" displayFolder: "Sales Metrics" // Grouped measure 'Sales YTD' = expression: ```CALCULATE([Total Sales], DATESYTD(Dim_Date[Date]))``` formatString: "$#,##0.00" displayFolder: "Sales Metrics\\Time Intelligence" // Nested folder ``` **Common Folder Patterns**: - `"Sales Metrics"` - `"Finance\\Profitability"` - `"Inventory\\Stock Levels"` - `"Time Intelligence"` - `"KPIs"` 7. **PROVIDE_DESCRIPTIONS_FOR_MEASURES** (Info): Complex measures (time intelligence, statistical calculations) SHOULD have `description` property. Appears as tooltip in Power BI. ```tmdl ✅ DO: measure 'Sales Same Period Last Year' = description: "Total sales for the same period in the previous year" expression: ``` CALCULATE([Total Sales], SAMEPERIODLASTYEAR(Dim_Date[Date])) ``` formatString: "$#,##0.00"
Auf GitHub ansehen
Diese SKILL.md ist sehr gross, daher zeigt SkillsMP hier nur den ersten Abschnitt. Auf GitHub ansehen