EP043 Table.Skip:跳过指定行数与按条件动态截断(表头垃圾清理与分段截取)

文 / 老汪(汽车零部件财务与商业智能实战派)
专栏:【Excel BI 财务建模实战课讲义(第2阶段)】 · 期数:EP043
核心函数:Table.Skip / Table.PromoteHeaders / Table.TransformColumnTypes


📌 老汪开篇导读:车间报表里的“牛皮癣”与流式截断黑科技

各位财务同仁、成本会计、往来核算BP与产线数据分析师:

在咱们汽车零部件制造企业(Tier 1 一级供应商)的一线财务分析工作中,大家从 SAP、用友、金蝶或者车间 MES 生产制造执行系统里导出流水账单时,经常会遇到以下两类让人血压飙升的“数据恶疾”:

  1. 恶疾一:报表顶部的“牛皮癣垃圾行”:
    系统导出的报表最顶端,往往横七竖八地堆着好几行非结构化说明,比如“【内部保密资料】安徽万向底盘精工制造有限责任公司”、“导出时间:2026-11-09 14:30:22”、“筛选条件:全部车间”、“制表人:老汪”……直到第 5 行才是真正的业务表头!初学者如果直接提升标题,整张表立即报废。
  2. 恶疾二:前置历史结算数据的“断头截断诉求”:
    在主机厂(如比亚迪、吉利、理想)的发货对账与挂账清单中,排在表格前面的往往是试制样件批次(OTS/PPAP 阶段,早已单独结算结清),后面紧接着才是真正需要咱们财务本月重点盯防的量产(SOP)未结清批次。很多同学第一反应是用 Table.SelectRows 去做多重筛选,但一旦遇到复杂的“前缀连续跳过、遇到首个未结清即停止”的业务逻辑,普通的行筛选就完全无能为力了!

今天老汪要传授给各位的,就是专门用来做表格流式头部截断与动态修剪的屠龙利刃——Table.Skip!


🛠️ 第一部分:老法师拆解底层——Table.Skip 双形态全景解密

Table.Skip 是 Power Query M 引擎中专门用于从表格顶部向下丢弃行记录的函数,它支持固定行数跳过与动态条件谓词跳过两大形态:

Table.Skip(table as table, optional countOrCondition as any) as table

1. 核心参数与运作机理

  • 第一参数 table:目标数据表。
  • 第二参数 countOrCondition(可选):
  • 缺省不填:默认跳过第 1 行,等价于 Table.Skip(table, 1);
  • 传入整数数值(count as number):精准截断并丢弃表格顶部的 N 行记录。比如 Table.Skip(table, 4),直接把前 4 行垃圾信息切掉;
  • 传入条件谓词函数(condition as function):传入形如 each [字段] = 某个值 或复合逻辑表达式。

2. 🚨 老汪敲黑板:学员最高频的致命认知误区!

⚠️ 高危预警:很多从 SQL 或 Excel 筛选思维转过来的同学,往往把 Table.Skip(table, each [状态] = "已结清") 误当成“把整张表中所有状态等于已结清的行全部删掉”。
大错特错!
Table.Skip 属于数据流式处理中的 SkipWhile 机制:它从表格第 1 行开始自上而下逐行扫描,只要条件成立(返回 true),就跳过该行;但是,一旦遇到第一行让条件为 false 的记录,扫描立即彻底停止,后续剩下的所有行哪怕完全满足条件,也绝不再跳过,而是 100% 完整保留!

理解了这一底层机理,你才能真正掌握它在处理“有序批次流”、“工序前缀清洗”时的降维打击威力。


🏭 第二部分:汽车零部件制造业发货结算看板实战

1. 业务背景与原始数据表结构

我们以一家为新能源汽车主机厂配套的底盘零部件制造企业为例。成本与往来会计老汪从 MES 系统导出了《底盘件发货结算流水》:
– 顶部前 4 行为系统说明与制表信息(垃圾行);
– 第 5 行是标准表头;
– 前 3 行数据(第 6~8 行)是早期 OTS/PPAP 样件测试批次,且挂账结算状态为“已全部结清”;
– 从第 4 行数据开始,进入本年度 SOP 量产阶段,包含“待对账挂账”、“未开票挂账”、“部分开票未回款”等关键资金沉淀批次。

行号 发货批次号 所属车间/产线 核心零部件名称 主机厂客户 批次类型 挂账结算状态 处理逻辑定位
1~4 【系统冗余行】公司保密申明、导出时间、统计期间、空行说明 固定截断:Table.Skip(_, 4)
5 发货批次号 / 所属产线 / 核心零件名称 / 主机厂客户 / 批次类型 / 结算状态… 提升标题:PromoteHeaders
6 BAT-202601-OTS01 精密压铸车间-DC01 铝合金底盘前下控制臂 比亚迪仰望U8 OTS样件试制 已全部结清 动态跳过(条件为真)
7 BAT-202601-OTS02 精密压铸车间-DC01 铝合金底盘前下控制臂 比亚迪仰望U8 OTS样件试制 已全部结清 动态跳过(条件为真)
8 BAT-202602-PPAP01 冲压焊接车间-W03 高强度轻量副车架总成 理想L7底盘 PPAP小批量验证 已全部结清 动态跳过(条件为真)
9 BAT-202603-SOP01 精密压铸车间-DC01 铝合金底盘前下控制臂 比亚迪仰望U8 SOP大批量量产 待对账挂账 🎯 触发终止!保留该行及后续

💻 第三部分:随堂课件完整 M 脚本工程实现

💡 老汪敲黑板(免改路径直接刷新秘籍):
平时做财务分析最怕换台电脑一刷新就报错“找不到文件路径”。老汪在给各位学员配套的实操课件【配置】表 A1 单元格中预置了自适应公式,大家把本课案例包解压后直接点击 Excel 的【全部刷新】即可秒级重现,绝不报红字!大家可以把这套自适应架构无缝迁移到公司的日常模型中! 实操指南点此篇文章:《实操指南》

// =========================================================================
// 专栏:【Excel BI 财务建模实战课讲义(第2阶段)】· EP043
// 模块:Table.Skip 跳过指定行数与按条件动态截断(表头垃圾清理与分段截取)
// 讲师:老汪(汽车零部件财务与商业智能实战派)
// =========================================================================

