📦 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 表中筛选出下一层级子物料,并按父物料用量计算子物料的实际需求,是递归展开的核心单元。
关键逻辑拆解:
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
y = HSTACK(TAKE(x,,1), TAKE(x,,-1)*TAKE(a,1,-1))
TAKE(x,,-1)*TAKE(a,1,-1):子物料单位用量 × 父物料实际需求,计算子物料总需求
HSTACK:重新组合为「子物料编码、总需求」的标准需求表格式
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))))
筛选(a,b):展开第一行物料的下一层级
TT(DROP(a,1),b):递归调用自身,展开剩余行物料的下一层级(回溯拆解)
VSTACK:垂直堆叠所有展开后的子物料需求
聚合:对堆叠后的需求表按物料分组求和,去重合并
核心原理:将「批量展开多物料」的大问题,拆解为「逐个展开单物料」的小问题,逐一解决后聚合汇总,实现批量递归展开。
5. 「TNT」函数:循环递归终止判断
excel
LAMBDA(x, y,IF(AND(IFNA(TT(x,y)=x,0)),x,TNT(TT(x,y),y)))
函数作用:循环递归的核心控制单元,通过「展开前后对比」判断是否完成所有层级的 BOM 展开,自动终止递归,避免无限循环。
关键逻辑拆解:
TT(x,y):对当前需求表x执行一次完整的批量展开
TT(x,y)=x:对比展开前后的需求表是否完全一致
AND(IFNA(...)):容错处理,确保对比逻辑稳定
若展开前后一致:说明所有物料均为底层物料,无下一层级,递归终止,返回最终汇总结果
若展开前后不一致:说明仍有可展开的父物料,递归调用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),对初始需求表进行第一次批量展开:
展开A(1):得到{"A1",1;"A2",3;"A3",5}
展开B(2):得到{"B1",10;"A2",6}
展开C(1):得到{"A1",3}
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),批量展开所有物料:
展开A1(4):得到{"B1",12;"B2",8;"B3",24}
展开A2(9):得到{"D2",45;"D3",54}
A3(5)、B1(10)无下一层级,直接保留
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),批量展开所有物料:
展开B2(8):得到{"C1",72;"C4",40}
展开B3(24):得到{"C3",72}
展开D3(54):得到{"E2",216}
A3(5)、B1(22)、D2(45)无下一层级,直接保留
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}
全流程结束。
五、使用步骤
整理数据:
BOM表(B5:D19):按「父物料、子物料、单位用量」格式整理,确保无重复、无错误
需求表(F5:G7):按「成品 / 父物料、需求数量」格式整理
输入公式:在空白单元格(如F16)粘贴完整公式,按回车确认
获取结果:公式自动执行多层级递归展开、聚合求和,一键输出所有底层物料的总需求
六、关键知识点 & 避坑指南
✅ 适用版本
必须是 WPS 365 / WPS 2021 及以上版本(需支持动态数组函数簇:LAMBDA、LET、GROUPBY、FILTER、VSTACK、TAKE、DROP 等)
低版本 WPS/Excel(如 Excel 2019 及以下)不支持,公式会直接报错
✅ 核心原理复盘
递归回溯 + 循环终止:通过TT函数逐层展开 BOM,TNT函数自动判断终止,实现任意层级 BOM 的自动展开
分组聚合去重:GROUPBY函数解决多来源物料的用量合并,确保汇总结果准确
动态数组运算:全流程基于动态数组实现,无需下拉、无需辅助列,一键溢出结果
容错处理:IFNA、IF(x=0)等逻辑确保公式在无匹配、空值场景下稳定运行
⚠️ 避坑注意事项
BOM 表规范:BOM 表中父物料、子物料编码必须唯一,无重复、无循环引用(否则会导致无限递归)
溢出错误(#SPILL!):公式所在单元格下方、右侧需预留足够空白空间,避免溢出报错
递归性能:BOM 层级过多、物料数量过大时,计算量会指数级增长,建议控制在 10 层级以内
数据类型:用量列必须为数值格式,文本格式会导致乘法运算错误
循环引用排查:BOM 中禁止出现「A→B、B→A」的循环结构,否则会导致无限递归报错
七、拓展用法
多成品需求汇总:直接在需求表中添加多个成品,公式自动批量展开汇总
BOM 成本核算:在 BOM 表中添加「物料单价」列,修改公式,用量 × 单价自动汇总总成本
缺件分析:结合库存表,用FILTER函数对比需求与库存,自动生成缺件清单
层级展开展示:在公式中添加层级标记,输出「层级 + 物料 + 用量」的结构化 BOM 展开表
动态参数引用:将需求表、BOM 表改为单元格引用,实现「修改数据自动更新汇总结果」
八、总结
该公式是制造业 BOM 管理的纯函数终极解决方案,依托LAMBDA递归回溯、GROUPBY聚合、动态数组等高阶函数,实现了「多层级 BOM 用量一键汇总」,彻底替代了传统的手动展开、VBA 宏、Power Query 等复杂操作。
核心价值在于:
零代码:纯函数实现,无需编程基础,新手也能直接用
全自动:自动多层级展开、自动聚合去重、自动终止递归
高兼容:适配任意层级、任意数量的 BOM 结构
易维护:修改 BOM / 需求表,公式自动更新结果
掌握这个公式,不仅能解决制造业 BOM 汇总的核心痛点,更能深入理解递归回溯、分治思想、动态数组等 WPS 高阶函数的核心逻辑,举一反三解决更多办公自动化难题!