@luquimbo/bi-superpowers 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (193) hide show
  1. package/.claude-plugin/plugin.json +8 -0
  2. package/.mcp.json +25 -0
  3. package/AGENTS.md +244 -0
  4. package/CHANGELOG.md +265 -0
  5. package/LICENSE +21 -0
  6. package/README.md +211 -0
  7. package/bin/build-plugin.js +30 -0
  8. package/bin/cli.js +1064 -0
  9. package/bin/commands/add.js +533 -0
  10. package/bin/commands/add.test.js +77 -0
  11. package/bin/commands/build-desktop.js +166 -0
  12. package/bin/commands/changelog.js +443 -0
  13. package/bin/commands/diff.js +325 -0
  14. package/bin/commands/lint.js +419 -0
  15. package/bin/commands/lint.test.js +103 -0
  16. package/bin/commands/mcp-setup.js +246 -0
  17. package/bin/commands/pull.js +287 -0
  18. package/bin/commands/pull.test.js +36 -0
  19. package/bin/commands/push.js +231 -0
  20. package/bin/commands/push.test.js +14 -0
  21. package/bin/commands/search.js +344 -0
  22. package/bin/commands/search.test.js +115 -0
  23. package/bin/commands/setup.js +545 -0
  24. package/bin/commands/setup.test.js +46 -0
  25. package/bin/commands/sync-profile.js +405 -0
  26. package/bin/commands/sync-profile.test.js +14 -0
  27. package/bin/commands/sync-source.js +418 -0
  28. package/bin/commands/sync-source.test.js +14 -0
  29. package/bin/commands/watch.js +206 -0
  30. package/bin/lib/generators/claude-plugin.js +266 -0
  31. package/bin/lib/generators/claude-plugin.test.js +110 -0
  32. package/bin/lib/generators/index.js +116 -0
  33. package/bin/lib/generators/shared.js +282 -0
  34. package/bin/lib/licensing/index.js +35 -0
  35. package/bin/lib/licensing/storage.js +364 -0
  36. package/bin/lib/licensing/storage.test.js +55 -0
  37. package/bin/lib/licensing/validator.js +213 -0
  38. package/bin/lib/licensing/validator.test.js +137 -0
  39. package/bin/lib/microsoft-mcp.js +176 -0
  40. package/bin/lib/microsoft-mcp.test.js +106 -0
  41. package/bin/lib/skills.js +84 -0
  42. package/bin/mcp/powerbi-modeling-launcher.js +38 -0
  43. package/bin/postinstall.js +44 -0
  44. package/bin/utils/errors.js +159 -0
  45. package/bin/utils/git.js +298 -0
  46. package/bin/utils/logger.js +142 -0
  47. package/bin/utils/mcp-detect.js +274 -0
  48. package/bin/utils/mcp-detect.test.js +105 -0
  49. package/bin/utils/pbix.js +305 -0
  50. package/bin/utils/pbix.test.js +37 -0
  51. package/bin/utils/profiles.js +312 -0
  52. package/bin/utils/projects.js +168 -0
  53. package/bin/utils/readline.js +206 -0
  54. package/bin/utils/readline.test.js +47 -0
  55. package/bin/utils/tui.js +314 -0
  56. package/bin/utils/tui.test.js +127 -0
  57. package/commands/contributions.md +265 -0
  58. package/commands/data-model-design.md +468 -0
  59. package/commands/dax-doctor.md +248 -0
  60. package/commands/fabric-scripts.md +452 -0
  61. package/commands/migration-assistant.md +290 -0
  62. package/commands/model-documenter.md +242 -0
  63. package/commands/pbi-connect.md +239 -0
  64. package/commands/project-kickoff.md +905 -0
  65. package/commands/report-layout.md +296 -0
  66. package/commands/rls-design.md +533 -0
  67. package/commands/theme-tweaker.md +624 -0
  68. package/config.example.json +23 -0
  69. package/config.json +23 -0
  70. package/desktop-extension/manifest.json +37 -0
  71. package/desktop-extension/package.json +10 -0
  72. package/desktop-extension/server.js +95 -0
  73. package/docs/openrouter-free-models.md +92 -0
  74. package/library/examples/README.md +151 -0
  75. package/library/examples/finance-reporting/README.md +351 -0
  76. package/library/examples/finance-reporting/data-model.md +267 -0
  77. package/library/examples/finance-reporting/measures.dax +557 -0
  78. package/library/examples/hr-analytics/README.md +371 -0
  79. package/library/examples/hr-analytics/data-model.md +315 -0
  80. package/library/examples/hr-analytics/measures.dax +460 -0
  81. package/library/examples/marketing-analytics/README.md +37 -0
  82. package/library/examples/marketing-analytics/data-model.md +62 -0
  83. package/library/examples/marketing-analytics/measures.dax +110 -0
  84. package/library/examples/retail-analytics/README.md +439 -0
  85. package/library/examples/retail-analytics/data-model.md +288 -0
  86. package/library/examples/retail-analytics/measures.dax +481 -0
  87. package/library/examples/supply-chain/README.md +37 -0
  88. package/library/examples/supply-chain/data-model.md +69 -0
  89. package/library/examples/supply-chain/measures.dax +77 -0
  90. package/library/examples/udf-library/README.md +228 -0
  91. package/library/examples/udf-library/functions.dax +571 -0
  92. package/library/snippets/dax/README.md +292 -0
  93. package/library/snippets/dax/business-domains.md +576 -0
  94. package/library/snippets/dax/calculate-patterns.md +276 -0
  95. package/library/snippets/dax/calculation-groups.md +489 -0
  96. package/library/snippets/dax/error-handling.md +495 -0
  97. package/library/snippets/dax/iterators-and-aggregations.md +474 -0
  98. package/library/snippets/dax/kpis-and-metrics.md +293 -0
  99. package/library/snippets/dax/rankings-and-topn.md +235 -0
  100. package/library/snippets/dax/security-patterns.md +413 -0
  101. package/library/snippets/dax/text-and-formatting.md +316 -0
  102. package/library/snippets/dax/time-intelligence.md +196 -0
  103. package/library/snippets/dax/user-defined-functions.md +477 -0
  104. package/library/snippets/dax/virtual-tables.md +546 -0
  105. package/library/snippets/excel-formulas/README.md +84 -0
  106. package/library/snippets/excel-formulas/aggregations.md +330 -0
  107. package/library/snippets/excel-formulas/dates-and-times.md +361 -0
  108. package/library/snippets/excel-formulas/dynamic-arrays.md +314 -0
  109. package/library/snippets/excel-formulas/lookups.md +169 -0
  110. package/library/snippets/excel-formulas/text-functions.md +363 -0
  111. package/library/snippets/governance/naming-conventions.md +97 -0
  112. package/library/snippets/governance/review-checklists.md +107 -0
  113. package/library/snippets/power-query/README.md +389 -0
  114. package/library/snippets/power-query/api-integration.md +707 -0
  115. package/library/snippets/power-query/connections.md +434 -0
  116. package/library/snippets/power-query/data-cleaning.md +298 -0
  117. package/library/snippets/power-query/error-handling.md +526 -0
  118. package/library/snippets/power-query/parameters.md +350 -0
  119. package/library/snippets/power-query/performance.md +506 -0
  120. package/library/snippets/power-query/transformations.md +330 -0
  121. package/library/snippets/report-design/accessibility.md +78 -0
  122. package/library/snippets/report-design/chart-selection.md +54 -0
  123. package/library/snippets/report-design/layout-patterns.md +87 -0
  124. package/library/templates/data-models/README.md +93 -0
  125. package/library/templates/data-models/finance-model.md +627 -0
  126. package/library/templates/data-models/retail-star-schema.md +473 -0
  127. package/library/templates/excel/README.md +83 -0
  128. package/library/templates/excel/budget-tracker.md +432 -0
  129. package/library/templates/excel/data-entry-form.md +533 -0
  130. package/library/templates/power-bi/README.md +72 -0
  131. package/library/templates/power-bi/finance-report.md +449 -0
  132. package/library/templates/power-bi/kpi-scorecard.md +461 -0
  133. package/library/templates/power-bi/sales-dashboard.md +281 -0
  134. package/library/themes/excel/README.md +436 -0
  135. package/library/themes/power-bi/README.md +271 -0
  136. package/library/themes/power-bi/accessible.json +307 -0
  137. package/library/themes/power-bi/bi-superpowers-default.json +858 -0
  138. package/library/themes/power-bi/corporate-blue.json +291 -0
  139. package/library/themes/power-bi/dark-mode.json +291 -0
  140. package/library/themes/power-bi/minimal.json +292 -0
  141. package/library/themes/power-bi/print-friendly.json +309 -0
  142. package/package.json +93 -0
  143. package/skills/contributions/SKILL.md +267 -0
  144. package/skills/data-model-design/SKILL.md +470 -0
  145. package/skills/data-modeling/SKILL.md +254 -0
  146. package/skills/data-quality/SKILL.md +664 -0
  147. package/skills/dax/SKILL.md +708 -0
  148. package/skills/dax-doctor/SKILL.md +250 -0
  149. package/skills/dax-udf/SKILL.md +489 -0
  150. package/skills/deployment/SKILL.md +320 -0
  151. package/skills/excel-formulas/SKILL.md +463 -0
  152. package/skills/fabric-scripts/SKILL.md +454 -0
  153. package/skills/fast-standard/SKILL.md +509 -0
  154. package/skills/governance/SKILL.md +205 -0
  155. package/skills/migration-assistant/SKILL.md +292 -0
  156. package/skills/model-documenter/SKILL.md +244 -0
  157. package/skills/pbi-connect/SKILL.md +241 -0
  158. package/skills/power-query/SKILL.md +406 -0
  159. package/skills/project-kickoff/SKILL.md +907 -0
  160. package/skills/query-performance/SKILL.md +480 -0
  161. package/skills/report-design/SKILL.md +207 -0
  162. package/skills/report-layout/SKILL.md +298 -0
  163. package/skills/rls-design/SKILL.md +535 -0
  164. package/skills/semantic-model/SKILL.md +237 -0
  165. package/skills/testing-validation/SKILL.md +643 -0
  166. package/skills/theme-tweaker/SKILL.md +626 -0
  167. package/src/content/base.md +237 -0
  168. package/src/content/mcp-requirements.json +69 -0
  169. package/src/content/routing.md +203 -0
  170. package/src/content/skills/contributions.md +259 -0
  171. package/src/content/skills/data-model-design.md +462 -0
  172. package/src/content/skills/data-modeling.md +246 -0
  173. package/src/content/skills/data-quality.md +656 -0
  174. package/src/content/skills/dax-doctor.md +242 -0
  175. package/src/content/skills/dax-udf.md +481 -0
  176. package/src/content/skills/dax.md +700 -0
  177. package/src/content/skills/deployment.md +312 -0
  178. package/src/content/skills/excel-formulas.md +455 -0
  179. package/src/content/skills/fabric-scripts.md +446 -0
  180. package/src/content/skills/fast-standard.md +501 -0
  181. package/src/content/skills/governance.md +197 -0
  182. package/src/content/skills/migration-assistant.md +284 -0
  183. package/src/content/skills/model-documenter.md +236 -0
  184. package/src/content/skills/pbi-connect.md +233 -0
  185. package/src/content/skills/power-query.md +398 -0
  186. package/src/content/skills/project-kickoff.md +899 -0
  187. package/src/content/skills/query-performance.md +472 -0
  188. package/src/content/skills/report-design.md +199 -0
  189. package/src/content/skills/report-layout.md +290 -0
  190. package/src/content/skills/rls-design.md +527 -0
  191. package/src/content/skills/semantic-model.md +229 -0
  192. package/src/content/skills/testing-validation.md +635 -0
  193. package/src/content/skills/theme-tweaker.md +618 -0
