EP039 List.TransformMany:笛卡尔积映射与多维结构重构(一对多交叉组合与自动化工资条)

文 / 老汪(汽车零部件财务与商业智能实战派)
专栏:【Excel BI 财务建模实战课讲义(第2阶段)】 · 期数:EP039
核心函数:List.TransformMany / Table.ToRows / Table.FromRows


📌 老汪开篇导读:突破维度壁垒的“笛卡尔积”神技

各位财务伙伴、薪酬核算会计与车间数据统计员:

平时在制造企业里做财务分析,我们绝大多数时候处理的都是一对一(One-to-One)的线型数据流——比如给每一行加个含税单价、给每条工单算个工时。但只要你负责过月末的薪资结算或者生产计划排程,你必然会被下面两类“一对多(One-to-Many)”的结构重构折磨得焦头烂额:

  1. 车间工资条制作:每个月一线工人的计件工资算出来了,整齐排列在一张大表里。但是车间现场发工资必须打印纸质工资条给工人签字确认!这意味着你必须在每一个工人记录上方插入一行表头,在下方插入一行空白裁切线。网上教的什么“辅助列排序法”、“公式隔行引用法”,只要人员一增减就错位瘫痪;
  2. 多维度交叉组合(笛卡尔积):比如厂部有 5 大工段,每个工段有 3 种轮班制,每种班制要排 4 道质检工序。很多人在 Excel 里只能一层层手工复制粘贴排列组合,耗时费力还极易漏项。

在 Power Query 的函数宝库中,有一张专门解决“维度交叉组合”与“一对多结构裂变”的终极王牌——List.TransformMany!

今天老汪就以汽车零部件一级供应商(Tier 1)压铸与机加车间的月度一线工人计件工资条生成为例,带大家彻底吃透笛卡尔积的数学底层逻辑,并手把手写出一键秒级自动化生成带表头与裁切线工资条的工业级 M 脚本!


🛠️ 一、 核心函数物理机制拆解

1. 函数语法与参数架构

💡 老汪敲黑板(免改路径直接刷新秘籍):
平时做财务分析最怕换台电脑一刷新就报错“找不到文件路径”。老汪在给各位学员配套的实操课件【配置】表 A1 单元格中预置了自适应公式,大家把本课案例包解压后直接点击 Excel 的【全部刷新】即可秒级重现,绝不报红字!大家可以把这套自适应架构无缝迁移到公司的日常模型中! 实操指南点此篇文章:《实操指南》

List.TransformMany(
    list as list, 
    collectionTransform as function, 
    resultSelector as function
) as list
参数名称 参数类型 形象代号 物理机制与老汪通俗拆解
list List 外层母集合 (x) 主循环驱动列表。比如传入 100 名工人的记录列表,每次遍历出一个工人 x。
collectionTransform Function 内层子集合 (y) 一对多裂变器。针对当前的 x,返回一个与之对应的子列表集合。比如返回 {表头, x, 空行}。
resultSelector Function 结果组装器 (x, y) => z 终极映射输出。接收外层元素 x 与内层当前元素 y,决定最终打平输出什么。若直接写 (x, y) => y,则直接把内层结果打平!

2. 笛卡尔积的核心原理与数学图解

假设母列表 $X = {A, B}$,子列表 $Y = {1, 2, 3}$:
通过 List.TransformMany(X, each Y, (x, y) => Text.From(x) & Text.From(y)),执行逻辑如下:
– $x = A$ 时,遍历 $Y$ ➔ 产出 $A1, A2, A3$
– $x = B$ 时,遍历 $Y$ ➔ 产出 $B1, B2, B3$
– 最终结果瞬间打平成一维列表:{"A1", "A2", "A3", "B1", "B2", "B3"}!
元素总个数等于 $2 \times 3 = 6$ 项,这就是经典的高等数学笛卡尔乘积!


🏭 二、 汽车零部件制造业业务场景实战

1. 业务背景

在我们汽车零部件 Tier 1 生产基地(包含精密压铸车间、CNC五轴机加组、机器人焊装班等),每月有大量一线计件工人的薪酬结算。

财务薪酬专员核算出的原始计件工资台账如下:

员工工号 员工姓名 所属车间工段 技能等级 计件基本工资(元) 超额计件奖(元) 满勤夜班津贴(元) 工装保养改善奖(元) 社保公积金代扣(元) 实发税后工资(元)
YG-202601 张建国 精密压铸一工段 高级压铸技师 6,800.0 1,850.0 600.0 450.0 1,150.0 8,550.0
YG-202602 李明亮 CNC数控五轴机加组 高级调机师 7,200.0 2,100.0 500.0 500.0 1,220.0 9,080.0
YG-202603 王志强 机器人激光焊装班 特种激光焊工 6,500.0 1,600.0 600.0 400.0 1,100.0 8,000.0
YG-202604 赵大宝 表面阳极钝化喷涂 中级表面处理工 5,800.0 1,400.0 550.0 350.0 980.0 7,120.0
YG-202605 孙海鹏 底盘总成智能装配 装配线技能能手 6,200.0 1,750.0 500.0 400.0 1,050.0 7,800.0
YG-202606 周福海 三坐标精密质检室 高级三坐标质检员 6,600.0 1,500.0 450.0 500.0 1,120.0 7,930.0

2. 现场打印需求与痛点

