VBA(Excel):基于多个搜索标准查找而不循环

use*_*577 7 excel search vba criteria excel-vba

我有一个大型数据表,我想根据3套标准在VBA中搜索.可以假设每个行条目是唯一的.由于要求,无法更改工作表/数据本身的格式.(我在相关问题上看过几篇帖子,但还没有找到有效的解决方案.)

起初我在循环中使用了经典的VBA 查找方法:

Set foundItem = itemRange.Find(What:=itemName, Lookin:=xlValues, lookat:=xlWhole, SearchOrder:=xlByRows)
If Not foundItem Is Nothing Then
    firstMatchAddr = foundItem.Address
    Do
        ' *Check the other fields in this row for a match and exit if found*
        Set foundItem = itemRange.FindNext(foundItem)
    Loop While foundItem.Address <> firstMatchAddr  And Not foundItem Is Nothing
End If
Run Code Online (Sandbox Code Playgroud)

但是因为这需要在大量数据集上多次调用,所以速度并不好.

我做了一些搜索,发现我可以使用带索引匹配方法.所以我没有尝试过很多变化,例如:

result = Evaluate("=MATCH(1, (""" & criteria1Name & """=A2:A" & lastRow & ")*(""" & criteria2Name & """=B2:B" & lastRow & ")*(""" & criteria3Name & """=C2:C" & lastRow & "), 0)")
Run Code Online (Sandbox Code Playgroud)

result = Application.WorksheetFunction.Index(resultRange, Application.WorksheetFunction.Match((criteria1Name = criteria1Range)*(criteria2Name = criteria2Range)*(criteria3Name = criteria3Range))
Run Code Online (Sandbox Code Playgroud)

result = Application.WorksheetFunction.Index(resultRange, Application.WorksheetFunction.Match((criteria1Range=criteria1Name )*(criteria2Range=criteria2Name )*(criteria3Range=criteria3Name ))
Run Code Online (Sandbox Code Playgroud)

然后我尝试使用AutoFilter进行排序:

.Range(.Cells(1,1), .Cells(lastRow, lastCol)).AutoFilter Field:=1, Criteria1:="=" & criteria1Name
.Range(.Cells(1,1), .Cells(lastRow, lastCol)).AutoFilter Field:=2, Criteria1:="=" & criteria2Name
.Range(.Cells(1,1), .Cells(lastRow, lastCol)).AutoFilter Field:=3, Criteria1:="=" & criteria3Name
Run Code Online (Sandbox Code Playgroud)

但由于其中一个排序列包含日期,因此我遇到了使AutoFilter正常工作的问题.

我的问题是,如何根据多个条件搜索Excel VBA中的列,而不循环,返回行号或该行感兴趣的单元格中的值

tig*_*tar 7

您可以使用高级过滤器.将列标题放在工作表的单独部分(或完全不同的工作表).在这些列标题下,将您要查找的条件放在每列中.然后将该范围(包括标题)命名为"Criteria".然后宏变成:

Sub Macro1()

    Sheets("Sheet1").Range("A1").CurrentRegion.AdvancedFilter xlFilterInPlace, Range("Criteria")

End Sub
Run Code Online (Sandbox Code Playgroud)

作为以下评论的后续内容,让VBA在幕后创建标准范围:

Sub Macro1()

    'Code up here that defines the criteria

    Application.ScreenUpdating = False
    Application.DisplayAlerts = False

    With Sheets.Add
        'Create the advanced filter criteria range
        .Range("A1") = "HeaderA"
        .Range("B1") = "HeaderB"
        .Range("C1") = "HeaderC"
        .Range("A2") = criteria1Name
        .Range("B2") = criteria2Name
        .Range("C2") = criteria3Name

        'Alternately, to save space:
        '.Range("A1:C1").Value = Array("HeaderA", "HeaderB", "HeaderC")
        '.Range("A2:C2").Value = Array(criteria1Name, criteria2Name, criteria3Name)

        'Then perform the advanced filter
        Sheets("Sheet1").Range("A1").CurrentRegion.AdvancedFilter xlFilterInPlace, .Range("A1:C2")

        'Remove behind the scenes sheet now that the filter is completed
        .Delete
    End With

    Application.ScreenUpdating = True
    Application.DisplayAlerts = True

End Sub
Run Code Online (Sandbox Code Playgroud)


bre*_*tdj 5

您可以使用EVALUATE多个条件来返回数学值的行号。这使用与是否可以用匹配特定条件的行号填充数组而不循环的方法相同的方法

  • 搜索50000行以匹配
    • A列中的前四个字母匹配 fred
    • B中的日期大于 1/1/2001
    • apple 在第5栏中
  • 符合这些条件的所有行都将作为行号进行重新调整 x

(下图中的第1和第5行)

Sub GetEm2()
x = Filter(Application.Transpose(Application.Evaluate("=IF((LEFT(A1:A10000,4)=""fred"")*(B1:B10000>date(2001,1,1))*(C1:C10000=""apple""),ROW(A1:A10000),""x"")")), "x", False)
End Sub
Run Code Online (Sandbox Code Playgroud)

Application.Transpose 限制为65536个单元,因此需要将更长的范围“分块”成碎片。

在此处输入图片说明