对于每个下一个循环意外跳过一些条目
我在Excel中编写了一个macros来扫描logging列表,在内容中find任何带有“CHOFF”的单元格,复制包含它的行,并将这些单元格粘贴到另一个表单中。 它是格式化报告的较长代码的一部分。
它工作得很好,除了“For Each”循环已经跳过一些看似随机的条目。 这不是每隔一行,我试图以不同的方式进行sorting,但不pipe怎样,相同的单元格都被忽略,所以它看起来并不是关于单元格的顺序。 我尝试使用InStr而不是cell.value,但仍然跳过了相同的单元格。
你有什么想法是什么可能导致代码只是不认识一些散布在范围内的细胞?
有问题的代码如下:
Dim Rng As Range Dim Cell As Range Dim x As Integer Dim y As Integer ActiveWorkbook.Sheets(1).Select Set Rng = Range(Range("C1"), Range("C" & Rows.Count).End(xlUp)) x = 2 For Each Cell In Rng If Cell.Value = "CHOFF" Then Cell.EntireRow.Select Selection.Cut ActiveWorkbook.Sheets(2).Select Rows(x).Select ActiveWorkbook.ActiveSheet.Paste ActiveWorkbook.Sheets(1).Select Selection.Delete Shift:=xlUp y = x x = y + 1 End If Next Cell
For Each...Next
循环不会自动跟踪您已删除的行。 当你删除一行时, Cell
仍然指向相同的地址(现在是原来的那一行,因为它被删除了)。 然后在下一个循环中, Cell
移动到下一个单元格,跳过一个单元格。
为了解决这个问题,你可以在If
语句中将Cell
向上移动一个(例如Set Cell = Cell.Offset(-1,0)
)。 但是我认为这是一个简单的For
循环比For Each
更好的例子之一:
Dim lngLastRow As Long Dim lngSourceRow As Long Dim lngDestRow As Long Dim objSourceWS As Worksheet Dim objDestWS As Worksheet Set objSourceWS = ActiveWorkbook.Sheets(1) Set objDestWS = ActiveWorkbook.Sheets(2) lngLastRow = objSourceWS.Range("C" & objSourceWS.Rows.Count).End(xlUp).Row lngDestRow = 1 For lngSourceRow = lngLastRow To 1 Step -1 If objSourceWS.Cells(lngSourceRow, 3).Value = "CHOFF" Then objSourceWS.Rows(lngSourceRow).Copy Destination:=objDestWS.Cells(lngDestRow, 1) objSourceWS.Rows(lngSourceRow).Delete lngDestRow = lngDestRow + 1 End If Next lngSourceRow
这反过来(根据波特兰亚军的build议),以避免对删除的行做任何事情。 它还可以整理代码中的其他一些东西:
- 你不需要做任何
Select
,最好不要(为什么要看这个问题 ) - 您可以在
Range.Copy
指定一个目的地,而不必单独进行select和粘贴 - 你可以改变一个variables的值,而不必先把它赋值给第二个variables(即
x = x + 1
是好的) - 对于包含行号的variables,您应该使用
Long
而不是Integer
,因为Excel电子表格中的行数多于Integer
可以处理的行数(至less为65536,而Integer
则为32767 max)
显然testing,它仍然做你所需要的!
尝试使用Selection.Copy而不是Selection.Cut
如果你不得不删除这些行,你可以在循环中标记这些行(例如在一个未使用的单元格中写入某些东西),然后在完成主循环后将其删除。
问候
当我试图删除某些行时,我遇到了类似的问题。 我克服它的方式是通过循环迭代几次,使用以下:
For c = 1 To 100 Dim d As Long: d = 1 With Sheets("Sheet") For e = 22 To nLastRow Step 1 If .Range("G" & e) = "" Or .Range("I" & e) = "" Then .Range("G" & e).EntireRow.Delete .Range("I" & e).EntireRow.Delete d = d + 1 End If Next End With c = c + 1 Next
所以,基本上如果你把我的代码中的outer for循环合并到代码中,它应该可以工作。