自动筛选与 ShowAllData

AutoFilter vs ShowAllData

背景:

最近我知道了一个秘密的命名范围,它是通过使用 AutoFilter 创建的。通常(如果不总是)这称为“_FilterDatabase”。

我想稍微玩一下这个,但后来卡在了它所指的 Range 对象上。让我用下面的例子来解释:


测试数据:

| Header1 | Header2 |
|---------|---------|
| 50      |         |
| 10      |         |
| 30      |         |
| 40      |         |
| 20      |         |

测试代码:

Sub Test()

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

End Sub

没有结果


问题:

如果我运行上面的宏不会有结果。


问题:

问题已使用 .ShowAllData 方法而不是 .AutoFilter 解决,并且 运行 两次调用代码:

Sub Test()

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

End Sub

但是,.AutoFilter 清除过滤器并将其从我们的范围中移除。在这两种情况下,秘密命名范围将保留在名称管理器下的 Formulas 选项卡中。

有人知道为什么 ShowAllData 会影响第二个 运行 返回的命名范围吗?

我找到了我自己问题的答案(事后看来,这似乎与我的发现不符,因此我对其进行了编辑)。

根据我的问题,AutoFilter 将立即在水下创建一个秘密命名范围,通常(如果不总是)称为 "_FilterDatabase"。我注意到以下内容:

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

但是:

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

这可以解释为什么我的代码末尾的 AutoFilter 使它第二次也无法正常工作。但是,由于 ShowAllData NOT 删除实际过滤器(只是标准),它将在第二个 运行 识别范围 A1:B6。因此,我需要做的是先设置 .AutoFilter 让命名范围选择正确的范围。现在以下工作正常:

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

因此,逻辑上行不通的是:

.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

简历:

AutoFilter 立即在 AutoFilter 方法上创建一个秘密命名范围。您不能直接使用条件初始化过滤器。这样做会混淆命名范围,现在只会引用第一行。它们必须按顺序使用!

有趣的是,这现在不需要知道最后使用的行来预先创建范围对象(但是,人们可能仍然更喜欢这种方法,因为数据中的间隙会导致命名范围失效).

此过滤器在不使用 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