图形界面按钮这么方便,为啥WPS QUERY还要上M语言函数编辑器?-逆透视三层境界

Lv.3 优质创作者
周五刚把期中成绩表整理利索,隔壁工位的小白端着奶茶凑过来:"哥,问你个扎心的。WPS QUERY里按钮这么全,点两下活儿就干完了,那官方为啥还要塞个M语言函数高级编辑器进去?那玩意儿密密麻麻全是代码,看着就头大。"
我指了指他手里的奶茶:"先别急着喝。考你一题——下学期学校加了物理课,成绩表多一列,你上个月做的那个'二维转一维'查询,还能用吗?"
小白一愣:"……再点一遍?"
"你看,这就是按钮的边界。"我把成绩表拉到他面前——20个学生,序号、姓名、性别、语文、数学、英语,规规矩矩20行×6列。"今天用这张表给你拆三层:第一层会用按钮,第二层看懂代码,第三层让查询免维护。拆完你就明白,那个代码窗口不是给程序员炫技的,是给'以后的你'留的后路。"
但很多人一听到"代码"俩字就想关窗口——其实你不需要从零写起。按钮已经把框架搭好了,编辑器只是让你能打开看一看、改一改。今天就从这张成绩表出发,带你走一遍"先用按钮干完活,再掀开盖子看代码,最后顺手改两行让查询永远不坏"的三层境界。
一、按钮和代码,本来就是一家人
一句话:WPS QUERY里每个按钮,按下时都在后台替你写一段M语言代码;高级编辑器,就是打开这些代码的窗户。
打个比方:按钮是"傻瓜相机",编辑器是"手动挡"。傻瓜相机拍九成照片都够用,但想拍夜空、拍流水,就得手动调光圈快门——不是傻瓜相机不行,是场景超出它的模板了。
对比 | 图形按钮 | 高级编辑器 |
干活方式 | 点选,代码自动生成 | 直接读写代码 |
擅长 | 常规转换一步到位 | 排错、微调、动态逻辑 |
一句话 | 覆盖八成日常(解决温饱问题) | 兜住剩下两成(吃大餐) |
二、它藏在哪儿
入口路径:选中数据区域任意单元格 → 【数据】→【获取数据】→【从表格/区域获取】进入WPS QUERY查询编辑器 → 【主页】→【高级编辑器】。
打开后长这样——let 开头、in 结尾,中间每个步骤一行,in 后面跟的是最终输出:
记住一个关键:每个按钮=一行代码,每个步骤只依赖上一步。看懂这一点,代码就没那么可怕了。
三、实战:一张成绩表,拆出三层境界
原始表:20名学生 × 3科目,二维表20行×6列。目标:转成一行一条成绩的一维表。
第一层·按钮境界:会用,就赢了一半
选中成绩表任意单元格,【数据】→【获取数据】→【从表格/区域获取】进入查询编辑器;
按住 Ctrl 点选"序号""姓名""性别"三列列头;
右键列头 →【逆透视其他列】——语文、数学、英语瞬间转竖,20行变60行;
双击"属性"列头改名为"科目","值"列改名为"成绩";
【主页】→【关闭并上载】。
小白:"这我熟啊!直接交差。那要编辑器干啥?"
第二层·看码境界:看懂按钮背后的那行字
点开【高级编辑器】,刚才点的一串按钮变成了4行代码:
let
源 = Excel.CurrentWorkbook(){[Name="考试成绩表"]}[Content],
更改的类型 = Table.TransformColumnTypes(源,{{"语文", type number}, {"数学", type number}, {"英语", type number}}),
逆透视的其他列 = Table.UnpivotOtherColumns(更改的类型, {"序号", "姓名", "性别"}, "科目", "成绩")
in
逆透视的其他列(在高级编辑器复制粘贴代码即可,步骤名和源行以你编辑器里实际生成的为准;Name 与工作簿中的表名一致。)
核心就是第三步那行:Table.UnpivotOtherColumns——"把清单之外的列全部转竖"。看懂它,立刻多两个本事:
改名不重做:想把"科目""成绩"换成别的名,在代码里改两个词就行,不用回界面翻步骤;
排错有据:按钮报错只给你一个红叉,代码能告诉你哪一行、哪个参数出了问题。
第三层·免维护境界:让代码替你扛变化
场景A:新学期加了物理列,查询还能用吗?
答案取决于你当初点的哪个按钮——它俩长得有点像,脾气完全不同,“逆透视其他列”更能打:
按钮 | 背后函数 | 加物理列后 |
逆透视列 | Table.Unpivot | 列名清单写死 {"语文","数学","英语"},物理进不来,得回界面重做 |
逆透视其他列 | Table.UnpivotOtherColumns | 写死的只是钉子 {"序号","姓名","性别"},刷新一下,80行自动到手 |
这种差别,界面上一个像素都看不出来——只有看代码才看得出。这就是第二个理由:按钮之间语义的差异,代码层面才见分晓。
场景B:又来了个文本列"班级",怎么办?
想一劳永逸,把类型转换也改成动态写法:"刨掉文本列,其余全转数值"。但注意——M不会读心,它不知道"班级"是你想保留的标识列。偷懒不告诉它,两个坑一起来:班级被强转数值整列变 Error;班级还被当科目转竖,一维表里混进"成绩=三年二班"的怪行。
正确姿势:把文本列收敛成一个变量,一处报名,两处引用:
let
源 = Excel.CurrentWorkbook(){[Name="考试成绩表"]}[Content],
文本列 = {"姓名", "性别", "班级"}, // ← 新增文本列,只需在这里报名字
更改的类型 = Table.TransformColumnTypes(
源,
List.Transform(
List.Difference(Table.ColumnNames(源), 文本列),
each {_, type number}
)
),
逆透视的其他列 = Table.UnpivotOtherColumns(
更改的类型,
{"序号"} & 文本列, // 数值型标识 + 文本列,都是"钉子"
"科目", "成绩"
)
in
逆透视的其他列此后:加文本列→改一行名单;加数值科目列→零改动。追求极致还可以让M按"每列第一个非空值的类型"自动识别身份(文本留、数值转),那是下一课了。
核心认知一句话:哪列该留、哪列该转,是业务语义,M猜不出来,必须写成规则——类型定身份:文本留、数值转,标识列单独点名。
三层境界对比
境界 | 会的动作 | 解决什么 |
会用 | 点按钮出结果 | 八成日常转换,一步到位 |
看懂 | 读 let-in 结构,改一行参数 | 改名不重做、排错有据、识破按钮差异 |
写活 | 名单收敛成变量,规则写明 | 加列免维护,查询永不过期 |
四、三步口诀
一按二看三写活:
按:UI按钮先把活儿干了(逆透视其他列,20行变60行);
看:打开高级编辑器,看懂按钮写的那行代码(改码不重做);
写活:把写死的名单收敛成变量,类型定身份(新列免维护)。
口诀:按钮生代码,改码不重做;Other 族自动收,类型定身份;语义写成规则,查询永不过期。
小白掏出小本本记完,若有所思:"所以官方塞这个M函数编辑器进来,不是让咱都转行当程序员,是等按钮转不动的那天,给咱留扇门?"
"孺子可教。"我指了指屏幕,"奶茶放下——下学期物理列进来的时候,刷新之前,先想想你当初点的是哪个按钮。"
| 📌 | 文中成绩为虚构教学示例。Table.UnpivotOtherColumns 的"保留清单"适用于任何结构:把"序号、姓名、性别"换成你的标识列(班级+姓名等)即可;文中M代码步骤名以查询编辑器实际生成为准。 |
Lv.3 优质创作者
Lv.3 优质创作者
Lv.3 优质创作者
Lv.3 优质创作者
Lv.3 优质创作者
Lv.3 优质创作者
Lv.1 新人创作者
Lv.3 优质创作者
Lv.3 优质创作者