当VBA中的自动筛选器返回没有数据时该怎么办?

我正在尝试过滤一系列的值,并根据我的标准,有时我可能没有符合我的标准的数据。 在这种情况下,我不想从过滤的数据中复制任何数据。 如果有过滤的数据,那么我想复制它。

这是我的代码:

With Workbooks(KGRReport).Worksheets(spreadSheetName).Range("A1:I" & lastrowinSpreadSheet) .AutoFilter Field:=3, Criteria1:=LimitCriteria, Operator:=xlFilterValues 'Do the filtering for Limit .AutoFilter Field:=9, Criteria1:=UtilizationCriteria, Operator:=xlFilterValues 'Do the filtering for Bank/NonBank End With 'Clear the template Workbooks(mainwb).Worksheets("Template").Activate Workbooks(mainwb).Worksheets("Template").Rows(7 & ":" & Rows.Count).Delete 'Copy the filtered data Workbooks(KGRReport).Activate Set myRange = Workbooks(KGRReport).Worksheets(spreadSheetName).Range("B2:H" & lastrowinSpreadSheet).SpecialCells(xlVisible) For Each myArea In myRange.Areas For Each rw In myArea.Rows strFltrdRng = strFltrdRng & rw.Address & "," Next Next strFltrdRng = Left(strFltrdRng, Len(strFltrdRng) - 1) Set myFltrdRange = Range(strFltrdRng) myFltrdRange.Copy strFltrdRng = "" 

它在给我一个错误

 Set myRange = Workbooks(KGRReport).Worksheets(spreadSheetName).Range("B2:H" & lastrowinSpreadSheet).SpecialCells(xlVisible) 

当没有数据时,它返回一个错误:“找不到单元格”。

尝试error handling像这样的post: 1004错误:找不到单元格,简单的解决scheme?

但是这并没有帮助。 需要一些指导如何解决这个问题。

尝试像这样的error handling:

 Dim myRange As Range On Error Resume Next Set myRange = Range("your range here").SpecialCells(xlVisible) On Error GoTo 0 If myRange Is Nothing Then MsgBox "no cells" Else 'do stuff End If 

你可以把代码打成一个函数。

 Set myRange = Workbooks(KGRReport).Worksheets(spreadSheetName).Range("B2:H" & lastrowinSpreadSheet).SpecialCells(xlVisible) 

在函数中,使用错误goto xxxx。 当错误从函数中不返回任何东西,并使用“如果myRange不是什么也没有”,忽略错误单元格。

没有error handling的方法

如果找不到任何东西,就可以用不会抛出错误的方式构buildAutoFilter 。 诀窍是包含标题行在特别的SpecialCells的调用 。 这将确保即使没有find任何东西,至less有一行是可见的(Excel不会隐藏标题行)。 这样可以防止错误干扰执行,并为您提供一组单元来检查数据是否被find。

要检查结果范围是否有数据,您需要检查Rows.Count > 1 Or Areas.Count > 1 。 这将处理两种可能的情况,即在标题正下方或标题行下方的不连续范围内find数据。 结果意味着AutoFilterfind了有效的行。

一旦您检查数据被发现,您可以然后对数据进行所需的对SpecialCells调用,而不必关心错误。

样本数据[栏C(栏位2)将被过滤]:

随机数据

 Sub TestAutoFilter() 'this is your block of data with headers Dim rngDataAndHeader As Range Set rngDataAndHeader = Range("B2").CurrentRegion 'this will knock off the header row if you want data only Dim rngData As Range Set rngData = Intersect(rngDataAndHeader, rngDataAndHeader.Offset(1)) 'autofilter rngDataAndHeader.AutoFilter Field:=2, Criteria1:=64 'get the visible cells INCLUDING the header row Dim rngVisible As Range Set rngVisible = rngDataAndHeader.SpecialCells(xlCellTypeVisible) 'check if there are more than 1 rows or if there are multiple areas (discontinuous range) If rngVisible.Rows.Count > 1 Or rngVisible.Areas.Count > 1 Then Debug.Print "found data" 'data is available, this call cannot throw an error now Set rngVisible = rngData.SpecialCells(xlCellTypeVisible) 'do your normal execution here ' ' ' Else Debug.Print "only header, no data included" End If End Sub 

结果与Criteria1:= 64

Immediate window: found data

在这里输入图像说明

结果与Criteria1:= 0

Immediate window: only header, no data included

在这里输入图像说明

其他说明:

  • 代码包含一个名为rngData的单独variables,如果你想访问没有标题的数据。 这只是一个INTERSECT-OFFSET,把它往下一排。
  • 对于发现结果的情况,代码将rngVisible重置为仅数据中的可见单元格(跳过标题)。 由于这个调用现在不能失败,所以没有error handling是安全的。 这给你一个范围,匹配你第一次尝试,但没有得到一个erorr的机会。 如果您可以处理包含标题的原始范围rngVisible ,则rngVisible 。 如果这是真的,你可以完全不用rngData (除非你有其他的需要)。

因为你使用myRange作为过滤动作的实际输出,你可以像下面这样

 Dim wbKGRR As Workbook '<== better set variable for workbooks you'll work with: it saves both typing time and possible errors Dim ws As Worksheet '<== better set variable for worksheets you'll work with: it saves both typing time and possible errors '... Set wbKGRR = Workbooks(KGRReport) '<== better set variable for workbooks: it saves both typing time and possible errors Set ws = wbKGRR.Worksheets(spreadSheetName) '<== better set variable for worksheets you'll work with: it saves both typing time and possible errors With ws With .Range("A1:I" & lastrowinSpreadSheet) .AutoFilter Field:=3, Criteria1:=LimitCriteria, Operator:=xlFilterValues 'Do the filtering for Limit .AutoFilter Field:=9, Criteria1:=UtilizationCriteria, Operator:=xlFilterValues 'Do the filtering for Bank/NonBank End With If Application.WorksheetFunction.Subtotal(103, .Columns("B")) > 0 Then Set myRange = .Range("B2:H" & lastrowinSpreadSheet).SpecialCells(xlVisible) '<== myRange will be set only if filtering has left some visible cells End With 'Clear the template 'Workbooks(mainwb).Worksheets("Template").Activate '<== no need to activate Workbooks(mainwb).Worksheets("Template").Rows(7 & ":" & Rows.Count).Delete 'Copy the filtered data ' Workbooks(KGRReport).Activate '<== no need to activate If Not myRange Is Nothing Then '<== "myRange" has been set properly if previous Autofilter method has left some visbile cells For Each myArea In myRange.Areas For Each rw In myArea.Rows strFltrdRng = strFltrdRng & rw.Address & "," Next rw Next myArea strFltrdRng = Left(strFltrdRng, Len(strFltrdRng) - 1) Set myFltrdRange = Range(strFltrdRng) myFltrdRange.Copy strFltrdRng = "" End If 

在那里我还build议一些工作簿和工作表variables设置,以“缓解”编码的生活