Live-Forum - Die aktuellen Beiträge
Anzeige
Archiv - Navigation
980to984
Aktuelles Verzeichnis
Verzeichnis Index
Übersicht Verzeichnisse
Vorheriger Thread
Rückwärts Blättern
Nächster Thread
Vorwärts blättern
Anzeige
HERBERS
Excel-Forum (Archiv)
20+ Jahre Excel-Kompetenz: Von Anwendern, für Anwender
980to984
980to984
Aktuelles Verzeichnis
Verzeichnis Index
Verzeichnis Index
Übersicht Verzeichnisse
Inhaltsverzeichnis

Code 'Zeilen löschen' hängt in Endlossschleife

Code 'Zeilen löschen' hängt in Endlossschleife
03.06.2008 21:19:42
Bernd
Liebe Freaks,
was mache ich hier falsch:
Ich habe eine Datei mit ca. 2.500 Zeilen, in der in der Spalte G die diversen Abteilungsbezeichnungen stehen.
Ich möchte alle Zeilen, die N I C H T "SF" lauten, gelöscht haben, und zwar beginnend ab der Zeile 5.
Aber der Code läuft und läuft und läuft. Ich habe das Gefühl einer Endlosschleife.

Sub sf_nicht_loeschen()
Dim i As Long
Application.ScreenUpdating = False
For i = Cells(Rows.Count, 7).End(xlUp).Row To 5 Step -1
If Cells(i, 7)  "sf" Then Rows(i).Delete
Next i
Application.ScreenUpdating = True
End Sub


Ergänzende Frage: wie muss ich denn den Code abändern, wenn neben "SF" auch "BC" erhalten, also nicht gelöscht werden soll (diese Frage ist aber sekundär)?
Vielen Dank im voraus.
bernd

13
Beiträge zum Forumthread
Beiträge zu diesem Forumthread

Betreff
Datum
Anwender
Anzeige
AW: Code 'Zeilen löschen' hängt in Endlossschleife
03.06.2008 21:44:00
Renee
Hi Bernd,
Versuch es mal damit:

Sub sf_nicht_loeschen()
Dim i As Long
GetMoreSpeed(True)
For i = Cells(Rows.Count, 7).End(xlUp).Row To 5 Step -1
If NOT(Cells(i, 7) = "sf" OR Cells(i,7) = "bc") Then Rows(i).Delete
Next i
GetMoreSpeed(False)
End Sub
Sub GetMoreSpeed(Optional ByVal Modus As Boolean = True)
Static intCalculation as Integer
If Modus = True Then intCalculation = Application.Calculation
With Application
.ScreenUpdating = Not Modus
.EnableEvents = Not Modus
.Calculation = IIf(Modus = True, xlManual, intCalculation)
.Cursor = IIf(Modus = True, 2, -4143)
End With
End Sub


GreetZ Renée

Anzeige
@renee :-))
03.06.2008 21:52:00
Bernd
Hi Renee,
Du Genie, Du hast mir geholfen - mal wieder! Läuft perfekt. Wenn ich den Code mit dem GetMoreSpeed nur verstehen würde...
Vielen herzlichen Dank!!!!!
Bernd

Der ist doch einfach zu verstehen...
03.06.2008 21:56:30
Renee
Bernd,
Bei Übergabe von TRUE
schaltet er das Screenupdating, das automatische Kalkulieren von Formeln (das war ziemlich sicher dein Bremser), und das Event-Handling (z.B. reagieren auf Worksheet_Change) ab und zeigt die Sanduhr an.
Bei FALSE macht er alles rückgängig... so simpel.
GreetZ Renée

Danke f.d Erläuterung
03.06.2008 21:58:45
Bernd
logisch, jetzt wo du es sagst. Die automatische Berchnunghatte ich nicht ausgeschalten, das stimmt.
Du bist halt ein Genie in Sachen Excel!
Grüße
Bernd

Anzeige
garantiert schneller
03.06.2008 22:40:59
Rudi
Hallo Renée,
erst Range aufbauen und den komplett löschen!

Sub sf_und_bc_nicht_loeschen()
Dim i As Long, rngDel As Range
For i = Cells(Rows.Count, 7).End(xlUp).Row To 5 Step -1
Select Case LCase(Cells(i, 7))
Case "sf", "bc"
Case Else
If rngDel Is Nothing Then
Set rngDel = Cells(i, 7)
Else
Set rngDel = Union(rngDel, Cells(i, 7))
End If
End Select
Next i
rngDel.EntireRow.Delete
End Sub


Gruß
Rudi

AW: noch schneller ist
03.06.2008 22:54:32
Daniel
wie schon beschrieben:
- mit formeln zu löschende Daten kennzeichnen
- Daten sortieren, so daß die zu löschenden Daten einen geschlossenen Block bilden
- diesen löschen
Gruß, Daniel

Anzeige
und noch schneller ist ...
04.06.2008 00:10:00
Rudi
Hallo,
... den kompletten Bereich in ein Array zu lesen, dieses zu durchsuchen, ein neues aufzubauen, den alten Bereich zu löschen und das neue Array dorthin zu schreiben.
Schema:

Sub tt()
Dim i As Long, j As Long, n As Long, tmp, tmp2(), t
tmp = Range("A5").CurrentRegion
ReDim tmp2(1 To UBound(tmp, 2), 1 To UBound(tmp))
t = Timer
For i = 1 To UBound(tmp)
Select Case tmp(i, 7)
Case "sf", "bc"
n = n + 1
For j = 1 To UBound(tmp, 2)
tmp2(j, n) = tmp(i, j)
Next j
End Select
Next i
ReDim Preserve tmp2(1 To UBound(tmp, 2), 1 To n)
With Range("A5")
.CurrentRegion.ClearContents
.Resize(n, UBound(tmp, 2)) = WorksheetFunction.Transpose(tmp2)
End With
Debug.Print Timer - t
End Sub


40000 Zeilen/ 15 Spalten in 0.8 Sekunden
Anzupassen auf die realen Verhältnisse.
Gruß
Rudi
Eine Kuh mach muh, viele Kühe machen Mühe.

Anzeige
AW: und noch schneller ist ...
04.06.2008 01:25:19
Daniel
Hi
also ganz so schnell ist mein Rechner nicht, bei folgender Versuchsanordnung:
- 40.000 Zeilen
- davon ist jede 2. zu löschen
- 15 Spalten
erreiche ich mit deinem Code 1,4 sec.
Wenn ich den Timer noch vor das Einlesen der Variablen setze (was meiner Ansicht nach korrekt wäre), sind es sogar nur 2,2 sec.
mit meinem Code dagegen komme ich auf 0,9 sec:

Sub ttt()
Dim t As Single
t = Timer
Columns(1).Insert
With Range(Cells(5, 1), Cells(Rows.Count, 2).End(xlUp).Offset(0, -1))
.FormulaLocal = "=wenn(oder(h5=""sf"";h5=""bc"");Zeile();wahr)"
.Formula = .Value
.EntireRow.Sort key1:=.Cells(1, 1), order1:=xlAscending, header:=xlNo
.SpecialCells(xlCellTypeConstants, 4).EntireRow.Delete
.EntireColumn.Delete
End With
Debug.Print Timer - t
End Sub


weiterer Vorteil meiner Variante, sollten die Daten Formeln enthalten, so bleiben diese erhalten.
dein Code ersetzt die Formeln durch Werte (oder kann man das auch noch berücksichtigen?)
Gruß. Daniel

Anzeige
AW: und noch schneller ist ...vielleicht?..
04.06.2008 07:52:34
Gerd
Hallo Daniel!
"Wenn ich den Timer noch vor das Einlesen der Variablen setze (was meiner Ansicht nach korrekt wäre),......"
Dann solltest dies bei deinem Code ebenfalls tun.
Außerdem, falls keine Umsortierung gewünscht ist,
benötigst eine zweite Hilfsspalte in die die ursprüngliche Reihenfolge vor 'm Sortieren eingetragen wird, musst anhand dieser nach dem Zeilenlöschen zurücksortieren u. die Einträge dieser zweiten Hilfsspalte zum Schluss wieder löschen.
Gruß Gerd

AW: hast du ...
04.06.2008 22:03:00
Daniel
Hi Gerd
...meinen Code mal getestet (im Einzelstepmodus vielleicht) ? wahrscheinlich nicht.
"Dann solltest dies bei deinem Code ebenfalls tun."
das setzen des Timers ist doch doch die erste Aktion in meinem Makro, weiter nach vorne kann ich es nicht stellen (die Variablendeklaration mit DIM sollte immer am Anfang stehen und ist was anderes als ne Variablenzuweisung - bitte nicht verwechslen)
Außderdem, falls es dir nicht aufgefallen sein sollte, mein Code verwendet keine Variablen, daher kann auch nichts zugewiesen werden (t ist ja nur drin, um die Zeit zu stoppen und kann im normalbetrieb entfallen.
das Rücksortieren ist ebenfalls nicht erforderlich, da die Formel für nicht zu löschende Zeilen die aktuelle Zeilen-Nr als Ergebnis hat, dh. beim Sortieren bleibt die originalreihenfolge erhalten (ausgenommen natürlich die zu löschenden Zeilen, aber für die ist es egal), dh. es muß nicht nochmal zurücksortiert werden!
und sollte es mal aus irgendeinem Grund doch erforderlich sein, dann macht das auch nicht viel aus, weil im Sortieren ist Excel auch bei grösseren Datenmengen fix wie nix.
Gruß, Daniel

Anzeige
AW: und noch schneller ist ...
04.06.2008 09:11:40
Rudi
Hallo,

(oder kann man das auch noch berücksichtigen?)


kann man.


tmp = Range("A5").CurrentRegion.Formula
'Code
.Resize(n, UBound(tmp, 2)).Formula = WorksheetFunction.Transpose(tmp2)


Gruß
Rudi

AW: nö, dein Code ist bloß langsam
03.06.2008 22:07:00
Daniel
Hallo
um zu prüfen, ob den dein Makro läuft, einfach mal auf ESC drücken, und dann auf DEBUGGEN gehen.
dann kannst du dir im Direktfenster die Variablen anzeigen lassen ("?i") und prüfen, ob das Makro läuft (zum Fortsetzen auf das blaue Icon klicken oder mit F8 im Einzelstepmodus arbeiten.
Zeilenlöschen in einer Schleife ist so ziemlich das inneffektivste, was man mit Excel machen kann, da gibt es wesentlich schnellere Methoden.
wesentlich schneller ist folgende Variante:
- Hilfsspalte einfügen
- Formel einfügen, die zu löschende Zeile mit einem Wahrheitswert kennzeichnet und in die anderen die aktuelle Zeiilen-Nr reinschreibt.
- über kopieren, Inhalte einfügen - Werte die Formeln durch werte ersetzen
- Daten nach Hilfsspalte sortieren
- über Bearbeiten - Gehte zu - Inhalte - Konstanten - Wahrheitswerte die zu löschenden Zellen selektieren und auf einen schlag löschen.
diese Mehtode ist je nach Datenmenge auch von Hand schneller als dein Makro.
wenn du es als Makro brauchst, kannst du ja mal den Recorder mitlaufen lassen.
den Code dazu hab ich schon mehrfach hier gepostet, beispielsweise hier: https://www.herber.de/forum/archiv/976to980/t976671.htm
(nach meinem Code suchen), der ist zwar für doppelte, aber was gelöscht wird, wird ja über die Formel gesteuert.
der erste Block mit sortieren kann für deine Zwecke entfallen.
als Formel zum Testen würde sich anbieten:
- Zellewerte müssen gleich sein: =wenn(oder(g5="SF";g5="BC");Zeile();wahr)
- Texte müssen in den Zellen enthalten sein: =wenn(zählenwenn(g5;"*SF*")+Zählenwenn(g5;"*BC*")>0;Zeile();wahr)
Gruß, Daniel

Anzeige
@Renee
03.06.2008 22:14:39
Bernd
Hi Renee,
jetzt machst du dir wirklich sehr viel Arbeit mit mir. Vielen Dank dafür. Ich werde mir deine Tipps ganz sicher ansehen.Aber heute abend muss ich leider noch die Dateien - Dank deines Codes - für morgen aufbereiten.
Liebe herzliche Grüße
Bernd

300 Forumthreads zu ähnlichen Themen

Anzeige
Anzeige
Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Anzeige