文 / 老汪(汽车零部件财务与商业智能实战派)
“老汪,我们车间有 5 道主要工序。每个班组导出的实际单件加工工时是一行数据,厂部工程部定的标准IE标杆工时是一组基准值。我想快速比对每个班组在‘哪几道工序上达到了全厂标杆水平’,难道要在高级编辑器里一条一条写
if A<=标杆A and B<=标杆B...吗?有没有批量拉链对齐比对的神奇搞法?”
在汽车零部件制造现场,标准工时(ST)、实际工时与定额计件单价的对比核算是成本会计与精益生产BP的日常重头戏。如果用传统思维硬拼,代码冗长且极难扩展。今天老汪就带大家拆解 M 语言中极具极客美感的一把高阶“拉链刀” ——List.Zip!
一、 为什么老汪说“理解了拉链(Zip),就推开了高阶函数式编程的大门”?
“Zip”在英文里就是拉链的意思。大家脑补一下拉衣服拉链的过程: 左边有一排牙齿,右边有一排牙齿。拉链头一拉过去,左边的第 0 个牙齿精准咬合右边的第 0 个牙齿,第 1 个咬合第 1 个……整整齐齐严丝合缝配对在一起。
在 Power Query 中,List.Zip 干的就是这件神奇的事情!
1. 函数基本语法拆解
List.Zip(lists as list) as list
- 参数(lists):一个由多个列表组成的“大列表”(List of Lists),形如
{ 列表1, 列表2, ... }; - 返回值(list):纵向压缩配对后的二维列表。
2. 白话工作原理极简演示
假设有两个长度相等的平行列表:
零件列表 = { "控制臂", "制动盘", "副车架" }
工时列表 = { 18.5, 12.0, 35.0 }
我们把它们放进一个大列表中,传给 List.Zip:
List.Zip({ 零件列表, 工时列表 })
瞬间返回由一组组对应元素咬合而成的新列表:
{
{ "控制臂", 18.5 },
{ "制动盘", 12.0 },
{ "副车架", 35.0 }
}
看到这个结构没有?这正是二维数据表的一行一行记录的原型!只要外层套上 Table.FromRows,瞬间就能转变成一张标准的二维表格!
💡 老汪敲黑板:列表长度不一致怎么办?(不齐长补空机制)
如果列表 1 有 3 个元素,列表 2 只有 2 个元素,List.Zip 绝不报红字崩溃,而是非常体贴地用 null 自动补齐短板:
List.Zip({ {"A", "B", "C"}, {1, 2} })
// ➔ 返回 { {"A", 1}, {"B", 2}, {"C", null} }
二、 走进车间:汽车零部件底盘产线工段精益工时标杆比对
拿老汪经手的一家知名汽车轻量化底盘零件制造企业(Tier 1)为例。厂里冲焊、压铸和机加车间共有 8 个主力生产工段。
工程技术部(IE)测定并发布了该控制臂产品 5 道工序的全厂精益标杆工时:
– 下料基准:4.2 分钟
– CNC机加基准:18.5 分钟
– 激光焊接基准:6.8 分钟
– 尺寸质检基准:3.2 分钟
– 防锈包装基准:2.5 分钟
月末成本部从 MES 系统导出的各工段《工段工序工时台账》如下(包含 8 列大宽表,文末可免费下载配套 Excel 随堂课件):
| 产线工段编号 | 责任带班班长 | 配套车型客户 | 型材精密下料(分) | CNC加工中心(分) | 机器人激光焊(分) | 三坐标尺寸质检(分) | 钝化防锈包装(分) |
|---|---|---|---|---|---|---|---|
| LINE-01-A | 张建国(精益先锋) | 比亚迪海豹 | 4.2 | 18.5 | 6.8 | 3.2 | 2.5 |
| LINE-01-B | 李明华 | 特斯拉Model Y | 4.8 | 19.2 | 7.5 | 3.5 | 2.8 |
| LINE-02-A | 王志刚 | 吉利极氪001 | 4.0 | 18.0 | 7.2 | 3.1 | 2.4 |
| LINE-02-B | 赵德利 | 蔚来ES6总成 | 4.5 | 21.0 | 8.0 | 3.8 | 3.0 |
| LINE-03-A | 孙强 | 理想L7底盘 | 4.1 | 18.2 | 6.5 | 3.0 | 2.6 |
| LINE-03-B | 刘波 | 小鹏G6三电 | 5.0 | 22.5 | 8.5 | 4.0 | 3.2 |
| LINE-04-A | 陈明 | 小米SU7总成 | 4.2 | 18.5 | 6.7 | 3.1 | 2.5 |
| LINE-04-B | 周福海 | 广汽埃安Hyper | 4.6 | 20.0 | 7.8 | 3.4 | 2.9 |
📱 移动端排版体验:上方表格已配置横向平滑滚动容器,在手机端手指左右滑动即可舒展查看完整 8 列数据,单元格字距舒展绝不挤爆!
我们要算清楚:每个工段在 5 道关键工序中,究竟有几道工序的耗时达到或超越了全厂 IE 标杆水平(即 实际工时 <= 标杆工时)?
三、 白话拆解:List.Zip 拉链对齐批量比对四步法
[工段实际工时列表] ───┐
├─ List.Zip ─→ { {4.2, 4.2}, {18.5, 18.5}, {6.8, 6.8}... }
[全厂IE标杆工时列表] ──┘ │
(List.Select 批量比对)
↓
{ 实际 <= 标杆 的优胜组 }
↓
List.Count ➔ 达标项数 (如 5 项)
- 第一步(取实际):用
Record.SelectFields与Record.ToList将当前行的 5 个工序工时提取为数值列表; - 第二步(拉拉链):调用
List.Zip({实际工时列表, 全厂标杆工时列表}),把对应工序的两组数据自动配成一个个小对子:{实际耗时, 标杆耗时}; - 第三步(批量断):用
List.Select(配对组, each _{0} <= _{1})瞬间抓出所有达标的工序(_{0}为实际,_{1}为标杆); - 第四步(数个数):套上
List.Count,立马得出该班组达到了几个标杆,彻底告别写 5 遍if判断的笨办法!
四、 高级编辑器手把手实操代码
在随堂 Excel 课件中,老汪已将 Q001 动态相对路径标准置入【配置】表。进入 Power Query 高级编辑器,贴入老汪的标准自适应代码:
let
// 💡 老汪敲黑板(免改路径直接刷新秘籍):换电脑解压后直接点【全部刷新】永不报红字!
当前路径 = try
let
raw = Text.From(Excel.CurrentWorkbook(){[Name="当前路径"]}[Content]{0}[Column1]),
clean = Text.Trim(raw)
in
if Text.EndsWith(clean, "\") then clean else clean & "\"
otherwise
"./",
// 1. 读取原始业务数据源
数据源路径 = 当前路径 & "原始业务数据表.xlsx",
源 = Excel.Workbook(File.Contents(数据源路径), null, true),
工段原始表 = 源{[Item="工段工序工时台账", Kind="Sheet"]}[Data],
提升标题 = Table.PromoteHeaders(工段原始表, [PromoteAllScalars=true]),
更改类型 = Table.TransformColumnTypes(提升标题, {
{"产线工段编号", type text},
{"责任带班班长", type text},
{"配套车型客户", type text},
{"型材精密下料(分)", type number},
{"CNC加工中心(分)", type number},
{"机器人激光焊(分)", type number},
{"三坐标尺寸质检(分)", type number},
{"钝化防锈包装(分)", type number}
}),
// 2. 统一定义需要比对的工序字段与标杆基准
工序字段列表 = {
"型材精密下料(分)",
"CNC加工中心(分)",
"机器人激光焊(分)",
"三坐标尺寸质检(分)",
"钝化防锈包装(分)"
},
// 5 道工序的标准基准耗时(分钟)
全厂标杆工时列表 = { 4.2, 18.5, 6.8, 3.2, 2.5 },
// 3. 核心大招:List.Zip 拉链配对 + 批量条件筛选
添加达标工序数 = Table.AddColumn(更改类型, "达到/优于标杆工序数(项)", each
let
当前工时记录 = Record.SelectFields(_, 工序字段列表),
当前工时列表 = Record.ToList(当前工时记录),
// ★核心拉链配对:瞬间组合为 {{实际1, 标杆1}, {实际2, 标杆2}...}
拉链配对列表 = List.Zip({当前工时列表, 全厂标杆工时列表}),
// 筛选出 实际耗时 <= 标杆耗时 的优胜工序对
达标组 = List.Select(拉链配对列表, each _{0} <= _{1}),
达标数量 = List.Count(达标组)
in
达标数量, Int64.Type),
// 4. 计算工段单件总耗时与标杆达成率
添加实际总工时 = Table.AddColumn(添加达标工序数, "实际单件总工时(分)", each
List.Sum(Record.ToList(Record.SelectFields(_, 工序字段列表))), type number),
添加达成率 = Table.AddColumn(添加实际总工时, "标杆工序达成率", each
Text.From(Number.Round([#"达到/优于标杆工序数(项)"] / List.Count(全厂标杆工时列表) * 100, 1)) & "%", type text),
// 5. 评定精益星级与激励
添加评级对策 = Table.AddColumn(添加达成率, "精益班组评级与激励", each
if [#"达到/优于标杆工序数(项)"] = 5 then "🏆 五星全能标杆班组(发放最高精益奖)"
else if [#"达到/优于标杆工序数(项)"] >= 3 then "⭐ 四星先锋班组(达标工序符合预期)"
else "⚠️ 效率滞后工段(列入下周IE改善辅导名单)", type text),
// 整理最终呈现报表
整理输出字段 = Table.SelectColumns(添加评级对策, {
"产线工段编号", "责任带班班长", "配套车型客户",
"实际单件总工时(分)", "达到/优于标杆工序数(项)", "标杆工序达成率", "精益班组评级与激励"
})
in
整理输出字段
五、 最终清洗效果与车间管理看板
运行上述 M 脚本后,我们在 Excel 中得到的标准化分析看板如下(支持移动端自由横向滑动):
| 产线工段编号 | 责任带班班长 | 配套车型客户 | 实际单件总工时(分) | 达到/优于标杆工序数(项) | 标杆工序达成率 | 精益班组评级与激励 |
|---|---|---|---|---|---|---|
| LINE-01-A | 张建国(精益先锋) | 比亚迪海豹 | 35.2 | 5 | 100.0% | 🏆 五星全能标杆班组(发放最高精益奖) |
| LINE-01-B | 李明华 | 特斯拉Model Y | 37.8 | 0 | 0.0% | ⚠️ 效率滞后工段(列入下周IE改善辅导名单) |
| LINE-02-A | 王志刚 | 吉利极氪001 | 34.7 | 4 | 80.0% | ⭐ 四星先锋班组(达标工序符合预期) |
| LINE-02-B | 赵德利 | 蔚来ES6总成 | 40.3 | 0 | 0.0% | ⚠️ 效率滞后工段(列入下周IE改善辅导名单) |
| LINE-03-A | 孙强 | 理想L7底盘 | 34.4 | 4 | 80.0% | ⭐ 四星先锋班组(达标工序符合预期) |
| LINE-03-B | 刘波 | 小鹏G6三电 | 43.2 | 0 | 0.0% | ⚠️ 效率滞后工段(列入下周IE改善辅导名单) |
| LINE-04-A | 陈明 | 小米SU7总成 | 35.0 | 5 | 100.0% | 🏆 五星全能标杆班组(发放最高精益奖) |
| LINE-04-B | 周福海 | 广汽埃安Hyper | 38.7 | 0 | 0.0% | ⚠️ 效率滞后工段(列入下周IE改善辅导名单) |
看!通过 List.Zip,全厂 8 个工段的标杆达标情况一秒算出。张建国班组和陈明班组全工序达标,稳稳拿下五星最高精益激励;而李明华、刘波工段工时偏长,IE 改善工程师直接进驻辅导!
六、 老汪从业多年总结的 2 个避坑指南
- 务必牢记外层需要传“列表的列表”
{ {A}, {B} }: – 很多初学者写List.Zip(列表A, 列表B),结果直接报错。牢记List.Zip只有一个参数,多个列表必须用大括号包起来成为一个母列表:List.Zip({列表A, 列表B})! - 多列构造二维表的神仙组合:
Table.FromRows+List.Zip: – 如果你有 3 个独立提取出的列表:工号列表、姓名列表、计件工资列表,怎么一瞬间把它们拼成一张数据表? – 答案是:powerquery Table.FromRows(List.Zip({工号列表, 姓名列表, 计件工资列表}), {"工号", "姓名", "实发计件工资"})– 这一招在解析多层嵌套 JSON、API 接口或者复杂分段汇总时,堪称降维打击利器!
大家赶紧在文末免费下载随堂实操课件包,打开 PQ 高级编辑器跟老汪同步动手操练起来!














暂无评论内容