简体   繁体   English

对于每个循环不会删除具有特定值的所有行

[英]For Each loop won't delete all rows with specific values

I want to delete all rows that do not contain the value "Total" in Range("B11:B25"). 我想删除Range(“ B11:B25”)中不包含值“ Total”的所有行。

Below is my code. 下面是我的代码。

Dim cell As Range

For Each cell In Range("B11:B25")
    If cell.Value <> "Total" Then
    cell.EntireRow.Delete
End If

Next

End Sub

Above code will only delete some rows with cells that do not have the value "Total". 上面的代码将只删除单元格中没有“ Total”值的某些行。 If I have to delete all rows that do not contain "Total", I will have to run this multiple times which is not practical. 如果必须删除所有不包含“总计”的行,则必须多次运行,这是不实际的。

Modifying a collection you're iterating is always a bad idea. 修改要迭代的集合始终是个坏主意。 Sure you could start at the bottom and call it a day, but then your next question is going to be "my code is painfully slow, how do I make it faster?" 当然,您可以从最底层开始命名,但是接下来的问题将是“我的代码非常缓慢,如何使它更快?”

Have a CombineRanges function responsible for Union -ing ranges: 有一个CombineRanges函数负责Union范围:

Private Function CombineRanges(ByVal source As Range, ByVal toCombine As Range) As Range
    If source Is Nothing Then
        Set CombineRanges = toCombine
    Else
        Set CombineRanges = Union(source, toCombine)
    End If
End Function

Now, change your loop so that instead of deleting rows, it determines what rows need to be removed: 现在,更改循环,以便代替删除行,而是确定需要删除哪些行:

Dim toDelete As Range
Dim cell As Range
For Each cell In ActiveSheet.Range("B11:B25")
    If cell.Value <> "Total" Then Set toDelete = CombineRanges(toDelete, cell)
Next

If Not toDelete Is Nothing Then toDelete.EntireRow.Delete

And now you have an efficient loop (always iterate object collections with a For Each loop) that doesn't modify the object collection it's iterating, does only one thing, and you have a single Delete operation going on, which will only trigger a single worksheet Changed event, one single recalculation, and will perform well regardless of whether you're deleting 20 or 2000 rows. 现在,您有了一个高效的循环(始终使用For Each循环迭代对象集合),该循环不会修改它正在迭代的对象集合,仅执行一件事,并且您正在进行单个Delete操作,它将仅触发一个工作表Changed事件,一次重新计算,无论删除20行还是2000行,其效果都很好。

try this, it will loop from row 25 to 11 backwards and find anything not "Total" 尝试此操作,它将从第25行向后循环到11,并找到非“总计”的内容

Dim i As Integer
For i = 25 To 11 Step -1 ' change to whatever row you want
    If Range("B" & i) <> "Total" Then
        Range("B" & i).EntireRow.Delete
    End If
Next

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM