自定义函数

基础用法:

在M语言中,标准库函数(standard library functions)约有700个。但是如果你觉得太少了,或者说不好用,那么也可以通过自定义函数来实现自己想要的效果。自定义函数的基本语法为:
函数名=(参数1,参数2,参数3...)=>表达式
先来看个例子:

let
    get_list = (start as number,end as number)=>{start..end},
    result = get_list(1,100)
in
    result

首先定义一个名为"get_list"的自定义函数,需要2个形参:start和end,并且限制类型为number,所以当如果我们传入的实参类型为text等时就会报错。as number可以不写,如果不写默认的类型为any,在M中定义变量类型是非必需的。最右边是函数的表达式,我们构建了一个起止分别为这两个参数的list。参数与表达式之间用=>隔开,这是固定组合。
然后调用自定义函数,将实参1和100传入函数,表达式变为{1..100},即最后的结果。
如果在变量前加上optional,则声明该参数为可选参数,比如optional end as number,那么调用该函数的时候这个参数就可省略。
但是在M中并没有默认参数的概念,不能对可选参数指定一个默认值。如果要实现默认参数的效果,可以在=>后面用if start is null then...else...的方式判断是否传入了实参,稍微麻烦了一点。

匿名函数:

先看案例:

let
    select = (x)=>Table.SelectRows(source, each [index] <= x),
    source = Excel.CurrentWorkbook(){[Name="table"]}[Content],
    result = Table.AddColumn(source, "acc", each List.Sum(select([index])[index]))
in
    result

定义一个名为"select"的自定义函数,筛选index<=变量的行,然后深化出筛选表的index列,再进行求和,实现根据index累计求和的效果。
那我们就想能不能不多写一个步骤,直接把自定义函数嵌套在里面呢?事实上也是可以的:

let
    source = Excel.CurrentWorkbook(){[Name="table"]}[Content],
    result = Table.AddColumn(source, "acc", each List.Sum(Table.SelectRows(source,(x)=>x[index]<=[index])[index]))
in
    result

这么一改,我们依然使用了一个自定义函数,但是并没有给函数命名,所以叫做匿名函数。这个参数x起到了突破上下文的作用,具体请参考《深入理解函数》

小技巧:

  • 如在查询的其中一个步骤中创建自定义函数,调用时函数名为步骤名,此时自定义函数只能供该查询内部调用;
  • 如单独将一个查询创建为自定义函数,调用时函数名为查询名,此时自定义函数可供其他所有查询调用;
  • 如在步骤之间创建自定义函数,继续添加步骤或调整步骤顺序时比较容易出错,所以建议打开高级编辑器,将自定义函数写作第一个步骤。

 

练习:

请根据以上介绍的方法,将累计求和的案例改为条件累计求和,即[name]为"a"只累计"a"的。

13 Replies to “自定义函数”

  1. 条件累计求和:

    let
    source = Excel.CurrentWorkbook(){[Name="table"]}[Content],
    result = Table.AddColumn(source, "acc", each List.Sum(Table.SelectRows(source,(x)=>x[index]<=[index] and x[name]=[name])[index]))
    in
    result

  2. let
    select = (x,y)=>Table.SelectRows(Table.SelectRows(source, each [name] = x),each [index]<=y),
    source = Excel.CurrentWorkbook(){[Name="Table"]}[Content],
    result = Table.AddColumn(source, "acc", each List.Sum(select([name],[index])[index]))
    in
    result

    1. 这里只是举个例子,实际如果对表中已有的列累计求和,可以先添加索引列,索引列不会重复的

  3. 老师,在创建自定义函数时,输入参数为字段时,
    在自定义函数内部要怎么表示这个字段,

    例如,自定义函数包含两个参数,T为表格,R为字段
    自定义函数内要怎么表达T表格里的R字段
    我写TR不行,T【R】也不行

  4. 就像楼上施老师说的一样,先加一个索引列,然后再将条件判断的地方列名称改为[索引]就行了。

  5. 请教下,我在A工作簿创建了一个自定义函数,但是想在B工作簿引用这个自定义函数,有没有什么办法

  6. 请教下,假如在A表创建了自定函数,想在另一个工作簿B引用自定义函数有什么方法吗

发表回复

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