Kurz gesagt — Eine Zeile zu löschen ist eine strukturelle Bearbeitung: Sie leert die Zeile nicht, sie entfernt sie und schiebt jede Zeile darunter um eins nach oben. Diese eine Tatsache steckt hinter dem häufigsten VBA-Bug überhaupt — eine vorwärts laufende Schleife, die Zeilen löscht, überspringt jede Zeile, die auf eine gelöschte folgte, weil sich die Zeilennummern unter der Schleife verschieben. Die Lösung ist ein Wort: schleifen Sie rückwärts (
For i = last To first Step -1). Löschen Sie die ganze Zeile mit.EntireRow.Delete, und sammeln Sie viele verstreute Zeilen in einem einzigenUnionund löschen Sie einmal — das ist schneller und umgeht das Verschiebeproblem vollständig.
' Jede Zeile löschen, deren Spalte A leer ist - von UNTEN nach OBEN schleifen.
Dim ws As Worksheet: Set ws = ThisWorkbook.Worksheets("Data")
Dim lastRow As Long, i As Long
lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
For i = lastRow To 2 Step -1 ' <-- rückwärts, sonst überspringen Sie Zeilen
If Trim(ws.Cells(i, "A").Value) = "" Then ws.Rows(i).EntireRow.Delete
Next i
„Diese Zeilen löschen“ klingt nach der einfachsten Aufgabe der Excel-Automatisierung, und es
ist die, an der fast jeder beim ersten Mal scheitert. Der Grund ist nicht die
Delete-Methode — es ist, dass das Löschen genau das verändert, worüber Sie gerade schleifen.
Stimmt die Laufrichtung, ist das Löschen nach Bedingung trivial; stimmt sie nicht, lässt Ihr
Makro klammheimlich die Hälfte der passenden Zeilen zurück. Diese Anleitung dreht sich um diese
eine Idee und die praktischen Muster, die daraus folgen.
Was Sie lernen
- Das mentale Modell — Löschen entfernt eine Zeile und schiebt alles darunter nach oben
- Die wichtigste Regel — schleifen Sie rückwärts, sonst überspringt eine vorwärts laufende Schleife Zeilen
- Warum
.EntireRow.Deletedas sichere Ziel ist und was.Deleteauf einer Zelle stattdessen anrichtet - Das schnellere Muster für verstreute Zeilen — ein
Unionbauen, einmal löschen - Leerzeilen entfernen und nach Bedingung löschen, ohne Verweisformeln zu zerstören
Das mentale Modell: Löschen verschiebt das Raster, es leert keine Zeile
Es gibt zwei völlig verschiedene Vorgänge, die beide „Löschen“ genannt werden. Ein Druck auf
Entf leert eine Zelle — die Zeile bleibt, der Wert verschwindet. Rechtsklick ▸
Löschen oder Rows(i).Delete im Code entfernt die Zeile — die Zeile hört auf zu
existieren, und jede Zeile darunter rutscht um eins nach oben und schließt die Lücke. Aus der
ehemaligen Zeile 11 wird Zeile 10.
Dieses Schließen der Lücke ist die ganze Geschichte. Wenn Sie Zeile 10 löschen, sitzen die Daten von Zeile 11 nun in Zeile 10. Jeder Code, der annahm „Zeile 11 enthält noch, was sie eben enthielt“, liegt jetzt falsch. Deshalb fühlt sich das Löschen von Zeilen anders an als jede andere Schleife, die Sie schreiben: Die Adresse der noch nicht verarbeiteten Daten ändert sich in dem Moment, in dem Sie löschen. Sie bearbeiten das Koordinatensystem, während Sie es durchschreiten.
Behalten Sie dieses Bild im Kopf — unterhalb der gelöschten Zeile verschiebt sich alles nach oben — und jede Regel weiter unten ist nur eine Folge davon.
Die wichtigste Regel: rückwärts schleifen, sonst überspringen Sie Zeilen
Hier ist der Bug, geschrieben so, wie ihn fast jeder beim ersten Mal schreibt:
' FALSCH - eine vorwärts laufende Schleife über Zeilen, die Sie löschen.
For i = 2 To lastRow
If ws.Cells(i, "A").Value = "DELETE" Then ws.Rows(i).EntireRow.Delete
Next i
Angenommen, die Zeilen 5 und 6 enthalten beide „DELETE“. Die Schleife erreicht i = 5, löscht
Zeile 5, und Zeile 6 rutscht nach oben zur neuen Zeile 5. Doch die Schleife geht nun weiter zu
i = 6 — das ist die Zeile, die früher Zeile 7 war. Die alte Zeile 6 wurde nie geprüft.
Zwei benachbarte Treffer, und der zweite überlebt. Bei einem Block von Treffern bleibt
ungefähr jeder zweite übrig, und das Symptom („einige Zeilen wurden nicht gelöscht“) wirkt
zufällig.
Die Lösung kostet nichts. Laufen Sie von unten nach oben:
' RICHTIG - von der letzten Zeile zurück zur ersten löschen.
For i = lastRow To 2 Step -1
If ws.Cells(i, "A").Value = "DELETE" Then ws.Rows(i).EntireRow.Delete
Next i
Rückwärts betrachtet schiebt das Löschen von Zeile 6 die Zeilen unterhalb von 6 nach oben —
aber die haben Sie schon erledigt. Die noch nicht betrachteten Zeilen liegen alle oberhalb
der gerade gelöschten, und ihre Nummern haben sich nicht bewegt. Das Verschieben passiert
weiterhin; es passiert nur hinter Ihnen, wo es keinen Schaden anrichten kann. Sobald eine
Schleife Zeilen löscht, läuft sie mit Step -1. Prägen Sie sich das ein, und die Hälfte
aller Löschbugs verschwindet.
Die Regel, die Ihre Daten ausgerichtet hält: die Zeile löschen, nicht eine Zelle
Delete steht auf jedem Bereich zur Verfügung, und je kleiner der Bereich, desto gefährlicher
ist es. Schreiben Sie ws.Cells(i, "A").Delete, löschen Sie eine einzelne Zelle, und Excel
schiebt nur die Zellen darunter in Spalte A nach oben — während die Spalten B, C und D genau
dort bleiben, wo sie waren. Jede Zeile von dort abwärts ist nun verschoben: Spalte A zeigt
einen Datensatz, während B und C den darunterliegenden zeigen. Nichts wirft einen Fehler; Ihre
Daten geraten einfach klammheimlich durcheinander.
Das Löschen der ganzen Zeile hält jede Spalte im Gleichschritt:
ws.Rows(i).EntireRow.Delete ' die ganze Zeile 11 geht; 12, 13... rutschen zusammen nach oben
ws.Cells(i, "A").EntireRow.Delete ' identisch - .EntireRow erweitert eine Zelle auf ihre ganze Zeile
.EntireRow ist die Erweiterung von „dieser Zelle“ zu „der ganzen Zeile, in der diese Zelle
sitzt“, und genau das wollen Sie fast immer. Das nackte Range.Delete mit
Shift:=xlUp/xlToLeft heben Sie sich für den seltenen Fall auf, in dem Sie wirklich einen
Zellblock verschieben und nicht einen Datensatz entfernen wollen.
Das schnellere, sicherere Muster: einen Union sammeln und einmal löschen
Zeilenweises Schleifen und Löschen funktioniert, sobald Sie rückwärts schleifen, doch auf
großen Blättern ist es langsam — jedes .Delete zwingt Excel, das Raster zu verschieben und
neu zu berechnen. Es gibt ein Muster, das sowohl schneller als auch immun gegen die
Verschiebefalle ist, weil es das gesamte Löschen in einem einzigen Schritt erledigt: Bauen Sie
mit Union einen Range aus jeder zu entfernenden Zeile auf und löschen Sie am Ende alles auf
einmal.
Dim victims As Range, i As Long
For i = 2 To lastRow ' Richtung egal - wir löschen später
If ws.Cells(i, "A").Value = "DELETE" Then
If victims Is Nothing Then
Set victims = ws.Rows(i)
Else
Set victims = Union(victims, ws.Rows(i))
End If
End If
Next i
If Not victims Is Nothing Then victims.EntireRow.Delete ' ein Löschvorgang, alle Zeilen auf einmal
Da keine Zeile entfernt wird, bevor die Schleife vorbei ist, bewegen sich die Zeilennummern
während des Durchlaufs nie — eine vorwärts laufende Schleife ist hier also völlig sicher. Und
ein einzelnes .Delete auf einem mehrflächigen Bereich ist dramatisch schneller als Hunderte
einzelner Löschungen. Meine Faustregel: eine Handvoll Zeilen, rückwärts schleifen; Hunderte
oder Tausende, einen Union sammeln (oder filtern — siehe unten) und einmal löschen. Verpacken
Sie beides in Application.ScreenUpdating = False / Calculation = xlManual, und große
Löschvorgänge gehen von Sekunden auf sofort.
Leerzeilen, Bedingungen und die Verweisfalle
Leerzeilen löschen hat einen Einzeiler, der jede Schleife schlägt — lassen Sie Excel die leeren Zellen finden:
On Error Resume Next ' SpecialCells wirft 1004, wenn es keine leeren Zellen gibt
ws.Range("A2:A" & lastRow).SpecialCells(xlCellTypeBlanks).EntireRow.Delete
On Error GoTo 0
SpecialCells(xlCellTypeBlanks) liefert jede leere Zelle in Spalte A als einen mehrflächigen
Bereich zurück, und .EntireRow.Delete entfernt all ihre Zeilen auf einen Schlag. Zwei
Vorbehalte: Es richtet sich nach einer Spalte (eine Zeile mit leerem A, aber gefülltem B
fliegt trotzdem raus), und es wirft einen Fehler, wenn es keine Leerzellen gibt — daher die
On Error-Absicherung.
Löschen nach Bedingung bei großen Datenmengen: Der professionelle Zug ist AutoFilter — filtern Sie auf die unerwünschten Zeilen, löschen Sie die sichtbaren, entfernen Sie den Filter. Das ist der schnellste Ansatz von allen, weil Excel den Abgleich übernimmt:
With ws.Range("A1").CurrentRegion
.AutoFilter Field:=1, Criteria1:="DELETE"
.Offset(1).SpecialCells(xlCellTypeVisible).EntireRow.Delete ' Kopfzeile überspringen
End With
ws.AutoFilterMode = False
Eine Falle überlebt sie alle: Das Löschen von Zeilen verschiebt Verweise. Zeigt eine Formel
anderswo auf =A20 und Sie löschen Zeile 5, schreibt Excel sie zu =A19 um — meist genau das,
was Sie wollen. Löschen Sie aber die Zeile, von der eine Formel abhängt, wird aus dieser
Formel #REF!. Zeilen unter laufenden Formeln wegzulöschen ist die klassische Ursache für ein
Blatt voller #REF!-Fehler; wissen Sie also vor einem Massenlöschen, ob irgendetwas weiter
unten auf die Zeilen verweist, die Sie entfernen. Herauszufinden, wo Ihre Daten enden, ist eine
verwandte Fertigkeit — siehe VBA Letzte Zeile.
Wie ExcelMaster hilft
Code zum Zeilenlöschen hat eine Handvoll stiller Fehlerquellen: die vorwärts laufende Schleife,
die Zeilen überspringt, das Einzelzellen-Löschen, das Spalten verschiebt, den
SpecialCells-Aufruf, der ohne Leerzellen abstürzt, das Massenlöschen, das #REF!
hinterlässt. Keine davon wirft einen offensichtlichen Fehler — sie produzieren einfach leicht
falsche Daten.
ExcelMaster lässt Sie
stattdessen das Ergebnis beschreiben. Sagen Sie „lösche jede Zeile, in der Spalte A leer ist“
oder „entferne Zeilen, deren Status Storniert ist“, und es schreibt die Schleife in der
sicheren Richtung (oder einen Union/Filter für große Datenmengen), zielt auf .EntireRow,
sichert die Randfälle ab und legt zuerst eine Sicherung des Blatts an. Sie behalten die
Arbeitsmappe und den Code; Sie sparen sich den Teil, in dem ein vergessenes Step -1
klammheimlich einen Bericht beschädigt.
Häufig gestellte Fragen
Warum überspringt meine VBA-Schleife beim Löschen Zeilen?
Weil das Löschen einer Zeile jede Zeile darunter um eins nach oben schiebt, eine vorwärts
laufende Schleife aber weiter hochzählt. Nachdem Sie Zeile 5 gelöscht haben, wird aus der alten
Zeile 6 die Zeile 5 — und die Schleife geht weiter zu Zeile 6 und überspringt sie. Schleifen
Sie stattdessen rückwärts: For i = lastRow To 2 Step -1. Die noch nicht geprüften Zeilen
liegen dann immer oberhalb der Löschung, ihre Nummern bewegen sich also nie.
Wie lösche ich in VBA eine ganze Zeile?
Nehmen Sie .EntireRow.Delete — zum Beispiel ws.Rows(11).EntireRow.Delete oder
ws.Cells(11, "A").EntireRow.Delete. Beide entfernen die ganze Zeile, sodass jede Spalte
ausgerichtet bleibt. Meiden Sie Cells(11, "A").Delete, das eine einzelne Zelle löscht und nur
diese Spalte verschiebt, was den Rest durcheinanderbringt.
Was ist der schnellste Weg, viele Zeilen in VBA zu löschen?
Bei Hunderten oder Tausenden von Zeilen löschen Sie nicht einzeln. Filtern Sie entweder per
AutoFilter auf die unerwünschten Zeilen und löschen Sie die sichtbaren Zellen in einem Schritt,
oder bauen Sie während der Schleife einen Union aller Zielzeilen und rufen Sie am Ende einmal
.EntireRow.Delete auf. Ein einzelnes Löschen mehrerer Zeilen ist weit schneller als viele
einzelne, besonders bei abgeschaltetem ScreenUpdating und Calculation.
Wie lösche ich in VBA alle Leerzeilen?
ws.Range("A2:A" & lastRow).SpecialCells(xlCellTypeBlanks).EntireRow.Delete entfernt jede
Zeile mit leerer Spalte A in einem Vorgang. Umschließen Sie es mit On Error Resume Next /
On Error GoTo 0, weil SpecialCells einen Fehler wirft, wenn es keine leeren Zellen zu finden
gibt.
Warum bekomme ich nach dem Löschen von Zeilen #REF!-Fehler?
Das Löschen von Zeilen verschiebt Zellbezüge. Formeln, die hinter die gelöschten Zeilen
zeigen, werden automatisch neu nummeriert, doch jede Formel, die auf eine Zelle innerhalb
einer gelöschten Zeile verwies, lässt sich nicht mehr auflösen und wird zu #REF!. Prüfen Sie
vor einem Massenlöschen, ob andere Zellen von den Zeilen abhängen, die Sie gleich entfernen.
Getestet in
Getestet in: Excel 365 (Windows 11), VBA 7.1 — zuletzt geprüft am 07.08.2026.
Verwandte Anleitungen: VBA Zeilen und Spalten einfügen · VBA Spalten und Zeilen ausblenden · VBA Letzte Zeile · VBA For-Schleife · VBA Range
