EP048 Text.Contains:文本模糊包含与智能质检打标(不区分大小写匹配与索赔扣款稽核)

文 / 老汪(汽车零部件财务与商业智能实战派)
专注制造业财务中台构建、Power Query/Power BI 自动化建模与业财融合落地


01 老汪开篇·痛点暴击:质检异常备注里的“索赔暗礁”

在汽车零部件制造企业(Tier 1)的供应链财务对账中,月末最让应付会计和成本会计头疼的,莫过于“供应商质量索赔与让步接收扣款”。

每一批来料入厂,质量部(IQC)都会在 ERP 或 MES 系统中录入检验台账。质检员在填写“检验异常与技术协议描述”时,几乎是自由文本录入:
– 有的写:“荧光探伤发现轮齿根部微细裂纹,判定NG严重不合格”;
– 有的写:“尺寸超差且带有ng标识,复核不合格”;
– 有的写:“压铸件局部密集气孔超标,强度测试不达标,建议报废”;
– 有的写:“法兰连接螺孔内壁轻微氧化,尺寸合格,允许让步接收”;
– 有的写:“包装箱轻微破损,外箱标签打码模糊,实物检验OK”。

按照主机厂与供应链质量协议:
1. 致命与严重缺陷(如裂纹、气孔、报废、明确判定 NG):必须整批退货,并按采购总额的 20% 计提质量违约索赔款,当期货款一律冻结不付!
2. 一般工艺与加工缺陷(如超差、氧化、划伤、滑丝):经工程评审特采让步接收,按 5% 扣减结算款;
3. 轻微标识与包装缺陷(如打码模糊、外箱破损):让步接收,按 1% 扣减管理费;
4. 合格检验:全额放行付款。

很多财务人员怎么做?
要么在 Excel 里用肉眼一条条读备注筛选,要么在单元格里套一层又一层的 IF(ISNUMBER(FIND(...)))。但很快就会遇到两颗“致命暗礁”:
– 暗礁一:大小写敏感导致漏判! 质检员随手打的小写 "ng",用大写 "NG" 去找直接返回错误或找不到,导致几十万的严重质量缺陷批次被当作合格放行付款,给公司带来不可挽回的资金损失!
– 暗礁二:多层条件逻辑臃肿不堪! 包含“裂纹”或“气孔”或“报废”,公式写得如同天书,一旦来料几千批,Excel 瞬间卡死。

今天老汪带大家拆解 M 语言中最为核心的文本查找函数——Text.Contains,结合第三参数比较器 Comparer.OrdinalIgnoreCase,打造一套工业级、免疫大小写、毫秒级智能打标与索赔扣款自动稽核模型!


02 函数档案·语法拆解

2.1 函数签名与参数说明

在 Power Query M 语言中,Text.Contains 的官方函数签名如下:

Text.Contains(
    string as nullable text, 
    substring as text, 
    optional comparer as nullable function
) as nullable logical
参数位置 参数名 数据类型 业务含义与输入要求
第 1 参数 string nullable text 被查找的原始文本(如质检异常描述字段、摘要字段、物料型号等)。允许为 null。
第 2 参数 substring text 需要搜索的目标子文本(如 “裂纹”、”NG”、”气孔” 等关键字)。
第 3 参数 optional comparer nullable function 【核心精髓】可选的比较器函数。如果不填,默认按二进制字符序严格区分大小写;若传入 Comparer.OrdinalIgnoreCase,则不区分英文字母大小写!

2.2 核心比较器机制:大小写敏感的“天坑”与破局之道

孙老师在逐字稿中特别强调:默认情况下,Text.Contains 是区分大小写的!

我们通过一组直观对比感受其底层差异:

// 场景 1:不填第三参数(默认区分大小写)
Text.Contains("零件尺寸超差(ng)", "NG") 
// 结果:false ❌(因为原串是小写 ng,目标是大写 NG,直接漏判!)

// 场景 2:显式指定忽略大小写比较器
Text.Contains("零件尺寸超差(ng)", "NG", Comparer.OrdinalIgnoreCase) 
// 结果:true ✅(成功命中,杜绝漏网之鱼!)

