文 / 老汪(汽车零部件财务与商业智能实战派)
大家好,我是老汪。
在咱们汽车零部件制造企业(Tier 1 一级供应商),月末关账和资产盘点的时候,做工装模具核算、固定资产会计或产线财务 BP 的朋友,经常会遇到一个棘手的场景:
工厂为了给各大主机厂(比亚迪、吉利、特斯拉、蔚来等)承制核心零部件(底盘控制臂、制动盘、电池壳体托盘、副车架),投入了大量价值几十万甚至数百万元的专用工模夹具。这些工装模具的累计冲压次数(或加工工时)与单件摊销成本,直接关乎产品的量产降本指标与资产转固报废节奏。
月末关账前夕,设备工程部和工厂财务总监把各车间的模具台账扔给你:
“老汪,把全厂所有在产核心模具排个座次:第一看负荷,累计冲压冲次高的必须排在最前面,我们要查哪些模具快到疲劳报废线该补提折旧了;第二,如果有冲次一样的模具,单件摊销成本低的排在前面,我们要核定谁的性价比更高!别在界面上一步步手工点排序了,下个月改模更新数据,你能一键全自动刷新吗?”
很多初学 Power Query 的同学第一反应是去点界面上的【排序】按钮,或者只知道 Table.Sort。但在编写复杂的高级 M 函数、自定义批量清洗逻辑(比如按车间分组后,在内存中直接对每组内部进行动态打平排序)时,在内存里直接操作列表(List)或记录(Record)是性能最高、最优雅的极客打法!
今天老汪就带大家彻底吃透 M 语言里控制列表顺序的核心函数:List.Sort,手把手教你搞定内存级的多条件复合排序!
一、 为什么老汪说“学会 List.Sort 才算真正推开 M 语言高级算力的大门”?
很多朋友问:“老汪,界面上点一下排序不就完了吗?为什么要学 List.Sort?”
老汪跟你们说句大实话:界面的排序是针对‘二维表格’(Table)的笨重操作;而 List.Sort 是直接在内存管道里对‘列表(List)’和‘行记录(Record)’进行轻量级的高性能瞬时排序!
当你后面学会了 Table.Group(高级分组)或者写自定义递归函数时,分组内部嵌套的往往根本不是一张实体大表,而是一串纯净的记录集合。如果你还要把它转回 Table 排序再转回来,电脑内存直接卡死;而用 List.Sort,几毫秒内直接在内存核心搞定!
1. 函数基本语法拆解
List.Sort(list as list, optional comparisonCriteria as any) as list
- 参数一(
list):待排序的列表(可以是纯数字、纯文本列表,也可以是更高级的“列表套列表List of Lists”或“记录列表List of Records”); - 参数二(
comparisonCriteria,可选):排序比较规则: - 默认缺省:升序(
Order.Ascending,或简写为0); - 降序:
Order.Descending,在 M 语言中可以直接简写为数字1!
2. 三大核心进阶语法(老汪亲测避坑)
-
单列纯值排序: – 升序:
List.Sort({3, 1, 4, 2})➔ 返回{1, 2, 3, 4}– 降序:List.Sort({3, 1, 4, 2}, Order.Descending)➔ 返回{4, 3, 2, 1}(也可以直接写List.Sort({3, 1, 4, 2}, 1),极其干脆!) -
嵌套子列表排序(List of Lists): – 如果一个大列表里面套着很多子列表(比如代表行数据):
{{“A”, 30}, {“B”, 10}, {“C”, 20}}– 我们想按第 2 个元素(下标为{1})降序排:powerquery List.Sort(大列表, {each _{1}, Order.Descending})> ⚠️ 老汪敲黑板:注意看!只要带了each且需要降序,外层必须用大括号{}把each和Order包裹起来,这是 M 语言的固定语法! -
记录列表排序(List of Records,★现代工程最推荐): – 当列表里包裹的是一条条 Record 记录时:
{[零件="摆臂", 冲次=18], [零件="卡钳", 冲次=24]}– 我们不再用数字下标,而是直接用字段名(Key)提取: “`powerquery // 单字段降序 List.Sort(记录列表, {each [冲次], Order.Descending})// 多字段复合排序(冲次降序,冲次相同按摊销升序) List.Sort(记录列表, { {each [冲次], Order.Descending}, {each [摊销成本], Order.Ascending} }) “` 外层一个大列表,内层每一个条件都是一个小列表,逻辑严密,层级分明!
二、 走进车间:汽车零部件模具资产数据现场
拿老汪经手的一家知名汽车底盘与动力总成零部件制造企业(Tier 1)为例。厂里冲压、压铸和机加车间共有 8 套骨干模具工装,承接各主机厂明星车型的关键部件。
老汪从设备管理系统里导出的原始明细台账如下(大家可以在文末下载随堂课件跟老汪同步动手):
| 模具工装编号 | 工装类型 | 配套核心零部件 | 主机厂配套项目 | 累计使用冲次(次) | 单件摊销成本(元/件) | 资产原值(万元) | 业务背景与关注点 |
|---|---|---|---|---|---|---|---|
| MOLD-DC-01 | 高压压铸双腔模 | 铝合金底盘下控制臂 | 比亚迪海豹项目 | 185,000 | 28.50 | 160.0 | 骨干稳产模具 |
| MOLD-ST-01 | 伺服连续冲压模 | 电池包下壳体托盘 | 吉利极氪001 | 240,000 | 32.00 | 220.0 | 冲次并列第一,摊销高 |
| MOLD-DC-02 | 高压重力铸造模 | 轻量化通风制动盘 | 特斯拉Model Y | 240,000 | 18.50 | 195.0 | 冲次并列第一,摊销低(优先排前) |
| TOOL-CNC-01 | 四轴数控精密夹具 | 双活塞制动卡钳体 | 蔚来ES6总成 | 95,000 | 14.20 | 65.0 | 爬坡期优良工装 |
| MOLD-ST-02 | 机器人多工位冲模 | 前悬架减震器支架 | 长安深蓝SL03 | 150,000 | 22.00 | 110.0 | 冲次并列第二档 |
| TOOL-WLD-01 | 底盘副车架焊接夹具 | 高强度轻量副车架 | 理想L7底盘 | 150,000 | 15.80 | 85.0 | 冲次并列,摊销更优 |
| MOLD-DC-03 | 精密压铸成型模 | 驱动电机端盖总成 | 小鹏G6三电 | 210,000 | 26.00 | 145.0 | 高负荷运转模具 |
| TOOL-CNC-02 | 高速加工中心专用刀架 | 转向节转向节臂 | 广汽埃安Hyper | 120,000 | 12.00 | 55.0 | 经济实用工装 |
大家注意看:这里面有两对典型的“冲次并列”:
1. MOLD-ST-01 与 MOLD-DC-02 的累计冲次都是 240,000 次;
2. MOLD-ST-02 与 TOOL-WLD-01 的累计冲次都是 150,000 次。
按照设备与财务考核要求:冲次高的排前面;若冲次并列,单件摊销成本低的排前面!
三、 老汪手把手带你在高级编辑器中实操
💡 老汪敲黑板(免改路径直接刷新秘籍):
平时做财务分析最怕换台电脑一刷新就蹦出一堆刺眼的红色报错:“找不到文件路径”。老汪在给你们配套的随堂 Excel 课件里,特意放了免改路径自适应刷新代码。在【配置】表的 A1 预置公式=LEFT(CELL("filename",$A$1), FIND("[", CELL("filename",$A$1))-1)并命名为【当前路径】。不管你解压到哪个文件夹,打开直接点击【全部刷新】即可秒出结果,绝不报红字!大家可以直接抄走用在自己的日常工作中!
打开 Power Query 编辑器,新建空查询,进入【高级编辑器】,直接看老汪调校的生产级 M 代码:
let
// 1. 【动态相对路径】:读取老汪预设的当前工作簿目录,换电脑绝不报错
当前路径 = 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
"./", // 兜底相对路径
源数据文件 = 当前路径 & "原始业务数据表.xlsx",
// 2. 加载工作簿并读取「工装模具台账表」
源工作簿 = Excel.Workbook(File.Contents(源数据文件), null, true),
模具表_Sheet = 源工作簿{[Item="工装模具台账表", Kind="Sheet"]}[Data],
提升标题 = Table.PromoteHeaders(模具表_Sheet, [PromoteAllScalars=true]),
更改类型 = Table.TransformColumnTypes(提升标题, {
{"模具工装编号", type text}, {"工装类型", type text}, {"配套核心零部件", type text},
{"主机厂配套项目", type text}, {"累计使用冲次(次)", Int64.Type},
{"单件摊销成本(元/件)", type number}, {"资产原值(万元)", type number}
}),
// =========================================================================
// 🚀【核心实战技巧】:利用 Record 记录列表执行极速多字段复合排序
// =========================================================================
// 3. 将二维表格化为“记录列表”(进入极致轻量的内存管道)
模具记录列表 = Table.ToRecords(更改类型),
// 4. 调用 List.Sort 双条件复合排序:
// 第一条件:累计使用冲次(次) 降序排列 (Order.Descending)
// 第二条件:单件摊销成本(元/件) 升序排列 (Order.Ascending)
记录复合排序 = List.Sort(模具记录列表, {
{each [#"累计使用冲次(次)"], Order.Descending},
{each [#"单件摊销成本(元/件)"], Order.Ascending}
}),
// 5. 瞬间将排好序的纯净内存结构还原为标准数据表
还原表 = Table.FromRecords(记录复合排序),
// 6. 追加序号与财务资产管控建议
添加序号 = Table.AddIndexColumn(还原表, "排序序号", 1, 1, Int64.Type),
添加评估建议 = Table.AddColumn(添加序号, "资产评估建议", each
if [#"累计使用冲次(次)"] >= 200000 then "临近报废大修线,优先安排转固复核"
else if [#"累计使用冲次(次)"] >= 150000 then "骨干模具稳定期,重点管控分摊单价"
else "新品量产爬坡期,设备工况优良",
type text
),
// 7. 整理列顺序,整洁呈现给管理层看板
最终呈现 = Table.ReorderColumns(添加评估建议, {
"排序序号", "模具工装编号", "工装类型", "配套核心零部件", "主机厂配套项目",
"累计使用冲次(次)", "单件摊销成本(元/件)", "资产原值(万元)", "资产评估建议"
})
in
最终呈现
四、 最终清洗效果与管理层看板对照
代码运行后,出来的最终财务看板表格如下:
| 排序序号 | 模具工装编号 | 工装类型 | 配套核心零部件 | 主机厂配套项目 | 累计使用冲次(次) | 单件摊销成本(元/件) | 资产原值(万元) | 资产评估建议 |
|---|---|---|---|---|---|---|---|---|
| 1 | MOLD-DC-02 | 高压重力铸造模 | 轻量化通风制动盘 | 特斯拉Model Y | 240,000 | 18.50 | 195.0 | 临近报废大修线,优先安排转固复核 |
| 2 | MOLD-ST-01 | 伺服连续冲压模 | 电池包下壳体托盘 | 吉利极氪001 | 240,000 | 32.00 | 220.0 | 临近报废大修线,优先安排转固复核 |
| 3 | MOLD-DC-03 | 精密压铸成型模 | 驱动电机端盖总成 | 小鹏G6三电 | 210,000 | 26.00 | 145.0 | 临近报废大修线,优先安排转固复核 |
| 4 | MOLD-DC-01 | 高压压铸双腔模 | 铝合金底盘下控制臂 | 比亚迪海豹项目 | 185,000 | 28.50 | 160.0 | 骨干模具稳定期,重点管控分摊单价 |
| 5 | TOOL-WLD-01 | 底盘副车架焊接夹具 | 高强度轻量副车架 | 理想L7底盘 | 150,000 | 15.80 | 85.0 | 骨干模具稳定期,重点管控分摊单价 |
| 6 | MOLD-ST-02 | 机器人多工位冲模 | 前悬架减震器支架 | 长安深蓝SL03 | 150,000 | 22.00 | 110.0 | 骨干模具稳定期,重点管控分摊单价 |
| 7 | TOOL-CNC-02 | 高速加工中心专用刀架 | 转向节转向节臂 | 广汽埃安Hyper | 120,000 | 12.00 | 55.0 | 新品量产爬坡期,设备工况优良 |
| 8 | TOOL-CNC-01 | 四轴数控精密夹具 | 双活塞制动卡钳体 | 蔚来ES6总成 | 95,000 | 14.20 | 65.0 | 新品量产爬坡期,设备工况优良 |
大家仔细看: – 第 1 名和第 2 名的冲次都是 240,000 次,但因为制动盘模具单件摊销成本只有 18.50 元,低于冲压模的 32.00 元,稳稳排在前面; – 第 5 名和第 6 名同样是 150,000 次冲次,焊接夹具摊销 15.80 元低于冲模的 22.00 元,同样精准排在前列!
这就是标准的多条件复合排序,整洁严密,毫厘不差!
五、 老汪从业多年总结的 2 个经典避坑指南
-
大括号嵌套规则(很多人写漏报错):
单条件排序时,如果只需要升序,写each [字段]就行;但只要加上降序或写了多条件,每一个排序规则都必须封装为一个子列表{each [字段], 排序方向},而且外层还要再套一个大列表{...}!写的时候务必检查括号是否成对配齐。 -
为什么推荐
Table.ToRecords而不是Table.ToRows?
用Table.ToRows得到的是数字下标(如_{4}、_{5})。如果车间下个月在中间插了一列,索引全部错位崩溃;而用Table.ToRecords是通过字段名(Key)寻找数据,不管列顺序怎么换,代码坚如磐石!
六、 随堂课件下载与动手实操
光看不练假把式。老汪已经把本节课涉及的完整练习题做成了一个标准课件包,内含:
– 📂 原始业务数据表.xlsx(包含 8 套工装模具台账明细,供你亲手演练)
– 📂 最终完成版_带PQ查询.xlsx(内嵌完整自适应 M 查询与配置表,解压即用)
– 📂 M_动态自适应脚本.m(可直接用记事本打开复制的纯净代码)
大家下载后解压,亲自把老汪这套流水线跑一遍。如果在实操中遇到任何问题,欢迎在评论区留言交流!














暂无评论内容