Wenn ich den zuletzt verwendeten Zellenwert finden möchte, verwende ich:
Dim LastRow As Long
LastRow = Range("E4:E48").End(xlDown).Row
Debug.Print LastRow
Ich erhalte die falsche Ausgabe, wenn ich ein einzelnes Element in eine Zelle einfüge. Wenn ich jedoch mehr als einen Wert in die Zelle eingebe, ist die Ausgabe korrekt. Was ist der Grund dafür?
excel
vba
excel-formula
James
quelle
quelle
Antworten:
HINWEIS : Ich beabsichtige, dies zu einem "One-Stop-Post" zu machen
Correct
, auf dem Sie die letzte Zeile finden können. Dies umfasst auch die Best Practices, die beim Auffinden der letzten Zeile zu befolgen sind. Und daher werde ich es weiter aktualisieren, wenn ich auf ein neues Szenario / eine neue Information stoße.Unzuverlässige Wege, um die letzte Zeile zu finden
Einige der gebräuchlichsten Methoden zum Auffinden der letzten Zeile, die sehr unzuverlässig sind und daher niemals verwendet werden sollten.
UsedRange
sollte NIEMALS verwendet werden, um die letzte Zelle mit Daten zu finden. Es ist sehr unzuverlässig. Versuchen Sie dieses Experiment.Geben Sie etwas in die Zelle ein
A5
. Wenn Sie nun die letzte Zeile mit einer der unten angegebenen Methoden berechnen, erhalten Sie 5. Färben Sie nun die ZelleA10
rot. Wenn Sie jetzt einen der folgenden Codes verwenden, erhalten Sie immer noch 5. Wenn Sie verwenden,Usedrange.Rows.Count
was erhalten Sie? Es wird nicht 5 sein.Hier ist ein Szenario, um zu zeigen, wie es
UsedRange
funktioniert.xlDown
ist ebenso unzuverlässig.Betrachten Sie diesen Code
Was würde passieren, wenn es nur eine Zelle (
A1
) gäbe, die Daten enthält? Am Ende erreichen Sie die letzte Zeile im Arbeitsblatt! Es ist so, als würde man eine Zelle auswählenA1
und dann die EndTaste drücken und dann die Down ArrowTaste drücken . Dies führt auch zu unzuverlässigen Ergebnissen, wenn sich leere Zellen in einem Bereich befinden.CountA
ist auch unzuverlässig, da es zu falschen Ergebnissen führt, wenn dazwischen leere Zellen liegen.Und daher sollte man die Verwendung von vermeiden
UsedRange
,xlDown
undCountA
die letzte Zelle zu finden.Finde die letzte Zeile in einer Spalte
Verwenden Sie diese Option, um die letzte Zeile in Spalte E zu finden
Wenn Sie bemerken, dass wir eine
.
vorher habenRows.Count
. Wir haben das oft ignoriert. Siehe DIESE Frage zu dem möglichen Fehler, den Sie möglicherweise erhalten. Ich rate immer.
vorRows.Count
undColumns.Count
. Diese Frage ist ein klassisches Szenario, in dem der Code aufgrund derRows.Count
Rückgabe65536
für Excel 2003 und früher sowie1048576
für Excel 2007 und höher fehlschlägt . EbensoColumns.Count
gibt256
und16384
, respectively.Die obige Tatsache, dass Excel 2007+
1048576
Zeilen enthält, unterstreicht auch die Tatsache, dass wir immer die Variable deklarieren sollten, die den Zeilenwert enthält, daLong
stattdessenInteger
eineOverflow
Fehlermeldung angezeigt wird .Beachten Sie, dass bei diesem Ansatz alle ausgeblendeten Zeilen übersprungen werden. Im Rückblick auf meinem Screenshot oben für Spalte A , wenn Zeile 8 versteckt waren, würde dieser Ansatz zurückkehrt
5
statt8
.Finde die letzte Reihe in einem Blatt
Effective
Verwenden Sie diese Option, um die letzte Zeile im Blatt zu finden . Beachten Sie die Verwendung vonApplication.WorksheetFunction.CountA(.Cells)
. Dies ist erforderlich, denn wenn das Arbeitsblatt keine Zellen mit Daten enthält.Find
, erhalten Sie dieseRun Time Error 91: Object Variable or With block variable not set
Letzte Zeile in einer Tabelle suchen (ListObject)
Die gleichen Prinzipien gelten zum Beispiel, um die letzte Zeile in der dritten Spalte einer Tabelle zu erhalten:
quelle
Usedrange.Rows.Count
was erhalten Sie? Es wird nicht 5 sein. Usedrange ist sehr unzuverlässig, um die letzte Zeile zu finden.remembers
die letzte Einstellung. Selbst wenn Sie manuell eine machenFind
, merkt es sich die letzte Einstellung, die in der Tat ein Segen ist, wenn man diese "Tatsache" kenntUsedRange
( es ist höchst unzuverlässig , die letzte Zelle mit Daten zu finden ) irreführend ist.UsedRange
ist einfach nicht für diesen Zweck gedacht, obwohl es in einigen Fällen das richtige Ergebnis liefern kann. Ich denke, dass das vorgeschlagene Experiment die Verwirrung noch verstärkt. Das mitUsedRange
($ A $ 1: $ A $ 8) erzielte Ergebnis hängt nicht davon ab, ob zuerst Daten eingegeben und gelöscht werden. Die Abbildung rechts bleibt auch ohne Eingabe und Löschung der Daten unverändert. Bitte sehen Sie meine Antwort.Hinweis: Diese Antwort wurde durch diesen Kommentar motiviert . Der Zweck von
UsedRange
unterscheidet sich von dem, was in der obigen Antwort erwähnt wird.Um die zuletzt verwendete Zelle richtig zu finden, muss man zunächst entscheiden, was als verwendet gilt , und dann eine geeignete Methode auswählen . Ich stelle mir mindestens drei Bedeutungen vor:
Verwendet = nicht leer, dh mit Daten .
Used = "... in Verwendung, dh der Abschnitt, der Daten oder Formatierungen enthält ." Laut offizieller Dokumentation ist dies das Kriterium, das Excel zum Zeitpunkt des Speicherns verwendet. Siehe auch diese offizielle Dokumentation . Wenn man sich dessen nicht bewusst ist, kann das Kriterium zu unerwarteten Ergebnissen führen, aber es kann auch absichtlich ausgenutzt werden (seltener, sicher), z. B. um bestimmte Regionen hervorzuheben oder zu drucken, die möglicherweise keine Daten enthalten. Und natürlich ist es wünschenswert, dass der Bereich beim Speichern einer Arbeitsmappe als Kriterium verwendet wird, damit nicht ein Teil der Arbeit verloren geht.
Used = "... in Verwendung, dh der Abschnitt, der Daten oder Formatierungen enthält " oder bedingte Formatierungen. Entspricht 2., enthält jedoch auch Zellen, die das Ziel für eine bedingte Formatierungsregel sind.
Wie Sie die zuletzt verwendete Zelle finden, hängt davon ab, was Sie möchten (Ihr Kriterium) .
Für Kriterium 1 schlage ich vor, diese Antwort zu lesen . Beachten Sie, dass dies
UsedRange
als unzuverlässig bezeichnet wird. Ich denke, das ist irreführend (dh "unfair"UsedRange
), daUsedRange
es einfach nicht dazu gedacht ist, die letzte Zelle mit Daten zu melden. Daher sollte es in diesem Fall nicht verwendet werden, wie in dieser Antwort angegeben. Siehe auch diesen Kommentar .Für Kriterium 2
UsedRange
ist dies die zuverlässigste Option im Vergleich zu anderen Optionen, die ebenfalls für diese Verwendung entwickelt wurden. Es ist sogar unnötig, eine Arbeitsmappe zu speichern, um sicherzustellen, dass die letzte Zelle aktualisiert wird. Ctrl+ Endwird vor dem Speichern in eine falsche Zelle verschoben ("Die letzte Zelle wird erst zurückgesetzt, wenn Sie das Arbeitsblatt speichern", von http://msdn.microsoft.com/en-us/library/aa139976%28v=office.10% 29.aspx . Es ist eine alte Referenz, aber in dieser Hinsicht gültig).Für Kriterium 3 kenne ich keine eingebaute Methode . Kriterium 2 berücksichtigt keine bedingte Formatierung. Man kann formatierte Zellen haben, basierend auf Formeln, die nicht von
UsedRange
oder Ctrl+ erkannt werden End. In der Abbildung ist die letzte Zelle B3, da die Formatierung explizit darauf angewendet wurde. Zellen B6: D7 haben ein Format, das von einer bedingten Formatierungsregel abgeleitet ist, und dies wird selbst von nicht erkanntUsedRange
. Um dies zu berücksichtigen, wäre eine gewisse VBA-Programmierung erforderlich.Zu Ihrer spezifischen Frage : Was ist der Grund dafür?
Ihr Code verwendet die erste Zelle in Ihrem Bereich E4: E48 als Trampolin, mit dem Sie nach unten springen können
End(xlDown)
.Die "fehlerhafte" Ausgabe wird erhalten, wenn sich in Ihrem Bereich keine anderen als die erste möglicherweise nicht leere Zellen befinden. Dann springen Sie im Dunkeln , dh das Arbeitsblatt hinunter (Sie sollten den Unterschied zwischen leerer und leerer Zeichenfolge beachten !).
Beachten Sie, dass:
Wenn Ihr Bereich nicht zusammenhängende nicht leere Zellen enthält, führt dies auch zu einem falschen Ergebnis.
Wenn es nur eine nicht leere Zelle gibt, aber nicht die erste, gibt Ihnen Ihr Code immer noch das richtige Ergebnis.
quelle
Ich habe diese One-Stop-Funktion zum Bestimmen der letzten Zeile, Spalte und Zelle erstellt, sei es für Daten, formatierte (gruppierte / kommentierte / versteckte) Zellen oder bedingte Formatierung .
Die Ergebnisse sehen folgendermaßen aus:
Für detailliertere Ergebnisse können einige Zeilen im Code unkommentiert sein:
Es gibt eine Einschränkung: Wenn das Blatt Tabellen enthält, können die Ergebnisse unzuverlässig werden. Daher habe ich beschlossen, den Code in diesem Fall nicht auszuführen:
quelle
Ein wichtiger Hinweis, den Sie bei der Verwendung der Lösung beachten sollten ...
... soll sicherstellen, dass Ihre
LastRow
Variable vomLong
Typ ist:Andernfalls werden in bestimmten Situationen in .XLSX-Arbeitsmappen OVERFLOW-Fehler angezeigt
Dies ist meine gekapselte Funktion, die ich für verschiedene Code-Verwendungen einsetze.
quelle
Ich würde der Antwort von Siddarth Rout hinzufügen, dass der CountA-Aufruf übersprungen werden kann, indem Find ein Range-Objekt anstelle einer Zeilennummer zurückgibt und dann das zurückgegebene Range-Objekt testet, um festzustellen, ob es Nothing ist (leeres Arbeitsblatt). .
Außerdem würde meine Version einer LastRow-Prozedur eine Null für ein leeres Arbeitsblatt zurückgeben, dann kann ich wissen, dass es leer ist.
quelle
Ich frage mich, dass niemand dies erwähnt hat, aber der einfachste Weg, die zuletzt verwendete Zelle zu erhalten, ist:
Dies gibt im Wesentlichen dieselbe Zelle zurück, die Sie nach Auswahl von Zelle mit Ctrl+ erhalten .End
A1
Ein Wort der Vorsicht: Excel verfolgt die Zelle unten rechts, die jemals in einem Arbeitsblatt verwendet wurde. Wenn Sie beispielsweise etwas in B3 und etwas anderes in H8 eingeben und später den Inhalt von H8 löschen , gelangen Sie durch Drücken von Ctrl+ Endimmer noch zur Zelle H8 . Die obige Funktion hat das gleiche Verhalten.
quelle
Last Cell
in Excel bezieht sich manchmal auf eine leere Zelle (vonUsed Range
), die sich von unterscheidetLast Used Cell
;).Cells(1,1).Select()
er möglicherweise ungültig istActiveSheet.Cells(1,1).Select
. Auch in VBA wird die Verwendung nicht empfohlenSelect
;).Set
.Da es bei der ursprünglichen Frage um Probleme beim Auffinden der letzten Zelle geht, werde ich in dieser Antwort die verschiedenen Möglichkeiten auflisten, wie Sie unerwartete Ergebnisse erzielen können. Siehe meine Antwort auf "Wie finde ich die letzte Zeile, die Daten in der Excel-Tabelle enthält, mit einem Makro?" für meine Einstellung zur Lösung dieses Problems.
Ich werde zunächst die Antwort von sancho.s und den Kommentar von GlennFromIowa erweitern und noch mehr Details hinzufügen:
Andere Dinge, die Sie vielleicht berücksichtigen möchten:
Lassen Sie uns vor diesem Hintergrund sehen, wie die gängigen Methoden zum Abrufen der "letzten Zelle" zu unerwarteten Ergebnissen führen können:
.End(xlDown)
Code aus der Frage wird aus den in der Antwort von Siddharth Rout hier erläuterten Gründen am leichtesten brechen (z. B. mit einer einzelnen nicht leeren Zelle oder wenn leere Zellen dazwischen liegen ) (Suche nach "xlDown ist ebenso unzuverlässig" )Count
ing (CountA
oderCells*.Count
) basiert oder.CurrentRegion
auch bei Vorhandensein leerer Zellen oder Zeilen break bricht.End(xlUp)
bei der vom Ende einer Spalte aus rückwärts gesucht wird, sucht ebenso wie STRG + AUF nach Daten (Formeln, die einen leeren Wert erzeugen, werden als "Daten" betrachtet) in sichtbaren Zeilen (daher kann die Verwendung mit aktiviertem Autofilter zu falschen Ergebnissen führen ⚠️) ).Sie müssen darauf achten, die Standard-Fallstricke zu vermeiden (für Details verweise ich hier noch einmal auf die Antwort von Siddharth Rout , siehe Abschnitt "Letzte Zeile in einer Spalte suchen " ), z. B. das Hardcodieren der letzten Zeile (
Range("A65536").End(xlUp)
) anstatt sich darauf zu verlassensht.Rows.Count
..SpecialCells(xlLastCell)
entspricht STRG + ENDE und gibt die Zelle ganz unten und ganz rechts des "verwendeten Bereichs" zurück. Daher gelten alle Einschränkungen, die für die Verwendung des "verwendeten Bereichs" gelten, auch für diese Methode. Darüber hinaus wird der "verwendete Bereich" nur beim Speichern der Arbeitsmappe und beim Zugriff zurückgesetztworksheet.UsedRange
, sodassxlLastCell
möglicherweise veraltete Ergebnisse mit nicht gespeicherten Änderungen auftreten (z. B. nachdem einige Zeilen gelöscht wurden). Siehe die Antwort in der Nähe von dotNET .sht.UsedRange
(ausführlich beschrieben in der Antwort von sancho.s hier) berücksichtigt sowohl Daten als auch Formatierungen (wenn auch keine bedingte Formatierung) und setzt den "verwendeten Bereich" des Arbeitsblatts zurück , der möglicherweise Ihren Wünschen entspricht oder nicht.Beachten Sie, dass ein häufiger Fehler bei der Verwendung von
.UsedRange.Rows.Count
⚠️ ist, bei dem die Anzahl der Zeilen im verwendeten Bereich und nicht die letzte Zeilennummer zurückgegeben wird (sie unterscheiden sich, wenn die ersten Zeilen leer sind). Weitere Informationen finden Sie in der Antwort von newguy auf Wie finde ich ? letzte Zeile, die Daten in der Excel-Tabelle mit einem Makro enthält?.Find
Mit dieser Option können Sie die letzte Zeile mit beliebigen Daten (einschließlich Formeln) oder einem nicht leeren Wert in einer beliebigen Spalte finden . Sie können wählen, ob Sie an Formeln oder Werten interessiert sind. Der Haken dabei ist jedoch, dass die Standardeinstellungen im Excel-Dialogfeld "Suchen" zurückgesetzt werden, was für Ihre Benutzer sehr verwirrend sein kann. Es muss auch sorgfältig verwendet werden, siehe die Antwort von Siddharth Rout hier (Abschnitt "Letzte Zeile in einem Blatt finden" )Cells
in einer Schleife prüfen , sind im Allgemeinen langsamer als die Wiederverwendung einer Excel-Funktion (obwohl sie immer noch performant sein können). Sie können jedoch genau angeben, was Sie suchen möchten. In meiner Lösung basierend aufUsedRange
und VBA-Arrays finden Sie die letzte Zelle mit Daten in der angegebenen Spalte. Sie verarbeitet ausgeblendete Zeilen, Filter und Leerzeichen, ändert die Standardeinstellungen für Suchen nicht und ist recht leistungsfähig.Egal für welche Lösung Sie sich entscheiden, seien Sie vorsichtig
Long
anstattInteger
die Zeilennummern zu speichern (um zu vermeiden, dassOverflow
mehr als 65.000 Zeilen verwendet werden) undDim ws As Worksheet ... ws.Range(...)
anstelle vonRange(...)
).Value
(was a istVariant
) implizite Umwandlungen,.Value <> ""
da diese fehlschlagen, wenn die Zelle einen Fehlerwert enthält.quelle
Diese Frage versucht jedoch, die letzte Zeile mit VBA zu finden. Ich denke, es wäre gut, eine Array-Formel für die Arbeitsblattfunktion aufzunehmen, da diese häufig besucht wird:
Sie müssen die Formel ohne Klammern eingeben und dann Shift+ Ctrl+ drücken Enter, um sie zu einer Array-Formel zu machen.
Dies gibt Ihnen die Adresse der zuletzt verwendeten Zelle in der Spalte D.
quelle
Hier A65536ist die letzte Zelle in Spalte A, in der dieser Code in Excel 2003 getestet wurde.
quelle
Ich war auf der Suche nach einem Weg zu imitieren die CTRL+ Shift+ End, so dotNET Lösung groß ist, es sei denn mit meiner Excel 2010 Ich brauche ein hinzufügen ,
set
wenn ich einen Fehler vermeiden wollen:und wie Sie dies selbst überprüfen können:
quelle
Hier sind meine zwei Cent.
Meiner Meinung nach ist das Risiko, dass eine versteckte Zeile mit Daten ausgeschlossen wird, zu hoch, um
xlUp
als One-Stop-Antwort angesehen zu werden . Ich bin damit einverstanden, dass es einfach ist und die meiste Zeit funktioniert, aber es birgt das Risiko, die letzte Zeile ohne Vorwarnung zu unterschätzen. Dies könnte zu CATASTROPHIC- Ergebnissen an einem bestimmten Punkt für jemanden führen, der auf Stack Overlow gesprungen ist und nach einem "sicheren Weg" gesucht hat, um diesen Wert zu erfassen.Die
Find
Methode ist einwandfrei und ich würde sie als One-Stop-Antwort billigen . Der Nachteil des Änderns derFind
Einstellungen kann jedoch ärgerlich sein, insbesondere wenn dies Teil einer UDF ist.Die anderen Antworten sind in Ordnung, die Komplexität wird jedoch etwas übertrieben. Hier ist mein Versuch, ein Gleichgewicht zwischen Zuverlässigkeit, minimaler Komplexität und Nichtverwendung zu finden
Find
.Warum das gut ist:
Find
EinstellungenWarum das so schlecht ist:
Ich denke jedoch, dass eine One-Stop-Lösung, die den Nachteil hat,
find
Einstellungen zu verfälschen oder langsamer zu arbeiten, eine bessere Gesamtlösung ist. Ein Benutzer kann dann an seinen Einstellungen basteln, um zu versuchen, sie zu verbessern, und weiß, was mit seinem Code los ist. Die VerwendungxLUp
warnt nicht vor potenziellen Risiken und sie könnten so lange weitermachen, wer weiß, wie lange sie nicht wissen, dass ihr Code nicht richtig funktioniert.quelle
In den letzten 3+ Jahren sind dies die Funktionen, mit denen ich die letzte Zeile und die letzte Spalte pro definierter Spalte (für Zeile) und Zeile (für Spalte) finde:
Letzte Spalte:
Letzte Reihe:
Für den Fall des OP ist dies der Weg, um die letzte Zeile in der Spalte zu erhalten
E
:Debug.Print lastRow(columnToCheck:=Range("E4:E48").Column)
Letzte Zeile, leere Zeilen mit Daten zählen:
Hier können wir die bekannten Excel-Formeln verwenden , die uns die letzte Zeile eines Arbeitsblatts in Excel geben, ohne VBA einzubeziehen -
=IFERROR(LOOKUP(2,1/(NOT(ISBLANK(A:A))),ROW(A:A)),0)
Um dies in VBA zu speichern und nichts in Excel zu schreiben, wobei die Parameter für die letzteren Funktionen verwendet werden, könnte Folgendes in Betracht gezogen werden:
quelle
EVAL()
und die berühmte Excel-Formel verwenden. Obwohl die Leute vielleicht denken, dassEval()
das böse ist und dies eine weitere interessante Geschichte ist, über die man schreiben kann ...quelle