Anzeige
Anzeige
HERBERS
Excel-Forum (Archiv)
20+ Jahre Excel-Kompetenz: Von Anwendern, für Anwender
Inhaltsverzeichnis

Range.Clear und SpecialCells(xlCellTypeLastCell)

Forumthread: Range.Clear und SpecialCells(xlCellTypeLastCell)

Range.Clear und SpecialCells(xlCellTypeLastCell)
25.01.2019 10:48:46
Burkhard
Hallo miteinander,
ich "lösche" mit
OutputSheet.Range(iRow - 1 & ":" & iRow).Clear

die letzten beiden Zeilen in einem Worksheet - sagen wir mal, die Zeilen 66 und 67.
Ein unmittelbar danach ausgeführtes
OutputSheet.UsedRange.SpecialCells(xlCellTypeLastCell).Row

bringt mir aber die soeben ge"löschte" Zeile 67 als "LastCell" (die ist im OutputSheet zwar leer, sieht aber trotzdem nicht so aus wie die nachfolgenden). Macht das .Clear nun doch nicht alles leer, wie in der Doku zu lesen? Oder ist der UsedRange der Übeltäter?
Aus Performancegründen möchte ich definitiv kein Range.Delete oder Row.Delete (anstelle von Range.Clear) verwenden. Auch den Workaround mit Range.Find würde ich lieber vermeiden.
Vielen Dank schon mal für eure Antworten!
Anzeige

7
Beiträge zum Forumthread
Beiträge zu diesem Forumthread

