AdvancedFilter在三列中同时过滤一个变量(vba)

时间:2016-03-01 10:20:53

标签: excel vba

我想基于一个变量同时过滤这些列。我在循环中使用此过滤器来创建包含基于此过滤器的数据的pdf文件。(我删除了创建pdf的代码)

让我们看看以下示例:

Name1   Name2   Name3

Michael George  Annet
George  Michael Michael
Michael Jorge   Annet
Jorge   Annet   Michtel

有3列有名称,我想根据一个包含名称的变量过滤这三列。所以例如name =" George"那么我希望看到每一行都包含名称" George"然后输出看起来:

Name1   Name2   Name3
Michael George  Annet
George  Michael Michael

我尝试了以下内容:

Set ws1 = Worksheets("Rooster")

For i = 1 To SelectionCount           
    name = NameArray(i)      

    If ws1.FilterMode Then ws1.ShowAllData        

    ws1.Range("AB8:AD157").AdvancedFilter _
        Action:=xlFilterInPlace, _
        CriteriaRange:=name, _
            Unique:=False
Next i

NameArray(i)是一个包含用户选择的所有名称的数组。 (NameArray()是一个名为的函数)

SelectionCount计算用户选择的单元格数。

("AB8:AD157")是Excel应搜索变量的三列范围。

运行此代码时没有错误,但没有过滤任何内容。怎么了?或者AdvancedFilter不是正确的选择吗?

2 个答案:

答案 0 :(得分:2)

afaik,你不能使用数组作为Range.AdvancedFilter method¹中的参数。但是,在VBA内存和范围引用中完全模仿.AdvancedFilter进程似乎并不太过分。

Sub pseudoAdvancvedFilter()
    Dim n As Long, fnd As Range, rng As Range, addr As String, vNAMEs As Variant

    vNAMEs = Array("george", "annet")

    With Worksheets("Rooster")
        With Range("AB8:AD157")
            .EntireRow.Hidden = False
            For n = LBound(vNAMEs) To UBound(vNAMEs)
                Set fnd = .Cells.Find(What:=vNAMEs(n), LookIn:=xlValues, LookAt:=xlWhole, _
                                      MatchCase:=False, SearchFormat:=False)
                If Not fnd Is Nothing Then
                    addr = fnd.Address
                    If rng Is Nothing Then Set rng = fnd
                    Do
                        Set rng = Union(rng, fnd)
                        Set fnd = .Cells.FindNext(After:=fnd)
                    Loop Until addr = fnd.Address
                End If
                addr = vbNullString
                Set fnd = Nothing
            Next n
            If Not rng Is Nothing Then
                'Debug.Print rng.Address(0, 0)
                .EntireRow.Hidden = True
                rng.EntireRow.Hidden = False
            End If
        End With
    End With

End Sub

将所有匹配项收集到数组中列出的名称后,使用循环Range.Find methodUnion method,整个范围被隐藏,然后匹配单元格的并集用于取消匹配的行。< / p>

pseudoAdvancvedFilter_Before pseudoAdvancvedFilter_After 在运行pseudoAdvancvedFilter 之后运行pseudoAdvancvedFilter

¹有关详情和替代方法,请参阅 Can Advanced Filter criteria be in the VBA rather than a range?

答案 1 :(得分:0)

我从OP的Q那里得到了他想要隐藏任何不包含NameArray中所有名字的行。如果这实际上是他的需要,那么这就是我的解决方案

Option Explicit

Sub FilterMoreColumnsByName()

Dim iName As Long
Dim dataRng As Range, cell As Range, fnd As Range
Dim nameArray As Variant, name As Variant

nameArray = Array("george", "annet") ' <== it will be hidden any row NOT containing ALL of these names

With Worksheets("Rooster")
    For iName = LBound(nameArray) To UBound(nameArray)
        name = nameArray(iName)
        Set dataRng = .Range("AB8: AB157").SpecialCells(xlCellTypeVisible) ' so as not to loop uselessly on rows that didn't match some previous name
        Set fnd = .Cells(1, 1) ' add a "dummy" cell to prevent Union method to fail the first time -> it will be hidden -> it must be unhidden before exiting sub
        For Each cell In dataRng
            If cell.Resize(, 3).Find(What:=name, LookIn:=xlValues, LookAt:=xlWhole, MatchCase:=False, SearchFormat:=False) Is Nothing Then Set fnd = Application.Union(fnd, cell)
        Next cell
        fnd.EntireRow.Hidden = True
    Next iName
    .Rows(1).Hidden = False 'show the "dummy" cell row
End With

End Sub