2016-09-14 5 views
0

Im folgenden Code versuche ich 2 Datumswerte zu überprüfen. Wenn sie existieren, berechnen Sie die Tage zwischen in Spalte BG. Wenn sie nicht vorhanden sind oder das Ergebnis kleiner als 0 ist, löschen Sie die Zeile.VBA For-Schleife Iterationsproblem

Das Problem, das ich habe ist, dass, sobald es löscht, eine Zeile, es verwendet Next I, und überspringt die Zeile direkt danach. Bsp .: Zeile 1 & 2 fehlt ein Datum. Zeile 1 wird gelöscht. Zeile 2 wird in Zeile 1 geschoben, dann folgt ich, also sind wir jetzt in Zeile 2 (was 3 war) und überspringt die Ergebnisse von Zeile 2. Die Verwendung von i = i-1 scheint mein Programm zum Absturz zu bringen. Gibt es noch einen weiteren Weg, um meinen Code effizienter zu machen, so dass er schneller durch mehrere Elemente iterieren kann?

Sub Func4() 

Dim N As Long, i As Long, j As Long, cnt As Long, date1 As Date, date2 As Date, date3 As Long ', iold As Long 

N = Cells(Rows.Count, "A").End(xlUp).Row 

j = 2 
cnt = 0 
For i = 2 To N 'main 
    j = j + 1 
    'iold = i 
    If Not IsEmpty(Cells(i, "AB").Value) And Not IsEmpty(Cells(i, "AE").Value) Then 
     date1 = Cells(i, "AB").Value 'AB=Entry Date 
     date2 = Cells(i, "AE").Value 'AE=Rec'd 
     date3 = Work_Days(date2, date1) 
     cnt = cnt + 1 

     If date3 >= 0 Then 
      Cells(i, "BG").Value = date3 

     Else 
      Rows(i).EntireRow.Delete 
      'i = i - 1 'HERE 
     End If 
    Else 
     Rows(i).EntireRow.Delete 
     'i = i - 1 'HERE 
    End If 

    'End If 
    'If i = iold Then 
Next i 

'Else 
'Next 
'End If 

End Sub 

RESOLVED ARBEITS ANTWORT:

Sub Func4() 
    Dim N As Long, i As Long, j As Long, cnt As Long, date1 As Date, date2 As Date, date3 As Long 
    N = Cells(Rows.Count, "A").End(xlUp).Row 
    j = 2 
    For i = N To 2 Step -1 
      j = j + 1 

     If Not IsEmpty(Cells(i, "AB").Value) And Not IsEmpty(Cells(i, "AE").Value) Then 
      date1 = Cells(i, "AB").Value 'AB=Entry Date 
      date2 = Cells(i, "AE").Value 'AE=Rec'd 
      date3 = Work_Days(date2, date1) 
      cnt = cnt + 1 
       If date3 >= 0 Then 
        Cells(i, "BG").Value = date3 

       Else 
        Rows(i).EntireRow.Delete 
       End If 
     Else 
     Rows(i).EntireRow.Delete 
     End If 
     Next i 

End Sub 
+4

Sie Schleife müssen nach hinten, wenn Sie Löschen von Zeilen. – Comintern

+2

Wie Komintern sagte 'Für i = N zu 2 Schritt -1' –

+0

Danke für den Tipp! Ich habe nie darüber nachgedacht. Ich habe es anscheinend perfekt funktionieren lassen! Bitte reichen Sie Ihre einfache Antwort als Antwort ein und ich werde Ihnen Punkte belohnen! – Josh

Antwort

0

Um das erste Problem zu lösen, können Sie die Schleife rückwärts laufen lassen. Auf diese Weise werden nur Zeilen verschoben, die bereits iteriert wurden.

For i = N To 2 Step -1 

Die zweite Frage ist ein bisschen offen. Dieser Leitfaden hat ein paar Vorschläge, wie Sie Ihren Code schneller zu machen:

http://datapigtechnologies.com/blog/index.php/ten-things-you-can-do-to-speed-up-your-excel-vba-code/

Einige Elemente aus der Anleitung, die mir am meisten an Ihren Code im Zusammenhang abheben.

  • „Disable Blatt Bildschirmaktualisierung“

Legen Sie die folgenden, um Ihren Code, vor allem wenn Sie viele der Zeilen antizipieren gelöscht werden.

Application.ScreenUpdating = False 
    Application.ScreenUpdating = True 
  • „Vermeiden Sie übermäßige Ausflüge zum Arbeitsblatt“

Dies würde am besten erreicht werden, indem Spalten „AB“ und „AE“ in ein Array, und Iterieren durch sie eher als Zellen Lesen auf Das Blatt. Hier ist eine Lösung, die zu erreichen:

Fastest way to read a column of numbers into an array

Dim Ar as Variant 

Ar = Sheets("Sheet").Range("A1:A10000").Value 
-1

ändern For i = 2 To N-Do until i > N und Next i zu Loop (vergessen Sie nicht i = 2 vorher zuweisen) und dann die Zeile unter der Zeile löschen Kommentar

+0

Der Punkt ist, dass das Löschen von Zeilen in einer Schleife die Elemente verschiebt, was dazu führt, dass Sie einige Iterationen "verpassen". Wenn Sie Objekte aus der Liste der geloopten Objekte löschen, kehren Sie immer rückwärts ein. –

+0

Ich stimme zu, dass Sie in fast allen Fällen in umgekehrter Schleife, aber nicht _always_ wiederholt werden müssen - es gibt bestimmte Ausnahmen – Jeremy

+0

Sicher gibt es immer Ausnahmen, aber die beste Vorgehensweise - in VBA liest immer in umgekehrter Reihenfolge beim Löschen von Elementen aus der Sammlung, die Sie iterieren Über. Nehmen Sie es von mir, dies ist einer der größten Fehler, die von Leuten gemacht wurden, die begannen, sich gegen das Office-Objektmodell zu entwickeln. Seien Sie also vorsichtig beim Starten von Office-Entwicklern, um etwas anderes zu tun. –

0

Erste Frage wurde von Komintern und Shai Rado in den Kommentaren beantwortet:

Durchlaufen Sie die Elemente immer in umgekehrter Reihenfolge, da das Löschen von Elementen aus dem Bereich die verbleibenden Elemente zurück verschiebt. Durch die umgekehrte Schleife wirken sich die gelöschten Elemente nicht auf die verbleibenden Elemente aus.

Zweite Frage, die Dinge zu beschleunigen, lesen Sie diesen Blog-Post:

https://blogs.office.com/2009/03/12/excel-vba-performance-coding-best-practices/

und vor allem den Teil unter: Read/Große Blöcke von Zellen in einer einzigen Operation schreiben

Es wird Seien Sie ein -lot- schneller, wenn Sie Ihre Daten in Arrays verarbeiten, die Daten in einem Array lesen und zurückschreiben, wie im Beispiel in diesem Blog gezeigt. Gerade bei Tausenden von Gegenständen wird dies von Bedeutung sein!