VBA筛选返回0行如何检测?避免Delete方法报错
解决ListObject筛选后删除行报错的问题
你的代码报错主要有两个原因:
- 未判断筛选状态就执行
ShowAllData,无筛选时会触发错误 - 未先检查
DataBodyRange是否存在,直接操作列的DataBodyRange易出现空引用
以下是修正后的代码,同时优化了行删除的安全性:
Sub EXC_L(lo As ListObject, ws As Worksheet) Dim colFornecedor As ListColumn Dim visibleData As Range With lo ' 仅当存在筛选时取消筛选 If .AutoFilter.FilterMode Then .AutoFilter.ShowAllData End If Set colFornecedor = .ListColumns("Fornecedor") ' 应用空值筛选 colFornecedor.Range.AutoFilter Field:=colFornecedor.Index, Criteria1:="" ' 先确认存在数据行,避免空引用错误 If Not .DataBodyRange Is Nothing Then On Error Resume Next ' 获取所有可见数据行 Set visibleData = .DataBodyRange.SpecialCells(xlCellTypeVisible) On Error GoTo 0 ' 存在可见行时才执行删除 If Not visibleData Is Nothing Then ' 直接删除ListObject内的可见数据行,避免误删外部行 visibleData.Delete End If End If ' 清理筛选状态 If .AutoFilter.FilterMode Then .AutoFilter.ShowAllData End If End With End Sub
关键优化点:
- 增加
FilterMode判断,避免无筛选时执行ShowAllData报错 - 先检查
DataBodyRange是否存在,杜绝空引用异常 - 使用整个ListObject的
DataBodyRange获取可见行,而非单列的DataBodyRange,范围更准确 - 直接删除
DataBodyRange的可见部分,无需EntireRow,避免误删ListObject外的行
如果你需要更可靠的遍历删除方式(比如处理复杂筛选场景),可以用Collection收集待删除行后倒序删除:
Sub EXC_L(lo As ListObject, ws As Worksheet) Dim colFornecedor As ListColumn Dim lr As ListRow Dim rowsToDelete As Collection Set rowsToDelete = New Collection With lo If .AutoFilter.FilterMode Then .AutoFilter.ShowAllData Set colFornecedor = .ListColumns("Fornecedor") colFornecedor.Range.AutoFilter Field:=colFornecedor.Index, Criteria1:="" ' 收集可见行(跳过隐藏行) If Not .DataBodyRange Is Nothing Then On Error Resume Next For Each lr In .ListRows If Not lr.Range.EntireRow.Hidden Then rowsToDelete.Add lr End If Next lr On Error GoTo 0 End If ' 倒序删除,避免遍历中索引混乱 Dim i As Integer For i = rowsToDelete.Count To 1 Step -1 rowsToDelete(i).Delete Next i If .AutoFilter.FilterMode Then .AutoFilter.ShowAllData End With End Sub
内容的提问来源于stack exchange,提问作者Cooper
相关产品推荐
相关产品推荐

