📌 WPS 递归 | 库位表:排列库位表一键生成!!!
做仓储库位、物料编码的朋友肯定都遇到过这个需求!自动生成完整库位编码。空值自动跳过、全部溢出动态生成、不用下拉填充、不用辅助列,纯原生函数一步搞定!
今天把自己打磨的2 套递归 LET+LAMBDA 公式完整公式、逐行语法、每一层递归执行全过程分步演示、两套思路对比、优缺点全部讲透,递归底层逻辑!
📌 案例背景
数据源区域:B5:D9
B 列(排):G01、G02、G03、G04、G05
C 列(列):01、02、03(中间大量空白单元格)
D 列(层):01、02、03、04、05
需求:3 列数据完整笛卡尔全排列,每一组数据用 - 连接,格式 排-列-层,自动溢出生成全部库位编码,空白单元格自动忽略,无冗余空值。最终效果就是表格里 G 列完整生成的全部组合:G01-01-01、G01-01-02、G01-01-03…… 一直到全部排列遍历完成。
🧩 方法一:极简切片递归版
完整公式源码
excel
=LET(TT,LAMBDA(a,
IF(COLUMNS(a)=1,a,
TOCOL(TOCOL(TAKE(a,,1),1)&"-"&TOROW(TT(DROP(a,,1)),1)))),
TT(B5:D9))
公式逐行语法拆解
先把每个函数、每个参数的含义讲明白
外层LET:自定义递归函数名TT,最后调用函数,传入数据源B5:D9
LAMBDA(a,……):自定义递归函数TT,唯一参数a= 每次递归传入的剩余数据区域
递归终止条件 IF(COLUMNS(a)=1,a,……)
判断:当前传入的区域a只剩下 1 列的时候,直接返回这一列所有数据!递归到此停止,不再向下调用自身。
递归拼接核心主体
TAKE(a,,1):提取当前数据区域a的第 1 列(本次要拼接的前缀列)
DROP(a,,1):砍掉当前数据区域a的第 1 列,剩下的所有列,作为下一轮递归的数据源
TT(DROP(a,,1)):递归调用自身,把剩下的列丢进函数继续跑,完成后续所有列的全排列
TOROW(...,1):把递归返回的结果强制转为横向单行数组,实现笛卡尔交叉拼接
TOCOL(前缀 & "-" & 横向递归结果,1):前缀列每一个值,和递归出来的所有后缀全部用-连接,最后整体转回纵向溢出数组。
📝 超详细递归分步执行全过程
我们把本次3列数据源 = 【排B列】【列C列】【层D列】,一步步跟着函数跑完全流程:
第 1 层调用:初始调用 TT(B5:D9)
传入参数 a = 3列完整区域 [排, 列, 层]判断条件:COLUMNS(a)=1? 3 列≠1 列,不满足终止条件,进入递归拼接逻辑
提取前缀:TAKE(a,,1) = B 列【排】数组 → {"G01";"G02";"G03";"G04";"G05"}
截取剩余数据:DROP(a,,1) = 砍掉第 1 列,剩下 [列 C 列,层 D 列] 2 列区域
触发第 2 层递归:调用 TT( [列, 层] )
第 2 层调用:TT( [C列列, D列层] )
传入参数 a = 2列区域 [列, 层]判断条件:COLUMNS(a)=1? 2 列≠1 列,不满足终止条件,继续递归
提取前缀:TAKE(a,,1) = C 列【列】数组 → {"01";"02";"03"}(空白单元格自动被函数数组化忽略)
截取剩余数据:DROP(a,,1) = 砍掉第 1 列,剩下 D 列【层】单独 1 列区域
触发第 3 层递归:调用 TT( D列层 )
第 3 层调用(递归终止层):TT( D列层 )
传入参数 a = 1列【层】数组判断条件:COLUMNS(a)=1? 条件成立!触发递归终止直接返回当前列全部数据:{"01";"02";"03";"04";"05"},不再向下递归。
回溯拼接全过程(递归从最内层往外回推计算)
回到第 2 层终止层返回的层数组,经TOROW(...,1)转为横向数组 {"01","02","03","04","05"}前缀【列】纵向数组 与 横向数组 交叉拼接:{"01";"02";"03"} & "-" & {"01","02","03","04","05"}一次性生成全部 列-层 组合:{"01-01";"01-02";"01-03";"01-04";"01-05";"02-01";……;"03-05"}TOCOL统一转为纵向数组,把这一整套结果,返回给第 1 层。
回到第 1 层第 2 层返回的全部列-层组合,经TOROW(...,1)转为横向数组前缀【排】纵向数组 与 横向后缀数组 交叉拼接:{"G01";"G02";"G03";"G04";"G05"} & "-" & 全部列-层组合最终一次性溢出生成全部排 - 列 - 层完整库位编码,完美匹配表格效果!
🧩 方法二:逐列遍历递归版
完整公式源码
excel
=LET(TT,LAMBDA(a,b,c,
IF(b>COLUMNS(a),c,
LET( x,TOROW(INDEX(a,,b),1),
y,IF(b=1,x,TOCOL(c&"-"&x)),
TT(a,b+1,TOCOL(y))))),
TT(B5:D9,1,""))
公式逐行语法拆解
同样先吃透每个参数、函数定义
外层LET:自定义递归函数TT,初始调用传入 3 个初始参数:
TT(数据源区域B5:D9, 起始列号b=1, 初始拼接值c=""空文本)
LAMBDA(a,b,c) 三参数递归函数定义
a:固定不变的原始完整数据源区域(全程不切片、不删减原数据)
b:当前遍历的列序号指针(从 1 开始,每轮 + 1 步进)
c:上一轮递归拼接完成的前缀结果
递归终止条件 IF(b>COLUMNS(a),c,……)
判断:当前列号b 已经超过数据源总列数 → 所有列全部遍历拼接完毕,直接返回最终拼接结果c,递归停止。
内部嵌套LET 分步计算
x, TOROW(INDEX(a,,b),1):精准提取当前第 b 列的所有数据,转为横向单行数组
y, IF(b=1,x,TOCOL(c&"-"&x)):拼接逻辑
若是第 1 列(b=1),没有前置内容,直接当前列本身就是前缀
非第 1 列,用上一轮的前缀c,和当前列所有值用-拼接
TT(a, b+1, TOCOL(y)):递归步进,列号指针b+1,把本轮拼接结果作为新前缀c,传入下一轮递归。
📝 超详细递归分步执行全过程
数据源总列数 COLUMNS(B5:D9)=3,列序号 1 = 排、2 = 列、3 = 层,初始调用 TT(B5:D9, 1, "")
第 1 层调用:初始调用 TT(完整3列区域, b=1, c="空值")
判断条件:b>3? 1>3 不成立,进入遍历逻辑
提取当前第 1 列:INDEX(a,,1) = B 列【排】数组 {"G01";"G02";"G03";"G04";"G05"},TOROW转为横向
拼接判断:b=1 是第 1 列,直接 y = 排数组本身
触发下一轮递归:TT(完整原区域, b=2, 新前缀c=排数组)
第 2 层调用:TT(完整3列区域, b=2, c=排数组)
判断条件:b>3? 2>3 不成立,继续遍历
提取当前第 2 列:INDEX(a,,2) = C 列【列】数组 {"01";"02";"03"},TOROW转为横向
拼接判断:b≠1,用上一轮前缀c(排) 和 当前列值拼接:c&"-"&x
也就是 每一个排值,拼接全部列值,生成 排-列 全部组合
触发下一轮递归:TT(完整原区域, b=3, 新前缀c=全部排-列组合)
第 3 层调用:TT(完整3列区域, b=3, c=排-列组合)
判断条件:b>3? 3>3 不成立,继续遍历
提取当前第 3 列:INDEX(a,,3) = D 列【层】数组 {"01";"02";"03";"04";"05"},TOROW转为横向
拼接判断:b≠1,用上一轮前缀c(排-列) 和 当前列层值拼接:c&"-"&x
每一个排-列组合,拼接全部层值,生成完整排-列-层库位编码
触发下一轮递归:TT(完整原区域, b=4, 新前缀c=全部完整编码)
第 4 层调用(递归终止层):TT(完整3列区域, b=4, c=全部库位编码)
判断条件:b>COLUMNS(a) → 4>3,条件成立!递归终止直接返回最终拼接完成的全部纵向数组,完整库位全部溢出生成!
⚖️ 两套公式思路 & 优缺点全方位对比
表格
对比维度 | 方法一 切片递归版 | 方法二 列指针步进递归版 |
代码长度 | 极致精简,公式最短 | 稍长,参数更多结构更清晰 |
递归核心 | 每次砍掉首列,剩余区域整体递归 | 列号指针步进,全程保留原始数据源 |
数据处理 | TAKE/DROP数组切片,原生处理多列区域 | INDEX按列号精准取值,可控精度极高 |
扩展性 | 不限列数!4 列、5 列编码拼接直接通用,不用改公式 | 同样不限列数,新增列只需要数据拓展,公式完全不动 |
空白兼容 | 自动忽略区域内空白单元格 | 精准提取非空单元格,空白完美过滤 |
新手理解难度 | 递归嵌套深,回溯逻辑抽象 | 一步一步列号遍历,线性步进,递归逻辑更好理解 |
适用场景 | 追求公式极简、多列通用拼接、数组笛卡尔全排列 | 仓储编码、序号步进、需要中途修改每一列拼接规则 |
💡 干货总结 & 函数知识点
递归底层通用逻辑
所有LET+LAMBDA递归,永远逃不开 2 个核心:终止条件 + 自身调用
没有终止条件会无限循环报错;没有自身调用,就只是普通自定义函数,不是递归。
本次 2 个公式全部实现了原生动态数组溢出,只需要在第一个单元格输入公式,一整列全部结果自动生成,完全不用下拉填充!
TOCOL/TOROW 是本次拼接灵魂函数!
纵向数组 + 横向数组做&拼接,会自动触发笛卡尔全排列,完美实现多列所有组合遍历,这也是仓储库位编码全部组合生成的核心原理。
两个公式WPS 最新版、365Excel 全部通用
📢 结尾互动
做仓储、物料、编码整理的朋友,这两套公式直接拿去套用!数据源区域改一下,多少列拼接都通用。还有想看更多 LAMBDA 递归案例、其他编码拼接公式的,评论区留言!