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 的筛选器参数中筛选整张表,而实际上只需筛选该表中的一个或多个列即可。 示例:
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 当使用条件表达式返回两个值中的较小值或较大值时,使用 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 重写 不要使用 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)在条件为 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 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编辑器 > 代码操作,自定义代码操作的行为。 在这里,你可以开启或关闭该功能,并为某些代码操作配置其他选项,例如用于变量名和扩展列的前缀。

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

代码操作偏好