Table of Contents

代码操作

Tabular Editor 3.18.0 引入了一项名为 代码操作 的新功能。 该功能默认启用,但你可以在 工具 > 偏好 对话框中,依次进入 文本编辑器 > DAX编辑器 > 代码操作 将其禁用。

代码操作是一项提升效率的功能,会在不打扰你的情况下,为你提供改进 DAX 代码的建议。 你只需单击一次即可应用这些建议。 代码操作还让你能轻松执行常见的代码重构操作。

代码操作分为三个不同的类别:

  1. 改进:这类建议可从以下方面帮助你改进 DAX 代码:
    • 遵循最佳做法
    • 避免常见陷阱和反模式
    • 避免使用过时或已弃用的 DAX 功能
    • 编写更好、性能更高的 DAX 代码
  2. 可读性:这些建议可通过以下方式提高 DAX 代码的可读性……
    • 在可能的情况下简化复杂表达式
    • 删除冗余或不必要的代码
    • 应用一致的格式和命名规范
  3. 重写:这些是用于重构 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 的筛选参数中使用 FILTER 对整张表进行筛选,而实际上只需筛选该表中的一个或多个列即可。 示例:
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 语句 对于 SWITCH 语句,如果其 <Expression> 参数指定为 TRUE(),并且所有 <Value> 参数都是对同一个 VAR 变量/度量值的简单比较,则可以简化。 示例:
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 当条件表达式用于返回两个值中的最小值或最大值时,使用 MINMAX 函数会更高效、更简洁。 示例:
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 重写 若要在 RETURN 中从一组表达式中返回第一个非空白值,不要使用 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 函数,例如 IFSWITCH,在条件不成立时已经会返回 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 TOTALMTDTOTALQTDTOTALYTD 等函数都可以使用 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编辑器 > 代码操作,来自定义代码操作的行为。 在这里,你可以开启或关闭该功能,并为某些代码操作配置其他选项,例如用于变量名和扩展列的前缀。

我们计划在未来版本中为此界面添加更多配置选项,例如提供单独开启或关闭各个代码操作的选项。 敬请期待!

代码操作偏好