代码操作
Tabular Editor 3.18.0 引入了一项名为 代码操作 的新功能。 该功能默认启用,但你可以在 工具 > 偏好 对话框中,依次进入 文本编辑器 > DAX编辑器 > 代码操作 将其禁用。
代码操作是一项提升效率的功能,会以低干扰的方式提供改进 DAX 代码的建议。 你只需单击一次即可应用这些建议。 代码操作还让你能轻松执行常见的代码重构操作。
代码操作分为三个不同的类别:
- 改进:这类建议可从以下方面帮助你改进 DAX 代码:
- 遵循最佳做法
- 避免常见陷阱和反模式
- 避免使用过时或已弃用的 DAX 功能
- 编写更好、性能更高的 DAX 代码
- 可读性:这些建议可通过以下方式提高 DAX 代码的可读性……
- 在可能的情况下简化复杂表达式
- 删除冗余或不必要的代码
- 应用一致的格式和命名规范
- 重写:这类建议用于重构你的 DAX 代码。 它们不一定是改进,但在进行较大规模的代码重构时通常很有用。 示例包括:
- 将 DAX “语法糖”改写为更冗长但更明确的代码
- 重命名某个变量或扩展列的所有出现位置
- 格式化代码
如何使用代码操作
新增了命令 显示代码操作 及其对应的工具栏/菜单按钮,默认快捷键为 Ctrl+.。 这个命令会显示当前光标位置可用的代码操作:

你也可以通过右键上下文菜单中的 重构 子菜单找到可用的代码操作:

最后,当光标位于有适用操作的代码分段上时,编辑器左侧边距会显示灯泡或螺丝刀图标。 点击该图标也会打开代码操作菜单:

将鼠标悬停在代码操作菜单中的某个操作上时,工具提示会显示该操作的更多信息。 点击“了解更多”链接,即可查看该操作对应的知识库 (KB) 文章。

代码操作指示器
在代码编辑器中,改进 和 可读性 代码操作也会以视觉标识显示。 这让你可以快速判断代码中哪些部分还能改进,或变得更易读。
- 改进会在代码分段开头的前几个字符下方以橙色圆点标示(除非该代码分段已显示橙色警告波浪线)。 当光标移到该代码分段上时,左侧边距会显示一个 灯泡 图标。
- 可读性操作会在代码分段前几个字符下方显示蓝绿色圆点。 当光标移到该代码分段上时,左侧边距会显示一个 螺丝刀 图标。
- 重写本身不会在代码中显示任何视觉标记;但当光标放在包含可用重写的代码分段上时,左侧边距会出现 螺丝刀 图标。
应用到所有出现处
某些代码操作可以应用于当前 DAX 表达式、DAX 脚本或 DAX 查询中的所有出现位置,而不只是光标所在的代码分段。 在这种情况下,该代码操作会显示在“代码操作”菜单中,并在操作描述后追加 " (All occurrences)"。 点击该操作后,将把更改应用于文档中的所有出现处。
例如,在下方截图中,为变量添加“_”前缀这个操作可以应用到文档中的所有出现位置(即所有变量),而不只是光标所在的 totalSales 变量:

