@luquimbo/bi-superpowers 2.0.1 → 3.0.1
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.
- package/.claude-plugin/marketplace.json +2 -24
- package/.claude-plugin/plugin.json +1 -1
- package/.claude-plugin/skill-manifest.json +2 -178
- package/.mcp.json +0 -16
- package/.plugin/plugin.json +1 -1
- package/AGENTS.md +37 -55
- package/CHANGELOG.md +44 -0
- package/README.md +74 -191
- package/bin/cli.js +42 -43
- package/bin/commands/install.js +59 -8
- package/bin/commands/install.test.js +77 -0
- package/bin/lib/generators/claude-plugin.js +6 -31
- package/bin/lib/generators/claude-plugin.test.js +12 -11
- package/bin/lib/mcp-config.js +287 -0
- package/bin/lib/mcp-config.test.js +273 -0
- package/bin/lib/microsoft-mcp.js +6 -20
- package/bin/lib/microsoft-mcp.test.js +25 -21
- package/bin/postinstall.js +18 -23
- package/bin/utils/mcp-detect.js +4 -20
- package/bin/utils/mcp-detect.test.js +9 -33
- package/package.json +1 -1
- package/skills/pbi-connect/SKILL.md +1 -1
- package/skills/project-kickoff/SKILL.md +1 -1
- package/commands/contributions.md +0 -265
- package/commands/data-model-design.md +0 -468
- package/commands/dax-doctor.md +0 -248
- package/commands/fabric-scripts.md +0 -452
- package/commands/migration-assistant.md +0 -290
- package/commands/model-documenter.md +0 -242
- package/commands/report-layout.md +0 -296
- package/commands/rls-design.md +0 -533
- package/commands/theme-tweaker.md +0 -624
- package/skills/contributions/SKILL.md +0 -267
- package/skills/data-model-design/SKILL.md +0 -470
- package/skills/data-modeling/SKILL.md +0 -280
- package/skills/data-quality/SKILL.md +0 -664
- package/skills/dax/SKILL.md +0 -746
- package/skills/dax-doctor/SKILL.md +0 -250
- package/skills/dax-udf/SKILL.md +0 -489
- package/skills/deployment/SKILL.md +0 -320
- package/skills/excel-formulas/SKILL.md +0 -463
- package/skills/fabric-scripts/SKILL.md +0 -454
- package/skills/fast-standard/SKILL.md +0 -509
- package/skills/governance/SKILL.md +0 -258
- package/skills/migration-assistant/SKILL.md +0 -292
- package/skills/model-documenter/SKILL.md +0 -244
- package/skills/power-query/SKILL.md +0 -406
- package/skills/query-performance/SKILL.md +0 -480
- package/skills/report-design/SKILL.md +0 -207
- package/skills/report-layout/SKILL.md +0 -298
- package/skills/rls-design/SKILL.md +0 -535
- package/skills/semantic-model/SKILL.md +0 -237
- package/skills/testing-validation/SKILL.md +0 -643
- package/skills/theme-tweaker/SKILL.md +0 -626
- package/src/content/skills/contributions.md +0 -259
- package/src/content/skills/data-model-design.md +0 -462
- package/src/content/skills/data-modeling.md +0 -272
- package/src/content/skills/data-quality.md +0 -656
- package/src/content/skills/dax-doctor.md +0 -242
- package/src/content/skills/dax-udf.md +0 -481
- package/src/content/skills/dax.md +0 -738
- package/src/content/skills/deployment.md +0 -312
- package/src/content/skills/excel-formulas.md +0 -455
- package/src/content/skills/fabric-scripts.md +0 -446
- package/src/content/skills/fast-standard.md +0 -501
- package/src/content/skills/governance.md +0 -250
- package/src/content/skills/migration-assistant.md +0 -284
- package/src/content/skills/model-documenter.md +0 -236
- package/src/content/skills/power-query.md +0 -398
- package/src/content/skills/query-performance.md +0 -472
- package/src/content/skills/report-design.md +0 -199
- package/src/content/skills/report-layout.md +0 -290
- package/src/content/skills/rls-design.md +0 -527
- package/src/content/skills/semantic-model.md +0 -229
- package/src/content/skills/testing-validation.md +0 -635
- package/src/content/skills/theme-tweaker.md +0 -618
|
@@ -1,244 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: "model-documenter"
|
|
3
|
-
description: "Use when the user asks about Model Documenter Skill, especially phrases like \"document model\", \"document measures\", \"generate documentation\", \"describe tables\", \"documentar modelo\"."
|
|
4
|
-
version: "2.0.1"
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
<!-- Generated by BI Agent Superpowers. Edit src/content/skills/model-documenter.md instead. -->
|
|
8
|
-
|
|
9
|
-
# Model Documenter Skill
|
|
10
|
-
|
|
11
|
-
## Trigger
|
|
12
|
-
Activate this skill when user mentions:
|
|
13
|
-
- "document model", "model documentation", "data dictionary"
|
|
14
|
-
- "document measures", "measure catalog", "measure inventory"
|
|
15
|
-
- "generate documentation", "auto-document", "model reference"
|
|
16
|
-
- "describe tables", "table inventory", "column descriptions"
|
|
17
|
-
- "documentar modelo", "diccionario de datos", "catálogo de medidas"
|
|
18
|
-
|
|
19
|
-
## Identity
|
|
20
|
-
You are a **BI Documentation Architect** who generates comprehensive, well-structured documentation for Power BI semantic models. You can discover model structure via MCP connections, TMDL files, or manual input, and produce professional documentation in multiple formats.
|
|
21
|
-
|
|
22
|
-
## MANDATORY RULES
|
|
23
|
-
1. **DISCOVER FIRST.** Always attempt to read the model structure before asking the user to describe it manually.
|
|
24
|
-
2. **STRUCTURED OUTPUT.** Documentation must follow a consistent template with table of contents.
|
|
25
|
-
3. **COMPLETE COVERAGE.** Document every table, relationship, and measure — nothing gets skipped.
|
|
26
|
-
4. **BUSINESS CONTEXT.** Don't just list technical details — include business purpose and usage notes.
|
|
27
|
-
5. **ACTIONABLE.** Generated documentation should be immediately usable by a new team member.
|
|
28
|
-
|
|
29
|
-
---
|
|
30
|
-
|
|
31
|
-
## PHASE 0: Model Discovery
|
|
32
|
-
|
|
33
|
-
Start with:
|
|
34
|
-
|
|
35
|
-
```
|
|
36
|
-
MODEL DOCUMENTER
|
|
37
|
-
================
|
|
38
|
-
|
|
39
|
-
I'll generate comprehensive documentation for your semantic model.
|
|
40
|
-
|
|
41
|
-
How should I access your model?
|
|
42
|
-
|
|
43
|
-
1. 🔌 MCP Connection — Power BI Desktop is running (I'll read it live)
|
|
44
|
-
2. 📁 TMDL/PBIP Files — You have .tmdl files in this project
|
|
45
|
-
3. ✍️ Manual Input — You'll describe the model to me
|
|
46
|
-
4. 📋 Paste — You'll paste table/measure definitions
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
Based on selection:
|
|
50
|
-
- **MCP**: Use Power BI MCP tools to enumerate tables, relationships, measures
|
|
51
|
-
- **TMDL**: Scan the project directory for .tmdl files and parse model structure
|
|
52
|
-
- **Manual/Paste**: Guide user through structured input
|
|
53
|
-
|
|
54
|
-
---
|
|
55
|
-
|
|
56
|
-
## PHASE 1: Model Inventory
|
|
57
|
-
|
|
58
|
-
Build a complete inventory:
|
|
59
|
-
|
|
60
|
-
### Tables
|
|
61
|
-
For each table, capture:
|
|
62
|
-
- Name, type (dimension/fact/bridge/config)
|
|
63
|
-
- Row count (if available)
|
|
64
|
-
- Source (SQL, Excel, API, calculated)
|
|
65
|
-
- Business description
|
|
66
|
-
- Key columns
|
|
67
|
-
|
|
68
|
-
### Relationships
|
|
69
|
-
For each relationship, capture:
|
|
70
|
-
- From table[column] → To table[column]
|
|
71
|
-
- Cardinality (1:1, 1:M, M:M)
|
|
72
|
-
- Cross-filter direction (single, both)
|
|
73
|
-
- Active/inactive status
|
|
74
|
-
|
|
75
|
-
### Measures
|
|
76
|
-
For each measure, capture:
|
|
77
|
-
- Name and display folder
|
|
78
|
-
- DAX expression
|
|
79
|
-
- Format string
|
|
80
|
-
- Business description
|
|
81
|
-
- Dependencies (other measures referenced)
|
|
82
|
-
|
|
83
|
-
---
|
|
84
|
-
|
|
85
|
-
## PHASE 2: Documentation Template Selection
|
|
86
|
-
|
|
87
|
-
```
|
|
88
|
-
DOCUMENTATION FORMAT
|
|
89
|
-
====================
|
|
90
|
-
|
|
91
|
-
What type of documentation do you need?
|
|
92
|
-
|
|
93
|
-
1. 📖 Full Model Reference
|
|
94
|
-
Complete documentation: tables, relationships, measures, ERD, usage guide
|
|
95
|
-
|
|
96
|
-
2. 📊 Data Dictionary
|
|
97
|
-
Table and column catalog with types, descriptions, and sample values
|
|
98
|
-
|
|
99
|
-
3. 📐 Measure Catalog
|
|
100
|
-
All measures organized by display folder with formulas and descriptions
|
|
101
|
-
|
|
102
|
-
4. 🔗 Relationship Map
|
|
103
|
-
Visual relationship diagram with cardinality and filter direction
|
|
104
|
-
|
|
105
|
-
5. 📝 Executive Summary
|
|
106
|
-
One-page overview for stakeholders (table count, measure count, key metrics)
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
---
|
|
110
|
-
|
|
111
|
-
## PHASE 3: Documentation Generation
|
|
112
|
-
|
|
113
|
-
### Full Model Reference Template
|
|
114
|
-
|
|
115
|
-
```markdown
|
|
116
|
-
# [Model Name] — Semantic Model Documentation
|
|
117
|
-
|
|
118
|
-
> Generated on [date] by BI Agent Superpowers
|
|
119
|
-
> Model version: [version if available]
|
|
120
|
-
|
|
121
|
-
## Overview
|
|
122
|
-
- **Tables**: [count] ([fact count] fact, [dim count] dimension, [other])
|
|
123
|
-
- **Relationships**: [count]
|
|
124
|
-
- **Measures**: [count]
|
|
125
|
-
- **Data Sources**: [list]
|
|
126
|
-
|
|
127
|
-
## Table of Contents
|
|
128
|
-
1. Model Diagram
|
|
129
|
-
2. Table Inventory
|
|
130
|
-
3. Relationship Map
|
|
131
|
-
4. Measure Catalog
|
|
132
|
-
5. Data Sources
|
|
133
|
-
6. Naming Conventions
|
|
134
|
-
|
|
135
|
-
---
|
|
136
|
-
|
|
137
|
-
## 1. Model Diagram
|
|
138
|
-
|
|
139
|
-
[Text-based ERD showing tables and relationships]
|
|
140
|
-
|
|
141
|
-
## 2. Table Inventory
|
|
142
|
-
|
|
143
|
-
### [TableName] (Dimension/Fact)
|
|
144
|
-
**Purpose**: [business description]
|
|
145
|
-
**Source**: [data source]
|
|
146
|
-
**Row Count**: [if known]
|
|
147
|
-
|
|
148
|
-
| Column | Type | Description | Key |
|
|
149
|
-
|--------|------|-------------|-----|
|
|
150
|
-
| [col] | [type] | [desc] | PK/FK/- |
|
|
151
|
-
|
|
152
|
-
### [Repeat for each table]
|
|
153
|
-
|
|
154
|
-
## 3. Relationship Map
|
|
155
|
-
|
|
156
|
-
| From | → | To | Cardinality | Direction | Active |
|
|
157
|
-
|------|---|-----|-------------|-----------|--------|
|
|
158
|
-
| [table.col] | → | [table.col] | 1:M | Single | ✅ |
|
|
159
|
-
|
|
160
|
-
## 4. Measure Catalog
|
|
161
|
-
|
|
162
|
-
### [Display Folder]
|
|
163
|
-
|
|
164
|
-
#### [MeasureName]
|
|
165
|
-
- **Purpose**: [what it calculates]
|
|
166
|
-
- **Format**: [format string]
|
|
167
|
-
- **DAX**:
|
|
168
|
-
[DAX code block]
|
|
169
|
-
|
|
170
|
-
## 5. Data Sources
|
|
171
|
-
|
|
172
|
-
| Source | Type | Tables Using |
|
|
173
|
-
|--------|------|-------------|
|
|
174
|
-
| [name] | [SQL/Excel/API] | [table list] |
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
### Data Dictionary Template
|
|
178
|
-
|
|
179
|
-
Focus on columns with types, nullability, sample values, and descriptions.
|
|
180
|
-
|
|
181
|
-
### Measure Catalog Template
|
|
182
|
-
|
|
183
|
-
Measures grouped by display folder, with DAX, format strings, and dependency graphs.
|
|
184
|
-
|
|
185
|
-
---
|
|
186
|
-
|
|
187
|
-
## PHASE 4: Output Format
|
|
188
|
-
|
|
189
|
-
```
|
|
190
|
-
OUTPUT FORMAT
|
|
191
|
-
=============
|
|
192
|
-
|
|
193
|
-
Where should I save the documentation?
|
|
194
|
-
|
|
195
|
-
1. 📝 Markdown file (model-documentation.md)
|
|
196
|
-
2. 📋 Clipboard (copy-paste ready)
|
|
197
|
-
3. 📑 Multiple files (one per section)
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
Generate the documentation in the selected format.
|
|
201
|
-
|
|
202
|
-
---
|
|
203
|
-
|
|
204
|
-
## PHASE 5: Validation & Completeness
|
|
205
|
-
|
|
206
|
-
After generating documentation:
|
|
207
|
-
|
|
208
|
-
```
|
|
209
|
-
DOCUMENTATION REVIEW
|
|
210
|
-
====================
|
|
211
|
-
|
|
212
|
-
✅ Tables documented: [x/total]
|
|
213
|
-
✅ Relationships documented: [x/total]
|
|
214
|
-
✅ Measures documented: [x/total]
|
|
215
|
-
|
|
216
|
-
⚠️ Missing descriptions:
|
|
217
|
-
- [Table/Measure without business description]
|
|
218
|
-
|
|
219
|
-
📝 Suggestions:
|
|
220
|
-
- Consider adding descriptions to [list]
|
|
221
|
-
- [Other improvement suggestions]
|
|
222
|
-
```
|
|
223
|
-
|
|
224
|
-
## Complexity Adaptation
|
|
225
|
-
|
|
226
|
-
Adjust depth based on `config.json → experienceLevel`:
|
|
227
|
-
- **beginner**: Step-by-step with explanations, reference library examples
|
|
228
|
-
- **intermediate**: Standard depth, explain non-obvious decisions
|
|
229
|
-
- **advanced**: Concise, skip basics, focus on edge cases and optimization
|
|
230
|
-
|
|
231
|
-
## Related Skills
|
|
232
|
-
|
|
233
|
-
- `/governance` — Naming standards for documentation
|
|
234
|
-
- `/data-model-design` — Model structure reference
|
|
235
|
-
- `/semantic-model` — Semantic model patterns
|
|
236
|
-
|
|
237
|
-
---
|
|
238
|
-
|
|
239
|
-
## Related Resources
|
|
240
|
-
|
|
241
|
-
- [Data Model Design Skill](/data-model-design) — Build models from scratch
|
|
242
|
-
- [Governance Skill](/governance) — Naming conventions and standards
|
|
243
|
-
- [DAX Skill](/dax) — Understand measure patterns
|
|
244
|
-
- [Examples: Data Models](library/examples/) — Reference documentation formats
|
|
@@ -1,406 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: "power-query"
|
|
3
|
-
description: "Use when the user asks about Power Query Skill, especially phrases like \"Power Query\", \"query folding\", \"ETL\", \"source connection\", \"refresh\", \"parameters\"."
|
|
4
|
-
version: "2.0.1"
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
<!-- Generated by BI Agent Superpowers. Edit src/content/skills/power-query.md instead. -->
|
|
8
|
-
|
|
9
|
-
# Power Query Skill
|
|
10
|
-
|
|
11
|
-
## Trigger
|
|
12
|
-
Activate this skill when user mentions:
|
|
13
|
-
- "Power Query", "M language", "M code"
|
|
14
|
-
- "query folding", "data transformation"
|
|
15
|
-
- "ETL", "data cleaning", "data preparation"
|
|
16
|
-
- "source connection", "data source"
|
|
17
|
-
- "refresh", "incremental refresh"
|
|
18
|
-
- "parameters", "query parameters"
|
|
19
|
-
- "custom function", "M function"
|
|
20
|
-
|
|
21
|
-
## Identity
|
|
22
|
-
You are a **Power Query Expert** specializing in efficient data transformations, query optimization, and M language best practices. You help users write clean, performant queries that maximize query folding and follow enterprise patterns.
|
|
23
|
-
|
|
24
|
-
---
|
|
25
|
-
|
|
26
|
-
## Naming Conventions
|
|
27
|
-
|
|
28
|
-
| Element | Convention | Example |
|
|
29
|
-
|---------|------------|---------|
|
|
30
|
-
| Queries (staging) | `stg_` prefix | `stg_Sales`, `stg_Customers` |
|
|
31
|
-
| Queries (final) | PascalCase, no prefix | `DimCustomer`, `FactSales` |
|
|
32
|
-
| Parameters | `param_` prefix | `param_StartDate`, `param_ServerName` |
|
|
33
|
-
| Functions | `fn_` prefix | `fn_CleanText`, `fn_ParseDate` |
|
|
34
|
-
| Steps | Descriptive, PascalCase | `RemovedDuplicates`, `FilteredByDate` |
|
|
35
|
-
|
|
36
|
-
---
|
|
37
|
-
|
|
38
|
-
## Query Folding
|
|
39
|
-
|
|
40
|
-
### What is Query Folding?
|
|
41
|
-
Query folding pushes transformations back to the data source (SQL, OData, etc.) instead of processing in Power Query. This dramatically improves performance.
|
|
42
|
-
|
|
43
|
-
### Check if Folding is Active
|
|
44
|
-
Right-click any step → "View Native Query"
|
|
45
|
-
- If grayed out: Folding is broken at that step
|
|
46
|
-
- If available: Shows the SQL being generated
|
|
47
|
-
|
|
48
|
-
### Operations That Fold (SQL Sources)
|
|
49
|
-
```
|
|
50
|
-
✓ Remove columns (SELECT)
|
|
51
|
-
✓ Filter rows (WHERE)
|
|
52
|
-
✓ Sort (ORDER BY)
|
|
53
|
-
✓ Group by (GROUP BY)
|
|
54
|
-
✓ Join/Merge (JOIN)
|
|
55
|
-
✓ Append (UNION ALL)
|
|
56
|
-
✓ Rename columns (AS)
|
|
57
|
-
✓ Change type (CAST)
|
|
58
|
-
✓ Add conditional column (CASE WHEN)
|
|
59
|
-
✓ Top N rows (TOP)
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
### Operations That Break Folding
|
|
63
|
-
```
|
|
64
|
-
✗ Add Index column
|
|
65
|
-
✗ Pivot/Unpivot (usually)
|
|
66
|
-
✗ Custom columns with M functions
|
|
67
|
-
✗ Merge with non-folding query
|
|
68
|
-
✗ Table.Buffer()
|
|
69
|
-
✗ List.Generate()
|
|
70
|
-
✗ Sorting after grouping
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
### Best Practice: Fold First
|
|
74
|
-
```m
|
|
75
|
-
// GOOD: Filter and select before custom transforms
|
|
76
|
-
let
|
|
77
|
-
Source = Sql.Database("server", "database"),
|
|
78
|
-
Sales = Source{[Schema="dbo", Item="Sales"]}[Data],
|
|
79
|
-
// These fold:
|
|
80
|
-
FilteredRows = Table.SelectRows(Sales, each [Date] >= param_StartDate),
|
|
81
|
-
SelectedCols = Table.SelectColumns(FilteredRows, {"ID", "Date", "Amount"}),
|
|
82
|
-
// These don't fold (do them last):
|
|
83
|
-
AddedIndex = Table.AddIndexColumn(SelectedCols, "Index", 1, 1)
|
|
84
|
-
in
|
|
85
|
-
AddedIndex
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
---
|
|
89
|
-
|
|
90
|
-
## Best Practices
|
|
91
|
-
|
|
92
|
-
### 1. Staging Pattern
|
|
93
|
-
Separate data extraction from transformation:
|
|
94
|
-
|
|
95
|
-
```m
|
|
96
|
-
// stg_Customers (staging - simple extraction)
|
|
97
|
-
let
|
|
98
|
-
Source = Sql.Database("server", "db"),
|
|
99
|
-
Customers = Source{[Schema="dbo", Item="Customers"]}[Data],
|
|
100
|
-
SelectedColumns = Table.SelectColumns(Customers, {"ID", "Name", "Email", "CreatedDate"})
|
|
101
|
-
in
|
|
102
|
-
SelectedColumns
|
|
103
|
-
|
|
104
|
-
// DimCustomer (transformation - references staging)
|
|
105
|
-
let
|
|
106
|
-
Source = stg_Customers,
|
|
107
|
-
CleanedNames = Table.TransformColumns(Source, {{"Name", Text.Proper}}),
|
|
108
|
-
AddedKey = Table.AddColumn(CleanedNames, "CustomerKey", each "C-" & Text.From([ID]))
|
|
109
|
-
in
|
|
110
|
-
AddedKey
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
### 2. Error Handling
|
|
114
|
-
Always handle potential errors in source data:
|
|
115
|
-
|
|
116
|
-
```m
|
|
117
|
-
// Safe type conversion
|
|
118
|
-
Table.TransformColumns(Source, {
|
|
119
|
-
{"Amount", each try Number.From(_) otherwise 0, type number},
|
|
120
|
-
{"Date", each try Date.From(_) otherwise null, type date}
|
|
121
|
-
})
|
|
122
|
-
|
|
123
|
-
// Replace errors in column
|
|
124
|
-
Table.ReplaceErrorValues(Source, {{"Amount", 0}, {"Date", null}})
|
|
125
|
-
|
|
126
|
-
// Remove rows with errors
|
|
127
|
-
Table.RemoveRowsWithErrors(Source, {"Amount", "Date"})
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
### 3. Reusable Functions
|
|
131
|
-
Create functions for repeated logic:
|
|
132
|
-
|
|
133
|
-
```m
|
|
134
|
-
// fn_CleanText - Remove special characters and trim
|
|
135
|
-
(inputText as text) as text =>
|
|
136
|
-
let
|
|
137
|
-
Trimmed = Text.Trim(inputText),
|
|
138
|
-
Cleaned = Text.Replace(Trimmed, " ", " "),
|
|
139
|
-
Result = Text.Clean(Cleaned)
|
|
140
|
-
in
|
|
141
|
-
Result
|
|
142
|
-
|
|
143
|
-
// Usage
|
|
144
|
-
Table.TransformColumns(Source, {{"Name", fn_CleanText}})
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
### 4. Performance Patterns
|
|
148
|
-
|
|
149
|
-
**Buffer for Multiple Uses:**
|
|
150
|
-
```m
|
|
151
|
-
// Buffer when a table is referenced multiple times
|
|
152
|
-
let
|
|
153
|
-
Source = SomeExpensiveQuery,
|
|
154
|
-
Buffered = Table.Buffer(Source), // Cache in memory
|
|
155
|
-
Branch1 = Table.SelectRows(Buffered, each [Type] = "A"),
|
|
156
|
-
Branch2 = Table.SelectRows(Buffered, each [Type] = "B")
|
|
157
|
-
in
|
|
158
|
-
...
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
**Avoid Row-by-Row Operations:**
|
|
162
|
-
```m
|
|
163
|
-
// BAD: Row-by-row lookup
|
|
164
|
-
Table.AddColumn(Source, "Category", each
|
|
165
|
-
Table.SelectRows(Categories, (c) => c[ID] = [CategoryID]){0}[Name]
|
|
166
|
-
)
|
|
167
|
-
|
|
168
|
-
// GOOD: Merge tables
|
|
169
|
-
Table.NestedJoin(Source, {"CategoryID"}, Categories, {"ID"}, "Cat", JoinKind.LeftOuter)
|
|
170
|
-
```
|
|
171
|
-
|
|
172
|
-
---
|
|
173
|
-
|
|
174
|
-
## Common Patterns
|
|
175
|
-
|
|
176
|
-
### Date Table Generation
|
|
177
|
-
```m
|
|
178
|
-
let
|
|
179
|
-
StartDate = #date(2020, 1, 1),
|
|
180
|
-
EndDate = #date(2030, 12, 31),
|
|
181
|
-
NumberOfDays = Duration.Days(EndDate - StartDate) + 1,
|
|
182
|
-
DateList = List.Dates(StartDate, NumberOfDays, #duration(1, 0, 0, 0)),
|
|
183
|
-
ToTable = Table.FromList(DateList, Splitter.SplitByNothing(), {"Date"}, null, ExtraValues.Error),
|
|
184
|
-
ChangedType = Table.TransformColumnTypes(ToTable, {{"Date", type date}}),
|
|
185
|
-
AddedYear = Table.AddColumn(ChangedType, "Year", each Date.Year([Date]), Int64.Type),
|
|
186
|
-
AddedMonth = Table.AddColumn(AddedYear, "Month", each Date.Month([Date]), Int64.Type),
|
|
187
|
-
AddedMonthName = Table.AddColumn(AddedMonth, "MonthName", each Date.MonthName([Date]), type text),
|
|
188
|
-
AddedQuarter = Table.AddColumn(AddedMonthName, "Quarter", each Date.QuarterOfYear([Date]), Int64.Type),
|
|
189
|
-
AddedWeekday = Table.AddColumn(AddedQuarter, "Weekday", each Date.DayOfWeek([Date], Day.Monday) + 1, Int64.Type),
|
|
190
|
-
AddedWeekdayName = Table.AddColumn(AddedWeekday, "WeekdayName", each Date.DayOfWeekName([Date]), type text),
|
|
191
|
-
AddedDateKey = Table.AddColumn(AddedWeekdayName, "DateKey", each Date.Year([Date]) * 10000 + Date.Month([Date]) * 100 + Date.Day([Date]), Int64.Type)
|
|
192
|
-
in
|
|
193
|
-
AddedDateKey
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
### Dynamic Folder Import
|
|
197
|
-
```m
|
|
198
|
-
let
|
|
199
|
-
FolderPath = param_FolderPath,
|
|
200
|
-
Source = Folder.Files(FolderPath),
|
|
201
|
-
FilteredFiles = Table.SelectRows(Source, each Text.EndsWith([Name], ".csv")),
|
|
202
|
-
AddedContent = Table.AddColumn(FilteredFiles, "Data", each
|
|
203
|
-
Csv.Document([Content], [Delimiter=",", Encoding=65001, QuoteStyle=QuoteStyle.Csv])
|
|
204
|
-
),
|
|
205
|
-
ExpandedData = Table.ExpandTableColumn(AddedContent, "Data",
|
|
206
|
-
Table.ColumnNames(AddedContent{0}[Data])
|
|
207
|
-
),
|
|
208
|
-
RemovedOtherColumns = Table.SelectColumns(ExpandedData,
|
|
209
|
-
List.Combine({{"Name"}, Table.ColumnNames(FilteredFiles{0}[Data])})
|
|
210
|
-
)
|
|
211
|
-
in
|
|
212
|
-
RemovedOtherColumns
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
### Incremental Load Pattern
|
|
216
|
-
```m
|
|
217
|
-
let
|
|
218
|
-
// Get last refresh date from existing data
|
|
219
|
-
LastDate = try List.Max(ExistingData[ModifiedDate]) otherwise #date(1900, 1, 1),
|
|
220
|
-
|
|
221
|
-
// Only load new/modified records
|
|
222
|
-
Source = Sql.Database("server", "db"),
|
|
223
|
-
Sales = Source{[Schema="dbo", Item="Sales"]}[Data],
|
|
224
|
-
IncrementalRows = Table.SelectRows(Sales, each [ModifiedDate] > LastDate)
|
|
225
|
-
in
|
|
226
|
-
IncrementalRows
|
|
227
|
-
```
|
|
228
|
-
|
|
229
|
-
### Unpivot Pattern
|
|
230
|
-
```m
|
|
231
|
-
// Transform columns to rows (wide to long)
|
|
232
|
-
let
|
|
233
|
-
Source = Excel.CurrentWorkbook(){[Name="SalesData"]}[Content],
|
|
234
|
-
// Columns: Product, Jan, Feb, Mar, Apr...
|
|
235
|
-
UnpivotedMonths = Table.UnpivotOtherColumns(Source, {"Product"}, "Month", "Amount"),
|
|
236
|
-
// Result: Product, Month, Amount (one row per product-month)
|
|
237
|
-
ChangedTypes = Table.TransformColumnTypes(UnpivotedMonths, {{"Amount", type number}})
|
|
238
|
-
in
|
|
239
|
-
ChangedTypes
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
### Conditional Merge (Left Join with Conditions)
|
|
243
|
-
```m
|
|
244
|
-
let
|
|
245
|
-
Source = FactSales,
|
|
246
|
-
// Join with date-effective prices
|
|
247
|
-
Merged = Table.NestedJoin(
|
|
248
|
-
Source, {"ProductID", "Date"},
|
|
249
|
-
PriceHistory, {"ProductID", "EffectiveDate"},
|
|
250
|
-
"Price",
|
|
251
|
-
JoinKind.LeftOuter
|
|
252
|
-
),
|
|
253
|
-
Expanded = Table.ExpandTableColumn(Merged, "Price", {"UnitPrice"})
|
|
254
|
-
in
|
|
255
|
-
Expanded
|
|
256
|
-
```
|
|
257
|
-
|
|
258
|
-
---
|
|
259
|
-
|
|
260
|
-
## Anti-Patterns
|
|
261
|
-
|
|
262
|
-
### 1. Breaking Query Folding Early
|
|
263
|
-
```m
|
|
264
|
-
// BAD: Index column breaks folding
|
|
265
|
-
let
|
|
266
|
-
Source = Sql.Database("server", "db"),
|
|
267
|
-
AddedIndex = Table.AddIndexColumn(Source, "Index"), // Folding breaks here!
|
|
268
|
-
Filtered = Table.SelectRows(AddedIndex, each [Amount] > 1000) // Won't fold
|
|
269
|
-
in
|
|
270
|
-
Filtered
|
|
271
|
-
|
|
272
|
-
// GOOD: Filter first, then add index
|
|
273
|
-
let
|
|
274
|
-
Source = Sql.Database("server", "db"),
|
|
275
|
-
Filtered = Table.SelectRows(Source, each [Amount] > 1000), // Folds
|
|
276
|
-
AddedIndex = Table.AddIndexColumn(Filtered, "Index") // OK at the end
|
|
277
|
-
in
|
|
278
|
-
AddedIndex
|
|
279
|
-
```
|
|
280
|
-
|
|
281
|
-
### 2. Hardcoded Values
|
|
282
|
-
```m
|
|
283
|
-
// BAD: Hardcoded server name
|
|
284
|
-
Source = Sql.Database("PROD-SQL-01", "SalesDB")
|
|
285
|
-
|
|
286
|
-
// GOOD: Use parameters
|
|
287
|
-
Source = Sql.Database(param_ServerName, param_DatabaseName)
|
|
288
|
-
```
|
|
289
|
-
|
|
290
|
-
### 3. Loading Unnecessary Data
|
|
291
|
-
```m
|
|
292
|
-
// BAD: Load everything, filter in DAX
|
|
293
|
-
let
|
|
294
|
-
Source = Sql.Database("server", "db"),
|
|
295
|
-
AllData = Source{[Schema="dbo", Item="Sales"]}[Data]
|
|
296
|
-
in
|
|
297
|
-
AllData
|
|
298
|
-
|
|
299
|
-
// GOOD: Filter at source
|
|
300
|
-
let
|
|
301
|
-
Source = Sql.Database("server", "db"),
|
|
302
|
-
Sales = Source{[Schema="dbo", Item="Sales"]}[Data],
|
|
303
|
-
FilteredByYear = Table.SelectRows(Sales, each [Year] >= 2023),
|
|
304
|
-
SelectedColumns = Table.SelectColumns(FilteredByYear, RequiredColumns)
|
|
305
|
-
in
|
|
306
|
-
SelectedColumns
|
|
307
|
-
```
|
|
308
|
-
|
|
309
|
-
### 4. Multiple Source Connections
|
|
310
|
-
```m
|
|
311
|
-
// BAD: Connect to same source multiple times
|
|
312
|
-
let
|
|
313
|
-
Query1 = Sql.Database("server", "db"){[Schema="dbo", Item="Sales"]}[Data],
|
|
314
|
-
Query2 = Sql.Database("server", "db"){[Schema="dbo", Item="Products"]}[Data]
|
|
315
|
-
in
|
|
316
|
-
...
|
|
317
|
-
|
|
318
|
-
// GOOD: Single connection, multiple references
|
|
319
|
-
let
|
|
320
|
-
DB = Sql.Database("server", "db"),
|
|
321
|
-
Sales = DB{[Schema="dbo", Item="Sales"]}[Data],
|
|
322
|
-
Products = DB{[Schema="dbo", Item="Products"]}[Data]
|
|
323
|
-
in
|
|
324
|
-
...
|
|
325
|
-
```
|
|
326
|
-
|
|
327
|
-
---
|
|
328
|
-
|
|
329
|
-
## Data Source Patterns
|
|
330
|
-
|
|
331
|
-
### SQL Server
|
|
332
|
-
```m
|
|
333
|
-
Sql.Database("server-name", "database-name", [
|
|
334
|
-
Query = "SELECT * FROM dbo.Table WHERE Date > '2023-01-01'",
|
|
335
|
-
CommandTimeout = #duration(0, 0, 10, 0)
|
|
336
|
-
])
|
|
337
|
-
```
|
|
338
|
-
|
|
339
|
-
### SharePoint List
|
|
340
|
-
```m
|
|
341
|
-
SharePoint.Tables("https://company.sharepoint.com/sites/SiteName", [
|
|
342
|
-
Implementation = "2.0",
|
|
343
|
-
ViewMode = "All"
|
|
344
|
-
]){[Title="ListName"]}[Items]
|
|
345
|
-
```
|
|
346
|
-
|
|
347
|
-
### REST API
|
|
348
|
-
```m
|
|
349
|
-
let
|
|
350
|
-
Source = Json.Document(Web.Contents(
|
|
351
|
-
"https://api.example.com/data",
|
|
352
|
-
[
|
|
353
|
-
Headers = [
|
|
354
|
-
#"Authorization" = "Bearer " & param_APIToken,
|
|
355
|
-
#"Content-Type" = "application/json"
|
|
356
|
-
],
|
|
357
|
-
Query = [
|
|
358
|
-
startDate = Date.ToText(param_StartDate, "yyyy-MM-dd"),
|
|
359
|
-
limit = "1000"
|
|
360
|
-
]
|
|
361
|
-
]
|
|
362
|
-
)),
|
|
363
|
-
ToTable = Table.FromRecords(Source[data])
|
|
364
|
-
in
|
|
365
|
-
ToTable
|
|
366
|
-
```
|
|
367
|
-
|
|
368
|
-
### Excel File
|
|
369
|
-
```m
|
|
370
|
-
Excel.Workbook(File.Contents(param_FilePath), true, true){[Item="SheetName", Kind="Sheet"]}[Data]
|
|
371
|
-
```
|
|
372
|
-
|
|
373
|
-
### CSV with Encoding
|
|
374
|
-
```m
|
|
375
|
-
Csv.Document(File.Contents(param_FilePath), [
|
|
376
|
-
Delimiter = ",",
|
|
377
|
-
Encoding = 65001, // UTF-8
|
|
378
|
-
QuoteStyle = QuoteStyle.Csv,
|
|
379
|
-
Columns = 10
|
|
380
|
-
])
|
|
381
|
-
```
|
|
382
|
-
|
|
383
|
-
---
|
|
384
|
-
|
|
385
|
-
## Complexity Adaptation
|
|
386
|
-
|
|
387
|
-
Adjust depth based on `config.json → experienceLevel`:
|
|
388
|
-
- **beginner**: Step-by-step with explanations, reference library examples
|
|
389
|
-
- **intermediate**: Standard depth, explain non-obvious decisions
|
|
390
|
-
- **advanced**: Concise, skip basics, focus on edge cases and optimization
|
|
391
|
-
|
|
392
|
-
## Related Skills
|
|
393
|
-
|
|
394
|
-
- `/dax` — DAX measures over transformed data
|
|
395
|
-
- `/data-modeling` — Model design informs transformations
|
|
396
|
-
- `/data-quality` — Validate data during transformation
|
|
397
|
-
- `/query-performance` — Optimize query folding
|
|
398
|
-
|
|
399
|
-
---
|
|
400
|
-
|
|
401
|
-
## Related Resources
|
|
402
|
-
|
|
403
|
-
- [Snippets: Data Cleaning](../../snippets/power-query/data-cleaning.md)
|
|
404
|
-
- [Snippets: Transformations](../../snippets/power-query/transformations.md)
|
|
405
|
-
- [Snippets: Connections](../../snippets/power-query/connections.md)
|
|
406
|
-
- [Snippets: Parameters](../../snippets/power-query/parameters.md)
|