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

时间:2016-04-12 02:23:22

标签: excel vba autofilter

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

这是我的代码:

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)

当根本没有数据时,它返回一个错误:“找不到细胞”。

尝试过这样的错误处理:1004 Error: No cells were found, easy solution?

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

5 个答案:

答案 0 :(得分:5)

尝试错误处理:

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

答案 1 :(得分:0)

您可以将代码放入函数中。

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

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

答案 2 :(得分:0)

没有错误处理的方法

如果没有找到任何内容,可以以不抛出错误的方式构建AutoFilter。诀窍是SpecialCells 的调用中包含标题行。这将确保即使找不到任何内容也至少可以看到1行(Excel不会隐藏标题行)。这可以防止错误阻塞执行,并为您提供一组单元格来检查是否找到了数据。

要检查结果范围是否包含数据,您需要检查Rows.Count > 1 Or Areas.Count > 1。这将处理两种可能的情况,即您的数据直接位于标题下方或标题行下方的不连续范围内。结果表示AutoFilter找到了有效行。

检查完数据后,您可以只对数据SpecialCells进行所需的调用,而无需担心错误。

样本数据[C列(字段2)将被过滤]:

random data

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

enter image description here

结果与Criteria1:= 0

Immediate window: only header, no data included

enter image description here

其他说明:

  • 如果您想要访问没有标头的数据,代码包含一个名为rngData的单独变量。这只是一个INTERSECT-OFFSET,可以将它向下撞一行。
  • 对于找到结果的情况,代码将rngVisible重置为仅数据中的可见单元格(跳过标题)。由于此调用现在不会失败,因此在没有错误处理的情况下是安全的。这为您提供的范围与您第一次尝试但与没有获得erorr的机会相匹配。如果您可以处理包含标题的原始范围rngVisible,则不需要这样做。如果这是真的,你可以完全取消rngData(除非你有其他需要)。

答案 3 :(得分:0)

因为您使用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

我还建议使用一些工作簿和工作表变量设置来“简化”编码生活

答案 4 :(得分:0)

以下任何回答均不适用于我。这是我最后发现有效的结果:

Sub fileterissues()

Dim VisibleRows as Long

‘Some code here

With Sheets(ws1).Range(“myrange”)
.Autofilter Field:=myfieldcolumn, criteria:=myfiltercriteria
VisibleRows = Application.Worksheetfunction.Subtotal(103, sheets(1).mycolumnfieldrange)
If VisibleRows = 0 then Resume Next
End with

‘More code

End sub