老汪划重点:
在工业级制造业数据清洗中,现场质检员、仓管员在移动端 PDA 或车间终端录入英文代码(如 NG、OK、SUS、Ra、ppm)时,输入法经常随机处于小写或大写状态。凡是涉及英文标识的模糊匹配,第三参数必须无条件加上 Comparer.OrdinalIgnoreCase!


03 业务场景重构:某汽车零部件制造厂来料质检与索赔台账

我们以国内某头部新能源汽车 Tier 1 零部件制造企业为例。企业当月采购入厂了 10 批次核心零部件,包含变速箱齿轮、副车架、制动卡钳、前挡风玻璃等。

3.1 原始入厂质检业务底表

送检批次号 供应商名称 零部件名称与图号 送货数量(件) 批次采购总额(元) IQC检验异常与技术协议描述
IQC-2026-001 精锻精密齿轮 变速箱二轴从动齿轮(G-208) 1,200 ¥360,000.00 荧光探伤发现轮齿根部微细裂纹,判定NG严重不合格
IQC-2026-002 拓普底盘科技 铝合金一体副车架(SF-04) 450 ¥405,000.00 压铸件局部密集气孔超标,强度测试不达标,建议报废
IQC-2026-003 万向传动轴 双万向节传动总成(DS-99) 600 ¥240,000.00 法兰连接螺孔内壁轻微氧化,尺寸合格,允许让步接收
IQC-2026-004 伯特利制动 电子驻车EPB制动卡钳(BC-12) 800 ¥320,000.00 密封面存在0.2mm轻微划伤,未伤及油封槽
IQC-2026-005 华阳车用连接 高压线束接插件端子(HT-08) 5,000 ¥150,000.00 抽检发现5件内螺纹滑丝超差,尺寸超差需特采返工
IQC-2026-006 敏实汽车饰件 车窗镀铬装饰亮条(TR-55) 1,500 ¥180,000.00 包装箱轻微破损,外箱标签打码模糊,实物检验OK
IQC-2026-007 保隆传感器 胎压监测高频传感器(TP-03) 2,000 ¥220,000.00 各项电性能检测合格,外观整洁无异常
IQC-2026-008 福耀汽车玻璃 双层夹胶前挡风玻璃(WS-88) 300 ¥210,000.00 玻璃边缘微小崩边,尺寸超差且带有ng标识,复核不合格
IQC-2026-009 三花智控 新能源膨胀热力阀(EX-02) 1,000 ¥280,000.00 气密性实验微漏,内腔含砂眼气孔,严重不合格
IQC-2026-010 常春汽车内饰 副仪表板中央通道饰件(CP-66) 800 ¥160,000.00 表面皮纹轻微划痕与划伤,试装配合良好,特采使用

04 M 语言核心代码深度剖析

💡 老汪敲黑板(免改路径直接刷新秘籍):
本讲义配套的随堂 Excel 课件包内置了动态自适应路径公式。下载解压后无需手动修改文件绝对路径,点击全部刷新即可直接复现全部清洗步骤!实操指南点此篇文章:《实操指南》

针对上述业务需求,我们在 Power Query 中建立一条完整的端到端自动化流水线。

// =========================================================================
// 案例:EP048 Text.Contains 文本包含与智能质检打标(Q001 动态相对路径标准)
// 业务背景:汽车零部件制造企业(Tier 1)入厂质检(IQC)与供应商索赔扣款对账台账
// 核心函数:Text.Contains(string, substring, optional comparer) 与 Comparer.OrdinalIgnoreCase
// 作者:老汪(汽车零部件财务与商业智能实战派)
// =========================================================================

