mcpField
P
power-bi-build

power-bi-build

github.com/gasserane数据与数据库3659 次安装1 周前更新
代码仓库

关于 power-bi-build

power-bi-build 用于构建带 IPPF 品牌元素的 Power BI 成品。它可创建 DAX 度量值和主题文件,并将页面方案存为 JSON 供手动应用;另提供从 Excel 构建完整 .pbip 仪表板的流程。

主要功能

  1. 01通过 pbi CLI 创建 DAX 度量值
  2. 02将 IPPF 主题写入 .pbip
  3. 03以 JSON 暂存页面方案
  4. 04从 Excel 生成完整 .pbip 项目

适用场景

  1. 01为现有 .pbip 模型添加度量值和品牌元素
  2. 02准备页面布局,供 Power BI Desktop 手动创建
  3. 03从 Excel 工作簿构建完整仪表板

MCP 相关

此技能使用 pbi CLI,该 CLI 封装了用于语义模型操作的 Power BI MCP 服务,包括度量值、表、列、关系和 DAX 执行。该接口不支持报表页面和视觉对象。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/gasserane/personal-skills --skill power-bi-build

安装后在 Claude Code 中输入/power-bi-build确认已加载。

附带文件CHANGELOG.md

详细介绍

/power-bi-build

构建带有 IPPF 品牌样式的 Power BI 构件。v1 范围:通过 pbi CLI 将 DAX 度量值写入语义模型;直接将 IPPF 主题 JSON 写入 .pbip 文件夹;将页面配方(指标仪表板、公平性、方法论)保存为 JSON 暂存构件,由用户在 Power BI Desktop 中手动应用。完整的页面和视觉对象自动化属于 v2。

工具现状

pbi CLI(软件包 pbi-cli-tool,命令名为 pbi)封装了一个 Power BI MCP 服务,但仅用于语义模型操作:

  • ✅ pbi measure create — 添加 DAX 度量值。
  • ✅ pbi table、pbi column、pbi relationship — 模型结构。
  • ✅ pbi dax — 执行和验证 DAX。
  • ❌ 没有 pbi theme 命令。主题 JSON 直接写入 .pbip 文件夹。
  • ❌ 没有 pbi page 或 pbi visual 命令。页面和视觉对象需在 Power BI Desktop 中手动创建,并以暂存配方 JSON 为参考。

上游工具添加报表层命令后,此技能将纳入这些功能。v1 仅提供上述范围。

两种路径。 下方的 v1 流程(使用 pbi CLI 添加度量值 + 主题 + 暂存页面配方)适用于用户仍要手动继续构建的现有模型。当源文件是 Excel 工作簿,且用户希望交付一份完整可用的仪表板(已加载数据、度量值、主题和报表页面均已构建)时,请改用下方专门章节中的完整 .pbip 编写路径。该路径已通过端到端验证(CERV Portfolio Dashboard,2026-06-20)。

预检

按顺序运行这些检查。首次失败时,停止并显示指定消息。

  1. 已安装 pbi。

    • 运行:pipx list | grep pbi-cli-tool。
    • 如果结果为空:停止。显示:"尚未安装 pbi CLI。运行:pipx install pbi-cli-tool && pipx ensurepath && pbi skills install。打开新的 shell,让 PATH 更新生效。"
  2. Power BI Desktop 正在运行,且有活动项目,并已命名连接。

    • 运行一次 pbi connect(不带参数),从 "Auto-detected Power BI Desktop on localhost:" 行读取端口。断开连接:pbi disconnect。
    • 使用与 MCP 服务内部标签匹配的显式名称重新连接:pbi connect -d localhost:<port> -n PBIDesktop-<pbip-basename>-<port>。必须使用从模型派生的名称 — pbi-cli 默认的保存名称 localhost-<port> 会被 MCP 服务的度量值/表操作拒绝,并返回 "Connection 'localhost-<port>' not found"。
    • 如果 pbi connect 报告没有活动项目:停止。显示:"打开 Power BI Desktop 并加载 .pbip 项目,然后重新运行。"
    • 如果 Analysis Services 端口在会话期间发生变化(Power BI Desktop 有时会在重新打开文件、切换到模型视图等操作时重启引擎),请使用新端口重新执行此步骤。
  3. 活动项目是 .pbip(文本格式),而不是旧版 .pbix 二进制格式。

    • pbi connect 输出中包含项目路径。如果路径以 .pbix 结尾:停止。显示:"请先将项目另存为 .pbip — 文件 → 另存为 → 将保存类型设为 Power BI Project。此技能仅适用于基于文本的 PBIP 格式。"
  4. 品牌层可导入。

    • 验证 ${WORK_FOLDER_ROOT}/ane_package/reporting/powerbi_dashboard/__init__.py 是否存在。
    • 如果不存在:停止。显示:"未在 ${WORK_FOLDER_ROOT}/ane_package/reporting/powerbi_dashboard/ 找到品牌层。请检查 OneDrive 同步。"

