3

我正在使用 Microsoft Excel 在 VBA 中使用 AutoFilters。我对它如何处理数组进行过滤有疑问;我已经将我原来的上下文淡化为一个简化版本(最初是为了理解这个问题):

在范围 A1:A5 的工作表中,假设我们分别有FruitAppleBananaOrangePear。已应用自动筛选器,即Fruit列标题。

运行以下代码会返回预期结果(Apple,BananaOrangebut not Pear):

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

在我正在处理的项目中,过滤条件作为字符串变量传入,其工作原理如上。问题是并非每次都应用每个标准,因此其中一些标准应该没有效果。

例如:

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

我过去使用过类似的代码(并且可以正常工作),尽管它使用了作为 ListObject 一部分的 AutoFilter。在这一点上,我唯一能想到的是将过滤器连接成一个带有分隔符的字符串并将其拆分为一个数组变量(这样它就是精确的大小,因为集合中的一个未设置的项目会以同样的方式搞砸一个标准变量确实如此)。但这似乎不直观且麻烦。

我在这里遗漏了一些明显的东西吗?

4

1 回答 1

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
于 2013-09-06T03:35:19.627 回答