let
    // 1. 动态获取当前工作簿所在文件夹相对路径(免疫文件移动与跨电脑拷贝路径报错)
    当前工作簿 = Excel.CurrentWorkbook(),
    配置表 = 当前工作簿{[Name="配置"]}[Content],
    当前文件夹路径 = 配置表{0}[当前值],

    // 2. 动态拼接并加载【原始业务数据表.xlsx】
    目标数据文件 = 当前文件夹路径 & "原始业务数据表.xlsx",
    文件二进制 = File.Contents(目标数据文件),
    打开Excel = Excel.Workbook(文件二进制, null, true),
    质检台账原始表 = 打开Excel{[Item="供应商零部件入厂质检台账", Kind="Sheet"]}[Data],

    // 3. 提升首行作为标题并规范数据类型
    提升标题 = Table.PromoteHeaders(质检台账原始表, [PromoteAllScalars=true]),
    规范基础类型 = Table.TransformColumnTypes(提升标题, {
        {"送检批次号", type text},
        {"供应商名称", type text},
        {"零部件名称与图号", type text},
        {"送货数量(件)", Int64.Type},
        {"批次采购总额(元)", type number},
        {"IQC检验异常与技术协议描述", type text},
        {"检验员", type text}
    }),

    // 4. 核心步骤:运用 Text.Contains 与 Comparer.OrdinalIgnoreCase 智能判定质量缺陷等级
    // 避坑要点:M 函数默认区分大小写!如果不加 Comparer.OrdinalIgnoreCase,
    // 质检员填写的 "ng" 或 "NG" 就会发生漏判,导致巨额质量索赔款流失!
    添加质量缺陷等级 = Table.AddColumn(规范基础类型, "质量缺陷等级", each 
        let
            desc = [IQC检验异常与技术协议描述]
        in
            if desc = null then "检验合格"
            // 第一层:致命/严重质量缺陷(裂纹、气孔、报废、或包含不区分大小写的 ng / NG)
            else if Text.Contains(desc, "裂纹") 
                 or Text.Contains(desc, "气孔") 
                 or Text.Contains(desc, "报废") 
                 or Text.Contains(desc, "ng", Comparer.OrdinalIgnoreCase) then "严重质量缺陷"
            // 第二层:一般工艺与加工缺陷(超差、氧化、划伤、划痕、滑丝)
            else if Text.Contains(desc, "超差") 
                 or Text.Contains(desc, "氧化") 
                 or Text.Contains(desc, "划伤") 
                 or Text.Contains(desc, "划痕") 
                 or Text.Contains(desc, "滑丝") then "一般工艺缺陷"
            // 第三层:轻微包装与标识缺陷(打码、标签、包装)
            else if Text.Contains(desc, "打码") 
                 or Text.Contains(desc, "标签") 
                 or Text.Contains(desc, "包装") then "轻微标识缺陷"
            // 第四层:合格放行
            else "检验合格",
        type text
    ),

    // 5. 根据质量缺陷等级,判定处理结论与索赔扣款比例
    添加处理结论与比例 = Table.AddColumn(添加质量缺陷等级, "处置与扣款方案", each 
        if [质量缺陷等级] = "严重质量缺陷" then [结论="退货并索赔违约金20%", 扣款比例=0.20, 实付退货=true]
        else if [质量缺陷等级] = "一般工艺缺陷" then [结论="特采让步接收扣款5%", 扣款比例=0.05, 实付退货=false]
        else if [质量缺陷等级] = "轻微标识缺陷" then [结论="让步接收扣款1%", 扣款比例=0.01, 实付退货=false]
        else [结论="正常全额放行付款", 扣款比例=0.00, 实付退货=false],
        type record
    ),

    展开处置方案 = Table.ExpandRecordColumn(添加处理结论与比例, "处置与扣款方案", 
        {"结论", "扣款比例", "实付退货"}, 
        {"处理结论", "索赔扣款比例", "是否退货"}
    ),

    // 6. 精确计算质量索赔扣款金额与最终应付结算净额
    添加索赔扣款金额 = Table.AddColumn(展开处置方案, "质量索赔扣款金额(元)", each 
        [批次采购总额(元)] * [索赔扣款比例], 
        type number
    ),

    添加应付结算净额 = Table.AddColumn(添加索赔扣款金额, "应付结算净额(元)", each 
        if [是否退货] then 0.0 // 严重缺陷整批退货,货款不付,另行扣收索赔款
        else [批次采购总额(元)] - [质量索赔扣款金额(元)], 
        type number
    ),

    // 7. 整理最终列并移除中间临时列
    移除临时列 = Table.RemoveColumns(添加应付结算净额, {"是否退货", "检验员"}),

    // 8. 规范最终报表字段类型
    规范最终类型 = Table.TransformColumnTypes(移除临时列, {
        {"索赔扣款比例", Percentage.Type},
        {"质量索赔扣款金额(元)", type number},
        {"应付结算净额(元)", type number}
    })
in
    规范最终类型

05 最终清洗与索赔稽核成果

通过上述查询刷新后,瞬间呈现出条理极其清晰的业财合规稽核报表:

送检批次号 供应商名称 批次采购总额 质量缺陷等级 处理结论 索赔比例 索赔扣款金额 应付结算净额
IQC-2026-001 精锻精密齿轮 ¥360,000.00 严重质量缺陷 退货并索赔违约金20% 20.0% ¥72,000.00 ¥0.00
IQC-2026-002 拓普底盘科技 ¥405,000.00 严重质量缺陷 退货并索赔违约金20% 20.0% ¥81,000.00 ¥0.00
IQC-2026-003 万向传动轴 ¥240,000.00 一般工艺缺陷 特采让步接收扣款5% 5.0% ¥12,000.00 ¥228,000.00
IQC-2026-004 伯特利制动 ¥320,000.00 一般工艺缺陷 特采让步接收扣款5% 5.0% ¥16,000.00 ¥304,000.00
IQC-2026-005 华阳车用连接 ¥150,000.00 一般工艺缺陷 特采让步接收扣款5% 5.0% ¥7,500.00 ¥142,500.00
IQC-2026-006 敏实汽车饰件 ¥180,000.00 轻微标识缺陷 让步接收扣款1% 1.0% ¥1,800.00 ¥178,200.00
IQC-2026-007 保隆传感器 ¥220,000.00 检验合格 正常全额放行付款 0.0% ¥0.00 ¥220,000.00
IQC-2026-008 福耀汽车玻璃 ¥210,000.00 严重质量缺陷 退货并索赔违约金20% 20.0% ¥42,000.00 ¥0.00
IQC-2026-009 三花智控 ¥280,000.00 严重质量缺陷 退货并索赔违约金20% 20.0% ¥56,000.00 ¥0.00
IQC-2026-010 常春汽车内饰 ¥160,000.00 一般工艺缺陷 特采让步接收扣款5% 5.0% ¥8,000.00 ¥152,000.00

06 财务 BP 管理洞察·避坑指南

1. 为什么福耀玻璃批次(IQC-2026-008)能被精准识别?

在该批次中,质检员写的是:“玻璃边缘微小崩边,尺寸超差且带有ng标识,复核不合格”。
注意两点:
– 它同时包含了“超差”和“ng”。如果把“超差”的判断放在第一层,就会被错误归入“一般工艺缺陷”(仅扣款 5%);
– 但因为我们在 M 语言规则中优先判决致命的“严重缺陷”,且使用了 Comparer.OrdinalIgnoreCase,即使质检员随手打的是小写 "ng",模型也敏锐抓取并判定为 严重质量缺陷(退货并索赔 20%,扣款 4.2 万元)!业务优先级的层级判定与忽略大小写比较器缺一不可!

2. 遭遇 null 值的健壮性防空处理

在实际业务中,许多完全合格的批次,质检员根本不会在异常描述栏填写任何字(即单元格为空 null)。
在 M 语言中:

Text.Contains(null, "裂纹") // 返回 null,而不是 false!

如果直接写 if Text.Contains(...) then ...,当遇到 null 时,虽然不走 then,但在复合逻辑 or 运算中极易引发逻辑歧义。老汪的黄金写法:在最前端加上 if desc = null then "检验合格",防患于未然!


07 随堂练习与课件下载

请各位财务小伙伴下载随堂课件包,打开 最终完成版_带PQ查询.xlsx,观察【配置】表中当前的相对路径动态抓取,并尝试:
1. 修改原始表中某一条记录的描述为 "探伤OK,外包装标签破损",点击全部刷新,观察其是否自动打标为“轻微标识缺陷”;
2. 如果你的企业有数十个敏感词库,如何结合 List.AnyTrue 与 Text.Contains 实现动态多词库批量匹配?(我们将在后续进阶课程中深入揭秘)。

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

请登录后发表评论

    暂无评论内容