如何用VBA嵌套循环动态提取Sheet1数据生成Sheet2结果表
VBA动态行数提取方案
完全可以用VBA嵌套循环实现这个需求,逻辑比你想的简单——你之前写固定5行的逻辑时是硬循环5次写数据,现在只需要把固定的5次,换成「统计当前物料对应多少条有效库区记录,就循环写多少次」即可,不需要额外复杂组件。
实现逻辑拆解
- 先清空Sheet2的历史存量数据,避免旧内容和新生成的数据混杂,预留好表头行位置
- 第一遍遍历Sheet1的A列,用字典提取所有不重复的物料编码,避免同个物料被重复多次处理
- 拿到不重复物料列表后,针对每一个物料编码,第二遍遍历Sheet1全表,筛选出「A列匹配当前物料、C列库存数大于0」的有效条目
- 每匹配到1条有效条目,就在Sheet2当前写入行填入对应物料编码、库区名称,写完后写入行号自动+1,直到当前物料的所有有效条目写完,再处理下一个物料
可直接运行的代码
Sub GenMaterialLocationList() Dim wsSrc As Worksheet, wsTgt As Worksheet Dim lastSrcRow As Long, writeRow As Long Dim matDict As Object Dim i As Long, matCode As Variant ' 绑定源表和结果表 Set wsSrc = ThisWorkbook.Worksheets("Sheet1") Set wsTgt = ThisWorkbook.Worksheets("Sheet2") Set matDict = CreateObject("Scripting.Dictionary") ' 关闭屏幕更新提升运行速度,数据量大时效果明显 Application.ScreenUpdating = False ' 清空Sheet2旧数据,默认第1行是表头,从第2行开始写入新内容 wsTgt.Range("A2:C" & wsTgt.Rows.Count).ClearContents writeRow = 2 ' 第一遍遍历源表,提取所有不重复的物料编码 lastSrcRow = wsSrc.Cells(wsSrc.Rows.Count, "A").End(xlUp).Row For i = 2 To lastSrcRow matCode = Trim(wsSrc.Cells(i, "A").Value) If matCode <> "" And Not matDict.Exists(matCode) Then matDict.Add matCode, matCode End If Next ' 第二遍逐物料匹配有效库区,动态按行数写入 For Each matCode In matDict.Keys For i = 2 To lastSrcRow ' 匹配规则:物料编码一致 + 库存数量>0 If Trim(wsSrc.Cells(i, "A").Value) = matCode And VBA.Val(wsSrc.Cells(i, "C").Value) > 0 Then wsTgt.Cells(writeRow, "A").Value = matCode ' 默认A列填物料编码,列位置不对可自行修改 wsTgt.Cells(writeRow, "C").Value = wsSrc.Cells(i, "B").Value ' 默认C列填库区 writeRow = writeRow + 1 End If Next Next Application.ScreenUpdating = True MsgBox "处理完成,共生成" & writeRow - 2 & "条有效记录" End Sub
使用提示
- 如果你的表表头不在第1行,直接改循环起始值、
writeRow初始值即可,比如表头在第3行就把初始值改成4,循环从4开始 - 代码默认Sheet2里A列存物料编码、C列存库区,要是你实际表的列位置不一样,修改
Cells对应的列标参数即可 - 不需要提前在Sheet2插行预留位置,代码会自动逐行追加,不会出现内容溢出或者空行问题
- 哪怕源表里同个物料的记录零散插在其他物料行中间,字典去重+二次遍历的逻辑也能全部匹配到,不会漏数据
内容的提问来源于stack exchange,提问作者fra ferra
相关产品推荐
相关产品推荐

