VBA循环未退出

3
我正在遍历表格的行,如果不满足某些条件则删除行。但奇怪的是,即使完成了循环,我的for循环也从未退出。我做错了什么?
lastr = Range("a2").End(xlDown).Row
For r = 2 To lastr
    If Cells(r, 1).Value <> "SHORT POSITIONS" And Cells(r, 7).Value = 0 And Cells(r, 10).Value <> "Yes" Then
        Rows(r).Delete
        r = r - 1
        lastr = lastr - 1
    End If
Next r

如果您在 For 行设置断点,lastr 的值是多少? - Vincent G
3
通常,在使用 for 循环删除行时,从末尾开始以 i 为起始值会更容易: For r = lastr to 2 step -1。这样,您就不必担心 r = r-1lastr = lastr -1。请注意,翻译中的句子顺序可能与原文略有不同,但意思保持一致。 - Vincent G
我该如何检查lastr的值?我设置了断点。 - baconwichsand
1
有多种方法。您可以将鼠标悬停在名称上,查看本地变量窗口,设置间谍,输入“? lastr”在立即窗口中... - Vincent G
这是正确的123。 - baconwichsand
2
在 For... 循环中,当计算 For 代码时,结束值会被保存。如果您逐步运行代码,当到达 Next 时,它会回到 For 之后的行而不是 For 本身。因此,您无法在循环内修改结束值,该循环将运行123次。 - Vincent G
3个回答

3

删除行时,始终从底部开始向上工作。如果未按照此方式进行操作,将导致跳过某些行,因为行的位置在删除后会被重置。

永远不要在 For ... Next 语句 中重置计数器。改变变量 r 会使事情变得混乱。更改变量 lastr 没有任何效果。循环仍将到达最初进入循环时的 lastr 值。

lastr = Range("a" & ROWS.COUNT).End(xlUP).Row
For r = lastr To 2 STEP -1   '<~~ VERY IMPORTANT
    If Cells(r, 1).Value <> "SHORT POSITIONS" And Cells(r, 7).Value = 0 And Cells(r, 10).Value <> "Yes" Then
        Rows(r).Delete
    End If
Next r

通常情况下,从底部向上查找最后一个有数据的单元格更好。

0

你正在从循环变量中减去1,因此它会无限循环。

在Visual Basic的for循环中,“from”和“to”在开始时计算一次(它们是固定的),但是循环变量每次增加。所以

For r = fromExp to toExp
  SomeCode()
End For

       行为与

相同。
    Dim f = fromExp
    Dim t = toExp

    r = f

    While (r < t)
       SomeCode()
       r = r + 1
    End While

在您的示例中,代码更改为 toExp。
For r = fromExp to toExp
   toExp = toExp + 1
   r = r - 1
EndFor

但是那并不影响循环:

    Dim f = fromExp
    Dim t = toExp

    r = f

    While (r < t)
       toExp = toExp + 1   // does not affect the loop
       r = r - 1
       r = r + 1           // r is unchanged
    End While

循环变量未改变,因此它会无限循环。

最佳实践:不要在 For 循环内更改循环变量。


0

如果你想循环并删除,最好先标记行,然后一次性删除它们或使用数组。

lastr = Range("a2").End(xlDown).Row
dim DR() as long
dim c as long
For r = 2 To lastr
    If Cells(r, 1).Value <> "SHORT POSITIONS" And Cells(r, 7).Value = 0 And Cells(r, 10).Value <> "Yes" Then
        c = c +1
        redim preserve DR(c)
        dr(c-1) = R
    End If
Next r
'delete the rows one by one, or you could build a string and delete once.
For r = 0 to UBound(DR)
    Rows(dr(i).delete ' or entirerow delete 
next i

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接