mcpField
T
tmdl

tmdl

github.com/data-goblin数据与数据库1.1k84 次安装今天更新
代码仓库

关于 tmdl

tmdl 是为在 PBIP 项目中直接编写和编辑 TMDL 文件提供的指导技能,适用于缺少 Tabular Editor CLI、Power BI MCP 服务或 connect-pbid 时的文本级修改。它涵盖语法与对象结构,但直接编辑不会验证 DAX 或引用完整性。

主要功能

  1. 01指导编辑表、列、度量值和关系
  2. 02说明缩进、命名与属性顺序
  3. 03提供 DAX 与描述的 TMDL 写法
  4. 04梳理 TMDL 文件类型和对象嵌套
  5. 05提醒直接编辑的验证限制

适用场景

  1. 01在 Git 仓库中修改 PBIP 模型文件
  2. 02快速调整描述或格式字符串
  3. 03添加或修改 TMDL 度量值
  4. 04检查 TMDL 语法规则

MCP 相关

该技能建议优先使用 Power BI MCP 服务等工具;当它不可用时,可作为直接编辑 TMDL 文件的替代指导。

安装

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

$npx skills add https://github.com/data-goblin/power-bi-agentic-development --skill tmdl

安装后在 Claude Code 中输入/tmdl确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

examples/SpaceParts.SemanticModel/definition/
database.tmdl
expressions.tmdl
functions.tmdl
model.tmdl
relationships.tmdl
examples/SpaceParts.SemanticModel/definition/perspectives/
Measure Selection.tmdl
No Measure Selection.tmdl
examples/SpaceParts.SemanticModel/definition/roles/
Account Managers.tmdl
Brand VPs.tmdl
Business Line Leaders.tmdl
Key Account Managers.tmdl
Station Sales Managers.tmdl
System Regional Managers.tmdl
System Sales Directors.tmdl
Territory Managers.tmdl
examples/SpaceParts.SemanticModel/definition/tables/
__Demo UDFs.tmdl
__Measures.tmdl
__SVGs.tmdl
1) Selected Metric.tmdl
2) Selected Unit.tmdl
3) Selected Target.tmdl
4) Selected Period.tmdl
Brands.tmdl
Budget Rate.tmdl
Budget.tmdl
Customers.tmdl
Date.tmdl
Employees.tmdl
Exchange Rate.tmdl
Forecast.tmdl

详细介绍

TMDL 编写

直接在 PBIP 项目中编写和编辑 TMDL(表格模型定义语言)文件的专家指南。

此技能仅作为最后手段。 直接编辑 TMDL 文件缺少 Tabular Editor CLI、Power BI MCP 服务或 connect-pbid 技能(通过 PowerShell 使用 TOM)提供的验证、原子性和 DAX 查询能力。条件允许时,请使用这些工具。适合编辑 TMDL 的情况:

  • 在未打开 Power BI Desktop 的情况下,处理 Git 仓库中的 PBIP 文件
  • 未安装 Tabular Editor CLI 或 MCP 服务
  • 快速修复文本内容(描述、格式字符串、显示文件夹),无需动用完整工具链

直接编辑 TMDL 不会验证 DAX 语法、检查引用完整性,也不会验证属性值是否合法。只有在模型下次由 Power BI Desktop 加载或通过 XMLA 部署时,才会显现错误。在 Power BI Desktop 中打开之前,请使用 pbip-validator Agent 检查 TMDL 文件中的语法问题、缩进错误和引用完整性。

何时使用此技能

仅当 Tabular Editor CLI、Power BI MCP 服务或 connect-pbid 技能不可用,且任务涉及以下内容时,才启用此技能:

  • 直接编辑 .tmdl 文件(度量值、列、表、关系)
  • 在 TMDL 中添加或修改度量值定义
  • 为列、度量值或表添加描述
  • 修复 summarizeBy 或 formatString 值
  • 了解 TMDL 语法规则(缩进、引号、属性顺序)
  • 以 TMDL 格式编写多行 DAX
  • 了解 /// 描述与 // 注释的区别

