2013-12-19 110 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

相關問題