我们的一位客户向我发送了这个巨大的 excel文件,其中一项任务是构建一个可以清理几张数据的宏。现在,我找到了这个excellent example
,其中一个用户建议使用Excel Find Method来加速这个过程...... BTW工作正常。
但是,在我的情况下,我想保留匹配的行并删除其余的行。我怎么能在VBA中做到这一点?例如,他们说的地方......
Set rFound = .Columns(1).Find(What:="Cat", After:=.Cells(1, 1), LookIn:=xlValues, LookAt:=...)
如何将WHAT的值设置为“NOT”?我尝试了几个不同的东西,如:
这可能是一个非常愚蠢的问题...但我无法在任何地方找到正确的答案并感到非常沮丧:(任何帮助将不胜感激!!
答案 0 :(得分: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
答案 1 :(得分:2)
根据我上面的评论,以及@TimWilliams的回答,我认为AutoFilter
可能就是这样。
我一直忘记Excel没有范围Difference
方法(与Intersect
相反),但这并不意味着你不能使用类似的逻辑和一些UDF创造力。
看看Chip Pearson's excellent FindAll
method。通常,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