# Pbi Report Generator

> Use when the operator wants to generate a complete Power BI report file as code — model tables, DAX measures, and report visuals — without opening Power BI Desktop. Covers both .pbit output (pbi-tools PbixProj compile, Desktop-free) and .pbip output (Desktop-native PBIR-Legacy + TMDL). Triggers include "generate a pbit", "generate a pbip", "power bi report as code", "compile a power bi file", "create a report file from my star schema", "pbit for databricks importBI", and the Portuguese variants "gerar pbit", "gerar pbip", "relatório power bi como código", "criar arquivo power bi por código".

- Skill: `gusbavia/pbi-report-generator` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add gusbavia/pbi-report-generator`
- Raw SKILL.md: https://api.skillmd.com/api/skills/gusbavia/pbi-report-generator/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- License: MIT
- Author: gusbavia (https://skillmd.com/u/gusbavia)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/gusbavia/pbi-report-generator

---


# Power BI Report Generator (as code) · v0.1.2

Generate a **complete, working Power BI report file** — semantic model (tables, columns, relationships, measures) AND report page (visuals) — entirely from code. No Power BI Desktop required to author. Two output routes:

| Route | Output | Toolchain | Best for |
|---|---|---|---|
| **A — PBIT** | `.pbit` (template, metadata-only) | PbixProj source → `pbi-tools compile` | Desktop-free pipelines, **Databricks AI/BI `/importBI`**, distributing templates, CI builds |
| **B — PBIP** | `.pbip` folder (PBIR-Legacy + TMDL) | Direct file generation | Ongoing development in Power BI Desktop, git-per-file diffs, integration with the `pbi-lifecycle` folder suite |

## Generic positioning · MANDATORY

This skill ships to any Power BI practitioner. Do not use the operator's personal context, memory, or session history to invent defaults. All examples stay neutral (`Client A`, `My Report`, `dim_customer`). If the operator volunteers specifics, use them for that run only.

## The questionnaire · ALWAYS the first action

Never start generating from assumptions. Collect the spec first (use AskUserQuestion when available, otherwise a numbered prompt). Ask only what the invocation didn't already answer:

1. **Format** — PBIT (route A) or PBIP (route B)? If unsure, offer the table above.
2. **Model** — tables with columns + data types (`int64`, `string`, `double`, `dateTime`, `boolean`, `decimal`). Sources accepted: the operator types them; OR points to an existing schema (SQL DDL, a warehouse `DESCRIBE`, a CSV header, a `measures.dax` file). One table may be marked as the **date table** (which column is the date key?).
3. **Relationships** — fact→dim pairs (from-column / to-column); flag inactive ones.
4. **Measures** — name + DAX + format string, per home table. Accept an existing `.dax` file and let the operator pick a subset.
5. **Report page(s)** — for each visual: type (`card`, `clusteredBarChart`, `clusteredColumnChart`, `lineChart`, `pieChart`, `tableEx`, `slicer`, `textbox`), fields (which column/measure in which role), and rough position (the skill defaults to a clean 1280×720 grid if the operator says "you lay it out").
6. **Output folder** + project name.
7. **Theme** (optional) — a theme.json to embed, or default.

Echo the collected spec back as a compact table and get a "go" before writing files.

## Route A · PBIT via pbi-tools

**REQUIRED READING:** `references/pbixproj-pbit.md` (the PbixProj source format — what `pbi-tools compile` actually reads; it is NOT Desktop's PBIP/PBIR).

1. Ensure `pbi-tools` Core is available: `pbi-tools.core.exe info`. If missing, download the `pbi-tools.core.<ver>_win-x64.zip` self-contained release from github.com/pbi-tools/pbi-tools (no Desktop, no .NET SDK needed).
2. Adapt `scripts/author_pbixproj.py` — edit its `TABLES` / `RELATIONSHIPS` / visuals spec to the questionnaire answers, set the output folder. Run it → emits the full PbixProj source.
3. Compile: `pbi-tools.core.exe compile <src-folder> <out>.pbit PBIT true` (positional args, not flags).
4. **Validate** — the `.pbit` is a zip: extract, parse `DataModelSchema` (UTF-16 LE) and confirm tables/relationships/measures/partition mode; parse `Report/Layout` and confirm sections + visuals. Report the counts to the operator.

## Route B · PBIP (PBIR-Legacy + TMDL)

**REQUIRED READING:** `references/pbip-tmdl.md` (folder anatomy, TMDL table syntax, locked recipe rules).

1. Generate the PBIP tree: `<Name>.pbip` + `Report/` (`.platform`, `definition.pbir`, `report.json` at root, `StaticResources/`) + `SemanticModel/` (`.platform`, `definition.pbism`, `definition/*.tmdl` including one `tables/<Table>.tmdl` per table with columns, partition, and measures).
2. Honor every locked rule in the reference — the expensive ones: **UTF-8 without BOM everywhere**, `__PBI_TimeIntelligenceEnabled = 0`, compatibilityLevel 1600, `report.json` at `Report/` root (PBIR-**Legacy**, not modular), theme `name` ≤ 16 chars, MAX_PATH 256 headroom.
3. **Validate** — JSON-parse every JSON artifact, BOM-sweep every file, path-budget check, then tell the operator to open the `.pbip` in Desktop and load data.

## Visual layout JSON (both routes)

**REQUIRED READING:** `references/visual-layout.md` — the classic Layout `visualContainer` config (`singleVisual`, `projections`, `prototypeQuery`, `queryRef`) used verbatim by route A's `Report/sections/` files and route B's `report.json` sections.

## Quick reference

| Task | Where |
|---|---|
| PbixProj source anatomy + compile gotchas | `references/pbixproj-pbit.md` |
| PBIP/TMDL anatomy + locked recipe | `references/pbip-tmdl.md` |
| Visual config JSON patterns (card, bar, line, table…) | `references/visual-layout.md` |
| Working PBIT generator to adapt | `scripts/author_pbixproj.py` |

## Common mistakes

| Mistake | Fix |
|---|---|
| Omitting `DiagramLayout.json` or leaving `QueriesSettings` empty (route A) | PBIT compiles but Desktop rejects it ("corrupted or unrecognized version", MashupValidationError). Both are REQUIRED — see `references/pbixproj-pbit.md` required-parts table. Verified 2026-06-12. |
| Authoring Desktop PBIP/PBIR source and feeding it to `pbi-tools compile` | `compile` reads **PbixProj** (pbi-tools' own layout). Route A only. |
| Measures inline in `table.json` (route A) | Measures live in `measures/<Name>.dax` + `<Name>.xml`; columns each in `columns/<col>.json`. |
| Table partition missing (route A) | Partition M comes from `Model/queries/<table>.m` — matched by filename. |
| M queries that need credentials | Use a **typed empty `#table`** partition — schema-complete, refresh-safe, credential-free. |
| BOM in any PBIP file (route B) | Power BI Desktop fails silently. Write UTF-8 **without** BOM. |
| Lowercase theme enums (`"left"`) | Must be CamelCase (`"Left"`); Power BI silently rejects the theme. |
| Forgetting the date table marking | Date table: `dataCategory: "Time"` (route A `table.json`) / `dataCategory: Time` (TMDL) + `isKey: true` on the date column. |
| Inventing visual types | Stick to the catalog in `references/visual-layout.md`; unknown types render as errors in Desktop. |

## Companions

`pbi-aibi-migrator` (takes the compiled `.pbit` into Databricks AI/BI — the import workflow lives there, not here), `pbi-lifecycle` (folder bootstrap, git, env promotion — its Phase 2 scaffolds an *empty* PBIP; this skill generates a *full* report), `pbi-theme` (theme JSON generation), `pbi-model-audit` / `pbi-model-doc` (post-generation quality).