确定意图

根据提示和本次会话中最近的分析构件,确定:

  • 指标 — MEL_DAX_LIBRARY 中的键。如果不明确,询问 Ane:"要使用哪些指标?可选项:{sorted(MEL_DAX_LIBRARY.keys())}"。
  • 受众层级 — 默认使用 Tier 1 工作简报;只有提示中明确提及时才使用 Tier 2 发布版。
  • 页面集 — 每个指标默认使用 (indicator_dashboard, equity_disaggregation, methodology_card)。
  • 来源说明 — 从先前的构件中推导;如果没有,则询问一次。
  • 暂存目录 — 默认为 ${PWD}/powerbi-build-output/。存放本次运行的 theme.json、measures.json 和页面配方。

构建(Python — 在内存中生成所有构件)

import json
from pathlib import Path
from ane_package.reporting.powerbi_dashboard import (
    MEL_DAX_LIBRARY,
    build_equity_disaggregation_page,
    build_indicator_dashboard_page,
    build_ippf_theme,
    build_methodology_card_page,
)

theme = build_ippf_theme()
measures = {k: MEL_DAX_LIBRARY[k] for k in selected_indicators}

pages = []
for indicator in selected_indicators:
    pages.append(build_indicator_dashboard_page(indicator, target, source))
    pages.append(build_equity_disaggregation_page(
        indicator, ("age", "gender", "geography", "wgss_disability"), source))
pages.append(build_methodology_card_page(method_note, evidence_base_sources, glossary_terms))

staging = Path("powerbi-build-output")
staging.mkdir(exist_ok=True)
(staging / "theme.json").write_text(json.dumps(theme, indent=2))
(staging / "measures.json").write_text(json.dumps(measures, indent=2))
for i, page in enumerate(pages):
    (staging / f"page_{page['page_id']}.json").write_text(json.dumps(page, indent=2))

应用

1. 通过 pbi measure create 创建 DAX 度量值

对于每个度量值,根据 DAX 表达式中的 [方括号] 引用推断表(启发式规则:表达式中的第一个 Table[Column] 引用;如果表达式仅引用其他度量值,则使用 _Measures)。

pbi measure create <measure-key> \
    --table <inferred-table> \
    --expression "<dax-expression>"

度量值名称是位置参数(不是 --name 标志)。已通过 pbi-cli-tool 0.5.6 验证。

原样显示任何错误。切勿重试——pbi 失败通常意味着模型中不存在所引用的表或列。pbi-cli 遇到任何“未找到表”错误都会回滚事务;度量值不会以红色图标的形式写入(与旧版 Power BI 的行为相反)。请预先创建一个占位表,或在重试前修正 DAX。

1a. 保存规范 — 每次 pbi 模型写入后都必须执行

每次执行 pbi table / pbi measure / pbi column / pbi relationship 写入后,都要告知 Ane 切换到 Power BI Desktop 并立即按 Ctrl+S。外部 pbi 写入仅保存在 Analysis Services 引擎的内存中;磁盘上的 .pbip 只有在 Power BI Desktop 中选择“文件 → 保存”后才会更新。如果引擎在保存前重启(端口切换、重新打开文件,有时也包括切换模型视图),写入内容会丢失。

2. 主题 JSON — 直接写入 .pbip 文件夹

.pbip 是文本格式的项目。主题 JSON 应作为自定义主题放入报表文件夹。路径布局(Power BI Desktop 2.140+):

<project>.pbip
<project>.Report/
    StaticResources/
        SharedResources/
            BaseThemes/
                ippf-visual-identity-2025.json   ← write theme here
        RegisteredResources/
            ippf-visual-identity-2025.json       ← also write here
    definition/
        report.json                              ← register the theme (see below)

将主题 JSON 写入这两个路径。然后更新 report.json 以注册主题(Power BI Desktop 从 report.json 元数据中读取主题名称;如果未注册,主题会显示在“主题”库中,但不会自动应用)。

如果用户尚未在 Power BI Desktop 中启用 PBIP 报表格式预览(文件 → 选项 → 预览功能 → Power BI Project (.pbip) 源代码管理),主题路径可能会有所不同。如果 <project>.Report/ 不存在,请明确告知用户。

重试时避开缓存。 Power BI Desktop 会按文件名缓存已注册的主题,即使导入失败也是如此——重新导入同名文件会再次显示旧的验证错误,即使文件已修正也是如此。验证失败后重试时,请使用带版本号的名称写入新的主题 JSON(ippf-visual-identity-2025-v2.json、-v3 等),以便 Power BI 将其作为新文件解析。

3. 页面方案 — v1 阶段仅暂存

将每个页面方案以 JSON 格式保存到暂存目录。v1 中不要尝试将 PBIR 页面文件写入 .pbip 文件夹(PBIR 格式仍处于预览阶段,架构尚不稳定)。

在聊天输出中,准确告知 Ane 每个页面方案存放在哪个文件中,以及需要手动创建哪些视觉对象:

Pages saved to staging — apply manually in Power BI Desktop:

powerbi-build-output/page_cyp_total-dashboard.json
  → New page "cyp_total Dashboard"
  → Card visual: measure [cyp_total], position (40, 40, 280, 120)
  → Line chart: x=Date[Month], y=[cyp_total], position (360, 40, 880, 320)
  → Bar chart: x=Geography[country], y=[cyp_total], position (40, 380, 1200, 280)

(repeat for each page)

v2 将在上游 pbi-cli 添加报表层支持后自动创建页面,或在我们接入直接 PBIR 写入器后实现自动创建。

使用 Excel 全面创作 .pbip(完整交付方案)

当源文件是 Excel 工作簿,且用户需要完整可用的仪表板而非暂存方案时使用。通过Python 生成器(一份可重复运行的脚本)创作整个 .pbip,因为 pbi CLI 无法导入 Excel 数据(DataSourceOperationsTool 在 PowerBI 兼容模式下会被跳过),且没有报表页面/视觉对象 API。参考构建脚本:${WORK_FOLDER_ROOT}/scripts/gen_cerv_dashboard_pbip.py。

