在日常办公的数据整理工作中,“层级式数据单列排版” 是一种非常常见的非规范数据格式:人事名册里,部门名只写在分组第一行,下方依次排列员工姓名;销售台账中,品类标题独占一行,下面罗列对应单品;门店统计表里,区域标注一次,后续门店默认归属该区域。这类格式人工阅读时层级清晰,却给后期的数据处理带来了阻碍。想要解决这类问题往往需要有一个共同前提:数据本身具备可识别的字符规律。就像这份车间人员清单,所有分组标题都统一包含“间”字,这个特征成了公式定位标题行的关键锚点;如果数据没有统一的标识规律,同类问题的处理成本会大幅上升,这也是Excel数据处理的核心逻辑:规律越强,自动化处理的效率越高。我们今天的案例数据集中在表格的B2:B10单列单元格区域:3个车间名称与对应员工姓名上下交错排布,每个车间下辖的人员数量各不相同。正是因为“1车间”、“2车间”、“3车间” 都带有“间”字这一稳定的字符特征,我们才能通过函数精准识别出每一个分组标题的位置,进而自动将车间名称填充到对应员工行,最终把这列“标题+明细”的混合结构,转换为“车间列+姓名列”的标准一维表,让每一行都包含完整的车间与人员对应关系。古时候的解决方式通常是插入辅助列、手工下拉填充车间名称,再筛选删除标题行,但后期维护数据的体验感很差;而如今借助动态数组函数体系,依托数据本身的规律特征,其实我们只需要用一条公式就能实现自动处理。=REGEXP(B2,"间",1)
Regexp(待检测文本, 匹配规则, 匹配模式)第3参数为1时,表示判断模式。文本能匹配到规则返回True,否则返回False。=IF(REGEXP(B2,"间",1),B2,D1)
这是Excel里“标题向下填充”的经典辅助列逻辑,是整条公式的原型。如果当前行B2是车间名称(正则匹配为True),就取B2本身的车间名;如果不是车间(匹配为False),就取上一行D1的值(也就是上一行已经填充好的车间名称)。逐行向下填充后,所有行都会自动带上对应所属的车间名称:对上面逻辑进行数组化、迭代化改写,是Lambda函数的核心计算式:IF(REGEXP(y,"间",1),y,x)
y:代表当前正在遍历的单元格值(对应B列每一行的内容)x:代表上一轮计算的累积结果(也就是上一行对应的车间名称)如果当前遍历的y包含“间”(是车间标题),就把累积值更新为y;否则保持x不变(沿用之前的车间名称)。Lambda是Excel的匿名自定义函数,用来把上面的这段逻辑封装成可被Scan等数组函数调用的计算规则:Lambda(x,y,IF(REGEXP(y,"间",1),y,x))
第1参数x:累积器,存储上一步的计算结果,供迭代使用=SCAN(0,B2:B10,LAMBDA(x,y,IF(REGEXP(y,"间",1),y,x)))
遍历目标数组,逐次应用Lambda逻辑,返回每一步的累积结果,最终生成一个与遍历区域等高的新数组。
第1参数0:累积器x的初始值,第一行计算前的初始值最后得到一个9行1列的数组,效果和手工向下填充车间名称完全一致。

=HSTACK(SCAN(0,B2:B10,LAMBDA(x,y,IF(REGEXP(y,"间",1),y,x))),B2:B10)
得到一个9行2列的新数组,数组第1列是对应车间,数组第2列是原始内容(车间标题+姓名混合)。继续对B2:B10整个区域批量执行正则判断:
=REGEXP(B2:B10,"间",1)
这就标记出了哪些行是车间标题、哪些行是员工姓名,为后续筛选做准备。利用Excel的逻辑值属性:True=1,False=0原车间标题行True:1-1=0。逻辑值等价于False原姓名行False:0-1=-1。非0值等价于True姓名行对应True,后续保留;车间行对应False,后续剔除。=FILTER(HSTACK(SCAN(0,B2:B10,LAMBDA(x,y,IF(REGEXP(y,"间",1),y,x))),B2:B10),REGEXP(B2:B10,"间",1)-1)
第1参数:Hstack生成的一列所属车间、一列“车间标题+姓名混合”数组剔除所有车间标题行(False=0),只保留员工姓名对应的6行数据(True=1)。因为公式中B2:B10一共引用了3次,如果数据源范围发生变化后,你仍需要手动调整3个位置的这个范围。
如果你觉得这个维护不方便的话,可以设置变量a,令a=B2:B10,加上Let函数,替换掉原公式后的3处B2:B10。
用Let函数:
=LET(a,B2:B10,FILTER(HSTACK(SCAN(0,a,LAMBDA(x,y,IF(REGEXP(y,"间",1),y,x))),a),REGEXP(a,"间",1)-1))
这样,如果后期数据源范围变动,可只需调整一次第2参数中的B2:B10即可。
还有另一种更一劳永逸的写法:
=LET(a,B2:.B999,FILTER(HSTACK(SCAN(0,a,LAMBDA(x,y,IF(REGEXP(y,"间",1),y,x))),a),REGEXP(a,"间",1)-1))
将B2:B10修改为B2:.B999,在冒号后面加上符号点“.”实现数据范围的裁剪功能,即数据最大行数可覆盖至999行,但末尾如果是空行的话,可自动剪裁掉,避免了数据的冗余和计算效率的下降。这个小点的用法等价于TrimRange剪裁函数。
(如果您觉得本文对自己有所启发,希望点一个“推荐”鼓励小编;如果您还有其它方面的问题,可后台消息框回复“提问”进行咨询)
学习Excel/你可以不常用/但不能不会用/如果你没有天赋/那就一直重复/当你快到本能反应的时候/你的重复就是别人眼中的天赋/冲破捆绑/展翅翱翔