Betreff
Datum
Anwender
Anzeige
AW: Range.Clear und SpecialCells(xlCellTypeLastCell)
25.01.2019 11:13:43
Piet
Hall Buckhard
die Antwort ist in deiner frage bereits enthalten! Du sprichst davon das du Clear statt Delete verwendest!
Bei Clear wird der Bereich nur gelöscht. Der UsedRange bleibt weiterhin bestehen!! Erst durch Delete verkleinerst du ihn!
Das erkennst du auch am Abspeichern der Datei. Wenn viele leere Zeilen drin waren und mit Delete gelöscht werden muss sich die Speichergrösse verkleinern. Achte bitte mal drauf.
mfg Piet
Anzeige
AW: Range.Clear und SpecialCells(xlCellTypeLastCell)
25.01.2019 11:45:39
Burkhard
Hallo Piet,
wenn ich dich recht verstehe, ist tatsächlich der UsedRange der Übeltäter. Was kann ich dann tun, damit nach .Clear der UsedRange angepasst wird? Ohne dadurch die Performance zu "killen"? Direkt komme ich da ja nicht ran, das ist (laut Doku) schreibgeschützt.
Oder kann ich bei der Abfrage der SpecialCells den UsedRange irgendwie umgehen (oder weglassen)?
mfg Burkhard
Anzeige
Performance ? Was für Performance ?
25.01.2019 12:16:13
EtoPHG
Hallo Burkhard,
Von was für einer Performance redest Du?
Piet hat klar gesagt: DELETE statt CLEAR und ich muss ganz klar zustimmen!
An UsedRange kannst und darfst du nicht rumschrauben!
Gruess Hansueli
AW: Performance bei 365
25.01.2019 12:57:08
Burkhard
Hallo Hansueli,
leider hat Office365 beim .delete ein gravierendes Performanceproblem (siehe meinen Beitrag https://www.herber.de/forum/messages/1669744.html vom 21.01.2019 13:50:28)- xl2007 braucht dazu größenordnungsmäßig eine Zehntelsekunde, xl2016 so um die sechs Sekunden! Solange dieses Problem nicht gelöst ist, kann ich .delete nicht einsetzen!
mfg Burkhard
Anzeige
letzte gefüllte Zelle ermitteln
25.01.2019 13:26:05
Rudi
Hallo,
jetzt schießen wir mal ein bisschen mit Kanonen auf Spatzen:
Sub test()
Dim x As Long, y As Long
y = LastUsedColumnInRange(ActiveSheet)
x = LastUsedRowInRange(ActiveSheet)
If x = 0 And y = 0 Then
MsgBox "Keine Zellen benutzt!"
Else
MsgBox Cells(x, y).Address
'Application.Goto Cells(x, y), True
End If
End Sub

Function LastUsedRowInRange( _
wks As Worksheet, _
Optional lngFirstRow&, _
Optional lngLastRow&, _
Optional lngFirstColumn&, _
Optional lngLastColumn&) _
As Long
'Letzte Zeile mit Inhalt in einem Bereich
'Parameter
'wks: das Blatt
'lngFirstRow&: die erste Zeile
'lngLastRow&: die letzte Zeile
'lngFirstColumn&: die erste Spalte, A=1, B=2 etc.
'lngLastColumn&; die letzte Spalte
Dim lngTmp&, blnFound As Boolean
'sicherstellen, dass die Parameter gültig sind
If lngFirstRow  Rows.Count Then lngFirstRow = 1
If lngLastRow  Rows.Count Then lngLastRow = Rows.Count
If lngFirstColumn  Columns.Count Then lngFirstColumn = 1
If lngLastColumn  Columns.Count Then lngLastColumn = Columns.Count
'drehen falls erster Wert > letzter Wert
If lngFirstRow > lngLastRow Then
lngTmp = lngLastRow
lngLastRow = lngFirstRow
lngFirstRow = lngTmp
End If
If lngFirstColumn > lngLastColumn Then
lngTmp = lngLastColumn
lngLastColumn = lngFirstColumn
lngFirstColumn = lngTmp
End If
'jetzt geht's los
With wks
If Application.CountA(.Range(.Cells(lngLastRow, lngFirstColumn), .Cells(lngLastRow,  _
lngLastColumn))) Then
LastUsedRowInRange = lngLastRow: Exit Function
End If
If Application.CountA(.Range(.Cells(lngFirstRow, lngFirstColumn), .Cells(lngLastRow,  _
lngLastColumn))) = 0 Then
LastUsedRowInRange = 0: Exit Function
End If
lngTmp = (lngFirstRow + lngLastRow) / 2
If lngLastRow > lngFirstRow + 1 Then
If Application.CountA(.Range(.Cells(lngTmp, lngFirstColumn), .Cells(lngLastRow,  _
lngLastColumn))) Then
lngFirstRow = lngTmp
blnFound = True
End If
If Not blnFound And _
Application.CountA(.Range(.Cells(lngFirstRow, lngFirstColumn), .Cells(lngTmp,  _
lngLastColumn))) Then
lngLastRow = lngTmp
End If
LastUsedRowInRange wks, lngFirstRow, lngLastRow, lngFirstColumn, lngLastColumn
End If
End With
LastUsedRowInRange = lngFirstRow
End Function

Function LastUsedColumnInRange( _
wks As Worksheet, _
Optional lngFirstRow&, _
Optional lngLastRow&, _
Optional lngFirstColumn&, _
Optional lngLastColumn&) _
As Long
'Letzte Spalte mit Inhalt in einem Bereich
'Parameter
'wks: das Blatt
'lngFirstRow&: die erste Zeile
'lngLastRow&: die letzte Zeile
'lngFirstColumn&: die erste Spalte, A=1, B=2 etc.
'lngLastColumn&; die letzte Spalte
Dim lngTmp&, blnFound As Boolean
'sicherstellen, dass die Parameter gültig sind
If lngFirstRow  Rows.Count Then lngFirstRow = 1
If lngLastRow  Rows.Count Then lngLastRow = Rows.Count
If lngFirstColumn  Columns.Count Then lngFirstColumn = 1
If lngLastColumn  Columns.Count Then lngLastColumn = Columns.Count
'drehen falls erster Wert > letzter Wert
If lngFirstRow > lngLastRow Then
lngTmp = lngLastRow
lngLastRow = lngFirstRow
lngFirstRow = lngTmp
End If
If lngFirstColumn > lngLastColumn Then
lngTmp = lngLastColumn
lngLastColumn = lngFirstColumn
lngFirstColumn = lngTmp
End If
'jetzt geht's los
With wks
If Application.CountA(.Range(.Cells(lngFirstRow, lngLastColumn), .Cells(lngLastRow,  _
lngLastColumn))) Then
LastUsedColumnInRange = lngLastColumn: Exit Function
End If
If Application.CountA(.Range(.Cells(lngFirstRow, lngFirstColumn), .Cells(lngLastRow,  _
lngLastColumn))) = 0 Then
LastUsedColumnInRange = 0: Exit Function
End If
lngTmp = (lngFirstColumn + lngLastColumn) / 2
If lngLastColumn > lngFirstColumn + 1 Then
If Application.CountA(.Range(.Cells(lngFirstRow, lngTmp), .Cells(lngLastRow,  _
lngLastColumn))) Then
lngFirstColumn = lngTmp
blnFound = True
End If
If Not blnFound And _
Application.CountA(.Range(.Cells(lngFirstRow, lngFirstColumn), .Cells(lngLastRow,  _
lngTmp))) Then
lngLastColumn = lngTmp
End If
LastUsedColumnInRange wks, lngFirstRow, lngLastRow, lngFirstColumn, lngLastColumn
End If
End With
LastUsedColumnInRange = lngFirstColumn
End Function

Gruß
Rudi
Anzeige
AW: letzte gefüllte Zelle ermitteln
25.01.2019 17:04:52
Piet
Hallo
ich kenne mich mit 365 überhaupt nicht aus, kann da nicht mitreden was mit Delete so schwierig ist?
Wenn es nur darum geht in allen Spalten ide LastZell zu suchen kann man es auch mit For Next machen.
Vielleicht hilft ja das kleine Demo Programm dein Problem zu lösen. Das Makro von Rudi ist beeindruckend, aber sehr lang!
mfg Piet
Sub LastZell_ermitteln()
Dim j As Integer, s As Integer
Dim c As Long, LastZell As Long
'durchsuche alle Spalten nach LastZell
For j = 1 To ActiveSheet.UsedRange.Columns.Count
c = Cells(Rows.Count, j).End(xlUp).Row
If c > LastZell Then LastZell = c: s = j
Next j
MsgBox LastZell & "  in Spalte:  " & s
End Sub

Anzeige
;
Anzeige

Infobox / Tutorial

Range.Clear und SpecialCells(xlCellTypeLastCell) in Excel VBA


Schritt-für-Schritt-Anleitung

  1. Zellen leeren mit .Clear: Verwende die Methode .Clear, um den Inhalt von Zellen zu löschen, ohne den UsedRange zu beeinflussen:

    OutputSheet.Range(iRow - 1 & ":" & iRow).Clear
  2. Überprüfen der letzten Zelle: Um die letzte benutzte Zelle zu ermitteln, kannst du UsedRange.SpecialCells(xlCellTypeLastCell).Row verwenden:

    LastCellRow = OutputSheet.UsedRange.SpecialCells(xlCellTypeLastCell).Row
  3. Verstehe den UsedRange: Beachte, dass .Clear den UsedRange nicht anpasst. Um sicherzustellen, dass der UsedRange aktualisiert wird, musst du .Delete verwenden, was jedoch längere Ladezeiten verursachen kann.

  4. Alternative zu .Delete: Du kannst versuchen, leere Zellen zu finden und diese dann gezielt zu leeren, anstatt den gesamten Bereich zu löschen.


Häufige Fehler und Lösungen

  • Problem: Nach .Clear wird die letzte Zelle immer noch als besetzt angezeigt.

    • Lösung: Verwende .Delete, um die Zeilen vollständig zu entfernen. Dies ist die einzige Methode, die den UsedRange tatsächlich anpasst.
  • Problem: Performance-Probleme bei Office 365.

    • Lösung: Es kann hilfreich sein, den Code zu optimieren oder alternative Methoden zu verwenden, um die Performance zu verbessern, z.B. das gezielte Suchen nach leeren Zellen.

Alternative Methoden

  • Verwenden von SpecialCells: Mit Range.SpecialCells(xlCellTypeBlanks) kannst du gezielt leere Zellen finden und diese leeren:

    On Error Resume Next
    OutputSheet.Cells.SpecialCells(xlCellTypeBlanks).Clear
    On Error GoTo 0
  • Makros zur Bestimmung der letzten benutzten Zelle: Implementiere ein Makro, das die letzte benutzte Zelle aufspürt und den UsedRange anpasst, ohne die Performance zu beeinträchtigen.


Praktische Beispiele

Hier ist ein Beispiel, wie du die letzte benutzte Zelle dynamisch ermitteln kannst:

Sub GetLastUsedCell()
   Dim lastRow As Long
   lastRow = OutputSheet.Cells.SpecialCells(xlCellTypeLastCell).Row
   MsgBox "Die letzte benutzte Zeile ist: " & lastRow
End Sub

Ein weiteres Beispiel zeigt die Verwendung von .Clear:

Sub ClearRows()
   OutputSheet.Range("66:67").Clear
   MsgBox "Zeilen 66 und 67 wurden geleert."
End Sub

Tipps für Profis

  • Optimierung der Performance: Wenn du mit großen Datenmengen arbeitest, kann es sinnvoll sein, die Bildschirmaktualisierung vor und nach dem Ausführen von VBA-Code auszuschalten:

    Application.ScreenUpdating = False
    ' Dein Code hier
    Application.ScreenUpdating = True
  • Verwende .CountA: Um die Anzahl nicht leerer Zellen in einem Bereich zu zählen, kann Application.CountA nützlich sein, um zu überprüfen, ob Zellen tatsächlich verwendet werden.


FAQ: Häufige Fragen

1. Was passiert, wenn ich .Clear verwende? Mit .Clear wird der Inhalt der Zellen gelöscht, aber der UsedRange bleibt unverändert.

2. Wie kann ich den UsedRange nach dem Löschen anpassen? Um den UsedRange anzupassen, musst du .Delete verwenden, was jedoch zu Performanceproblemen führen kann, insbesondere in Office 365.

3. Gibt es eine Möglichkeit, die letzte benutzte Zelle effizient zu ermitteln? Ja, du kannst die Funktionen LastUsedRowInRange und LastUsedColumnInRange verwenden, um die letzte benutzte Zelle in einem bestimmten Bereich zu finden.

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Anzeige