代码操作列表
下表列出了当前所有可用的代码操作。 你可以在 工具 > 偏好 对话框的 文本编辑器 > DAX编辑器 > 代码操作 下关闭代码操作(后续更新将允许你单独开关各项操作,以获得更个性化的体验)。 某些代码操作还提供额外的配置选项,例如为变量名使用哪个前缀。
改进
以下代码操作会在适用代码的前两个字符下方显示橙色圆点;当光标位于该代码分段上时,左侧边距还会出现灯泡图标:
| ID | 名称 | 描述 |
|---|---|---|
| DI001 | 删除未使用的变量 | 未在任何地方被引用的变量应删除。 示例:VAR a = 1 VAR b = 2 RETURN a -> VAR a = 1 RETURN a |
| DI002 | 删除所有未使用的变量 | 在 VAR 变量块中,凡是在 RETURN 部分未被使用的变量(无论是直接使用,还是通过其他变量间接使用)都应删除。 示例:VAR a = 1 VAR b = a RETURN 123 -> 123 |
| DI003 | 移除表名 | 度量值引用中不应包含表名,因为引用度量值时表名是多余的。 此外,这样做也能让度量值引用与列引用更容易区分。 示例:Sales[Total Sales] -> [Total Sales] |
| DI004 | 添加表名 | 列引用应包含表名,以避免歧义,并更容易将列引用与度量值引用区分开来。 示例:SUM([SalesAmount]) -> SUM(Sales[SalesAmount]) |
| DI005 | 将表筛选 FILTER 重写为标量谓词 | DAX 中一个常见的反模式是,在 CALCULATE 的筛选器参数中筛选整张表,而实际上只需筛选该表中的一个或多个列即可。 示例:CALCULATE([Total Sales], FILTER(Products, Products[Color] = "Red")) -> CALCULATE([Total Sales], KEEPFILTERS(Products[Color] = "Red"))此代码操作支持原始表达式的多种变体。 |
| DI006 | 将多列筛选拆分为多个筛选 | 当使用 AND(或等效的 && 运算符)将多个列组合起来筛选表时,通常可通过为每一列分别指定筛选条件来获得更好的性能。 示例:CALCULATE(..., Products[Color] = "Red" && Products[Size] = "Large") -> CALCULATE(..., Products[Color] = "Red", Products[Size] = "Large") |
| DI007 | 简化 SWITCH 语句 | 将 TRUE() 指定为 <Expression> 参数,且所有 <Value> 参数都是对同一 VAR 变量/度量值进行简单比较的 SWITCH 语句,可以简化。 示例:SWITCH(TRUE(), a = 1, ..., a = 2, ...) -> SWITCH(a, 1, ..., 2, ...) |
| DI008 | 移除多余的 CALCULATE | 如果 CALCULATE 并非必需——例如它不会修改筛选语境,或即使省略也会发生隐式语境转换——则应将其移除。 示例:CALCULATE([Total Sales]) -> [Total Sales]AVERAGEX(Product, CALCULATE([Total Sales])) -> AVERAGEX(Product, [Total Sales])如果 CALCULATE / CALCULATETABLE 的第一个参数是 DAX 变量,也同样适用,例如:VAR x = [Total Sales] RETURN CALCULATE(x, Product[Color] = "Red") ->VAR x = [Total Sales] RETURN x |
| DI009 | 避免使用 CALCULATE 简写语法 | 示例:[Total Sales](Products[Color] = "Red") -> CALCULATE([Total Sales], Products[Color] = "Red") |
| DI010 | 使用 MIN/MAX 代替 IF | 当使用条件表达式返回两个值中的较小值或较大值时,使用 MIN 或 MAX 函数会更高效,也更简洁。 示例:IF(a > b, a, b) -> MAX(a, b) |
| DI011 | 使用 ISEMPTY 代替 COUNTROWS | 检查表是否为空时,使用 ISEMPTY 函数比统计表的行数更高效。 示例:COUNTROWS(Products) = 0 -> ISEMPTY(Products) |
| DI012 | 使用 DIVIDE 代替除法 | 当分母为任意表达式时,应使用 DIVIDE 而不是除法运算符,以避免除以零错误。 示例:x / y -> DIVIDE(x, y) |
| DI013 | 使用除法运算符代替 DIVIDE | 当 DIVIDE 的第 2 个参数是非零常量时,使用除法运算符会更高效。 示例:DIVIDE(x, 2) -> x / 2 |
| DI014 | 用 DIVIDE 代替 IFERROR | 除法的分母为零时,如果要提供替代结果,使用 DIVIDE 函数,而不是 IFERROR。 示例:IFERROR(x / y, 0) -> DIVIDE(x, y, 0) |
| DI015 | 用 DIVIDE 替换 IF | 如果想更轻松地检查分母是否为零或空白,使用 DIVIDE 函数,而不是 IF。 示例:IF(y <> 0, x / y) -> DIVIDE(x, y) |
| DI016 | 使用正确的 UDF 语法 | 用户定义函数表达式应使用正确的语法。 示例:(x, y) => x + y |
可读性
将光标置于代码分段上时,下面的代码操作会在适用代码的前两个字符下方显示青绿色圆点,并在左侧边距显示螺丝刀图标
| ID | 名称 | 描述 |
|---|---|---|
| DR001 | 转换为标量谓词 | 列筛选可以更简洁地写成标量谓词,而无需显式使用 FILTER 函数。 示例:FILTER(ALL(Products[Color]), Products[Color] = "Red") -> Products[Color] = "Red"FILTER(VALUES(Products[Color]), Products[Color] = "Red") -> KEEPFILTERS(Products[Color] = "Red") |
| DR002 | 使用聚合函数而非迭代器函数 | 在可能的情况下,使用聚合函数而不是迭代器函数,以简化代码。 示例:SUMX(Products, Products[SalesAmount]) -> SUM(Products[SalesAmount]) |
| DR003 | 使用 VALUES 而非 SUMMARIZE | 当 SUMMARIZE 只指定一个列,且该列属于第一个参数指定的表时,可改用 VALUES 让代码更简洁。 示例:SUMMARIZE(Products, Products[Color]) -> VALUES(Products[Color]) |
| DR004 | 为 VAR 变量添加前缀 | 变量应使用一致的命名规范。 建议使用前缀,例如下划线。 你可以配置要使用的前缀,以匹配你偏好的风格。 示例:VAR totalSales = SUM(Sales[SalesAmount]) -> VAR _totalSales = SUM(Sales[SalesAmount]) |
| DR005 | 为临时列设置前缀 | 建议为临时列使用统一的前缀,以便更轻松地将其与基础列或度量值区分开来。 你可以配置要使用的前缀,以符合你偏好的风格。 示例:ADDCOLUMNS(Product, "SalesByProd", [Sales]) -> ADDCOLUMNS(Product, "@SalesByProd", [Sales]) |
| DR006 | 将常量聚合移入 VAR 变量 | 当聚合函数在迭代器或标量谓词中使用时,该聚合会为迭代中的每一行产生相同的结果。 因此,可以将该聚合移到迭代之外的 DAX VAR 变量中。 示例:CALCULATE(..., 'Date'[Date] = MAX('Date'[Date])) ->VAR _maxDate = MAX('Date'[Date]) RETURN CALCULATE(..., 'Date'[Date] = _maxDate) |
| DR007 | 简化 1 变量块 | 仅包含一个 VAR 变量的变量块可通过将表达式直接移到该块的 RETURN 部分来简化。 这假定该变量只被引用一次,且没有任何上下文修饰符。 示例:VAR _result = [Sales] * 1.25 RETURN _result -> [Sales] * 1.25 |
| DR008 | 简化多变量 VAR 块 | 如果一个 VAR 变量块包含多个变量,且每个变量都只是简单的度量值引用,并且在 RETURN 部分仅使用一次且不带任何上下文修饰符,则应将该变量块简化。 示例:VAR _sales = [Sales] VAR _cost = [Cost] RETURN _sales - _cost -> [Sales] - [Cost] |
| DR009 | 使用 DISTINCTCOUNT 重写 | 要统计列中不同值的数量,不要使用 COUNTROWS(DISTINCT(T[c]),而应使用 DISTINCTCOUNT 函数。 |
| DR010 | 使用 COALESCE 重写 | 不要使用 IF 从一组表达式中返回第一个非空白值,而应使用 COALESCE 函数。 示例:IF(ISBLANK([Sales]), [Sales2], [Sales]) -> COALESCE([Sales], [Sales2]) |
| DR011 | 使用 ISBLANK 重写 | 与其将表达式同 BLANK() 进行比较,不如使用 ISBLANK 函数。 示例:IF([Sales] = BLANK(), [Budget], [Sales]) -> IF(ISBLANK([Sales], [Budget], [Sales]) |
| DR012 | 移除不必要的 BLANK | 某些 DAX 函数(例如 IF 和 SWITCH)在条件为 false 时本身就会返回 BLANK(),因此无需显式指定 BLANK()。 示例:IF(a > b, a, BLANK()) -> IF(a > b, a) |
| DR013 | 简化取反逻辑 | 当逻辑表达式取反时,通常用取反后的运算符重写该表达式会更易读。 示例:NOT(a = b) -> a <> b |
| DR014 | 使用 IN 简化 | 使用 IN 运算符来重写复合谓词(即针对同一表达式的相等比较,并通过 OR 或 \|\| 进行组合)。 示例:a = 1 \|\| a = 2 \|\| a = 100 -> a IN { 1, 2, 100 } |
重写
当光标放在代码分段上时,下方这些代码操作会以螺丝刀图标的形式显示在左侧边距。
| ID | 名称 | 描述 |
|---|---|---|
| RW001 | 使用 CALCULATE 重写 TOTALxTD | TOTALMTD、TOTALQTD 和 TOTALYTD 等函数都可以使用 CALCULATE 函数重写。这样表达力更强,也提供了更高的灵活性。 示例:TOTALYTD([Total Sales], 'Date'[Date]) -> CALCULATE([Total Sales], DATESYTD('Date'[Date])) |
| RW002 | 使用 FILTER 重写 | CALCULATE 的筛选器参数中的标量谓词可以用 FILTER 改写。 例如,当你需要添加更复杂的筛选逻辑时,这会很有用。 示例:CALCULATE(..., Products[Color] = "Red") -> CALCULATE(..., FILTER(ALL(Products[Color]), Products[Color] = "Red")) |
| RW003 | 反转 IF | 为了提高可读性,有时反转 IF 语句会很有帮助。 示例:IF(a < b, "B is greater", "A is greater") -> IF(a > b, "A is greater", "B is greater") |
自定义代码操作
你可以在 工具 > 偏好 对话框中,依次进入 文本编辑器 > DAX编辑器 > 代码操作,自定义代码操作的行为。 在这里,你可以开启或关闭该功能,并为某些代码操作配置其他选项,例如用于变量名和扩展列的前缀。
我们计划在未来版本中为此界面添加更多配置选项,例如提供可单独启用或禁用各个代码操作的选项。 敬请期待!
