AutoFilter vs ShowAllData

核能气质少年 提交于 2019-12-06 00:26:03

I have found the answer to my own question (which hindsight, does not seem to comply with my findings and therefor I edited it).

As per my question, AutoFilter will immediately create a secred named range under water, usually (if not always) called "_FilterDatabase". What I noticed is the following:

.Range("A1:B1").AutoFilter 1, ">40"  '-> Named range will refer to A1:B1

However:

.Range("A1:B1").AutoFilter '-> Named range will refer to A1:B1
.Range("A1:B1").AutoFilter 1, ">40" '-> Named range will refer to A1:B6

This would explain why AutoFilter at the end of my code makes that the second time it wouldn't work correctly either. However, since ShowAllData does NOT remove the actual filter (just the criteria) it will on the second run recognize the range A1:B6. Therefor, what I needed to do is to set .AutoFilter first to let the named range pick up the correct range. Now the following works correctly:

Sub Test()

With Sheet1
    .Range("A1:B1").AutoFilter
    .Range("A1:B1").AutoFilter 1, ">40"
    Dim rng As Range: Set rng = .Range("_FilterDatabase")
    If rng.SpecialCells(12).Count > rng.Rows(1).Cells.Count Then
        rng.Columns(2).Offset(1).Resize(rng.Rows.Count - 1, 1).Value = "Check"
    End If
    .Range("A1:B1").AutoFilter
End With

End Sub

What would therefor, logically not work is something like:

.Range("A1:B1").AutoFilter '-> Named range will refer to A1:B1
Set rng = Set rng = .Range("_FilterDatabase")
rng.AutoFilter 1, ">40" '-> rng still refers to A1:B1

Resume:

AutoFilter creates a secret named range on the AutoFilter method instantly. You cannot initialize the filter with a criteria directly. Doing so confuses the named range and will now only refer to the first row. They have to be used in sequence!

The fun part is that this would now remove the need to know the last used row to create a range object beforehand (however, one may still prefer that method, since a gap in the data will throw the named range off).

This filters correctly without using the AutoFilter.Range:

Sub test2()
Dim var As Range
Dim i As Long
With Sheets("Sheet1").Range("A1:C1")
    .Range("B2:B6").Clear
    .AutoFilter
    .AutoFilter 1, ">50"
        Set var = Sheet1.AutoFilter.Range
        Set var = Intersect(var.SpecialCells(12), var.Offset(1, 0))
        If Not (var Is Nothing) Then
            For i = 1 To var.Areas.Count
                var.Areas(i).Offset(0, 1).Resize(var.Areas(i).Rows.Count, 1).Value = "Check"
            Next i
        End If
    .AutoFilter
End With
End Sub
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!