如果目标 .pbip 已存在,请遵循 mel_wiki/wiki/concepts/edit-preservation-protocol.md。 如果用户已打开目标项目,请在新的项目文件夹中创作(以避免文件锁);用户关闭项目但不保存,然后重新打开。 步骤:

  1. 镜像架构。 读取现有空 .pbip 的骨架,并原样复制其版本(compatibilityLevel 1600;report.json 3.3.0;visual 2.9.0;page 2.1.0;pbism 4.2)。要求在 Desktop 中启用 PBIP + PBIR 预览功能。
  2. 检查 Excel,使用 openpyxl 检查工作表名称、精确的表头字符串(不要去除空格——末尾空格会导致列引用失效)、表头行位置,以及各列的数据类型。将预期汇总值与工作簿中现有的仪表板选项卡进行核对。
  3. 编写语义模型 TMDL(使用制表符缩进):database.tmdl、model.tmdl(包含 ref table X 行和 relationship 块)、cultures/,以及 tables/*.tmdl(列 + 度量值 + M partition)。M 块的缩进要比 source = 更深。
  4. 编写报表 PBIR:definition.pbir(使用指向 SemanticModel 的相对 byPath——此链接在文件夹移动后仍然有效)、report.json(注册 IPPF 自定义主题 + 基础主题)、pages/<id>/page.json,以及 pages/<id>/visuals/<id>/visual.json。
  5. 将度量值与源汇总值进行核对,然后让用户打开并刷新。加载后,通过 CLI 验证:pbi connect,然后执行 pbi dax execute "EVALUATE <Table>" 并读取 RowCount=(CLI 不会打印单元格值;使用表格 EVALUATE 并读取行数)。

Power Query M 注意事项(每项都会导致一次刷新错误循环——请提前处理):

  • Excel.Workbook(File.Contents(path), null, true) 会删除开头完全为空的行,因此固定的 Table.Skip(n) 会导致表头错位。请动态定位表头:HeaderRow = List.PositionOf(Sheet[Column1], "<key header>"),然后执行 Table.Skip(Sheet, HeaderRow),再执行 Table.PromoteHeaders(.., [PromoteAllScalars=true])。
  • 应使用 List.PositionOf(列表 + 值),而不是 Table.PositionOf(表 + 记录)——后者会报错 "cannot convert List to Table"。
  • 仅对仪表板需要的列设置固定类型(金额 → type number,计数 → Int64.Type)。对计算所得列或 "(auto)" 列设置类型时,若待填充行返回非数值("" / "Pending"),每个单元格都会报 "N errors"。这些列应保持未指定类型。
  • 多行表头 / 合并表头工作表:跳过 PromoteHeaders;使用位置参数 Table.Range + Table.SelectColumns({"Column1",...}) + 重命名。
  • M 文件路径是字面值(无需转义反斜杠)。在共享表达式中只定义一次源路径,或始终以内联方式一致地填写。

PBIR 视觉对象 JSON(盲写,均可正确渲染): 最小结构为 visual.query.queryState.<role>.projections[{field:{Measure|Column:{Expression:{SourceRef:{Entity}},Property}}, queryRef:"Entity.Prop", nativeQueryRef:"Prop"}]。角色:card → Values;clusteredColumnChart/clusteredBarChart → Category + Y(多度量值图表省略 Category);tableEx → Values(列表)。省略标题对象——让 IPPF 主题和自动标题统一设置样式。其他内容:切片器多选 + 全选 = objects.selection[{properties:{singleSelect:{Literal false}, selectAllCheckboxEnabled:{Literal true}}}];导航栏 = visualType pageNavigator;徽标 = visualType image,使用 ResourcePackageItem(RegisteredResources) + 将 PNG 复制到 StaticResources/RegisteredResources/ + 在 report.json 中注册;页眉色带 = 带有 visualContainerObjects.background 的文本框。

易读布局(1280×720): 紧凑的全宽切片器栏(切片器会呈现为下拉菜单)、KPI 卡片行,然后是横跨全宽的大图表——避免使用右侧空出大片区域的半宽切片器行。将页面 displayOption 设为 FitToWidth,使页面填满显示器宽度并可垂直滚动。

分发与许可(向用户提供建议)

  • .pbip 是一种开发/源代码管理格式——刷新前打开时内容为空,不适合新手。
  • 对于新手查看者,请提供一个 .pbix(文件 → 另存为 → .pbix 会嵌入数据,打开后内容完整,且无需许可证)。只有 Power BI Desktop 能写入 .pbix;命令行或脚本都无法做到,而且嵌入数据前必须先进行一次实时刷新。
  • 发布到 Power BI Service 后,只有当工作区位于 Premium(P SKU)或 Fabric F64+ 容量上时,免费版同事才能查看;否则,每位查看者也需要 Pro/PPU。对于敏感数据(SRHR/财务/次级受资助方),切勿使用“发布到 Web”——该方式会公开数据。
  • 页面导航器和按钮在阅读视图/已发布状态下单击即可导航,在编辑视图下按 Ctrl 并单击才可导航(这是 Power BI 固有行为,并非错误)。
  • 通过绝对本地路径/OneDrive 路径引用的 Excel 源文件,移至 SharePoint 后会失效。要实现云端计划刷新,请通过 SharePoint 连接器重新指定源;每次刷新都会重新读取源文件。

输出(一级工作简报)

Power BI build complete (v1 scope: measures + theme + page recipes).

Measures applied to semantic model: {N} ({list of keys}).
Theme written to: {project}.Report/StaticResources/SharedResources/BaseThemes/ippf-visual-identity-2025.json

Page recipes staged at powerbi-build-output/:
  - page_<id>.json — {N} visuals each. Apply manually per the recipe.

Source: {derived source line}.

常见错误

错误可能原因修复方法
安装后出现 pbi: command not foundPATH 尚未更新运行 pipx ensurepath;打开新的 shell。
pbi connect 提示没有会话Power BI Desktop 未运行,或未打开 .pbip打开 Power BI Desktop 并加载 .pbip。
pbi measure create 失败:“找不到表”DAX 度量值引用了模型中不存在的表确认数据模型符合度量值的假设;添加该表或调整 DAX。
指标不在 MEL_DAX_LIBRARY 中正在添加新指标将其添加到 dax_library.py,并附上对应的 wiki 条目;向 anework-package 提交 PR。
Power BI Desktop 未应用主题PBIP 预览功能已禁用,或主题未在 report.json 中注册启用 PBIP 预览(File → Options → Preview features);检查 report.json 是否包含主题名称。
页面配方中的 visualType 是用户找不到的类型Power BI Desktop UI 的命名与配方中的 type 不同使用可视化对象库:card = “Card”;lineChart = “Line chart”;barChart / stackedBarChart = “Stacked bar chart”;slicer = “Slicer”;table = “Table”;textbox = “Text box”。
pbi measure create 失败:Connection 'localhost-<port>' not foundpbi-cli 自动保存的名称与 MCP 服务的内部名称不同使用 -n PBIDesktop-<pbip-basename>-<port> 重新连接——参见准备步骤 2。
pbi 模型写入的内容在命令之间消失AS 引擎在 File → Save 之前重启每次使用 pbi 写入后,都在 Power BI Desktop 中按 Ctrl+S。参见应用步骤 1a。
主题导入在修复后仍因引用相同键而出现 oneOf 验证错误Power BI Desktop 按文件名缓存了上一次解析失败的结果将主题 JSON 重写为 -v2(或 -v3)文件名,然后重新浏览选择。参见应用步骤 2。
pbi table refresh 失败并显示 Invalid operation: Refreshpbi-cli 0.5.6 发送 Refresh 操作名称;MCP 服务只接受 REFRESHWITHXMLA / REFRESHWITHAPIpbi-cli 上游 bug。解决方法:在 Power BI Desktop 中手动触发刷新(Home → Refresh)。
pbi measure get 或 pbi table export-tmdl 失败并显示 References is requiredpbi-cli 0.5.6 未将 References 参数传递给 MCP 服务pbi-cli 上游 bug。使用 pbi measure list --table <name> 确认度量值是否存在;使用 Power BI Desktop 的 Tabular Editor 视图检查 TMDL。
刷新:“未找到表的列 ‘’”(提升标题的表)Excel.Workbook 删除了开头的空行,导致固定的 Table.Skip 与标题错位动态查找标题:Table.Skip(Sheet, List.PositionOf(Sheet[Column1], "<key>"))。参见完整创作流程。
刷新:“无法将 List 类型的值转换为 Table 类型”对列使用了 Table.PositionOf使用 List.PositionOf(list, value),而不是 Table.PositionOf(table, record)。
刷新:某个表显示“已加载 N 行。出现 M 个错误”类型化的计算列 / “(auto)” 列对尚未填充的行返回非数值移除该列的类型转换;仅为仪表板需要的列指定类型。
报表已打开,但刷新后所有可视化对象均为空白导入模型加载了 0 行(M 失败)——这不是绑定 bug使用 pbi 连接,运行 pbi dax execute "EVALUATE <Table>",读取 RowCount=;修复 M,而不是可视化对象。
收件人打开 .pbip 后看到空报表.pbip 不存储数据;打开后会显示为空,直到刷新分发包含数据的 .pbix,或发布到 Service。参见分发与许可。

评论

支持 Markdown