EP034 List.PositionOf:列表元素下标动态定位(首次/末次/全量匹配与容错处理)

文 / 老汪(汽车零部件财务与商业智能实战派)

“老汪,我们车间工单在制品流转表里,每一个批次当前所在的工序名字都各不相同。怎样才能动态查出这道工序在整条标准工艺路线里排第几步?距离关键水压质检瓶颈还有几道工序?”
在汽车零部件制造现场,标准工艺工序流(Process Routing)是环环相扣的。要想计算在制品完工百分比、抓取瓶颈工序前后停留批次,或者在杂乱的表格中雷达扫描表头行位置,动态查找列表元素的下标(Index / Position)是财务BP与运营分析师的必备基本功。今天老汪就带大家用最通俗易懂的语言,把 List.PositionOf 彻底吃透!


一、 为什么老汪说“学会 List.PositionOf,数据定位才具备动态智能”?

很多财务同学在 Excel 里习惯用 MATCH 函数查找某个值是第几个。而在 Power Query 的 M 语言世界里,列表(List)是内存级计算的基础容器。

要确定某个值在列表中处于哪一个位置,核心函数就是 List.PositionOf。

1. 函数基本语法拆解

List.PositionOf(
    list as list, 
    value as any, 
    optional occurrence as nullable number, 
    optional equationCriteria as any
) as any
  • 第 1 参数(list):你要在哪个列表中进行查找(目标列表);
  • 第 2 参数(value):你要找的具体目标值(如某道工序名称、某个特定工单号);
  • 第 3 参数(occurrence,核心参数!):查找模式(匹配第几次出现),支持 3 种模式:
  • Occurrence.First(或直接写数字 0,默认值):只找第一次出现的位置下标;
  • Occurrence.Last(或直接写数字 1):找最后一次出现的位置下标;
  • Occurrence.All(或直接写数字 2):找所有出现的位置下标,返回一个包含所有位置的子列表 {pos1, pos2...}!
  • 第 4 参数(equationCriteria):比较规则。默认区分大小写;若传入 Comparer.OrdinalIgnoreCase 则忽略英文字符大小写。

二、 老汪敲黑板:使用 List.PositionOf 的两大核心铁律

💡 铁律一:M 语言的下标是从 0 开始计数的(0-indexed)!

很多习惯 Excel 的同学第一次用会懵圈: – 列表中第 1 个元素,它的下标是 0; – 列表中第 2 个元素,它的下标是 1; – 如果整条工艺线有 7 道工序,最后一道工序的下标是 6!

老法师公式:实际对应的业务序号 = List.PositionOf(...) + 1。

💡 铁律二:查找失败不会弹红字报错,而是返回 -1!

如果查找的目标值在列表中根本不存在,List.PositionOf 不会像普通公式那样报 #N/A 崩溃,而是非常绅士地返回 -1! 在工程实战中,我们必须通过以下防崩护盾进行严密防御:

if [工艺节点下标] = -1 then "⚠️ 非标工序/录入错误" else ...

三、 走进车间:汽车零部件在制品工单工艺路线流转现场

拿老汪服务的一家汽车轻量化底盘与动力总成制造企业(Tier 1)为例。厂里新能源汽车托盘和副车架的生产遵循一条极其严格的标准工艺路线(共 7 道工序):

[0]型材下料 ➔ [1]精密CNC加工 ➔ [2]激光焊接 ➔ [3]气密性水压检测(★核心瓶颈) ➔ [4]三坐标质检 ➔ [5]表面钝化涂装 ➔ [6]成品包装入库

月末车间统计员导出的《在制品生产工单流转台账》如下(文末可免费下载配套 Excel 随堂课件):

生产工单号 配套核心零部件 主机厂客户 当前所在工序 计划投产数(件) 已发生累计制费(元) 责任车间班组 工序异常返修记录
WO-202611-01 电池包下壳体托盘 吉利极氪001 型材下料 2,000 15,000.00 下料一组 无
WO-202611-02 轻量化通风制动盘 特斯拉Model Y 气密性水压检测 5,000 78,000.00 质检三组 精密CNC加工,气密性水压检测,精密CNC加工
WO-202611-03 铝合金底盘下控制臂 比亚迪海豹 激光焊接 3,000 42,000.00 焊装二组 激光焊接
WO-202611-04 双活塞制动卡钳体 蔚来ES6总成 三坐标质检 4,000 92,000.00 质检一组 型材下料,激光焊接
WO-202611-05 前悬架高强副车架 理想L7底盘 表面钝化涂装 1,500 56,000.00 涂装车间 表面钝化涂装
WO-202611-06 驱动电机前置端盖 小鹏G6三电 成品包装入库 6,000 135,000.00 总成包装 无
WO-202611-07 转向节转向节臂管 广汽埃安Hyper 待排产录入 3,500 0.00 生产调度 无
WO-202611-08 双腔减震塔铸铝件 小米SU7总成 精密CNC加工 2,500 36,000.00 机加二组 精密CNC加工,激光焊接,精密CNC加工

📱 移动端排版体验:上方表格已配置横向平滑滚动容器,在手机端手指左右滑动即可舒展查看完整 8 列数据,绝不挤压折行!

