TL;DR — Hören Sie auf,
Range("A1:A100")fest zu verdrahten. Ihre Daten wachsen und schrumpfen, finden Sie ihre Grenze also zur Laufzeit. Das kanonische Idiom istCells(Rows.Count, "A").End(xlUp).Row— es simuliert das Drücken vonStrg + ↑vom untersten Ende der Spalte. Nutzen SieRows.Count, niemals ein fest verdrahtetes65536. Es gibt vier Wege zu fragen „wo enden die Daten?", und jeder beantwortet eine leicht andere Frage:.End(xlUp)findet die letzte nicht-leere Zelle in einer Spalte,.End(xlDown)stoppt an der ersten Lücke,.UsedRangemeldet zu viel und.Findist der einzige wirklich lückensichere Weg. Wählen Sie die falsche Methode, verarbeiten Sie die falschen Zeilen — ohne dass ein Fehler Sie warnt.
Die letzte Zeile zu finden ist das Häufigste, was ein Makro erledigen muss, bevor
es schleifen, kopieren, sortieren oder löschen kann. Es ist auch die Stelle, an
der Anfänger die fragilste Zeile der ganzen Prozedur schreiben: ein fest
verdrahtetes A2:A500. Fügen Sie eine Zeile hinzu, und das Makro übersieht sie;
löschen Sie Zeilen, und es verarbeitet Hunderte von Leerzeilen. Echtes VBA nimmt
die Größe der Daten nie an — es misst sie.
Was Sie lernen
- Das kanonische Idiom
Cells(Rows.Count, "A").End(xlUp).Row, Stück für Stück entschlüsselt - Warum
65536eine Tretmine ist undRows.Countdie Lösung - Der Fehlermodus, der sich in jeder der vier Methoden versteckt (
.End(xlUp),.End(xlDown),.UsedRange,.Find) - Wie Sie die letzte Spalte finden, nicht nur die letzte Zeile
- Wann Lücken in Ihren Daten bedeuten, dass Sie von
.Endauf.Findumsteigen müssen
Das mentale Modell: Ihre Daten haben eine Grenze, und Excel gibt sie Ihnen nicht
Ein Arbeitsblatt ist ein Raster mit einer Million Zeilen. Ihre Daten belegen irgendein Rechteck darin, aber Excel führt keine ordentliche „letzte Zeile"-Eigenschaft, die Sie einfach auslesen könnten. Sie müssen also bis an die Grenze laufen und fragen, wo Sie gelandet sind. Jede zuverlässige Technik ist eine Variante von „Starten Sie an einer Stelle, von der Sie wissen, dass sie hinter den Daten liegt, und springen Sie dann zurück zum letzten Eintrag, der tatsächlich vorhanden ist".
Das Bild vor dem inneren Auge für das kanonische Idiom ist eine Person, die ganz
unten in einer Spalte steht und Strg + ↑ drückt: Der Cursor fliegt nach oben
und stoppt auf der letzten Zelle mit Inhalt. Genau das macht .End(xlUp) im Code.
Sub FindLastRow()
Dim ws As Worksheet
Set ws = ActiveSheet
Dim lastRow As Long
lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
Debug.Print "Last row with data in column A: " & lastRow
End Sub
Lesen Sie es von innen nach außen: ws.Rows.Count ist die Anzahl der Zeilen auf
dem Blatt (1.048.576 im modernen Excel). Cells(that, "A") ist die unterste Zelle
der Spalte A. .End(xlUp) springt hoch zur letzten nicht-leeren Zelle. .Row
liest deren Zeilennummer ab. Diese eine Zeile ist das Arbeitspferd — aber nur,
wenn Sie die Falle verstehen, die sie mit sich bringt.
Die Regel, die Sie vor dem schlimmsten Letzte-Zeile-Bug bewahrt: niemals 65536 fest verdrahten
Ein Jahrzehnt lang schrieben Tutorials Cells(65536, 1).End(xlUp).Row, weil
65.536 die letzte Zeile des alten .xls-Formats war. Moderne .xlsx-Blätter
haben 1.048.576 Zeilen. Wenn Ihre Daten über Zeile 65.536 hinausreichen und
Sie Ihren Sprung nach oben bei 65.536 beginnen, starten Sie oberhalb eines Teils
Ihrer Daten und liefern stillschweigend eine letzte Zeile zurück, die zu klein
ist — was Ihre Schleife mitten in der Tabelle abschneidet.
' FRAGIL — startet oberhalb aller Daten unterhalb von Zeile 65536
lastRow = Cells(65536, 1).End(xlUp).Row
' KORREKT — startet immer vom echten unteren Rand DIESES Blatts
lastRow = Cells(Rows.Count, 1).End(xlUp).Row
Rows.Count liest die tatsächliche Zeilenzahl des Blatts, auf dem der Code läuft
— es ist damit zukunfts- und versionssicher. Es gibt kein Szenario, in dem das
feste Verdrahten der Zahl besser ist. Machen Sie Cells(Rows.Count, col) zum
Reflex.
Die Regel, die jede Methode mit ihrem Fehlermodus verknüpft
Hier ist der Teil, den jedes Tutorial überspringt: Die vier gängigen Methoden liefern nicht dieselbe Antwort, weil sie unterschiedliche Fragen beantworten. Lernen Sie den Fehlermodus jeder einzelnen, und Sie wissen immer, zu welcher Sie greifen müssen.
.End(xlUp) — letzte nicht-leere Zelle in einer Spalte. Der Standard. Sein
blinder Fleck: Es betrachtet nur eine Spalte. Wenn Sie eine Spalte wählen, die
eine Lücke hat, in der die letzte Zeile leer ist (etwa der Name in Zeile 500 ist
leer, der Betrag aber nicht), halten Sie zu früh an. Wählen Sie eine Spalte, die
auf jeder Datenzeile garantiert befüllt ist — eine ID oder einen Schlüssel — oder
finden Sie die letzte Zeile über die gesamte Tabelle mit .Find.
.End(xlDown) — erste Lücke von oben. Das ist Strg + ↓ ab Zeile 1. Es
findet nicht die letzte Zeile; es findet die Zeile unmittelbar vor der ersten
leeren Zelle. Eine einzige leere Zelle mitten in Ihrer Spalte kappt Sie auf den
obersten Block. Verwenden Sie .End(xlDown) niemals, um das Ende der Daten zu
finden — nur, um das Ende eines ununterbrochenen Blocks zu finden.
' A1:A10 enthält Daten, A6 ist leer, A7:A10 enthält weitere Daten
Cells(1, 1).End(xlDown).Row ' -> 5 (hält an der Lücke — FALSCH für „letzte Zeile")
Cells(Rows.Count, 1).End(xlUp).Row ' -> 10 (echte letzte Zeile — RICHTIG)
.UsedRange — Excels zwischengespeicherter Umgrenzungsrahmen. ws.UsedRange
sind nicht Ihre Daten; es ist jede Zelle, die Excel jemals angefasst hat,
einschließlich Zellen, die nur Formatierung tragen, und es schrumpft nicht,
wenn Sie Zeilen löschen — erst wenn die Arbeitsmappe gespeichert oder neu berechnet
wird. Es meldet zu viel, sodass eine Schleife über UsedRange sich durch Hunderte
von Phantomzeilen quälen kann. Es beginnt zudem nicht zwangsläufig bei Zeile 1
(siehe FAQ). Behandeln Sie UsedRange als „ungefähr das ganze Blatt", niemals als
präzise Nummer der letzten Zeile.
.Find — die einzige lückensichere Methode. Rückwärts nach der letzten Zelle
zu suchen, die irgendetwas, irgendwo auf dem Blatt enthält, ist immun gegen
interne Leerstellen und gegen die Spalte, die Sie wählen:
Function LastDataRow(ws As Worksheet) As Long
Dim c As Range
Set c = ws.Cells.Find(What:="*", After:=ws.Cells(1, 1), _
LookIn:=xlFormulas, SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious)
If c Is Nothing Then
LastDataRow = 0 ' leeres Blatt
Else
LastDataRow = c.Row
End If
End Function
.Find ist umständlich, und Sie müssen den Nothing-Fall behandeln (ein leeres
Blatt), aber es ist die richtige Antwort, wenn Ihre Daten ausgefranste Ränder oder
interne Lücken haben. LookIn:=xlFormulas findet Zellen mit einer Formel, selbst
wenn diese aktuell zu "" ausgewertet wird; xlValues ignoriert solche — wählen
Sie bewusst.
Die Ermessensentscheidung: welche Methode wann
- Saubere einspaltige Liste oder eine Tabelle mit einer soliden
Schlüsselspalte →
Cells(Rows.Count, keyCol).End(xlUp).Row. Schnell, lesbar, korrekt. - Daten mit internen Leerzeilen oder einem ausgefransten rechten Rand →
.Find(What:="*", SearchDirection:=xlPrevious). Lückensicher. - „Wie groß ist ungefähr alles auf diesem Blatt, damit ich es leeren kann" →
.UsedRange. Das Zuviel-Melden ist harmlos, wenn Sie ohnehin löschen. - Niemals
.End(xlDown)für die letzte Zeile verwenden und niemalsUsedRange.Rows.Countlesen, als wäre es die Nummer der letzten Zeile.
Auch die letzte Spalte finden
Derselbe Sprung-Trick funktioniert auch seitwärts. Beginnen Sie an der ganz
rechten Zelle Ihrer Kopfzeile und drücken Sie im Code Strg + ←:
Dim lastCol As Long
lastCol = Cells(1, Columns.Count).End(xlToLeft).Column
Mit beiden Zahlen können Sie den exakten Datenbereich bauen, ohne irgendetwas fest zu verdrahten:
Dim rng As Range
Set rng = ws.Range(ws.Cells(1, 1), ws.Cells(lastRow, lastCol))
Genau darum geht es: Sobald Sie die Ränder finden können, tippen Sie nie wieder
eine feste Adresse. Um einen Bereich zu bauen, der die Kopfzeile überspringt,
kombinieren Sie dies mit Offset und Resize; um den
zusammenhängenden Block in einem Aufruf zu greifen, siehe UsedRange vs.
CurrentRegion.
Wie ExcelMaster hilft
Fast jede „Wie finde ich die letzte Zeile"-Frage ist in Wahrheit ein Schritt zu einem größeren Ziel: diese Spalte durchlaufen und Duplikate markieren, neue Zeilen auf ein anderes Blatt kopieren, nach Gruppe summieren. ExcelMaster nimmt dieses Ziel in einfachem Deutsch entgegen — „Kopiere für jede Zeile in der Bestelltabelle die unerledigten auf das Blatt Backlog" — und schreibt die Bereichsarithmetik für Sie, findet die Ränder der Daten auf die robuste Weise, statt eine feste Größe anzunehmen.
Sie werden .End(xlUp) weiterhin von Hand schreiben, wenn es in einem geplant
laufenden Makro steckt. Aber für die alltägliche „Verarbeite einfach die Zeilen,
die heute da sind"-Aufgabe schlägt das Beschreiben des Ergebnisses das jedes Mal
korrekte Hinbekommen von Rows.Count und Lückenbehandlung.
Häufig gestellte Fragen
Was ist der beste Weg, die letzte Zeile in VBA zu finden?
Bei einer Tabelle mit einer zuverlässig befüllten Schlüsselspalte nehmen Sie
Cells(Rows.Count, keyColumn).End(xlUp).Row. Es ahmt Strg + ↑ vom unteren
Blattrand nach und ist schnell und lesbar. Haben Ihre Daten interne Leerzeilen
oder einen ausgefransten Rand, nehmen Sie stattdessen
Cells.Find(What:="*", SearchDirection:=xlPrevious).Row, weil .End an einer
Lücke anhalten kann.
Warum sollte ich Rows.Count statt 65536 verwenden?
65536 war die letzte Zeile des alten .xls-Formats. Moderne .xlsx-Blätter
haben 1.048.576 Zeilen, sodass ein Sprung nach oben, der bei 65.536 beginnt,
oberhalb aller Daten unterhalb dieses Punktes startet und eine zu kleine letzte
Zeile zurückgibt. Rows.Count spiegelt immer die tatsächliche Größe des aktuellen
Blatts wider.
Warum liefert UsedRange die falsche letzte Zeile?
UsedRange ist ein zwischengespeicherter Umgrenzungsrahmen jeder Zelle, die Excel
jemals angefasst hat, einschließlich reiner Formatierungszellen, und er schrumpft
beim Löschen von Daten erst, wenn die Datei gespeichert wird. Er beginnt außerdem
möglicherweise nicht bei Zeile 1, weshalb UsedRange.Rows.Count eine Anzahl
ist, keine Nummer der letzten Zeile. Nehmen Sie .End(xlUp) oder .Find für
eine präzise letzte Zeile.
Wie finde ich die letzte Spalte in VBA?
Spiegeln Sie das Letzte-Zeile-Idiom seitwärts:
Cells(1, Columns.Count).End(xlToLeft).Column. Es springt von der ganz rechten
Zelle der Kopfzeile zurück zur letzten Spalte mit Inhalt.
Wie finde ich die letzte Zeile, wenn die Spalte Leerstellen hat?
.End(xlUp) betrachtet nur eine Spalte, sodass eine Leerstelle in der letzten
Datenzeile dieser Spalte es zu früh anhalten lässt. Richten Sie es entweder auf
eine Spalte, die immer befüllt ist (eine ID), oder nutzen Sie
Cells.Find(What:="*", SearchDirection:=xlPrevious).Row, das die letzte befüllte
Zelle irgendwo auf dem Blatt findet, unabhängig von Lücken.
Getestet in
Getestet in: Excel 365 (Windows 11), VBA 7.1 — zuletzt geprüft am 30.07.2026.
Verwandte Anleitungen: VBA Offset · VBA UsedRange vs. CurrentRegion · VBA Range · VBA For-Schleife
