簡體   English   中英

當 VBA 中的自動過濾器不返回數據時該怎么辦?

[英]What to do when autofilter in VBA returns no data?

我正在嘗試根據我的標准過濾一系列值,有時我可能沒有符合我的標准的數據。 在這種情況下,我不想從過濾后的數據中復制任何數據。 如果有過濾數據,那么我想復制它。

這是我的代碼:

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 錯誤:未找到單元格,簡單的解決方案?

但它沒有幫助。 需要一些有關如何解決此問題的指導。

嘗試錯誤處理,如下所示:

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

一種沒有錯誤處理的方法

如果未找到任何內容,則可以以不引發錯誤的方式構建自動AutoFilter器。 訣竅是在對SpecialCells的調用中包含標題行 這將確保即使未找到任何內容也至少有 1 行可見(Excel 不會隱藏標題行)。 這可以防止錯誤阻塞執行,並為您提供一組單元格來檢查是否找到了數據。

要檢查結果范圍是否有數據,您需要檢查Rows.Count > 1 Or Areas.Count > 1 這處理了直接在標題下或在標題行下方的不連續范圍內找到數據的兩種可能情況。 任何一個結果都意味着自動AutoFilter找到了有效的行。

一旦您檢查發現數據,您就可以只對數據執行所需的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的單獨變量。 這只是一個 INTERSECT-OFFSET 將它向下移動一行。
  • 對於找到結果的情況,代碼將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

我還建議了一些工作簿和工作表變量設置以“簡化”編碼生活

你可以把代碼吹成一個函數。

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

在函數中,在出錯時使用 goto xxxx。 當錯誤從函數返回任何內容並使用“if myRange is not nothing then”來忽略錯誤單元格時。

下面的回答都不適合我。 這是我最終發現有效的方法:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM