📦 WPS 递归 | BOM清单:BOM 多层级用量汇总,递归 + 聚合一键算全量物料!!!

一、效果展示

输入成品需求表BOM 物料清单,1 个公式自动完成多层级 BOM 用量递归汇总,直接算出所有底层物料的总需求,无需手动展开、无需辅助列,纯函数一键出结果!


二、核心公式

excel

=LET(

聚合,LAMBDA(a, GROUPBY(TAKE(a,,1), TAKE(a,,-1), SUM, 0, 0)),

筛选, LAMBDA(a, b, LET(

x, FILTER(DROP(b,,1), TAKE(b,,1)=TAKE(a,1,1), 0),

y, HSTACK(TAKE(x,,1), TAKE(x,,-1)*TAKE(a,1,-1)),

IF(x=0, TAKE(a,1), y))),

TT,

LAMBDA(a, b,

IF(ROWS(a)=1,筛选(a,b),聚合(VSTACK(筛选(a,b), TT(DROP(a,1),b))))),

TNT,

LAMBDA(x, y,

IF(AND(IFNA(TT(x,y)=x,0)),x,TNT(TT(x,y),y) )),

TNT(F5:G7, B5:D19))


三、公式逐行拆解

1. 外层 LET 函数:自定义函数封装与递归入口

excel

=LET(

聚合,LAMBDA(...),

筛选,LAMBDA(...),

TT,LAMBDA(...),

TNT,LAMBDA(...),

TNT(F5:G7, B5:D19)

)

  • LET 函数:WPS 动态数组核心函数,用于封装自定义函数、简化公式结构,避免重复计算,提升运算效率。

  • 4 个核心自定义函数:

  • 聚合:物料用量去重求和函数

  • 筛选:单物料下一层级 BOM 展开函数

  • TT:批量递归展开函数

  • TNT:循环递归终止判断函数

  • 最后TNT(F5:G7, B5:D19)递归入口,传入需求表(F5:G7)BOM表(B5:D19),启动全流程计算。


2. 「聚合」函数:物料用量去重求和

excel

LAMBDA(a, GROUPBY(TAKE(a,,1), TAKE(a,,-1), SUM, 0, 0))

  • 函数作用:对同物料的用量进行分组聚合求和,解决多来源物料的用量合并问题,是 BOM 汇总的核心基础。

  • 关键参数解析:

  • a:待聚合的物料需求表(两列:物料编码、用量)

  • TAKE(a,,1):提取第一列(物料编码)作为分组依据

  • TAKE(a,,-1):提取最后一列(用量)作为求和对象

  • GROUPBY:WPS 分组聚合函数,按物料分组,对用量求和,0,0为缺省值与排序参数

  • 示例:若输入{"A1",4;"A2",9;"A3",5;"B1",10},直接输出聚合后的去重求和结果。


3. 「筛选」函数:单物料下一层级 BOM 展开

excel

LAMBDA(a, b,LET(

x, FILTER(DROP(b,,1), TAKE(b,,1)=TAKE(a,1,1), 0),

y, HSTACK(TAKE(x,,1), TAKE(x,,-1)*TAKE(a,1,-1)),

IF(x=0, TAKE(a,1), y)))

  • 函数作用:针对单个物料,从 BOM 表中筛选出下一层级子物料,并按父物料用量计算子物料的实际需求,是递归展开的核心单元。

  • 关键逻辑拆解:

  1. x = FILTER(DROP(b,,1), TAKE(b,,1)=TAKE(a,1,1), 0)

  • DROP(b,,1):去除 BOM 表的父物料列,保留子物料 + 单位用量

  • TAKE(b,,1)=TAKE(a,1,1):按当前父物料筛选对应子物料

  • 若未匹配到子物料(底层物料),返回0

  1. y = HSTACK(TAKE(x,,1), TAKE(x,,-1)*TAKE(a,1,-1))

  • TAKE(x,,-1)*TAKE(a,1,-1):子物料单位用量 × 父物料实际需求,计算子物料总需求

  • HSTACK:重新组合为「子物料编码、总需求」的标准需求表格式

  1. IF(x=0, TAKE(a,1), y)

  • x=0(无下一层级,底层物料),直接返回当前物料需求

  • 否则返回展开后的子物料需求表

  • 示例:父物料A需求1,BOM 中A→A1(1)、A→A2(3)、A→A3(5),展开后得到{"A1",1;"A2",3;"A3",5}


4. 「TT」函数:批量递归展开(递归回溯核心)

excel

