Excel VBA自动筛选数组

时间:2013-09-06 03:11:37

标签: excel vba autofilter

我正在使用Microsoft Excel在VBA中使用AutoFilters。我遇到了如何处理数组进行过滤的问题;我已经将我的原始背景淡化为简化版本(原本希望能够理解这个问题):

在范围A1:A5的工作表中,假设我们分别有FruitAppleBananaOrangePear。已应用AutoFilter,Fruit是列标题。

运行以下代码会返回预期结果(AppleBananaOrange,但不会返回Pear):

Range("A1").Select
ActiveSheet.Range("A1:A5").AutoFilter Field:=1, _
    Criteria1:=Array("=*an*", "=*app*"), Operator:=xlFilterValues

在我正在处理的项目中,过滤条件作为String变量传递,如上所述。问题在于并非每次都适用所有标准,因此其中一些标准应该没有效果。

例如:

Dim A As String, B As String, C As String
A = "=*an*"
B = Empty
C = "=*ap*"

Range("A1").Select
ActiveSheet.Range("A1:A5").AutoFilter Field:=1, _
    Criteria1:=Array(A, B, C), Operator:=xlFilterValues

混合使用B时,过滤不返回任何记录(无论是否为空,设置为Empty,还是使用=*等通配符。但是,在实际条件数组中用B(硬编码)替换Empty会返回预期结果。

我过去曾使用类似的代码(并且有效),尽管AutoFilter是ListObject的一部分。在这一点上,我唯一能想到的是将过滤器连接成带有分隔符的String并将其拆分为一个Array变量(这样它就是精确的大小,因为集合中未设置的项目会以同样的方式混淆标准变量确实)。但这似乎不直观且麻烦。

我错过了一些明显的东西吗?

1 个答案:

答案 0 :(得分:4)

我想不出一种不涉及测试空参数的方法,这里有一种可能对你有用的方法,也可以防止重复的表达。

Sub Main()
    Dim a As String
    Dim B As String
    Dim C As String
    Dim filterCriteria as Variant
    a = "=*an*"
    B = Empty
    C = "=*ap*"
    filterCriteria = CombineArrays(Array(a, B, C))

    If Not uBound(filterCriteria) = -1 Then 

        Range("A1").Select
        ActiveSheet.Range("A1:A5").AutoFilter Field:=1, _
            Criteria1:=filterCriteria, Operator:=xlFilterValues

    End If
End Sub

Function CombineArrays(arr As Variant) As Variant
    Dim a As Variant
    Dim filterDic As Object 'Scripting.Dictionary
    Set filterDic = CreateObject("Scripting.Dictionary")

    For Each a In arr
        If Not filterDic.Exists(a) And Not a = vbNullString Then
            filterDic.Add a, a
        End If
    Next

    CombineArrays = filterDic.Keys

    Set filterDic = Nothing
End Function