let
    // ---------------------------------------------------------------------
    // 步骤 1:【Q001 自适应路径规范】动态定位当前工作簿同级目录
    // ---------------------------------------------------------------------
    当前目录 = try 
        let 
            rawPath = Text.From(Excel.CurrentWorkbook(){[Name="当前路径"]}[Content]{0}[Column1]),
            cleanPath = Text.Trim(rawPath),
            fixedPath = if Text.EndsWith(cleanPath, "\") then cleanPath else cleanPath & "\"
        in 
            fixedPath
    otherwise 
        "./",

    // ---------------------------------------------------------------------
    // 步骤 2:动态读取同级「原始业务数据表.xlsx」中 MES 导出的发货结算流水
    // ---------------------------------------------------------------------
    数据文件路径 = 当前目录 & "原始业务数据表.xlsx",
    源文件 = Excel.Workbook(File.Contents(数据文件路径), null, true),
    原始明细表 = 源文件{[Item="MES系统导出_底盘件发货结算流水", Kind="Sheet"]}[Data],

    // ---------------------------------------------------------------------
    // 步骤 3:核心技法 1 ——【Table.Skip 数值形态】跳过顶部 4 行非结构化垃圾行
    // 说明:MES 系统导出的前 4 行是标题、导出时间、统计期间等说明文字,不是真正表头
    // ---------------------------------------------------------------------
    跳过顶部垃圾行 = Table.Skip(原始明细表, 4),

    // ---------------------------------------------------------------------
    // 步骤 4:将第 5 行提升为标准业务字段表头
    // ---------------------------------------------------------------------
    提升的标题 = Table.PromoteHeaders(跳过顶部垃圾行, [PromoteAllScalars=true]),

    // ---------------------------------------------------------------------
    // 步骤 5:类型规范转换
    // ---------------------------------------------------------------------
    更改的数据类型 = Table.TransformColumnTypes(提升的标题, {
        {"发货批次号", type text},
        {"所属产线", type text},
        {"核心零件名称", type text},
        {"主机厂客户", type text},
        {"批次类型", type text},
        {"发货状态", type text},
        {"发货数量(件)", Int64.Type},
        {"单件合同价(元)", type number},
        {"批次发货金额(元)", type number},
        {"挂账结算状态", type text}
    }),

    // ---------------------------------------------------------------------
    // 步骤 6:核心技法 2 ——【Table.Skip 条件形态】按条件连续动态截断
    // 业务逻辑:跳过排在前面的样件试制阶段(OTS/PPAP)或已全部结清的历史批次,
    //          一旦遇到第一行量产(SOP)且未结清的流水,立即停止跳过,保留后续全部数据!
    // ---------------------------------------------------------------------
    动态跳过历史已结清批次 = Table.Skip(
        更改的数据类型, 
        each ([批次类型] = "OTS样件试制" or [挂账结算状态] = "已全部结清")
    )
in
    动态跳过历史已结清批次

📊 第四部分:清洗前后数据效果对照表

通过 Table.Skip 的两级管道组合清洗,原本混杂了前置文本噪音与历史陈旧批次的原始表,秒级重构为干净纯粹的量产发货管理大表:

发货批次号 所属产线 核心零部件 主机厂客户 批次类型 发货数量(件) 合同单价(元) 发货金额(元) 挂账结算状态
BAT-202603-SOP01 精密压铸车间-DC01 铝合金底盘前下控制臂 比亚迪仰望U8 SOP大批量量产 1,200 420.00 504,000.00 待对账挂账
BAT-202603-SOP02 CNC机加车间-CNC02 通风型打孔刹车制动盘 吉利极氪001 SOP大批量量产 2,000 185.00 370,000.00 未开票挂账
BAT-202604-SOP03 总成装配线-ASY01 驱动电机铝合金端盖 小鹏G6三电 SOP大批量量产 1,500 310.00 465,000.00 待对账挂账
BAT-202604-SOP04 冲压焊接车间-W03 高强度轻量副车架总成 理想L7底盘 SOP大批量量产 800 780.00 624,000.00 部分开票未回款
BAT-202605-SOP05 精密压铸车间-DC02 电池包下壳体总成 蔚来ET5T SOP大批量量产 900 1,250.00 1,125,000.00 待对账挂账

🚦 第五部分:老汪实战避坑指南(三大血泪经验)

1. 动态跳过空行的工业级防爆写法

很多 ERP 导出的表格顶部垃圾行数是不固定的(有时候导出来 3 行说明,有时候导出来 5 行)。如果你写死了 Table.Skip(源, 4),下个月换个账期可能第一行就是有效数据,直接把数据给切掉了!
💡 老汪推荐动态跳法:

// 只要第一列是空值,或者包含“公司/导出”字样,就一直跳过,直到遇到真正的列头关键字!
动态跳行 = Table.Skip(原始明细, each [Column1] = null or Text.Contains([Column1], "公司") or Text.Contains([Column1], "导出"))

2. 避免在未显式类型转换前进行数值大小比较

如果直接对从 Excel 抓进来的原生文本执行 each [发货数量] > 1000,由于此时字段默认为 any 或 text,M 引擎在比较大小时可能导致不可预测的比较异常或抛出 Expression.Error。务必先通过 Table.TransformColumnTypes 固化数值类型再进行谓词比较!

3. Table.Skip 与 Table.SelectRows 的精准分工

  • 如果需要截除连续的头部阶段(如只截掉开头的测试样件),必须用 Table.Skip;
  • 如果需要把分散在表格各处的所有“已结清”记录无论位置一律剔除,则必须使用 Table.SelectRows。二者配合,才是高手的数据清洗流水线!

🎁 老汪结语与随堂课件包下载

掌握了 Table.Skip,从今往后面对任何 ERP 导出带有各类奇葩前置标题、多余说明行或需要动态截断连续前缀的历史流水,你都可以在 M 语言中一笔搞定,再也不用手动去逐行删除!

[评论可见]隐藏内容 – 管理员可见
📦

EP043 随堂实操课件与 M 脚本原码包

本压缩包内含本节讲解使用的 Excel 随堂课件、M 脚本源码及清洗前后对照表。
已配置绝对自适应相对路径,下载解压后即可直接一键刷新演练!

📁 文件名:EP043_Table_Skip_跳过指定行数与按条件动态截断_课件包.zip


🚀 立即下载随堂课件包 (.zip)

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

请登录后发表评论

    暂无评论内容