Expression.Evaluate

官方说明:

Expression.Evaluate( document as text, optional environment as nullable record) as any

解读:

这是一个神奇的函数,登场率并不高,可能你也是第一次见,甚至连官方说明里都不愿意给上半个字的解释,但是在合适的地方用上它,可能会带来意想不到的惊喜。
M函数库规范文档中有对该函数的解释:需要一个包含M的表达式并返回运算结果,类似宏表函数中的evaluate。直接上案例:
 
给一个文本形式的"6+4",直接返回运算结果10:

 
仅仅是这样吗?上面说的是包含M的表达式,所以你甚至可以给一个包含let in的完整语句:

 
用它来构建list:

 
那么也一定可以直接使用函数咯?注意引号的使用,""表示文本,若文本内本身包含引号就要写成两个引号。

 
结果发现报错了,报的还让人看不懂,这是为什么?正确的写法应该是:

简单来说,就是缺少运算环境。此时需要第二参数,类型为record,也就是说我帮你算没问题,但你得告诉我怎么算,规则在哪?而我们知道输入= #shared不仅会返回所有函数的函数名还包含函数的语法规则,且类型刚好为record,所以此时该参数就相当于声明允许使用全局函数的表达式。当然你也可以写[Text.ToList=Text.ToList],虽然看上去有点傻。再来看一个:
 

let
    a = {1..10},
    b = Expression.Evaluate("a{0}",#shared)
in
    b

首先创建一个1到10的list,然后取出list中的第一个值,此时已经加了第二参数,可是发现又报错了:

这是因为该函数只对括号内的环境运算,a是另一个步骤和它没关系,所以它并不知道你这个a是什么鬼,你得指定一个record告诉它。而此时第二参数给的是#shared,里面并没有a,正确的写法应该是:

 
那么问题来了,如果是这样呢?

let
    a = "ABCDEFG",
    b = Expression.Evaluate("Text.ToList(a)")
in
    b

这时候感觉第二参数写#shared也不是,写[a=a]也不是,那怎么办?那就两个一起写呗,把两个record合并起来,写成:

 

案例:

例1:

看到这你应该对该函数的语法有所了解了,但是可能还并不知道怎么用,或者说什么时候用,甚至会感觉有些多余。。。
来看一个题:

根据逗号分隔的数字求和,常规思路如图中的公式,先拆分再求和,但我们既然学了这个不寻常的函数,是不是就该来些不寻常的套路?把逗号替换成加号,直接求和:

 

例2:


把范围拆成列表,如果按照常规的套路一个个提取你肯定得发狂,而使用该函数构建list是不是会让你眼前一亮。
= Table.AddColumn(源, "列表", each Expression.Evaluate("{"&Text.Replace([范围],"-","..")&"}"))
 

例3:


通过时长计算分钟数,如果按照常规套路得写很长,而这个就很巧妙。先把"分钟"去掉,然后把"小时"替换成"*60+",处理成数学表达式运算一步出结果。
= Table.AddColumn(源, "迟到分钟数", each Expression.Evaluate(Text.Replace(Text.BeforeDelimiter([迟到时长],"分钟"),"小时","*60+")))
你可能会问,这个括号里也有函数名但为什么不要加第二参数呢?因为这里的函数只是对文本的嵌套处理而已,并不在引号内没有参与运算,这个要搞清楚。

11 Replies to “Expression.Evaluate”

    1. 第一参数类型是文本,文本外面加引号,文本内是一个独立的运算环境,引用环境外部的步骤或函数等就需要第二参数

  1. 这个如果自己研究的话,估计研究到死也研究不出来,还是看大神们研究成果比较好。谢谢。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注