车间主任要求:每名工人必须拥有独立的 3 行打印单元:
– 行 1:清晰的 10 列标题(让工人清楚看到哪一列是基本工资、哪一列是超额奖);
– 行 2:该工人本月的实际金额明细;
– 行 3:一行空行(打印出来作为裁纸刀裁切的留白区)。

如果用 Excel 传统做法,每个月要复制几十次表头并插入空行,只要下个月多了 2 个新员工,公式和格式全得推倒重来。我们现在用 M 语言写一套全动态自适应工资条生成管道!


🚀 三、 老汪手把手推导:三大阶段实现工资条极速重构

阶段一:提取纯净表头与行列表

在我们在上一课(EP038)学过 Table.ColumnNames 和 Table.ToRows:
– 表头字段名列表 = Table.ColumnNames(更改类型):提取 10 个标题名称;
– 按行拆解数据集合 = Table.ToRows(更改类型):将整张表转为 6 个员工行子列表;
– 空裁切行 = List.Repeat({null}, 10):动态生成包含 10 个 null 的占位空行。


阶段二:调用 List.TransformMany 实施结构重构(核心大招!)

我们要把每个员工行 $x$ 变成 3 行,这就是最典型的“1 对 3 笛卡尔积裂变”:

工资条平铺行列表 = List.TransformMany(
    按行拆解数据集合,
    each {表头字段名列表, _, 空裁切行},
    (x, y) => y
)

💡 老汪敲黑板:
1. 按行拆解数据集合 作为主列表传给第 1 参数;
2. each {表头字段名列表, _, 空裁切行} 作为第 2 参数:对于每一个被遍历的员工行 _(下划线代表当前行记录),瞬间构建出由 3 个子列表组成的集合!
3. (x, y) => y 作为第 3 参数:告诉 PQ 我们不需要对 $x$ 和 $y$ 做文本拼接,直接把内层的每一行 $y$ 依序平铺输出!

执行这一步后,原本只有 6 行的员工数据,瞬间被重构为了 $6 \times 3 = 18$ 行包含表头、明细与裁切空行的平铺大列表!


阶段三:还原二维表格并提升首行标题

现在平铺的 18 行只是内存中的嵌套列表,我们调用在 EP038 掌握的 Table.FromRows 还原二维表,并调用 Table.PromoteHeaders 提升第一行作为全局表头:

生成工资条表格 = Table.FromRows(工资条平铺行列表),
提升首行标题 = Table.PromoteHeaders(生成工资条表格, [PromoteAllScalars=true])

最终生成的车间工资条效果如下(部分展示):

员工工号 员工姓名 所属车间工段 技能等级 计件基本工资(元) 超额计件奖(元) 满勤夜班津贴(元) 工装保养改善奖(元) 社保公积金代扣(元) 实发税后工资(元)
YG-202601 张建国 精密压铸一工段 高级压铸技师 6,800.0 1,850.0 600.0 450.0 1,150.0 8,550.0
✂️ ————————— [ 裁 切 线 ] —————————
员工工号 员工姓名 所属车间工段 技能等级 计件基本工资(元) 超额计件奖(元) 满勤夜班津贴(元) 工装保养改善奖(元) 社保公积金代扣(元) 实发税后工资(元)
YG-202602 李明亮 CNC数控五轴机加组 高级调机师 7,200.0 2,100.0 500.0 500.0 1,220.0 9,080.0
✂️ ————————— [ 裁 切 线 ] —————————

💡 老汪敲黑板:工业级实战避坑三要诀

  1. 第三参数的映射陷阱:
    很多人在写 (x, y) => ... 时容易晕掉。请记住口诀:x 是外层大集合的当前元素,y 是内层裂变后子集合的当前元素。如果只是为了打平插入,直接写 (x, y) => y;如果需要拼接编码(如工号+工序代码),则用 Text.From(x) & "_" & Text.From(y)。
  2. 空行的列数对齐铁律:
    空裁切行 = List.Repeat({null}, List.Count(表头字段名列表)) 必须严格采用动态计数 List.Count!因为 Table.FromRows 对每一行的元素个数有强校验,如果空行少了一个 null,整个查询会立即崩溃报错!
  3. Q001 动态相对路径机制(免改路径直接刷新秘籍):
    平时做财务分析最怕换电脑报错,老汪已经在随堂课件的【配置】表写好公式,大家解压到任意电脑或工位,直接点击【数据】➔【全部刷新】即可,绝不报红字路径不存在!

🎁 随堂实操课件包下载

本节课专属配套实操资产已全量打包,包含:
1. 《原始业务数据表.xlsx》:车间一线计件工人月度薪酬台账原始数据;
2. 《最终完成版_带PQ查询.xlsx》:内嵌 Q001 自适应配置表与自动生成带表头与裁切线工资条的标准报表;
3. 《M_动态自适应脚本.m》:标准工业级 M 语言核心脚本(含详细中文逐行注释);
4. 《PowerQuery随堂实操课件学员使用与M脚本演练指南.docx》:【学员必备实操指引】手把手带您新建空白查询、注入 M 脚本并单步回溯演练。

[评论可见]隐藏内容 – 管理员可见
📦

EP039 随堂实操课件与 M 脚本原码包

本压缩包内含本节讲解使用的 Excel 随堂课件、M 脚本源码及清洗前后对照表。
已配置绝对自适应相对路径,下载解压后即可直接一键刷新演练!

📁 文件名:EP039_List_TransformMany_笛卡尔积与工资条重构_课件包.zip


🚀 立即下载随堂课件包 (.zip)

© 版权声明
THE END
喜欢就支持一下吧
点赞8 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容