文 / 老汪(汽车零部件财务与商业智能实战派)
“老汪,我把 6 个车间料工费字段用加号相加算总成本:
[材料] + [人工] + [电耗] + ...,为什么只要某个零件没有发生外协表面处理(值为 null),加出来的总成本整格全变成 null 了?难道我还得写一串又臭又长的判断公式吗?”
月末成本结账时,成本会计小陈抓着头发跑来诉苦。在 Excel BI 财务建模中,多列横向汇总(Row-Level Horizontal Aggregation)是一个极高频的刚需。很多初学者习惯用 Excel 的加号思维,结果在 Power Query 里被null空值撞得头破血流。今天老汪就带大家拆解一把行级横向计算的瑞士军刀 ——Record.ToList!
一、 为什么老汪说“横向多列计算,必用 Record.ToList”?
在 Power Query 的底层对象模型中:
– 一张表(Table)是由一行一行的记录(Record)组成的;
– 每一条记录本质上是一个键值对(Key-Value Pair),比如:[零件="控制臂", 材料=125, 人工=28.5]。
很多时候,我们不需要关心左边的“字段名(Key)”,我们只想把右边的“具体数值(Values)”抓取出来进行求和、求最大值、求平均值或者统计非空个数。
这时候,核心神器就是 Record.ToList。
1. 函数基本语法拆解
Record.ToList(record as record) as list
- 参数(record):目标行记录;
- 返回值(list):由该记录中所有字段值组成的纯净列表!
- 等价函数:M 语言里还有一个叫
Record.FieldValues的函数,功能与Record.ToList完全等价,但从语义直观度和书写简短度来看,老汪强烈推荐直接使用Record.ToList,简单好记!
2. 白话工作原理演示
假设有一行成本记录:
记录 = [主材=125, 人工=28.5, 动力=12, 外协=null]
直接调用函数:
Record.ToList(记录)
返回的结果就是一个纯粹的 M 语言列表:
{ 125, 28.5, 12, null }
有了这个列表,外层直接套上列表家族的强大函数,战斗力瞬间爆表:
– 横向求和(免疫 null):List.Sum(Record.ToList(...)) ➔ 结果是 165.5(自动忽略 null 空值,绝不报错!)
– 求单行最大支出项:List.Max(Record.ToList(...)) ➔ 结果是 125
– 统计有效发生项数:List.NonNullCount(Record.ToList(...)) ➔ 结果是 3 项
二、 走进车间:汽车零部件单件料工费横向成本核算现场
拿老汪经手的一家知名汽车底盘与动力总成零部件制造企业(Tier 1)为例。厂里生产比亚迪、特斯拉、吉利极氪等明星车型的核心总成。
财务部月末从 ERP 导出的《产品成本横向明细表》如下(包含 9 列大宽表,文末可免费下载随堂 Excel 课件):
| 零件图号 | 核心零部件名称 | 主机厂客户 | 主材铝锭成本(元) | CNC加工人工(元) | 产线动力电耗(元) | 专用工装模具摊销(元) | 表面阳极钝化外协(元) | 包装与辅材消耗(元) |
|---|---|---|---|---|---|---|---|---|
| P-812-ARM | 铝合金底盘下控制臂 | 比亚迪海豹 | 125.00 | 28.50 | 12.00 | 15.00 | 18.00 | 6.50 |
| P-605-CAL | 双活塞制动卡钳体 | 蔚来ES6总成 | 95.00 | 32.00 | 14.50 | 12.00 | null | 5.00 |
| P-901-TRAY | 电池包下托盘托架 | 吉利极氪001 | 380.00 | 65.00 | 35.00 | 45.00 | 52.00 | 18.00 |
| P-302-ROTOR | 轻量化通风制动盘 | 特斯拉Model Y | 85.00 | 22.00 | 11.00 | 9.50 | null | 4.50 |
| P-408-SUB | 高强前悬架副车架 | 理想L7底盘 | 260.00 | 55.00 | 28.00 | 30.00 | 36.00 | 12.00 |
| P-510-COV | 驱动电机前置端盖 | 小鹏G6三电 | 145.00 | 36.00 | 16.00 | 18.00 | null | 7.00 |
| P-715-ARM | 后悬架双球节摆臂 | 小米SU7总成 | 110.00 | 26.00 | 10.50 | 14.00 | 15.50 | 6.00 |
| P-204-STEER | 高精度转向节臂管 | 广汽埃安Hyper | 75.00 | 18.50 | 8.00 | 8.00 | null | 3.50 |
📱 移动端排版体验:上方表格已配置横向平滑滚动容器,在手机端手指左右滑动即可舒展查看完整 9 列数据,单元格字距舒展绝不挤爆!
大家注意看:制动卡钳体、通风制动盘、电机端盖等零件是不需要外协阳极钝化的,所以【表面阳极钝化外协(元)】列存在真实的 null 空值。如果直接用 + 加号相加,这些零件的单件总成本将全部阵亡变成 null!
三、 高级编辑器手把手实操代码
在随堂 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},
{"包装与辅材消耗(元)", type number}
}),
// 2. 统一定义需要横向计算的成本科目清单
成本科目列表 = {
"主材铝锭成本(元)",
"CNC加工人工(元)",
"产线动力电耗(元)",
"专用工装模具摊销(元)",
"表面阳极钝化外协(元)",
"包装与辅材消耗(元)"
},
// 3. 核心大招:Record.SelectFields 截取数值记录,配合 Record.ToList 转列表后求和
// 💡 自动忽略 null,彻底根除普通加号报空崩溃的顽疾!
添加单台总成本 = Table.AddColumn(更改类型, "单台全制造成本(元)", each
List.Sum(Record.ToList(Record.SelectFields(_, 成本科目列表))), type number),
// 4. 横向求单项最大成本金额(List.Max)
添加单项最高成本 = Table.AddColumn(添加单台总成本, "单项最高成本项金额(元)", each
List.Max(Record.ToList(Record.SelectFields(_, 成本科目列表))), type number),
// 5. 统计有效发生费用的科目数量(剔除 null)
添加有效科目数 = Table.AddColumn(添加单项最高成本, "发生费用项目数(项)", each
List.Count(List.RemoveNulls(Record.ToList(Record.SelectFields(_, 成本科目列表)))), Int64.Type),
// 6. 注入财务结构诊断建议
添加管理建议 = Table.AddColumn(添加有效科目数, "成本结构诊断建议", each
if [#"单台全制造成本(元)"] >= 300 then "🚨 高价值重载件,重点稽核主材铝锭利用率"
else if [#"单台全制造成本(元)"] >= 150 then "🟡 骨干中型总成,强化CNC机加工时管控"
else "🟢 紧凑型零部件,成本构成稳健受控", type text),
// 整理最终呈现报表
整理输出字段 = Table.SelectColumns(添加管理建议, {
"零件图号", "核心零部件名称", "主机厂客户",
"单台全制造成本(元)", "单项最高成本项金额(元)", "发生费用项目数(项)", "成本结构诊断建议"
})
in
整理输出字段
四、 最终清洗效果与车间管理看板
运行上述 M 脚本后,我们在 Excel 中得到的标准化分析看板如下(支持移动端自由横向滑动):
| 零件图号 | 核心零部件名称 | 主机厂客户 | 单台全制造成本(元) | 单项最高成本项金额(元) | 发生费用项目数(项) | 成本结构诊断建议 |
|---|---|---|---|---|---|---|
| P-812-ARM | 铝合金底盘下控制臂 | 比亚迪海豹 | 205.00 | 125.00 | 6 | 🟡 骨干中型总成,强化CNC机加工时管控 |
| P-605-CAL | 双活塞制动卡钳体 | 蔚来ES6总成 | 158.50 | 95.00 | 5 | 🟡 骨干中型总成,强化CNC机加工时管控 |
| P-901-TRAY | 电池包下托盘托架 | 吉利极氪001 | 595.00 | 380.00 | 6 | 🚨 高价值重载件,重点稽核主材铝锭利用率 |
| P-302-ROTOR | 轻量化通风制动盘 | 特斯拉Model Y | 132.00 | 85.00 | 5 | 🟢 紧凑型零部件,成本构成稳健受控 |
| P-408-SUB | 高强前悬架副车架 | 理想L7底盘 | 421.00 | 260.00 | 6 | 🚨 高价值重载件,重点稽核主材铝锭利用率 |
| P-510-COV | 驱动电机前置端盖 | 小鹏G6三电 | 222.00 | 145.00 | 5 | 🟡 骨干中型总成,强化CNC机加工时管控 |
| P-715-ARM | 后悬架双球节摆臂 | 小米SU7总成 | 182.00 | 110.00 | 6 | 🟡 骨干中型总成,强化CNC机加工时管控 |
| P-204-STEER | 高精度转向节臂管 | 广汽埃安Hyper | 113.00 | 75.00 | 5 | 🟢 紧凑型零部件,成本构成稳健受控 |
大家仔细观察第二行制动卡钳体(P-605-CAL):即使它缺少外协钝化费用,全制造成本依然精准算出了 158.50 元,有效项目数准确识别为 5 项,整张表没有任何一行因 null 崩溃!
五、 老汪从业多年总结的 2 个避坑指南
- 务必先用
Record.SelectFields过滤非数值列: – 很多同学直接写Record.ToList(_),把整行的所有字段都转成了列表。结果列表中混入了【零件图号】、【核心零部件名称】等文本,传给List.Sum时就会直接报“类型不匹配”错误! – 牢记老汪的标准套路:Record.ToList(Record.SelectFields(_, {"科目1", "科目2"...})),先圈定数值科目,再转列表求和,百发百中! - 动态获取所有数值列(高阶免维护秘籍):
– 如果表里有 30 个费用科目,连科目名字都不想手写怎么办?
– 我们可以先用
Table.ColumnNames获取所有列名,用List.RemoveMatchingItems剔除掉前 3 个文本列,剩下的动态传给Record.SelectFields,以后哪怕财务加了新科目,公式一行都不用改!
大家赶紧在文末免费下载随堂实操课件包,打开 PQ 高级编辑器跟老汪同步动手操练起来!












暂无评论内容