重要事项

  • ///(三个斜杠)会为其紧随其后的对象设置 Description 属性。 /// 行必须紧接声明(measure、column、table 等),不能是空行或另一行 ///。普通注释请使用 //。
  • 缩进具有语义。 TMDL 使用空白缩进表示层级,缩进深度对应嵌套层级(TMDL 规范 — 缩进)。PBIP 文件每层使用一个制表符,因为 Power BI Desktop 和 TOM TmdlSerializer 默认采用 IndentationMode.Tabs。空格也有效(IndentationMode.Spaces,默认每层 4 个空格),但同一文件中必须保持一致;混用或错误缩进会破坏模型。表的属性缩进一层;列的属性(列属于表)缩进两层。
  • 名称的引号规则: 仅当名称包含空格、特殊字符或以数字开头时,才需要加引号。简单名称和以下划线开头的名称不加引号。详情请参阅“名称引号”部分。
  • M 表达式和表共用同一命名空间。 expressions.tmdl 中由 expression <name> 声明的名称,与 tables/*.tmdl 中由 table <name> 声明的名称冲突时,Power BI Desktop 会在加载时失败并报错 'duplicate member <name>'。请使用不同的名称;惯用的解决方法是在 M 表达式名称后添加 Query 或 Source 后缀,并让分区通过 source = #"<Name> Query" 引用该表达式。validate_pbip.py 会将此问题作为错误进行检查。

TMDL 文件类型

文件内容位置
model.tmdl模型配置、ref table 条目、查询组、注释definition/
database.tmdl兼容性级别、模型 IDdefinition/
relationships.tmdl表之间的所有关系definition/
expressions.tmdl共享 M 表达式和参数definition/
functions.tmdlDAX 用户定义函数(可重用的参数化 DAX)definition/
roles/<RoleName>.tmdl每个安全角色对应一个文件(RLS 筛选器、角色成员、OLS)definition/roles/
perspectives/<Name>.tmdl每个透视对应一个文件(对象成员资格)definition/perspectives/
dataSources.tmdl旧版数据源定义(若存在)definition/
tables/<Name>.tmdl表定义,包含列、度量值、层次结构、分区definition/tables/
cultures/<locale>.tmdl语言元数据和翻译definition/cultures/

对象嵌套规则

对象必须嵌套在正确的父对象中。验证器会强制执行以下规则:

对象允许的父对象
column、measure、hierarchy、partition、calculationGrouptable
levelhierarchy
calculationItemcalculationGroup
tablePermissionrole
columnPermissiontablePermission
perspectiveTableperspective
perspectiveColumn、perspectiveMeasure、perspectiveHierarchyperspectiveTable
linguisticMetadata、translationcultureInfo
dataAccessOptionsmodel
formatStringDefinitionmeasure、calculationItem
detailRowsDefinitionmeasure、table
alternateOfcolumn
memberrole
annotation、extendedProperty任意对象(包括 queryGroup、function、member)
refmodel、table

根级对象(仅限缩进 0):model、database、table、relationship、role、cultureInfo、perspective、dataSource、expression、queryGroup、function。

语法规则

缩进

TMDL 使用空白缩进,缩进深度等于嵌套层级。PBIP 文件每层使用一个制表符(TOM TmdlSerializer 的默认设置),因此以下所有示例都使用制表符:

table Product                              // depth 0: top-level declaration
	lineageTag: abc-123                    // depth 1: table property

	measure '# Products' =                // depth 1: measure declaration
			COUNTROWS (                    // depth 3: DAX expression body (one deeper than properties)
			    VALUES ( Product[Name] )   // depth 3: continued
			)                              // depth 3: continued
		formatString: #,##0               // depth 2: measure property
		displayFolder: Measures            // depth 2: measure property
		lineageTag: def-456               // depth 2: measure property

	column 'Product Name'                  // depth 1: column declaration
		dataType: string                   // depth 2: column property
		lineageTag: ghi-789               // depth 2: column property
		summarizeBy: none                  // depth 2: column property
		sourceColumn: Product Name         // depth 2: column property

		annotation SummarizationSetBy = Automatic  // depth 2: column annotation

主要规则:

  • PBIP 文件中使用制表符(Power BI Desktop 的默认设置);空格替代方案请参阅上文的“关键”部分
  • 表级对象(列、度量值、层次结构、分区)的深度为 1
  • 这些对象的属性深度为 2
  • 多行 DAX 表达式主体的缩进深度始终比其所属声明深 2 层(表内度量值/列的深度为 3;顶级函数的深度为 2;calculationItem 的深度为 4)
  • 注释的缩进深度与其父对象的属性相同,中间以空行分隔
描述(///)

三斜线会将 Description 属性设置到下一条声明。这是原生 TMDL 语法(不是 Tabular Editor 扩展);TMDL 规范将 /// 视为一等描述支持。

/// Count of distinct products in the current filter context.
measure '# Products' =
		COUNTROWS ( VALUES ( Product[Product Name] ) )
	formatString: #,##0
	lineageTag: abc-123

规则:

  • /// 的下一行必须紧接一条声明
  • /// 和声明之间不得有空行
  • 多个 /// 行会合并为一条描述
  • /// 适用于下一条 measure、column、table、hierarchy 或 level

常见错误:

// WRONG: blank line between /// and declaration
/// This is a description.

measure 'My Measure' = 1

// WRONG: /// used as a separator comment
///
measure 'My Measure' = 1

// RIGHT: /// immediately before declaration
/// This is a description.
measure 'My Measure' = 1

// RIGHT: // used for regular comments
// This is just a comment, not a description.
measure 'My Measure' = 1
注释(//)

双斜线是普通注释,不具备语义效果:

// This is a comment — it does not set any property
measure 'My Measure' = 1
属性顺序

虽然 TMDL 不严格要求属性顺序,但应保持一致。常用顺序如下:

列: dataType、isHidden、isKey、displayFolder、lineageTag、summarizeBy、isNameInferred、sourceColumn、sortByColumn,然后是注释。

度量值: DAX 表达式(位于 = 行或跨多行)、formatString 或 formatStringDefinition、displayFolder、lineageTag,然后是注释。

名称引号

何时使用引号

名称中含有以下任一字符时,请使用单引号括起来:

  • 空格:'Product Name'
  • 句点:'Sales.Amount'
  • 等号:'Price = Target'
  • 冒号:'Date:Key'
  • 单引号(通过重复单引号进行转义):'Customer''s Name'
  • 其他特殊字符:'Sales ($)'、'OTD % (Value)'、'1) Selected Metric'
  • 以数字开头的名称:'4) Selected Period'
何时不使用引号

简单标识符无需使用引号:

  • Product(简单单词)
  • _Measures(下划线前缀,无空格)
  • Date(简单单词)
  • CgMetricQuantity(PascalCase,无空格)
示例
table Product                    // unquoted: simple name
table _Measures                  // unquoted: underscore prefix
table 'Budget Rate'              // quoted: contains space
table 'Invoice Document Type'    // quoted: contains spaces
table '1) Selected Metric'       // quoted: starts with digit
table 'On-Time Delivery'         // quoted: contains space

列定义

完整的列示例(基本、隐藏、键、sortByColumn、描述)请参阅 references/tmdl-file-examples.md。完整的属性参考请参阅 references/column-properties.md。

关键列模式:

column 'Product Name'
	dataType: string
	displayFolder: 1. Product Hierarchy
	lineageTag: abc-123
	summarizeBy: none
	sourceColumn: Product Name

	annotation SummarizationSetBy = Automatic

度量值定义

单行 DAX
measure '# Products' = COUNTROWS ( VALUES ( Product[Product Name] ) )
	formatString: #,##0
	displayFolder: Measures
	lineageTag: abc-123
多行 DAX

多行 DAX 有两种语法:

1. 缩进代码块(最常见)——表达式正文的缩进比声明多两级:

2. 三反引号代码块——将 DAX 放在 ``` 围栏中,适用于缩进较复杂的表达式:

measure Percentage = ```
		VAR _Total = CALCULATE( SUM ( 'Table'[Quantitative] ), REMOVEFILTERS ( ) )
		RETURN
		DIVIDE ( SUM ( 'Table'[Quantitative] ), _Total )
		```
	formatString: 0.0%;-0.0%;0.0%
	lineageTag: abc-123

缩进代码块语法(标准方式)——比度量值的父级(表)多缩进两个制表符:

measure 'Actuals MTD' =
		CALCULATE (
		    [Actuals],
		    CALCULATETABLE (
		        DATESMTD ( 'Date'[Date] ),
		        'Date'[IsDateInScope]
		    )
		)
	formatString: #,##0
	displayFolder: 2. MTD\Actuals
	lineageTag: abc-123
带描述的度量值
/// Number of workdays elapsed month-to-date, considering only dates in scope.
measure '# Workdays MTD' =
		CALCULATE(
		    MAX( 'Date'[Workdays MTD] ),
		    'Date'[IsDateInScope] = TRUE
		)
	formatString: #,##0
	displayFolder: 5. Weekday / Workday\Measures\# Workdays
	lineageTag: abc-123
带 formatStringDefinition(动态格式)的度量值
measure 'Sales Target MTD vs. Actuals (%)' =
		Comparison.RelativeToTarget (
		    [Actuals MTD],
		    [Sales Target MTD]
		)
	displayFolder: 2. MTD\Sales Target
	lineageTag: abc-123

	formatStringDefinition =
			FormatString.Comparison.RelativeToTarget (
			    "SUFFIX",
			    1,
			    "ARROWS",
			    "",
			    ""
			)

**注意:**通过 DAX 表达式动态计算格式时(通常使用计算组格式函数),formatStringDefinition 会取代 formatString。

其他对象类型

计算列、角色(RLS/OLS)、计算组、日期表标记、层次结构、分区、关系、共享表达式和模型配置的完整示例,请参阅 references/tmdl-file-examples.md。

常见数据质量模式

summarizeBy 规则
列类型正确的 summarizeBy原因
键(代理键/自然键)none键永不聚合
属性(名称、代码、类型)none文本属性永不求和
日期none日期永不求和
布尔标志none标志永不求和
可加数值事实(金额、数量)sum默认聚合方式为 SUM
不可加数值事实(比率、百分比)none无法进行有意义的求和

常见修正模式——将键列的 summarizeBy: sum 改为 summarizeBy: none:

// Before (wrong - key column should not sum)
column 'Customer Key'
	dataType: int64
	isHidden
	lineageTag: abc-123
	summarizeBy: sum
	sourceColumn: Customer Key

// After (correct)
column 'Customer Key'
	dataType: int64
	isHidden
	lineageTag: abc-123
	summarizeBy: none
	sourceColumn: Customer Key
formatString 模式
数据类型模式示例
整数#,##01,234
小数(2 位)#,##0.001,234.56
百分比#,##0% 或 0.00%85% 或 85.00%
货币$#,##0.00$1,234.56
日期mm/dd/yyyy 或 dd/mm/yyyy01/15/2024
PBI_FormatHint 注释

Power BI Desktop 可能会在 formatString 旁添加 PBI_FormatHint 注释:

column Amount
	dataType: decimal
	formatString: #,##0.00
	lineageTag: abc-123
	summarizeBy: sum
	sourceColumn: Amount

	annotation SummarizationSetBy = Automatic

	annotation PBI_FormatHint = {"isGeneralNumber":true}

**不要尝试移除此注释。**Power BI 工具会自动重新添加。设置 formatString 时,请保留任何已有的 PBI_FormatHint。如果 Power BI 重新添加已移除的 PBI_FormatHint,请接受。

快速参考

属性速查表

如需查看每种对象类型的完整属性参考,请参阅 references/object-properties.md。

对象属性值备注
列dataTypestring、int64、double、decimal、dateTime、boolean、binary、unknown、variant、automatic数据列必填
列summarizeBydefault、none、sum、min、max、count、average、distinctCount键/属性请使用 none
列typedata、calculated、rowNumber、calculatedTableColumn列类型变体
列isHidden(标志,无值)布尔标志:单独一行仅写关键字
列isKey(标志,无值)将该列标记为表的键
列isNullable(标志,无值)列允许为空值
列isUnique(标志,无值)列值唯一
列isNameInferred(标志,无值)根据源推断名称
列isDefaultLabel(标志,无值)表的默认标签
列isDefaultImage(标志,无值)表的默认图像
列isDataTypeInferred(标志,无值)根据源推断数据类型
列isAvailableInMdx(标志,无值)可用于 MDX 查询
列keepUniqueRows(标志,无值)保留唯一行
列encodingHintdefault、hash、value存储编码提示
列alignmentdefault、left、right、center列对齐方式
列displayFolder文件夹路径字符串使用 \ 表示嵌套:1. Year\Quarter
列sourceColumn源列名称必须与 Power Query 输出列匹配
列sortByColumn列名称引用用于排序的列(例如,按月份编号对月份名称排序)
列expressionDAX 表达式用于计算列
度量值formatString格式模式例如,#,##0、0.00%
度量值displayFolder文件夹路径字符串使用 \ 表示嵌套
度量值formatStringDefinitionDAX 表达式块动态格式字符串(替代 formatString)
度量值isHidden(标志,无值)隐藏度量值
度量值isSimpleMeasure(标志,无值)简单的隐式样式度量值
度量值dataCategory字符串语义数据类别
分区modeimport、directQuery、default、push、dual、directLake存储模式
分区sourceTypequery、calculated、none、m、entity、policyRange、calculationGroup、inferred源类型
关系crossFilteringBehavioroneDirection、bothDirections、automatic交叉筛选方向
关系securityFilteringBehavioroneDirection、bothDirections、noneRLS 筛选方向
关系fromCardinality / toCardinalitynone、one、many基数端点
关系isActive(标志,无值)活动关系
角色modelPermissionnone、read、readRefresh、refresh、administrator角色权限级别
模型discourageImplicitMeasures(标志,无值)禁用隐式度量值
模型defaultPowerBIDataSourceVersionpowerBI_V1、powerBI_V2、powerBI_V3PBI 数据源版本
模型directLakeBehaviorautomatic、directLakeOnly、directQueryOnlyDirect Lake 模式
全部lineageTagGUID唯一标识符,请勿更改现有值
缩进深度概要

规则:多行 DAX 主体的缩进深度始终比其所属对象声明深 2 级。

上下文深度制表符
顶层声明(table、relationship、expression)00
表属性、列/度量值/层次结构声明11
列/度量值属性、层次结构级别22
在深度 1 声明的度量值/列的 DAX 主体(位于表内)33
级别属性33
在深度 0 声明的顶层 function 的 DAX 主体22
calculationGroup 内的 calculationItem(深度 1)22
深度 2 的 calculationItem 的 DAX 主体44

其他资源

参考文件
  • references/object-properties.md - 涵盖 30 多种 TMDL 对象类型的完整属性参考,其中包含每种属性类型的有效枚举值(dataType、summarizeBy、modeType、crossFilteringBehavior 等)
  • references/column-properties.md - 列专属属性指南,涵盖 summarizeBy 规则、formatString 模式和 PBI_FormatHint 行为
  • references/naming-conventions.md - SQLBI 命名约定、显示文件夹约定、度量值表约定和计算组命名
  • references/bim-to-tmdl.md - 通过 Tabular Editor CLI 或 TOM TmdlSerializer 在 model.bim(TMSL)与 definition/(TMDL)之间进行转换
  • references/tmdl-file-examples.md - 每种 TMDL 文件类型的完整示例(model、database、expressions、relationships、roles、perspectives、tables、cultures),包括反引号括起的表达式、字段参数、计算组和日期表
获取文档

如需获取最新的 TMDL 参考文档,请搜索 https://learn.microsoft.com 并获取相关页面。根据用户的请求进行搜索,并按需执行多次搜索,以确保在继续操作前获得充分的上下文。

示例模型
  • examples/SpaceParts.SemanticModel/ —— 完整的真实 TMDL 模型(SpaceParts),包含 40 个表、152 个度量值、8 个计算组、8 个 RLS 角色、2 个透视,以及 DAX UDF(functions.tmdl)、共享 M 表达式、关系和区域设置。涵盖所有 TMDL 文件类型。值得查看的关键文件:
    • definition/functions.tmdl —— 带参数、类型和多行表达式的 DAX 用户定义函数
    • definition/tables/Z04CG1 - Time Intelligence.tmdl —— 带三重反引号 DAX 的计算组
    • definition/tables/__Measures.tmdl —— 带计算组引用的度量值表
    • definition/tables/Invoices.tmdl —— 大型事实表(51 个度量值,18 列)
    • definition/tables/Date.tmdl —— 包含 42 列的计算日期表
    • definition/roles/Account Managers.tmdl —— 带 DAX 筛选器表达式的 RLS 角色
    • definition/relationships.tmdl —— 27 个关系,其中包括非活动关系
    • definition/expressions.tmdl —— 共享 M/Power Query 表达式和参数
    • definition/perspectives/Measure Selection.tmdl —— 透视定义
外部参考

评论

支持 Markdown