Can Advanced Filter criteria be in the VBA rather than a range?
Asked Answered
H

1

4

After trying in vain to set more than 2 criteria in a normal AutoFilter fashion via VBA, I have come to learn that it must be done via advanced filter.

offending example:

Worksheets(1).Range("A1").AutoFilter Field:=ColNum, Criteria1:="A*", Operator:=xlOr, Criteria2:="B*", Operator:=xlOr, Criteria3:="C*"

I am hoping to pass the criteria through to a function (rather than a macro) from a PowerShell script. I have it all working fine and as expected for 1 criteria, but now I'd like 3.

I suppose I could instead write a macro to insert a new sheet, write in the criteria then filter on that new range but I'd rather check the preferred way first.

Huldahuldah answered 30/12, 2015 at 15:24 Comment(4)
Can't be anything but a range I'm afraid.Tetrasyllable
Create a variant array of wildcard matches and then use the array of full values with the standard AutoFilter method. I've done this with a dictionary object to use its unique index property.Cassiterite
Won't this become a custom filter and fail due to >2?Huldahuldah
@Huldahuldah - see my generic solution below.Cassiterite
C
6

To filter on multiple wildcards, create a variant array of wildcard matches and then use the array of full values with the standard AutoFilter method. You can minimize the array by putting a dictionary object to use with its unique index property.

Consider the following sample data.

      autofilter_multi_wilcard

Run this code.

Sub multiWildcards()
    Dim v As Long, vVALs As Variant, dVALs As Object
    Dim colNum As Long

    Set dVALs = CreateObject("Scripting.Dictionary")
    dVALs.comparemode = vbTextCompare
    colNum = 2 'column B

    With Worksheets(1)
        If .AutoFilterMode Then .AutoFilterMode = False
        With .Cells(1, 1).CurrentRegion
            vVALs = .Columns(colNum).Cells.Value2
            For v = LBound(vVALs, 1) To UBound(vVALs, 1)
                If Not dVALs.exists(vVALs(v, 1)) Then
                    Select Case UCase(Left(vVALs(v, 1), 1))
                        Case "A", "B", "C"
                            dVALs.Add Key:=vVALs(v, 1), Item:=vVALs(v, 1)
                        Case Else
                            'do nothing
                    End Select
                End If
            Next v

            If CBool(dVALs.Count) Then
                'populated the dictionary; now use the keys
                .AutoFilter Field:=colNum, Criteria1:=dVALs.keys, Operator:=xlFilterValues
            Else
                Debug.Print "Nothing to filter on; dictionary is empty"
            End If

            '.CurrentRegion is now filtered on A*, B*, C* in column B
            'do something with it
        End With
    End With

    dVALs.RemoveAll: Set dVALs = Nothing
End Sub

Results should be:

      autofilter_multi_wilcard_results

These results can be duplicated with many other wildcard scenarios. The Select Case statement is ideal as it supports the Like keyword for building your collection of matches. By starting with a value dump into a regular variant array, cycling through even large rows of data can be done quickly.

Cassiterite answered 30/12, 2015 at 16:8 Comment(18)
Interesting, will give it a go. Thanks very much. Next step is passing the array of values to VBA from PowerShell!Huldahuldah
Just tried to run this and get type mismatch on .AutoFilter Field:=colNum, Criteria1:=dVALs.keys, Operator:=xlFilterValuesHuldahuldah
This may have something to do with your version of Excel and its SP. Try Criteria1:=(dVALs.keys). I honestly did not make the image up.Cassiterite
I wouldn't dare suggest you did! It's likely me making some mistake. I've added the brackets but get the same error. I'm using Excel 2013 if it helpsHuldahuldah
Could you try this sample workbook? It is a small XLSB.Cassiterite
If the dictionary is empty, you will receive that error. See my error control addition above.Cassiterite
Apologies for the slow reply, thank you very much for the further help. Will give it a test this morning.Huldahuldah
I now get no error but nothing happens, I've tried updating the cases to my actual values to be filtered on, including and not including wildcard. I remember you mentioning the Like keyword but don't see it used anywhere, is this intended? I'm unable to use your test spreadsheet as dropbox is not available on this network. I run all my macros from a personal XLSB, is this sufficient? The autofilter is removed so I know the macro is being run.Huldahuldah
I can confirm the issue now is the dictionary is empty, wasn't sure where to see the debug output so I added a MsgBox and it appears.Huldahuldah
Ignore the above - got it working. Absolutely a case of user not being clear of requirements! Once I properly went through your code I realized it was selecting on 1 letter of the value (from the A,B,C example). My actual scenario needs to filter on the first 3, so I updated the "Select Case" line and it works perfectly. Thank you so much for your time and effort.Huldahuldah
Glad you got that working. It's a powerful tool in just a handful of code lines.Cassiterite
Absolutely, I've put in a "sub" select to try on lengths of 2 as well which works! I want to extend it now to take an array of values, but I'll give that a go and create a separate question in the future if I get stuck. Thanks againHuldahuldah
btw, Debug.Print reports to the VBE's Immediate window. Tap Ctrl+G to reveal it (alternately View ► Immediate Window).Cassiterite
is there a way to specifically exclude a wildcard? For example I want to include "A*" and "B*", but exclude "BB*"?Huldahuldah
After meeting the B requirement, you could easily add a line like If Not Left(vVALs(v, 1), 2) = "BB" Then dVALs.Add Key:=.... If there were many of these, it might make sense to assign vVALs(v, 1) to a string variable just above the Select Case ands use the string var in all subsequent conditions.Cassiterite
Hmm ok, I need to make it a bit more flexible. This has so many comments now and I've altered the macro so it might be better to make a new question.Huldahuldah
Drop one more note here when you do and I'll try to have a look.Cassiterite
New question here #34614917Huldahuldah

© 2022 - 2024 — McMap. All rights reserved.