2013-12-19 80 views
1

对不起,如果这很简单,这是我第一次尝试VBA。删除基于单元格内容的行(动态金额)

所以我想这个宏摆脱我不需要的行,并为每个实体有一个总场(大约每20个记录或左右)我做了这个脚本:

Dim i As Integer 
Dim LastRow As Integer 
LastRow = Range("A65536").End(xlUp).Row 

For i = 3 To LastRow 
    If Range("C" & i) = "Result" Then 
     Rows(i & ":" & i).Select 
     Selection.Delete Shift:=x1Up 
    End If 
Next 

而且,这工作完美!然后我尝试了类似的东西..我试图通过数据集中的每一行(记录),然后如果某个字段不包含字符串“INVOICE”,那么我不需要该行,我可以删除它。于是我就加入到我的电流回路(为什么两次循环?)所以,现在它看起来像这样:

Dim i As Integer 
Dim LastRow As Integer 
LastRow = Range("A65536").End(xlUp).Row 

For i = 3 To LastRow 
    If Range("C" & i) = "Result" Then 
     Rows(i & ":" & i).Select 
     Selection.Delete Shift:=x1Up 
    End If 
    If Not InStr(1, Range("Q" & i), "INVOICE") Then 
     Rows(i & ":" & i).Select 
     Selection.Delete Shift:=x1Up 
    End If 
Next 

那第二位,据我可以告诉只是随机开始删除没有无缘无故行。 Q字段不包含发票的行有时会保留,如果包含发票,行也会保持不变。任何想法我做错了什么?

+2

不要循环。使用Autofilter :)请参阅[这](http://stackoverflow.com/questions/11631363/how-to-copy-a-line-in-excel-using-a-specific-word-and-pasting-to-another -excel -s) –

+1

...或者如果你打算循环,那么从最后一行开始并运行('For i = LastRow to 3 Step -1'),这样你就不会踩到你的循环索引当你删除一行(因此向上移动下面的行...) –

回答

0

确实有两种方法:AutoFilterFor Loop。其中,AutoFilter要快得多,特别是对于大型数据集,但它通常需要非常好的设置。 For Loop很容易,但它具有微不足道的回报,尤其是当您的数据开始触及10万行或更多行时。

另外,Not InStr(1, Range("Q" & i), "INVOICE")可能看起来像最好的方式,但恕我直言,它不是。 InStr返回一个数字,所以如果您进一步比较Not InStr(1, Range("Q" & i), "INVOICE") > 0或仅仅是InStr(1, Range("Q" & i), "INVOICE") = 0会更好。无论如何,我在下面的第二个代码中使用了前者。

以下是两种方法。他们在简单的数据上进行测试。代码看起来可能有点笨重,但逻辑是合理的。请参阅评论以及其他内容。

自动筛选方法:

Sub RemoveViaFilter() 

    Dim WS As Worksheet: Set WS = ThisWorkbook.Sheets("ModifyMe") 
    Dim LastRow As Long 

    Application.ScreenUpdating = False 
    With WS 
     '--For condition "Result" 
     .AutoFilterMode = False 
     LastRow = .Cells(Rows.Count, 1).End(xlUp).row '--Compatible if there are more rows. 
     With Range("A2:Q" & LastRow) '--Assuming your header is in Row 2 and records start at Row 3. 
      .AutoFilter Field:=3, Criteria1:="Result" '--Field:=3 is Column C if data starts at A 
      .Cells.Offset(1, 0).SpecialCells(xlCellTypeVisible).EntireRow.Delete '--Delete the visible ones. 
     End With 
     '--For condition "<>*INVOICE*" 
     .AutoFilterMode = False 
     LastRow = .Cells(Rows.Count, 1).End(xlUp).row 
     With Range("A2:Q" & LastRow) 
      .AutoFilter Field:=17, Criteria1:="<>*INVOICE*" '--Field:=17 is Column Q if data starts at A 
      .Cells.Offset(1, 0).SpecialCells(xlCellTypeVisible).EntireRow.Delete 
     End With 
     .AutoFilterMode = False 
    End With 
    Application.ScreenUpdating = True 

End Sub 

for循环的方法:

Sub RemoveViaLoop() 

    Dim WS As Worksheet: Set WS = ThisWorkbook.Sheets("Sheet6") 
    Dim LastRow As Long: LastRow = WS.Cells(Rows.Count, 1).End(xlUp).row 
    Dim Iter As Long 

    Application.ScreenUpdating = False 
    With WS 
     For Iter = LastRow To 3 Step -1 '--Move through the rows from bottom to up by 1 step (row) at a time. 
      If .Range("C" & Iter) = "Result" Or Not InStr(1, .Range("Q" & Iter).Value, "Invoice") > 0 Then 
       .Rows(Iter).EntireRow.Delete 
      End If 
     Next Iter 
    End With 
    Application.ScreenUpdating = True 

End Sub 

让我们知道这会有所帮助。

+0

谢谢,我今天会使用自动过滤器来试试这个,因为我的数据集可能会变得笨重,并且这是一个我不想陷入困境的后台机器。 – Birdd

1

您应该将OR条件放在一起,以便在出现任何原因时删除该行。否则,由于您正在删除预设范围内的行,因此您最终会跳过比目前更多的行。目前看起来你每次删除一行都会跳过一行,所以你错过了任何连续的情况。蒂姆从最后一排开始工作的建议是现成的。

For i = LastRow to 3 Step -1 
    If Range("C" & i) = "Result" OR Not InStr(1, Range("Q" & i), "INVOICE") Then 
    Rows(i & ":" i).Delete Shift:=x1Up 
    End If 
Next i 
+0

这很有道理,感谢您的帮助!我想我会切换到autofilter选项,因为它速度更快,而且我的数据集非常庞大。 – Birdd

相关问题