调整Excel VBA代码,避免过滤后无数据时UsedRange.Rows报错
解决Excel VBA过滤后无数据行时的统计与复制问题
我太懂你这个糟心的情况了——过滤完只剩表头,统计可见行直接报错,加了On Error Resume Next反而把所有原始数据都复制过去了,完全不是想要的结果。咱们来一步步把这个问题搞定:
问题根源
当snowCsatDetails工作表过滤后仅存表头(第1行),用SpecialCells(xlCellTypeVisible)获取可见范围时,因为没有数据行,这个方法会抛出运行时错误。如果错误处理没做好,比如一直开着On Error Resume Next,代码会跳过错误直接执行后续的复制操作,这时候就会默认复制整个原始数据区域,而不是过滤后的可见内容。
正确的代码调整方案
核心思路是:先安全捕获可见范围,再判断是否有数据行,最后针对性复制,同时要及时关闭错误处理,避免影响后续逻辑。
下面是完整的修正代码,我加了详细注释,你可以直接替换到你的项目里:
Sub CopyFilteredCsatData() Dim wsSource As Worksheet Dim wsTarget As Worksheet Dim visibleDataRange As Range Dim dataRowCount As Long ' 初始化工作表对象(避免硬编码出错) Set wsSource = ThisWorkbook.Worksheets("snowCsatDetails") Set wsTarget = ThisWorkbook.Worksheets("snowCsatSummary") ' 清除目标表的旧数据(假设目标表表头在第1行,只清除数据行) wsTarget.Range("2:" & wsTarget.Rows.Count).ClearContents ' 执行你的双条件过滤(这里替换成你实际的过滤字段和条件) With wsSource .AutoFilterMode = False ' 先清除之前的过滤状态 ' 示例:第1列条件为"已完成",第3列条件为"满意",你改成自己的字段和条件 .Range("A1").AutoFilter Field:=1, Criteria1:="已完成" .Range("A1").AutoFilter Field:=3, Criteria1:="满意" End With ' 安全获取可见范围:临时开启错误处理捕获无数据的情况 On Error Resume Next Set visibleDataRange = wsSource.Range("A1").CurrentRegion.SpecialCells(xlCellTypeVisible) On Error GoTo 0 ' 立刻关闭错误处理!这步很关键,别让错误处理影响后面的代码 ' 判断可见范围是否存在 If Not visibleDataRange Is Nothing Then ' 计算有效数据行:总可见行数减去表头行(第1行) dataRowCount = visibleDataRange.Rows.Count - 1 If dataRowCount > 0 Then ' 只复制数据行(跳过表头),粘贴到目标表的第2行开始 visibleDataRange.Offset(1).Resize(dataRowCount).Copy _ Destination:=wsTarget.Range("A2") MsgBox "搞定!成功复制 " & dataRowCount & " 条符合条件的数据~" Else ' 只有表头,没有数据行的情况 MsgBox "过滤后没有找到符合条件的数据哦!" End If Else ' 极端情况:连表头都不可见(一般不会发生,以防万一) MsgBox "过滤后没有任何可见内容!" End If ' 最后清除源表的过滤状态,方便下次操作 wsSource.AutoFilterMode = False End Sub
关键细节说明
- 及时关闭错误处理:用
On Error Resume Next捕获SpecialCells的错误后,立刻用On Error GoTo 0关闭,这样后续代码不会被错误处理干扰,避免出现“复制全部原始数据”的问题。 - 区分表头和数据行:统计行数时减去1(表头行),这样就能准确判断是否有有效数据。
- 精准复制数据:用
Offset(1).Resize(dataRowCount)跳过表头,只复制过滤后的有效数据行,避免重复复制表头到目标表。
内容的提问来源于stack exchange,提问作者sbagnato
相关产品推荐
相关产品推荐

