[英]VBA filter by Array of strings as criteria
I have a column that I need to filter and check if a cell contains any words from a list.我有一列需要过滤并检查单元格是否包含列表中的任何单词。
If I had a list like this如果我有这样的清单
Targeted = Array("Word 1", "Word 2", "Word 3")
I would like to filter and see any cell that contains any of those words, I thougth something like this would do it:我想过滤并查看包含任何这些单词的任何单元格,我认为这样的事情会做到:
Dim Targeted As Variant
Targeted = Array("*Word 1*", "*Word 2*", "*Word 3*")
Dim Targeted_ColNum As Integer
Targeted_ColNum = Range("1:1").Find("Targeted", , xlValues, xlWhole).Column
Cells.AutoFilter Field:=Targeted_ColNum, Criteria1:=Targeted
But I only seem to be filtering by the last word, so in this example I am only seeing cells that contain the text “Word 3”, as oppose to seeing any cell with “Word 1“ or “Word 2” or “Word 3” in them但我似乎只过滤了最后一个单词,所以在这个例子中,我只看到包含文本“Word 3”的单元格,而不是看到任何包含“Word 1”或“Word 2”或“Word 3”的单元格“ 在他们中
What am I doing wrong?我究竟做错了什么?
after learning a lot i figurred it out, this does not work with arrays BUT i does work with diccionaries keys, so what i needed to do was to build a dictionary with all the entreys that i want to filter out.在学习了很多之后,我想通了,这不适用于 arrays 但我确实可以使用字典键,所以我需要做的是构建一个包含我想要过滤掉的所有条目的字典。
Dim dicCriteria As Object
Dim ColumToFilter As Variant
Dim i As Long
Set dicCriteria = CreateObject("Scripting.Dictionary")
dicCriteria.CompareMode = 1 'vbTextCompare
'this is just how i find the specific range to filter out
With Range(Cells(2, LookFor_ColNum), Cells(lastrow, LookFor_ColNum))
ColumToFilter = .Cells.Value
For i = 1 To UBound(ColumToFilter, 1)
If Not dicCriteria.Exists(ColumToFilter(i, 1)) Then
Dim k As Integer
For k = LBound(words) To UBound(words)
Select Case True
Case ColumToFilter(i, 1) Like words(k)
dicCriteria.Add Key:=ColumToFilter(i, 1), Item:=ColumToFilter(i, 1)
End Select
Next k
End If
Next i
here i am creating an empty dictionary called dicCriteria then i am getting the values of the column i want to filter into an array called ColumntoFilter在这里,我正在创建一个名为 dicCriteria 的空字典,然后我将要过滤的列的值放入一个名为 ColumntoFilter 的数组中
now i go though every value in the array and i check, first if its already on the dictionary, then if its not now i go whogh the array i called words现在我 go 虽然数组中的每个值,我检查,首先它是否已经在字典中,然后如果它不是现在我 go 我称之为单词的数组
and i check if its like any of the values in that array, if it is then i add the current Columntofilter value into the dictionary, as both the key and the item我检查它是否像该数组中的任何值,如果是,那么我将当前的 Columntofilter 值添加到字典中,作为键和项
by the end i end up with a dictonary populated with all the entreys that matched the criteria.最后,我得到了一个包含所有符合条件的条目的字典。
now i just need to filter using the dictionary keys现在我只需要使用字典键进行过滤
If CBool(dicCriteria.Count) Then
.AutoFilter Field:=LookFor_ColNum, Criteria1:=dicCriteria.keys, Operator:=xlFilterValues
End If
and thats it ahah a bit longer than expected but it works就是这样啊,比预期的要长一点,但它有效
Module1
Module1
filterMultipleCriteria
, the rest is being called by it.filterMultipleCriteria
,它正在调用 rest。 The Code编码
Option Explicit
Sub filterMultipleCriteria()
Const wsName As String = "Sheet1"
Const HeaderRow As Long = 1
Const HeaderCriteria As String = "Targeted"
Const CriteriaStrings As String = "Word 1,Word 2,Word 3"
Const CriteriaDelimiter As String = ","
Dim wb As Workbook
Set wb = ThisWorkbook
Dim ws As Worksheet
Set ws = wb.Worksheets(wsName)
If ws Is Nothing Then Exit Sub
Debug.Print ws.Name
Dim cel As Range
Set cel = findCellInRow(ws.Rows(HeaderRow), HeaderCriteria)
If cel Is Nothing Then Exit Sub
Debug.Print cel.Address
Dim rng As Range
Set rng = defineNonEmptyColumnRange(cel.Offset(1))
If rng Is Nothing Then Exit Sub
Debug.Print rng.Address
Dim Data As Variant
Data = getColumn(rng)
If IsEmpty(Data) Then Exit Sub
Debug.Print "[" & LBound(Data, 1) & "," & UBound(Data, 1) & "]"
Dim wcFilter As Variant
wcFilter = getWildcardFilters(Data, CriteriaStrings, CriteriaDelimiter)
If IsEmpty(wcFilter) Then Exit Sub
Debug.Print Join(wcFilter, vbLf)
ws.Cells.AutoFilter Field:=cel.Column, Criteria1:=wcFilter, _
Operator:=xlFilterValues
End Sub
Function findCellInRow(RowRange As Range, ByVal Criteria As Variant) As Range
Dim cel As Range
Set cel = RowRange.Find(What:=Criteria, _
After:=RowRange.Cells(RowRange.Columns.Count), LookIn:=xlFormulas)
If Not cel Is Nothing Then Set findCellInRow = cel
End Function
Function defineNonEmptyColumnRange(FirstCell As Range) As Range
Dim cel As Range
With FirstCell.Resize(FirstCell.Worksheet.Rows.Count - FirstCell.Row + 1)
Set cel = .Find(What:="*", LookIn:=xlFormulas, _
SearchDirection:=xlPrevious)
If Not cel Is Nothing Then
Set defineNonEmptyColumnRange = .Resize(cel.Row - .Row + 1)
End If
End With
End Function
Function getColumn(ColumnRange As Range) As Variant
If ColumnRange.Columns(1).Rows.Count > 1 Then
getColumn = ColumnRange.Value
Else
Dim Data As Variant: ReDim Data(1 To 1, 1 To 1)
Data(1, 1) = ColumnRange.Value
getColumn = Data
End If
End Function
Function getWildcardFilters(ColumnData As Variant, CriteriaStrings As String, _
Optional ByVal CriteriaDelimiter As String = ",") _
As Variant
Dim Crit As Variant: Crit = Split(CriteriaStrings, CriteriaDelimiter)
Dim cUpper As Long: cUpper = UBound(Crit)
Dim Key As Variant, i As Long, n As Long
With CreateObject("Scripting.Dictionary")
.CompareMode = vbTextCompare
For i = 1 To UBound(ColumnData, 1)
Key = ColumnData(i, 1)
For n = 0 To cUpper
If InStr(1, Key, Crit(n), vbTextCompare) > 0 Then
.Item(Key) = Empty
Exit For
End If
Next n
Next i
If .Count > 0 Then getWildcardFilters = .Keys
End With
End Function
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.