@@ -0,0 +1,489 @@
1
+ # Calculation Groups in DAX
2
+
3
+ Patterns for creating and using calculation groups for time intelligence, currency conversion, and measure formatting.
4
+
5
+ ---
6
+
7
+ ## What Are Calculation Groups?
8
+
9
+ Calculation groups modify how measures are evaluated without changing the measures themselves. They're created in external tools (Tabular Editor, TMDL) and consist of:
10
+
11
+ - **Calculation Group**: Container table
12
+ - **Calculation Items**: Individual modifiers (e.g., YTD, PY, MTD)
13
+ - **SELECTEDMEASURE()**: Reference to the measure being modified
14
+
15
+ ---
16
+
17
+ ## Time Intelligence Calculation Group
18
+
19
+ ### Basic Time Intelligence Items
20
+
21
+ ```dax
22
+ // Calculation Group: Time Calculations
23
+ // Column: Time Calculation
24
+
25
+ // Item: Current
26
+ SELECTEDMEASURE()
27
+
28
+ // Item: YTD (Year-to-Date)
29
+ CALCULATE(
30
+ SELECTEDMEASURE(),
31
+ DATESYTD('Date'[Date])
32
+ )
33
+
34
+ // Item: PY (Prior Year)
35
+ CALCULATE(
36
+ SELECTEDMEASURE(),
37
+ SAMEPERIODLASTYEAR('Date'[Date])
38
+ )
39
+
40
+ // Item: YTD PY (Prior Year YTD)
41
+ CALCULATE(
42
+ SELECTEDMEASURE(),
43
+ DATESYTD(SAMEPERIODLASTYEAR('Date'[Date]))
44
+ )
45
+
46
+ // Item: QTD (Quarter-to-Date)
47
+ CALCULATE(
48
+ SELECTEDMEASURE(),
49
+ DATESQTD('Date'[Date])
50
+ )
51
+
52
+ // Item: MTD (Month-to-Date)
53
+ CALCULATE(
54
+ SELECTEDMEASURE(),
55
+ DATESMTD('Date'[Date])
56
+ )
57
+
58
+ // Item: Rolling 12 Months
59
+ CALCULATE(
60
+ SELECTEDMEASURE(),
61
+ DATESINPERIOD('Date'[Date], MAX('Date'[Date]), -12, MONTH)
62
+ )
63
+
64
+ // Item: Rolling 3 Months
65
+ CALCULATE(
66
+ SELECTEDMEASURE(),
67
+ DATESINPERIOD('Date'[Date], MAX('Date'[Date]), -3, MONTH)
68
+ )
69
+ ```
70
+
71
+ ### YoY Variance Items
72
+
73
+ ```dax
74
+ // Item: YoY Abs (Year-over-Year Absolute)
75
+ VAR _Current = SELECTEDMEASURE()
76
+ VAR _PY = CALCULATE(SELECTEDMEASURE(), SAMEPERIODLASTYEAR('Date'[Date]))
77
+ RETURN
78
+ _Current - _PY
79
+
80
+ // Item: YoY % (Year-over-Year Percentage)
81
+ VAR _Current = SELECTEDMEASURE()
82
+ VAR _PY = CALCULATE(SELECTEDMEASURE(), SAMEPERIODLASTYEAR('Date'[Date]))
83
+ RETURN
84
+ DIVIDE(_Current - _PY, ABS(_PY))
85
+
86
+ // Item: YTD YoY % (YTD Year-over-Year Percentage)
87
+ VAR _CurrentYTD = CALCULATE(SELECTEDMEASURE(), DATESYTD('Date'[Date]))
88
+ VAR _PYYTD = CALCULATE(SELECTEDMEASURE(), DATESYTD(SAMEPERIODLASTYEAR('Date'[Date])))
89
+ RETURN
90
+ DIVIDE(_CurrentYTD - _PYYTD, ABS(_PYYTD))
91
+ ```
92
+
93
+ ### Fiscal Year Time Intelligence
94
+
95
+ ```dax
96
+ // Item: FYTD (Fiscal Year-to-Date)
97
+ // Assumes July 1 fiscal year start
98
+ CALCULATE(
99
+ SELECTEDMEASURE(),
100
+ DATESYTD('Date'[Date], "6-30") // Fiscal year end
101
+ )
102
+
103
+ // Item: FY PY (Fiscal Prior Year)
104
+ CALCULATE(
105
+ SELECTEDMEASURE(),
106
+ DATEADD('Date'[Date], -1, YEAR)
107
+ )
108
+ ```
109
+
110
+ ---
111
+
112
+ ## Currency Conversion Calculation Group
113
+
114
+ ### Multi-Currency Items
115
+
116
+ ```dax
117
+ // Calculation Group: Currency
118
+ // Column: Currency Display
119
+
120
+ // Item: Local Currency
121
+ SELECTEDMEASURE()
122
+
123
+ // Item: USD
124
+ VAR _Result = SELECTEDMEASURE()
125
+ VAR _AvgRate = AVERAGE(DimCurrency[ToUSD_Rate])
126
+ RETURN
127
+ _Result * _AvgRate
128
+
129
+ // Item: EUR
130
+ VAR _Result = SELECTEDMEASURE()
131
+ VAR _AvgRate = AVERAGE(DimCurrency[ToEUR_Rate])
132
+ RETURN
133
+ _Result * _AvgRate
134
+
135
+ // Item: GBP
136
+ VAR _Result = SELECTEDMEASURE()
137
+ VAR _AvgRate = AVERAGE(DimCurrency[ToGBP_Rate])
138
+ RETURN
139
+ _Result * _AvgRate
140
+ ```
141
+
142
+ ### With Historical Rates
143
+
144
+ ```dax
145
+ // Item: USD (Historical Rate)
146
+ SUMX(
147
+ VALUES('Date'[Date]),
148
+ VAR _DailyAmount = CALCULATE(SELECTEDMEASURE())
149
+ VAR _DailyRate =
150
+ CALCULATE(
151
+ VALUES(DimExchangeRate[ToUSD]),
152
+ DimExchangeRate[Date] = EARLIER('Date'[Date])
153
+ )
154
+ RETURN
155
+ _DailyAmount * _DailyRate
156
+ )
157
+ ```
158
+
159
+ ---
160
+
161
+ ## Budget vs Actual Calculation Group
162
+
163
+ ### Scenario Comparison Items
164
+
165
+ ```dax
166
+ // Calculation Group: Scenario Analysis
167
+ // Column: Scenario
168
+
169
+ // Item: Actual
170
+ CALCULATE(
171
+ SELECTEDMEASURE(),
172
+ DimScenario[ScenarioName] = "Actual"
173
+ )
174
+
175
+ // Item: Budget
176
+ CALCULATE(
177
+ SELECTEDMEASURE(),
178
+ DimScenario[ScenarioName] = "Budget"
179
+ )
180
+
181
+ // Item: Forecast
182
+ CALCULATE(
183
+ SELECTEDMEASURE(),
184
+ DimScenario[ScenarioName] = "Forecast"
185
+ )
186
+
187
+ // Item: Variance (Actual - Budget)
188
+ VAR _Actual = CALCULATE(SELECTEDMEASURE(), DimScenario[ScenarioName] = "Actual")
189
+ VAR _Budget = CALCULATE(SELECTEDMEASURE(), DimScenario[ScenarioName] = "Budget")
190
+ RETURN
191
+ _Actual - _Budget
192
+
193
+ // Item: Variance %
194
+ VAR _Actual = CALCULATE(SELECTEDMEASURE(), DimScenario[ScenarioName] = "Actual")
195
+ VAR _Budget = CALCULATE(SELECTEDMEASURE(), DimScenario[ScenarioName] = "Budget")
196
+ RETURN
197
+ DIVIDE(_Actual - _Budget, ABS(_Budget))
198
+
199
+ // Item: Attainment %
200
+ VAR _Actual = CALCULATE(SELECTEDMEASURE(), DimScenario[ScenarioName] = "Actual")
201
+ VAR _Budget = CALCULATE(SELECTEDMEASURE(), DimScenario[ScenarioName] = "Budget")
202
+ RETURN
203
+ DIVIDE(_Actual, _Budget)
204
+ ```
205
+
206
+ ---
207
+
208
+ ## Format String Calculation Group
209
+
210
+ ### Dynamic Formatting Items
211
+
212
+ ```dax
213
+ // Calculation Group: Display Format
214
+ // Column: Format
215
+
216
+ // Item: Number
217
+ SELECTEDMEASURE()
218
+ // Format String: #,##0
219
+
220
+ // Item: Currency
221
+ SELECTEDMEASURE()
222
+ // Format String: $#,##0
223
+
224
+ // Item: Percent
225
+ SELECTEDMEASURE()
226
+ // Format String: 0.0%
227
+
228
+ // Item: Thousands (K)
229
+ DIVIDE(SELECTEDMEASURE(), 1000)
230
+ // Format String: #,##0 K
231
+
232
+ // Item: Millions (M)
233
+ DIVIDE(SELECTEDMEASURE(), 1000000)
234
+ // Format String: #,##0.0 M
235
+
236
+ // Item: Billions (B)
237
+ DIVIDE(SELECTEDMEASURE(), 1000000000)
238
+ // Format String: #,##0.00 B
239
+ ```
240
+
241
+ ### Conditional Formatting
242
+
243
+ ```dax
244
+ // Item: Auto Scale
245
+ VAR _Value = SELECTEDMEASURE()
246
+ RETURN
247
+ SWITCH(
248
+ TRUE(),
249
+ ABS(_Value) >= 1000000000, DIVIDE(_Value, 1000000000),
250
+ ABS(_Value) >= 1000000, DIVIDE(_Value, 1000000),
251
+ ABS(_Value) >= 1000, DIVIDE(_Value, 1000),
252
+ _Value
253
+ )
254
+ // Dynamic format string (requires Tabular Editor 3):
255
+ // "Auto" -- or implement via FORMAT in the item
256
+ ```
257
+
258
+ ---
259
+
260
+ ## Advanced Patterns
261
+
262
+ ### Moving Averages
263
+
264
+ ```dax
265
+ // Calculation Group: Moving Averages
266
+ // Column: Moving Average
267
+
268
+ // Item: Current
269
+ SELECTEDMEASURE()
270
+
271
+ // Item: 3-Month Moving Average
272
+ AVERAGEX(
273
+ DATESINPERIOD('Date'[Date], MAX('Date'[Date]), -3, MONTH),
274
+ CALCULATE(SELECTEDMEASURE())
275
+ )
276
+
277
+ // Item: 6-Month Moving Average
278
+ AVERAGEX(
279
+ DATESINPERIOD('Date'[Date], MAX('Date'[Date]), -6, MONTH),
280
+ CALCULATE(SELECTEDMEASURE())
281
+ )
282
+
283
+ // Item: 12-Month Moving Average
284
+ AVERAGEX(
285
+ DATESINPERIOD('Date'[Date], MAX('Date'[Date]), -12, MONTH),
286
+ CALCULATE(SELECTEDMEASURE())
287
+ )
288
+ ```
289
+
290
+ ### Period-over-Period
291
+
292
+ ```dax
293
+ // Item: MoM (Month-over-Month)
294
+ VAR _Current = SELECTEDMEASURE()
295
+ VAR _PM = CALCULATE(SELECTEDMEASURE(), DATEADD('Date'[Date], -1, MONTH))
296
+ RETURN
297
+ _Current - _PM
298
+
299
+ // Item: MoM %
300
+ VAR _Current = SELECTEDMEASURE()
301
+ VAR _PM = CALCULATE(SELECTEDMEASURE(), DATEADD('Date'[Date], -1, MONTH))
302
+ RETURN
303
+ DIVIDE(_Current - _PM, ABS(_PM))
304
+
305
+ // Item: QoQ (Quarter-over-Quarter)
306
+ VAR _Current = SELECTEDMEASURE()
307
+ VAR _PQ = CALCULATE(SELECTEDMEASURE(), DATEADD('Date'[Date], -1, QUARTER))
308
+ RETURN
309
+ _Current - _PQ
310
+
311
+ // Item: QoQ %
312
+ VAR _Current = SELECTEDMEASURE()
313
+ VAR _PQ = CALCULATE(SELECTEDMEASURE(), DATEADD('Date'[Date], -1, QUARTER))
314
+ RETURN
315
+ DIVIDE(_Current - _PQ, ABS(_PQ))
316
+ ```
317
+
318
+ ### Growth Rates
319
+
320
+ ```dax
321
+ // Item: CAGR (Compound Annual Growth Rate)
322
+ VAR _StartValue =
323
+ CALCULATE(
324
+ SELECTEDMEASURE(),
325
+ FIRSTDATE('Date'[Date])
326
+ )
327
+ VAR _EndValue =
328
+ CALCULATE(
329
+ SELECTEDMEASURE(),
330
+ LASTDATE('Date'[Date])
331
+ )
332
+ VAR _Years =
333
+ DATEDIFF(
334
+ MIN('Date'[Date]),
335
+ MAX('Date'[Date]),
336
+ YEAR
337
+ )
338
+ RETURN
339
+ IF(
340
+ _Years > 0 && _StartValue > 0,
341
+ POWER(DIVIDE(_EndValue, _StartValue), DIVIDE(1, _Years)) - 1,
342
+ BLANK()
343
+ )
344
+ ```
345
+
346
+ ---
347
+
348
+ ## Multiple Calculation Groups
349
+
350
+ ### Combining Time + Currency
351
+
352
+ When you have multiple calculation groups, they compose:
353
+
354
+ ```
355
+ Revenue with "YTD" + "USD" =
356
+ Revenue calculated YTD, then converted to USD
357
+ ```
358
+
359
+ **Order matters in Tabular Editor:**
360
+ - Set precedence for each calculation group
361
+ - Higher precedence applies outer (last)
362
+
363
+ ```dax
364
+ // If Time has precedence 10, Currency has precedence 20:
365
+ // Currency(Time(SELECTEDMEASURE()))
366
+
367
+ // The currency conversion wraps the time calculation
368
+ ```
369
+
370
+ ### Precedence Example
371
+
372
+ ```
373
+ Calculation Group: Time Intelligence (Precedence: 10)
374
+ Calculation Group: Currency (Precedence: 20)
375
+ Calculation Group: Format (Precedence: 30)
376
+
377
+ Result: Format(Currency(Time(Measure)))
378
+ ```
379
+
380
+ ---
381
+
382
+ ## Using in Reports
383
+
384
+ ### Slicer on Calculation Group
385
+
386
+ 1. Add calculation group column to slicer
387
+ 2. User selects "YTD" or "PY"
388
+ 3. All measures automatically adjust
389
+
390
+ ### Matrix with Calculation Items
391
+
392
+ | Product | Current | YTD | PY | YoY % |
393
+ |---------|---------|-----|----|----- |
394
+ | Widget A | 100K | 800K | 90K | 11% |
395
+ | Widget B | 75K | 600K | 80K | -6% |
396
+
397
+ ### Combining with Regular Measures
398
+
399
+ ```dax
400
+ // Measure that uses calculation group result
401
+ Revenue with Time Calc =
402
+ VAR _TimeCalc = SELECTEDVALUE('Time Calculations'[Time Calculation], "Current")
403
+ RETURN
404
+ SWITCH(
405
+ _TimeCalc,
406
+ "Current", [Revenue],
407
+ "YTD", [Revenue YTD], // Explicit measure
408
+ [Revenue] // Fallback
409
+ )
410
+ ```
411
+
412
+ ---
413
+
414
+ ## Best Practices
415
+
416
+ ### 1. Name Items Clearly
417
+
418
+ ```
419
+ ✓ "YTD (Year-to-Date)"
420
+ ✓ "PY (Prior Year)"
421
+ ✓ "YoY % (Year-over-Year %)"
422
+
423
+ ✗ "Calc1"
424
+ ✗ "Time1"
425
+ ```
426
+
427
+ ### 2. Include "Current" Item
428
+
429
+ ```dax
430
+ // Always have a baseline item
431
+ // Item: Current
432
+ SELECTEDMEASURE()
433
+ ```
434
+
435
+ ### 3. Handle Blanks
436
+
437
+ ```dax
438
+ // Item: YoY % (with blank handling)
439
+ VAR _Current = SELECTEDMEASURE()
440
+ VAR _PY = CALCULATE(SELECTEDMEASURE(), SAMEPERIODLASTYEAR('Date'[Date]))
441
+ RETURN
442
+ IF(
443
+ ISBLANK(_PY) || _PY = 0,
444
+ BLANK(),
445
+ DIVIDE(_Current - _PY, ABS(_PY))
446
+ )
447
+ ```
448
+
449
+ ### 4. Set Format Strings
450
+
451
+ Each calculation item can have its own format string:
452
+
453
+ | Item | Format String |
454
+ |------|---------------|
455
+ | Current | #,##0 |
456
+ | YoY % | 0.0% |
457
+ | YoY Abs | +#,##0;-#,##0;0 |
458
+
459
+ ### 5. Test with Multiple Measures
460
+
461
+ Calculation groups apply to ALL measures. Test with:
462
+ - Sum measures (Revenue, Quantity)
463
+ - Average measures (Avg Price)
464
+ - Count measures (Customer Count)
465
+ - Ratio measures (Margin %)
466
+
467
+ ---
468
+
469
+ ## Limitations
470
+
471
+ | Limitation | Workaround |
472
+ |------------|------------|
473
+ | Cannot use with semi-additive measures (Avg, Distinct Count) without care | Create explicit measures for these |
474
+ | Format strings limited in Power BI Desktop | Use Tabular Editor 3 |
475
+ | No nested calculation groups | Set precedence carefully |
476
+ | Can't reference another calc item | Use explicit measures |
477
+
478
+ ---
479
+
480
+ ## Setup Checklist
481
+
482
+ - [ ] Identify repetitive time intelligence patterns
483
+ - [ ] Create calculation group in Tabular Editor
484
+ - [ ] Add calculation items with clear names
485
+ - [ ] Set format strings for each item
486
+ - [ ] Set precedence if multiple groups
487
+ - [ ] Test with various measure types
488
+ - [ ] Add slicer to report
489
+ - [ ] Document for users