[英]Fuzzy Vlookup to Display All Matched Results Across a Single Row
I'm aware that vlookup only returns one result, but I'm looking for a way to search across 2 columns and return all results that match this query: 我知道vlookup仅返回一个结果,但是我正在寻找一种方法来搜索2列并返回与该查询匹配的所有结果:
SUBSTITUTE("*"&C2&"*"," ","*")
This way it returns similar matches as well. 这样,它也返回相似的匹配。 I'm able to return the first match (through a vlookup), but I need to return all matches and display them across a row.
我能够返回第一个匹配项(通过vlookup),但是我需要返回所有匹配项并在一行中显示它们。
If it would create an array, I could display the first match in the row with the first element in the array, display the second match with the second element.. and so on. 如果它将创建一个数组,则可以在该行中与该数组中的第一个元素显示第一个匹配项,在第二个元素与第二个元素显示第二个匹配项,依此类推。
VBA so far: 到目前为止的VBA:
Function Occur(text, occurence, column_to_check)
newarray = Split(text, " ")
Dim temp As New Collection
Dim intX As Integer
For i = 1 To 90000
intX = 1
For j = 0 To Len(newarray)
If Not InStr(Range(column_to_check + i).Value, newarray(j)) Then
intX = 0
End If
Next j
Exit For
If intX = 1 Then
temp.Add (Cells(i, column_to_check))
End If
Next i
End Function
Thanks! 谢谢!
Use a scripting dictionary and some array/range manipulation. 使用脚本字典和一些数组/范围操作。 I tested this on about 30,000 rows and it returned about 10,000 matches faster than I could blink.
我在大约30,000行中对此进行了测试,它返回的匹配项比我眨眼的速度快约10,000。
Sub TestWithoutRE()
Dim dict As Object
Dim srchStrings() As String
Dim s As Variant
Dim colsToSearch As Range
Dim cl As Range
Dim allMatch As Boolean
Dim matchArray As Variant
'Define the strings you're looking for
srchStrings = Split([C2], " ")
'Define the ranges to search:
Set colsToSearch = Range("F1:G33215")
'Build a dictionary of the column data
Set dict = CreateObject("Scripting.Dictionary")
For Each cl In colsToSearch.Cells
allMatch = True 'this will be set to false on the first non-matching value, no worries
'Make sure each word is in the cell's value:
For Each s In srchStrings
If InStr(1, LCase(cl), LCase(s)) = 0 Then
allMatch = allMatch + 1
Exit For 'exit this if ANY substring is not found
End If
Next
If allMatch Then
'## As long as all strings were found, add this item to the dictionary
dict.Add cl.Address, cl.Value
End If
Next
'## Here is your array of matching values:
matchArray = dict.Items
End Sub
Basically I split your search parameter ( C2
) in to an array. 基本上,我将搜索参数(
C2
)拆分为一个数组。 I then iterate each cell in these columns, testing against each element of the split array from C2
. 然后,我迭代这些列中的每个单元格,针对
C2
中的拆分数组的每个元素进行测试。 If any of the words from C2
are not found then I ignore it as a partial match, you're only looking for both words matching, in no particular order. 如果找不到
C2
中的任何单词,那么我会将其作为部分匹配项而忽略,您只是在寻找两个匹配的单词,没有特定顺序。
If both words match, add the value to a dictionary object. 如果两个单词都匹配,则将值添加到字典对象。
You can then access all matching values by referring to the dictionary.Items
which returns an array. 然后,您可以通过引用返回数组的
dictionary.Items
访问所有匹配的值。
Try this. 尝试这个。 You can either use it as an array formulae selecting a reasonable number of cells to display the result, or use it in code and dump to the worksheet in whatever fashion you like.
您既可以将其用作选择合理数量的单元格以显示结果的数组公式,也可以将其以代码形式使用,并以您喜欢的任何方式转储到工作表中。
It accepts a single string to search for (which it splits and tests each word within the single string), then a Param Array of strings, ranges or arrays to search in. It returns an array of matches so you can either use it as an array formula or use in code as any other array. 它接受一个要搜索的字符串(它将对单个字符串中的每个单词进行拆分和测试),然后接受要搜索的字符串,范围或数组的参数数组。它返回一个匹配数组,因此您可以将其用作数组公式或在代码中用作其他数组。
Usage examples: 用法示例:
=GetAllMatches("two three",A1:A5)
example with single contiguous range =GetAllMatches("two three",A1:A5)
示例 =GetAllMatches("two three",A1,A3:A20,B5:B8,D1)
'example with non-contiguous cells =GetAllMatches("two three",A1,A3:A20,B5:B8,D1)
'非连续单元格的示例 =GetAllMatches("two three",{"one two","three two","one two three"})
example with array =GetAllMatches("two three",{"one two","three two","one two three"})
带有数组的示例 =GetAllMatches("two three","one two","one","three two","one two three")
example with strings =GetAllMatches("two three","one two","one","three two","one two three")
带字符串的示例 For each match in GetAllMatches(blah,blahblah):Debug.Print match:Next match
example of use in code instead of a formula For each match in GetAllMatches(blah,blahblah):Debug.Print match:Next match
在代码中代替公式的For each match in GetAllMatches(blah,blahblah):Debug.Print match:Next match
示例 You may have to tweak to taste but I have commented what it is doing in the code. 您可能需要调整口味,但是我已在代码中注释了它的功能。
Code example: 代码示例:
Public Function GetAllMatches(searchFor As String, ParamArray searchWithin()) As Variant
'I use a ParamArray to handle the case of wanting to pass in non-contiguous ranges to search other
'e.g. Blah(A1,A2,A3,C4:C10,E5)
'nice little feature of Excel formulae :)
Dim searchRange, arr, ele, searchComponents
Dim i As Long
Dim results As Collection
Dim area As Range
Set results = New Collection
'generate words to test
searchComponents = Split(searchFor, " ")
For Each searchRange In searchWithin
If TypeOf searchRange Is Range Then 'range (we test to handle user passing in arrays)
For Each area In searchRange.Areas 'we enumerate to handle multi-area ranges
arr = area.Value
If VarType(arr) < vbArray Then 'we test to handle single cell areas
If isMatch(arr, searchComponents) Then results.Add arr 'is a match so add to results
Else 'is an array, so enumerate
For Each ele In arr
If isMatch(ele, searchComponents) Then results.Add ele 'is a match so add to results
Next ele
End If
Next area
Else
Select Case VarType(searchRange)
Case Is > vbArray 'user passed in an array not a range
For Each ele In searchRange 'enumerate, not iterate, to handle multiple dimensions etc
If isMatch(ele, searchComponents) Then results.Add ele 'is a match so add to results
Next ele
Case vbString
If isMatch(searchRange, searchComponents) Then results.Add searchRange 'is a match so add to results
Case Else 'no idea - return an error then fail fast (suppressed if called by an excel formula so ok)
GetAllMatches = CVErr(XlCVError.xlErrRef)
Err.Raise 1, "GetAllMatches", "Invalid Argument"
End Select
End If
Next searchRange
'Process Results
If results.Count = 0 Then 'no matches
GetAllMatches = CVErr(XlCVError.xlErrNA) 'return #N/A
Else
'process results into an array
ReDim arr(0 To results.Count - 1)
For i = 0 To UBound(arr)
arr(i) = results(i + 1)
Next i
GetAllMatches = arr 'Return the array of matches
End If
End Function
Private Function isMatch(ByRef searchIn, ByRef searchComponents) As Boolean
Dim ele
For Each ele In searchComponents
If Not (InStr(1, searchIn, ele, vbTextCompare) > 0) Then
Exit Function
End If
Next ele
isMatch = True
End Function
Example spreadsheet: 电子表格示例:
one
one two
one two three
one three two
four three one two
results: one two three
one three two
four three one two
结果:
one two three
one three two
four three one two
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.