1

我们的一位客户向我发送了这个巨大的Excel 文件,我的任务之一是构建一个宏,该宏将在几张纸上清理数据。现在,我发现excellent example一位用户建议使用Excel 查找方法来加快进程……顺便说一句,它工作得很好。

但是,就我而言,我想保留匹配的行并删除其余的行。我怎么能在 VBA 中做到这一点?例如,他们在哪里说...

 Set rFound = .Columns(1).Find(What:="Cat", After:=.Cells(1, 1), LookIn:=xlValues, LookAt:=...) 

如何将 WHAT 的值设置为“NOT”?我尝试了几种不同的方法,例如:

  • 暗猫作为字符串 || 猫 = "猫" || 设置 notCat <> cat ..... 什么:=notCat
  • DIM notCat <> "Cat" ..... 什么:=notCat
  • 什么:<>“猫”
  • What:="<>" & cat ...{我不知道他们为什么这样建议,它只是将字符串从 'Cat' 更改为 '<>Cat'...我认为这是错误的}

这可能是一个非常愚蠢的问题......但我只是无法在任何地方找到正确的答案并且感到非常沮丧:(任何帮助将不胜感激!

4

2 回答 2

2
With ActiveSheet.Range(Range("A1"), Cells(Rows.Count, 1).End(xlUp))
    .AutoFilter Field:=1, Criteria1:="<>cat"
    .Offset(1, 0).SpecialCells(xlCellTypeVisible).EntireRow.Delete
    .AutoFilter
End With
于 2013-10-08T20:46:29.500 回答
2

根据我上面的评论以及@TimWilliams 的回答,我认为AutoFilter这可能是解决这个问题的方法。

我一直忘记 Excel 没有范围Difference方法(与 相反Intersect,但这并不意味着您不能将类似的逻辑用于某些 UDF 创造力。

看看Chip Pearson 的绝妙FindAll方法。通常,Excel 的.Find方法只返回一个单元格区域(或Nothing)。这对您的问题不是特别有用,因为它需要您进行笨拙的迭代,FindNext直到您用尽范围。

使用该FindAll方法,返回所有匹配单元格的范围。然后我们可以遍历列中的单元格,并测试它们是否与FindAll方法返回的范围相交。如果它们不相交,则不匹配,因此我们可以删除该行。

Sub TestFindAll()
Dim ws As Worksheet
Dim col As Range
Dim allFound As Range
Dim c As Long
Dim cl As Range

Set ws = ActiveSheet
Set col = Intersect(ws.Columns(1), ws.UsedRange)
Set allFound = FindAll(col, "Cat", xlValues, xlPart)

For c = col.Cells.Count To 1 Step -1
    Set cl = col.Cells(c)
    If Intersect(allFound, cl) Is Nothing Then
        'cl.Interior.ColorIndex = 39  '## I use this line for debugging
        cl.EntireRow.Delete         
    End If
Next

End Sub

'http://www.cpearson.com/excel/findall.aspx
Function FindAll(SearchRange As Range, _
                FindWhat As Variant, _
               Optional LookIn As XlFindLookIn = xlValues, _
                Optional LookAt As XlLookAt = xlWhole, _
                Optional SearchOrder As XlSearchOrder = xlByRows, _
                Optional MatchCase As Boolean = False, _
                Optional BeginsWith As String = vbNullString, _
                Optional EndsWith As String = vbNullString, _
                Optional BeginEndCompare As VbCompareMethod = vbTextCompare) As Range
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' FindAll
' This searches the range specified by SearchRange and returns a Range object
' that contains all the cells in which FindWhat was found. The search parameters to
' this function have the same meaning and effect as they do with the
' Range.Find method. If the value was not found, the function return Nothing. If
' BeginsWith is not an empty string, only those cells that begin with BeginWith
' are included in the result. If EndsWith is not an empty string, only those cells
' that end with EndsWith are included in the result. Note that if a cell contains
' a single word that matches either BeginsWith or EndsWith, it is included in the
' result.  If BeginsWith or EndsWith is not an empty string, the LookAt parameter
' is automatically changed to xlPart. The tests for BeginsWith and EndsWith may be
' case-sensitive by setting BeginEndCompare to vbBinaryCompare. For case-insensitive
' comparisons, set BeginEndCompare to vbTextCompare. If this parameter is omitted,
' it defaults to vbTextCompare. The comparisons for BeginsWith and EndsWith are
' in an OR relationship. That is, if both BeginsWith and EndsWith are provided,
' a match if found if the text begins with BeginsWith OR the text ends with EndsWith.
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Dim FoundCell As Range
Dim FirstFound As Range
Dim LastCell As Range
Dim ResultRange As Range
Dim XLookAt As XlLookAt
Dim Include As Boolean
Dim CompMode As VbCompareMethod
Dim Area As Range
Dim MaxRow As Long
Dim MaxCol As Long
Dim BeginB As Boolean
Dim EndB As Boolean


CompMode = BeginEndCompare
If BeginsWith <> vbNullString Or EndsWith <> vbNullString Then
    XLookAt = xlPart
Else
    XLookAt = LookAt
End If

' this loop in Areas is to find the last cell
' of all the areas. That is, the cell whose row
' and column are greater than or equal to any cell
' in any Area.

For Each Area In SearchRange.Areas
    With Area
        If .Cells(.Cells.Count).Row > MaxRow Then
            MaxRow = .Cells(.Cells.Count).Row
        End If
        If .Cells(.Cells.Count).Column > MaxCol Then
            MaxCol = .Cells(.Cells.Count).Column
        End If
    End With
Next Area
Set LastCell = SearchRange.Worksheet.Cells(MaxRow, MaxCol)

On Error GoTo 0
Set FoundCell = SearchRange.Find(what:=FindWhat, _
        after:=LastCell, _
        LookIn:=LookIn, _
        LookAt:=XLookAt, _
        SearchOrder:=SearchOrder, _
        MatchCase:=MatchCase)

If Not FoundCell Is Nothing Then
    Set FirstFound = FoundCell
    Do Until False ' Loop forever. We'll "Exit Do" when necessary.
        Include = False
        If BeginsWith = vbNullString And EndsWith = vbNullString Then
            Include = True
        Else
            If BeginsWith <> vbNullString Then
                If StrComp(Left(FoundCell.Text, Len(BeginsWith)), BeginsWith, BeginEndCompare) = 0 Then
                    Include = True
                End If
            End If
            If EndsWith <> vbNullString Then
                If StrComp(Right(FoundCell.Text, Len(EndsWith)), EndsWith, BeginEndCompare) = 0 Then
                    Include = True
                End If
            End If
        End If
        If Include = True Then
            If ResultRange Is Nothing Then
                Set ResultRange = FoundCell
            Else
                Set ResultRange = Application.Union(ResultRange, FoundCell)
            End If
        End If
        Set FoundCell = SearchRange.FindNext(after:=FoundCell)
        If (FoundCell Is Nothing) Then
            Exit Do
        End If
        If (FoundCell.Address = FirstFound.Address) Then
            Exit Do
        End If

    Loop
End If

Set FindAll = ResultRange

End Function
于 2013-10-08T21:00:28.800 回答