大家注意看:WO-202611-07 工单的工序是“待排产录入”,这在标准工艺路线中根本不存在!正好用来检验我们的 -1 容错逻辑!


四、 高级编辑器手把手实操代码

在随堂 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 text},
        {"计划投产数(件)", Int64.Type},
        {"已发生累计制费(元)", type number},
        {"责任车间班组", type text},
        {"工序异常返修记录", type text}
    }),

    // 2. 定义标准工艺路线(0-indexed 从0开始计数的7道标准工序)
    标准工序路线 = {
        "型材下料",         // 下标 0
        "精密CNC加工",      // 下标 1
        "激光焊接",         // 下标 2
        "气密性水压检测",   // 下标 3 (★核心报废控制点)
        "三坐标质检",       // 下标 4
        "表面钝化涂装",     // 下标 5
        "成品包装入库"      // 下标 6
    },

    // 3. 核心 List.PositionOf:动态定位当前工序下标
    添加工序下标 = Table.AddColumn(更改类型, "工艺节点下标", each 
        List.PositionOf(标准工序路线, [当前所在工序]), Int64.Type),

    // 4. 计算工序流转进度百分比(注入 -1 容错防护)
    总工序数 = List.Count(标准工序路线),
    添加进度百分比 = Table.AddColumn(添加工序下标, "工序流转进度", each 
        if [工艺节点下标] = -1 then "0.0% (非标异常)"
        else Text.From(Number.Round(([工艺节点下标] + 1) / 总工序数 * 100, 1)) & "%", type text),

    // 5. 瓶颈质检管控与预警分类
    添加管控预警 = Table.AddColumn(添加进度百分比, "瓶颈质检管控预警", each 
        if [工艺节点下标] = -1 then "⚠️ 非标工序或未排产异常(返回 -1)"
        else if [工艺节点下标] < 3 then "🟢 早期加工阶段(水压检测前)"
        else if [工艺节点下标] = 3 then "🚨 关键瓶颈工序(水压水密测试中)"
        else if [工艺节点下标] < 6 then "🟡 后道精饰质检阶段"
        else "✅ 全部工序完工入库", type text),

    // 整理最终呈现报表
    整理输出字段 = Table.SelectColumns(添加管控预警, {
        "生产工单号", "配套核心零部件", "主机厂客户", "当前所在工序", 
        "工艺节点下标", "工序流转进度", "瓶颈质检管控预警", "已发生累计制费(元)"
    })
in
    整理输出字段

五、 最终清洗效果与车间管理看板

运行上述 M 脚本后,我们在 Excel 中得到的标准化分析看板如下(支持移动端自由横向滑动):

生产工单号 配套核心零部件 主机厂客户 当前所在工序 工艺节点下标 工序流转进度 瓶颈质检管控预警 已发生累计制费(元)
WO-202611-01 电池包下壳体托盘 吉利极氪001 型材下料 0 14.3% 🟢 早期加工阶段(水压检测前) 15,000.00
WO-202611-02 轻量化通风制动盘 特斯拉Model Y 气密性水压检测 3 57.1% 🚨 关键瓶颈工序(水压水密测试中) 78,000.00
WO-202611-03 铝合金底盘下控制臂 比亚迪海豹 激光焊接 2 42.9% 🟢 早期加工阶段(水压检测前) 42,000.00
WO-202611-04 双活塞制动卡钳体 蔚来ES6总成 三坐标质检 4 71.4% 🟡 后道精饰质检阶段 92,000.00
WO-202611-05 前悬架高强副车架 理想L7底盘 表面钝化涂装 5 85.7% 🟡 后道精饰质检阶段 56,000.00
WO-202611-06 驱动电机前置端盖 小鹏G6三电 成品包装入库 6 100.0% ✅ 全部工序完工入库 135,000.00
WO-202611-07 转向节转向节臂管 广汽埃安Hyper 待排产录入 -1 0.0% (非标异常) ⚠️ 非标工序或未排产异常(返回 -1) 0.00
WO-202611-08 双腔减震塔铸铝件 小米SU7总成 精密CNC加工 1 28.6% 🟢 早期加工阶段(水压检测前) 36,000.00

看!第 7 行异常工单稳稳返回 -1 并触发预警,不仅整个看板逻辑滴水不漏,而且进度百分比一目了然,车间生产调度和成本会计随时能掌握每道工序的沉淀资金!


六、 老汪从业多年总结的 2 个高阶进阶技巧

1. 抓取“最后一次”异常返工:Occurrence.Last(传参数 1)

如果一批在制品在流转中多次发生返工(如工单 02 和 08 多次经历 精密CNC加工),若我们只想查出它最后一次经历该返工工序的位置:

// 传入 Occurrence.Last 或者数字 1,返回最后一次出现的下标
List.PositionOf(返修列表, "精密CNC加工", Occurrence.Last)

2. 抓取“全部”出现位置:Occurrence.All(传参数 2)

若需要全量质检追溯,查出该工件所有经历 CNC 加工的完整下标清单:

// 传入 Occurrence.All 或者数字 2,返回一个子列表,例如 {0, 2}
List.PositionOf(返修列表, "精密CNC加工", Occurrence.All)

大家赶紧在文末免费下载随堂实操课件包,打开 PQ 高级编辑器跟老汪同步练起来!

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

请登录后发表评论

    暂无评论内容