LAMBDA(a, b,

IF(ROWS(a)=1,筛选(a,b),聚合(VSTACK(筛选(a,b), TT(DROP(a,1),b)))))

  • 函数作用:依托递归回溯思想,批量展开需求表中所有物料的下一层级 BOM,并自动聚合去重,实现多层级 BOM 的逐层展开。

  • 关键逻辑拆解:

  • 递归终止条件IF(ROWS(a)=1, 筛选(a,b), ...)

当需求表仅 1 行(单个物料),直接调用筛选函数展开下一层级,作为递归出口。

  • 递归回溯过程IF(ROWS(a)>1, 聚合(VSTACK(筛选(a,b), TT(DROP(a,1),b))))

  1. 筛选(a,b):展开第一行物料的下一层级

  1. TT(DROP(a,1),b):递归调用自身,展开剩余行物料的下一层级(回溯拆解)

  1. VSTACK:垂直堆叠所有展开后的子物料需求

  1. 聚合:对堆叠后的需求表按物料分组求和,去重合并

  • 核心原理:将「批量展开多物料」的大问题,拆解为「逐个展开单物料」的小问题,逐一解决后聚合汇总,实现批量递归展开。


5. 「TNT」函数:循环递归终止判断

excel

LAMBDA(x, y,IF(AND(IFNA(TT(x,y)=x,0)),x,TNT(TT(x,y),y)))

  • 函数作用循环递归的核心控制单元,通过「展开前后对比」判断是否完成所有层级的 BOM 展开,自动终止递归,避免无限循环。

  • 关键逻辑拆解:

  1. TT(x,y):对当前需求表x执行一次完整的批量展开

  1. TT(x,y)=x:对比展开前后的需求表是否完全一致

  1. AND(IFNA(...)):容错处理,确保对比逻辑稳定

  1. 展开前后一致:说明所有物料均为底层物料,无下一层级,递归终止,返回最终汇总结果

  1. 展开前后不一致:说明仍有可展开的父物料,递归调用TNT(TT(x,y),y),用新的需求表继续展开

  • 核心价值:实现自动多层级展开,无需手动指定展开层数,适配任意层级的 BOM 结构。


四、完整运行过程明细(递归回溯 + 循环终止)

以案例中需求表:A(1)、B(2)、C(1)BOM表:A→A1(1)、A→A2(3)、A→A3(5)...为例,完整拆解运行逻辑:

第一步:TNT 初始调用(TNT (初始需求表,BOM 表))

  • 初始需求表x{"A",1;"B",2;"C",1}

  • 执行TT(x,y),对初始需求表进行第一次批量展开:

  1. 展开A(1):得到{"A1",1;"A2",3;"A3",5}

  1. 展开B(2):得到{"B1",10;"A2",6}

  1. 展开C(1):得到{"A1",3}

  1. VSTACK堆叠所有子物料,聚合去重求和,得到第一次过程结果{"A1",4;"A2",9;"A3",5;"B1",10}

  • 对比展开前后:初始表 ≠ 第一次结果,继续递归调用TNT(第一次结果, BOM表)

第二步:第二次递归展开(TNT (第一次结果,BOM 表))

  • 当前需求表x{"A1",4;"A2",9;"A3",5;"B1",10}

  • 执行TT(x,y),批量展开所有物料:

  1. 展开A1(4):得到{"B1",12;"B2",8;"B3",24}

  1. 展开A2(9):得到{"D2",45;"D3",54}

  1. A3(5)B1(10)无下一层级,直接保留

  1. VSTACK堆叠 +聚合去重,得到第二次过程结果{"A3",5;"B1",22;"B2",8;"B3",24;"D2",45;"D3",54}

  • 对比展开前后:第一次结果 ≠ 第二次结果,继续递归调用TNT(第二次结果, BOM表)

第三步:第三次递归展开(TNT (第二次结果,BOM 表))

  • 当前需求表x{"A3",5;"B1",22;"B2",8;"B3",24;"D2",45;"D3",54}

  • 执行TT(x,y),批量展开所有物料:

  1. 展开B2(8):得到{"C1",72;"C4",40}

  1. 展开B3(24):得到{"C3",72}

  1. 展开D3(54):得到{"E2",216}

  1. A3(5)B1(22)D2(45)无下一层级,直接保留

  1. VSTACK堆叠 +聚合去重,得到第三次过程结果{"A3",5;"B1",22;"C1",72;"C3",72;"C4",40;"D2",45;"D3",54;"E2",216}

  • 对比展开前后:第二次结果 ≠ 第三次结果,继续递归调用TNT(第三次结果, BOM表)

第四步:第四次递归展开(TNT (第三次结果,BOM 表))

  • 当前需求表x{"A3",5;"B1",22;"C1",72;"C3",72;"C4",40;"D2",45;"D3",54;"E2",216}

  • 执行TT(x,y):所有物料均为底层物料,无下一层级可展开

  • 展开前后需求表完全一致,触发递归终止条件,返回最终汇总结果:

{"A3",5;"B1",22;"C1",72;"C3",72;"C4",40;"D2",45;"E2",216}

  • 全流程结束。


五、使用步骤

  1. 整理数据

  • BOM表(B5:D19):按「父物料、子物料、单位用量」格式整理,确保无重复、无错误

  • 需求表(F5:G7):按「成品 / 父物料、需求数量」格式整理

  1. 输入公式:在空白单元格(如F16)粘贴完整公式,按回车确认

  1. 获取结果:公式自动执行多层级递归展开、聚合求和,一键输出所有底层物料的总需求


六、关键知识点 & 避坑指南

适用版本

  • 必须是 WPS 365 / WPS 2021 及以上版本(需支持动态数组函数簇:LAMBDA、LET、GROUPBY、FILTER、VSTACK、TAKE、DROP 等)

  • 低版本 WPS/Excel(如 Excel 2019 及以下)不支持,公式会直接报错

核心原理复盘

  1. 递归回溯 + 循环终止:通过TT函数逐层展开 BOM,TNT函数自动判断终止,实现任意层级 BOM 的自动展开

  1. 分组聚合去重GROUPBY函数解决多来源物料的用量合并,确保汇总结果准确

  1. 动态数组运算:全流程基于动态数组实现,无需下拉、无需辅助列,一键溢出结果

  1. 容错处理IFNAIF(x=0)等逻辑确保公式在无匹配、空值场景下稳定运行

⚠️ 避坑注意事项

  1. BOM 表规范:BOM 表中父物料、子物料编码必须唯一,无重复、无循环引用(否则会导致无限递归)

  1. 溢出错误(#SPILL!):公式所在单元格下方、右侧需预留足够空白空间,避免溢出报错

  1. 递归性能:BOM 层级过多、物料数量过大时,计算量会指数级增长,建议控制在 10 层级以内

  1. 数据类型:用量列必须为数值格式,文本格式会导致乘法运算错误

  1. 循环引用排查:BOM 中禁止出现「A→B、B→A」的循环结构,否则会导致无限递归报错


七、拓展用法

  1. 多成品需求汇总:直接在需求表中添加多个成品,公式自动批量展开汇总

  1. BOM 成本核算:在 BOM 表中添加「物料单价」列,修改公式,用量 × 单价自动汇总总成本

  1. 缺件分析:结合库存表,用FILTER函数对比需求与库存,自动生成缺件清单

  1. 层级展开展示:在公式中添加层级标记,输出「层级 + 物料 + 用量」的结构化 BOM 展开表

  1. 动态参数引用:将需求表、BOM 表改为单元格引用,实现「修改数据自动更新汇总结果」


八、总结

该公式是制造业 BOM 管理的纯函数终极解决方案,依托LAMBDA递归回溯、GROUPBY聚合、动态数组等高阶函数,实现了「多层级 BOM 用量一键汇总」,彻底替代了传统的手动展开、VBA 宏、Power Query 等复杂操作。

核心价值在于:

  • 零代码:纯函数实现,无需编程基础,新手也能直接用

  • 全自动:自动多层级展开、自动聚合去重、自动终止递归

  • 高兼容:适配任意层级、任意数量的 BOM 结构

  • 易维护:修改 BOM / 需求表,公式自动更新结果

掌握这个公式,不仅能解决制造业 BOM 汇总的核心痛点,更能深入理解递归回溯、分治思想、动态数组等 WPS 高阶函数的核心逻辑,举一反三解决更多办公自动化难题!

浙江省
浏览 157
收藏
7
分享
7 +1
3
+1
全部评论 3
 
十一年
函数吧,应该是可以进行部分递归操作,替代vba是不行的 一个是数据量稍微大的时候函数不就行了 第二个是,vba是可以写任何递归问题的 ,比如bom, 迷宫问题,包括八皇后问题....
· 黑龙江省
回复
腿腿
仅针对数据源进行替代,而不是说所有都能替代,递归有深度限制,WPS5000次这是缺点。运行效率不高。
· 浙江省
回复