基于在 2 列中找到 2 个不同单词的选择

Selection based on finding 2 different words in 2 columns

我想使用 Excel VBA 执行以下操作:

1) 在一列中查找某个word_1;

2) 如果在步骤 (1) 中找到了 word_1,请向右转一栏并寻找另一个名为 word_2 的词。如果也找到 word_2,则删除整行。

如果另一方面 word_2 未找到,则不必删除该行。

一般的想法是在一列中搜索多个词,如果找到它们,还要仔细检查(为了安全起见)某些附属词是否在第 2 列中。只有这样才能删除整行。

我做了下面的小例子来测试:

Col1 Col2

xxx xxx
xxx xxx
xxx xxx
findme  acg
xxx xxx
findme  xxx

在此示例中,我在第 1 列中搜索词 "findme" 并在第 2 列中搜索关联词 "acg"。如您所见,必须删除第 4 行,因为两者单词出现在一行中,而不是例如第 6 行,情况并非如此。

我的最终代码:

    Sub xxx()

    Dim aCell As Range, bCell As Range, aSave As String

    Dim fndOne As String, fndTwo As String
    fndOne = "findme"
    fndTwo = "acg"

    Dim ws As Worksheet: Set ws = ActiveWorkbook.ActiveSheet

    Application.DisplayAlerts = False
    Application.ScreenUpdating = False

    With ws

        Set aCell = .Columns(1).Find(What:=fndOne, LookIn:=xlValues, _
            lookat:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
            MatchCase:=False, SearchFormat:=False)

        If Not aCell Is Nothing Then

            aSave = aCell.Address

            Do

                If LCase(.Cells(aCell.row, 2).Value) Like Chr(42) & fndTwo & Chr(42) Then

                    If bCell Is Nothing Then
                        Set bCell = .Range("A" & aCell.row)
                    Else
                        Set bCell = Union(bCell, .Range("A" & aCell.row))
                    End If

                End If

                Set aCell = .Columns(1).FindNext(After:=aCell)

            Loop Until aCell.Address = aSave

        End If

        Set aCell = Nothing
        If Not bCell Is Nothing Then bCell.EntireRow.Delete


    End With

    Application.DisplayAlerts = True
    Application.ScreenUpdating = True

End Sub

此代码使用您的条件对所用范围的前两列应用过滤器。然后删除可见行:

Sub DeleteSelected()
Dim RangeToFilter As Excel.Range

Set RangeToFilter = ActiveSheet.UsedRange
With RangeToFilter
    .AutoFilter Field:=1, Criteria1:="find me"
    .AutoFilter Field:=2, Criteria1:="access granted"
    .SpecialCells(xlCellTypeVisible).EntireRow.Delete Shift:=xlUp
End With
End Sub

如果您使用了 Range.Find method and Range.FindNext method,随时删除并在每次删除后检查匹配的记录,您应该能够快速遍历各种可能性。

'delete rows as they are found
Sub delTwofers()
    Dim rw As Long, n As Long, cnt As Long, rng As Range
    Dim v As Long, sALLTERMs As String, vPAIRs As Variant, vTERMs As Variant

    On Error GoTo bm_SafeExit
    Application.ScreenUpdating = False
    Application.EnableEvents = False
    Application.Calculation = xlCalculationManual

    Debug.Print Timer

    sALLTERMs = "aa;bb|cc;dd|ee;ff"

    With Worksheets("Sheet1")   'set this worksheet reference properly!
        vPAIRs = Split(LCase(sALLTERMs), Chr(124))
        For v = LBound(vPAIRs) To UBound(vPAIRs)
            vTERMs = Split(vPAIRs(v), Chr(59))
            cnt = Application.CountIfs(.Columns(1), Chr(42) & vTERMs(0) & Chr(42), .Columns(2), Chr(42) & vTERMs(1) & Chr(42))
            rw = 1
            For n = 1 To cnt
                rw = .Columns(1).Find(what:=vTERMs(0), lookat:=xlPart, _
                                      after:=.Columns(1).Cells(rw + (rw <> 1)), MatchCase:=False).Row
                Do While True
                    If LCase(.Cells(rw, 2).Value2) Like Chr(42) & vTERMs(1) & Chr(42) Then
                        .Rows(rw).Delete
                        Exit Do
                    Else
                        rw = .Columns(1).FindNext(after:=.Cells(rw, 1)).Row
                    End If
                Loop
            Next n
        Next v
    End With

    Debug.Print Timer

bm_SafeExit:
    Application.Calculation = xlCalculationAutomatic
    Application.ScreenUpdating = True
    Application.EnableEvents = True
End Sub

'collect rows with Union, delete them all at once
Sub delTwofers2()
    Dim rw As Long, n As Long, cnt As Long, rng As Range
    Dim v As Long, sALLTERMs As String, vPAIRs As Variant, vTERMs As Variant

    On Error GoTo bm_SafeExit
    Application.ScreenUpdating = False
    Application.EnableEvents = False
    Application.Calculation = xlCalculationManual

    Debug.Print Timer

    sALLTERMs = "aa;bb|cc;dd|ee;ff"

    With Worksheets("Sheet1")   'set this worksheet reference properly!
        vPAIRs = Split(LCase(sALLTERMs), Chr(124))
        For v = LBound(vPAIRs) To UBound(vPAIRs)
            vTERMs = Split(vPAIRs(v), Chr(59))
            cnt = Application.CountIfs(.Columns(1), Chr(42) & vTERMs(0) & Chr(42), .Columns(2), Chr(42) & vTERMs(1) & Chr(42))
            rw = 1
            For n = 1 To cnt
                rw = .Columns(1).Find(what:=vTERMs(0), lookat:=xlPart, _
                                      after:=.Columns(1).Cells(rw), MatchCase:=False).Row
                Do While True
                    If LCase(.Cells(rw, 2).Value2) Like Chr(42) & vTERMs(1) & Chr(42) Then
                        If rng Is Nothing Then
                            Set rng = .Cells(rw, 1)
                        Else
                            Set rng = Union(rng, .Cells(rw, 1))
                        End If
                        Exit Do
                    Else
                        rw = .Columns(1).FindNext(after:=.Cells(rw, 1)).Row
                    End If
                Loop
            Next n
        Next v
    End With

    Debug.Print Timer  'check timer before deleting discontiguous rows
    If Not rng Is Nothing Then _
        rng.EntireRow.Delete

    Debug.Print Timer

bm_SafeExit:
    Application.Calculation = xlCalculationAutomatic
    Application.ScreenUpdating = True
    Application.EnableEvents = True
End Sub

首先检查确定有什么东西要删除,这样可以避免一些错误控制;您只需要找到您知道存在的双重匹配条件的条目。

附录: 删除一组不连续的行非常耗时。上面的第二个例程 (delTwofers2) 比发现行时删除行的例程慢 5%。 25,000 个值,755 个随机删除 - 第一个 3.60 秒;后者3.75秒。