Live-Forum - Die aktuellen Beiträge
Anzeige
Archiv - Navigation
1736to1740
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
Inhaltsverzeichnis

Geschwindigkeit Excel

Geschwindigkeit Excel
27.01.2020 12:28:31
Georg
Liebe Mitglieder,
ich habe ein generelle Frage zur Geschwindigkeit, da ich nicht so fit bin in professionellem Schreiben von VBA Codes. Der Code macht was er soll, ist allerdings langsam - nicht weil ich 500.000 Datensätze bearbeite - sondern momentan rede ich von ca. 1500 Datensätzen.
Gibt es eine Möglichkeit das Ganze zu beschleunigen - eventuell auch einen grundsätzlichen Tipp, wie man sowas anders und somit schneller aufbauen kann.
Danke Georg
Sub DatenKopieren()
Dim Wks1 As Worksheet
Dim Wks2 As Worksheet
Dim Found As Range
Dim c As Range
Dim i As Long
Dim j As Long
Dim lgCount As Long
Set Wks1 = Sheets("Daten")
Set Wks2 = Sheets("t_Report")
Dim lastRowWks1 As Long
Dim lastRowWks2 As Long
'----------------------------------------------------------------------------------------------- _
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
'Daten kopieren von Daten zu t_Report
With Wks1 'also in den Daten
For Each c In .Range("B2:B" & .Cells(.Rows.Count, "B").End(xlUp).Row)
If Not IsEmpty(c) Then
Set Found = Wks2.Columns("B").Find(c, LookIn:=xlValues, LookAt:=xlWhole)
If Found Is Nothing Then
lastRowWks2 = Wks2.Cells(Rows.Count, "B").End(xlUp).Row
.Rows(c.Row).Copy Destination:=Wks2.Rows(lastRowWks2 + 1)
End If
End If
Next
End With
'----------------------------------------------------------------------------------------------- _
'Vorhandene  Datensätze in t_Report überschreiben, da Änderung in den "Daten"stattgefunden hat
' z. b. hier noch offene Tickets wurden zwischenzeitlich geschlossen
With Wks1
lastRowWks1 = Wks1.Cells(Rows.Count, "G").End(xlUp).Row
lastRowWks2 = Wks2.Cells(Rows.Count, "G").End(xlUp).Row
For i = 2 To lastRowWks1
For j = 7 To 15
If .Cells(i, 7).Value  Wks2.Cells(i, 7) Then
.Cells(i, j).Copy Destination:=Wks2.Cells(i, j)
End If
Next j
Next i
End With
'----------------------------------------------------------------------------------------------- _
Wks2.Activate
'Tabellengröße anpassen in t_Report
Dim lastRowNew As Long
lastRowNew = Wks2.Cells(Rows.Count, "B").End(xlUp).Row
Wks2.ListObjects("t_DatenGradient").Resize Range("$A$1:$O" & lastRowNew)
With Wks2
For lgCount = lastRowWks2 To 2 Step -1
If IsEmpty(Cells(lgCount, 2)) Then
Cells(lgCount, 2).Delete shift:=xlUp
End If
Next
End With
'----------------------------------------------------------------------------------------------- _
'Sortieren
ActiveWorkbook.Worksheets("t_Report").ListObjects("t_DatenGradient").sort. _
SortFields.Clear
ActiveWorkbook.Worksheets("t_Report").ListObjects("t_DatenGradient").sort. _
SortFields.Add Key:=Range( _
"t_DatenGradient[[#All],[Datum der Störungsmeldung]]"), SortOn:= _
xlSortOnValues, Order:=xlAscending, DataOption:=xlSortTextAsNumbers
With ActiveWorkbook.Worksheets("t_Report").ListObjects("t_DatenGradient").sort
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Application.CutCopyMode = False:
Application.ScreenUpdating = True
Application.EnableEvents = True
Application.Calculation = xlCalculationAutomatic
''Das Blatt Daten löschen
Application.DisplayAlerts = False
Wks1.Delete
Application.DisplayAlerts = True
ThisWorkbook.Worksheets("Arbeitsanleitung").Activate
End Sub

11
Beiträge zum Forumthread
Beiträge zu diesem Forumthread

Betreff
Datum
Anwender
Anzeige
Quantensprünge im Speed per Variantzuweisungen
27.01.2020 12:36:20
lupo1
Wenn Du beispielsweise die Zeile 19 löschen möchtest, geht das sehr schnell so:
...
a = [A20:K999]
[A19:K998] = a
...
a ist dabei eine Variant-Variable, die einen Tabellenbereich enthält (nur dessen Werte, nicht Formate oder so)
...
a = Range("A" & i &":K" & i + 999)
Range("A" & i - 1 &":K" & i + 998) = a
...
ist die dynamische Variante dazu.
AW: Quantensprünge im Speed per Variantzuweisungen
27.01.2020 12:43:48
Georg
Hallo , danke für den Tipp, ich habe mom. noch eine sehr vage Vorstellung was du meinst - ich weiß, es ist immer wenig Zeit - aber könntest du mir das Ganze noch etwas mehr konkretisieren. Wie gesagt, ich bin jetzt nicht der Überflieger in VBA. Gruß G
Anzeige
Eigentlich gibt's da nichts zu fragen ...
27.01.2020 14:00:07
lupo1
... teste mein Beispiel doch einfach. Packe die Tabelle A1:K400 voll mit Daten und lösche dann mit der dynamischen Variante die Zeilen 19, 33 und 71 (Beispiele).
Im Gegensatz zu Daniel funktioniert es mit Zuweisungen, ohne jegliche Befehle, die den Excelmenüs nachempfunden sind. Das ist auch die schnellste Variante.
Daniel bleibt hingegen bei Befehlen wie .Delete stehen. Außerdem geht Daniel wie immer nie auf die Antworten anderer ein.
AW: Quantensprünge im Speed per Variantzuweisungen
27.01.2020 17:21:20
Daniel
das Prinzip, das Lupo hier anwendet, ist eigentlich ganz einfach:
um eine Zeile zu löschen, kopiert er alle Werte von der Zeile unterhalb der zu löschenden Zeile bis einschließlich der ersten Leerzeile unterhalb der Tabelle und fügt sie dann in die zu löschende Zeile wieder ein.
das ist von der Bearbeitungszeit her etwas günstiger als das normale Löschen von Zeilen, weil einige Arbeitsschritte, die Excel beim Löschen von Zeilen ausführen muss, entfallen.
Diese Methode ist auch dann anzuraten, wenn man beispielsweise aufwendige Formatierungen mit Rahmenlinien hat, die nicht verändert werden sollen (bspw eine dicke Rahmenlinie alle 5 Zeilen oder so) oder wenn mit Bedingten Formatierungen gearbeitet wird (Excel neigt dann dazu, bei solchen Aktionen aus einer Bedingten Formatierung, die für einen größeren Zellbereich gilt, eine zweite Bedingte Formatierung zu erzeugen, wobei die erste dann für den oberen Teil vor der Löschung und die zweite dann für den unteren Teil gilt, so dass man dann irgendwann eine unübersichtliche Anzahl an Bedingten Formatierungen mit negativer Auswirkung auf die Performance der Datei hat (längere Rechenzeiten))
allerdings hat die Methode, so wie sie Lupo hier zeigt den großen Nachteil, dass sie nur die Werte kopiert und somit Formeln - so sie in der Tabelle vorhanden sind - überschreiben würde.
besser wäre daher die Copy-Paste-Variante, die bei großen Datenmengen auch schneller ist als die Zuweisung an die Variable.
wenn die Zeile i gelöscht werden soll:
Range(Cells(i + 1, 1), Cells(999, 10)).copy
Cells(i, 1).PasteSpecial xlpasteformulas
das ist schneller, braucht keine zusätzliche Variable und Formeln bleiben erhalten.
bei großen Datenmengen würde ich es trotzdem vorziehen, durch Sortieren (darin ist Excel sehr schnell) die zu löschenden Zeilen zu einem lückenlosen Block zusammenzuführen und dann alle in einem schritt zu löschen.
mein persönlicher Favorit fürs Löschen von Zeilen mit Bedingung ist jedoch, folgendes vorgehen:
1. markiere in einer Hilfsspalte per Formel alle zu löschenden Zeilen mit einer 0 und die die stehen bleiben mit der aktuellen Zeilennummer
2. schreibe in Überschriftenzeile der Hilfsspalte ebenfalls die 0
3. wende dann das Daten - Datentools - Duplikate entfernen an.
das ist auch ohne Sortierung mit größten Datenmengen und vielen zu löschenden Zeilen sehr schnell und außerdem flexibel, da man über die Formel auch komplexe Löschbedingungen darstellen kann.
Weitere Vorteile dieser Methode wären, dass man sie auch ohne Makro in Tabellen mit beliebiger Größe problemlos von Hand anwenden kann und dass sie beim Testen des Makros im Einzelstepmodus sehr angenehm sind, weil man sich nicht durch endlose Schleifen klicken muss und weil man vorab kontrollieren kann, welche Zeilen alle gelöscht werden und man dann noch während dem Test korrigierend eingreifen kann (falls die Formel nicht richtig arbeitet)
Gruß Daniel
Anzeige
Sind wir hier bei KlickiBunti?
27.01.2020 20:42:31
lupo1
bla bla
dass sie nur die Werte kopiert und somit Formeln - so sie in der Tabelle vorhanden sind - überschreiben würde.
besser wäre daher die Copy-Paste-Variante, die bei großen Datenmengen auch schneller ist als die Zuweisung an die Variable.
wenn man beispielsweise aufwendige Formatierungen mit Rahmenlinien hat, die nicht verändert werden sollen (bspw eine dicke Rahmenlinie alle 5 Zeilen oder so) oder wenn mit Bedingten Formatierungen gearbeitet wird

bla bla
Das hat alles in Daten nichts zu suchen!
AW: Sind wir hier bei KlickiBunti?
27.01.2020 23:02:51
Daniel
naja Lupo, ich schrieb ja nicht, dass man sowas in seinen Daten verwenden sollte, sondern ich habe nur beschrieben, in welchen Situationen man deine Löschmethode am sinnvollsten einsetzt.
du schriebst ja, dass deine Methode besonders schnell sei.
das habe ich mal überprüft und mit deiner Methode aus einem Datensatz mit 1500 Zeilen (so die Vorgabe) 500 Zeilen gelöscht (per Schleife jede dritte Zeile, reine Daten, keine Formatierungen oder Formeln)
deine Methode braucht dafür seblst unter Einsatz der GetMoreSpeed-Einstellungen 10-11 Sekunden.
die von mir beschriebene Methode mit dem per Formel markieren, sortieren und dann im Block löschen schafts in 0,01 Sekunden.
(nein du hast dich nicht verlesen "zehn Sekunden zu einer hundertstel Sekunde")
dich denke mal das muss man jetzt nicht weiter kommentieren, da kann jeder selbst daraus ableiten wie fundiert deine Kommentare sind.
Gruß Daniel
Anzeige
falls du das nicht glauben willst, hier
27.01.2020 23:26:39
Daniel
der Code mit dem ich getestet habe.
für den Test ein leeres Tabellenblatt aktivieren und das Makro TEST starten.
Ergebnisse stehen im Direktfenster.
Sub test()
Dim M
Dim t As Double
For Each M In Array("test1", "test2")
Call Szenario
Debug.Print M & ": ";
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
t = Timer
Application.Run M
Debug.Print Timer - t,
Application.ScreenUpdating = True
Application.EnableEvents = True
Application.Calculation = xlCalculationAutomatic
Next
Debug.Print
End Sub
Sub test1()
Dim a
Dim z As Long
For z = 1500 To 1 Step -3
a = Range("A" & z + 1 & ":Z1501").Value
Range("A" & z & ":Z1500").Value = a
Next
End Sub
Sub test2()
With ActiveSheet.Cells(1, 1).CurrentRegion
With .Columns(.Columns.Count + 1)
.FormulaR1C1 = "=If(mod(row(), 3)=0,true,"""")"
.Formula = .Value
.EntireRow.Sort key1:=.Cells(1, 1), order1:=xlDescending, Header:=xlNo
.SpecialCells(xlCellTypeConstants, 4).EntireRow.ClearContents
.ClearContents
End With
End With
End Sub
Sub Szenario()
Cells.Clear
Range("A1:Z1500").Value = "xxx"
End Sub
und bei 500 Zeilen zum löschen reden wir noch nicht wirklich über "Daten", das können dann schon mal ein paar mehr sein.
bei 100.000 Zeilen (also echten Daten) braucht man mit deiner Methode nicht mehr antreten, da lösche ich die Zeilen von Hand schneller als du mit deinem Makro.
Anzeige
reichlich konstruiert
28.01.2020 04:24:04
lupo1
a) meine Lösung ist im Code viel klarer und kürzer und ist als Blocklösung für "einmalig-jeweiliges" Satzlöschen zu sehen. Die Leistungsfähigkeit Deiner Lösung sei damit nicht bestritten, und sie ist auch das richtige Vorgehen in Excel bei gegebenen Vorgaben nicht perfekter Daten. Immerhin quälst Du meine Lösung ja auch vielhundertfach in eine Blockzuweisung, wo der einzige Schwachpunkt der Variantzuweisung liegt. Der Sinn einer Variantverwendung liegt aber darin, nach Zuweisung an das Variant vielfach innerhalb des Variants zu arbeiten und erst am Ende das manipulierte Variant an die Tabelle zurückzugeben.
Das zeigt (wieder mal), dass Du immer nur wörtlich Vorschläge anderer aufnimmst (die von denen einfach aus Unlust nicht zu Ende dargestellt wurden, weil sie sich nicht so wichtig nehmen) und dann beginnst, darauf rumzutrampeln. Vornehm ist es hingegen, die Gegner-Lösung auch zu verteidigen und deren Vorzüge hervorzuheben. Aber da kommst Du in Deinem Leben und mit Deiner fehlenden Empathie nicht mehr hin: "Ich mach mir die Welt so, wie sie mir gefällt, widdewiddewitt juchheirassa".
b) bei mehrfachem oder vielfachem regelmäßigem Löschen kann man das mit manuellen Sub-Zählern in Schleifen erledigen: http://xxcl.de/0052.htm ("Anwendungsbeispiel", ist sehr schnell in Excel 2000, müsste aber zugegeben für neueres Excel optimiert werden)
c) es bleibt dabei, dass man nur Werte in Daten derart manipulieren muss. Formeln, Rahmen und Formate haben da nichts verloren. Rahmen gehören in Berichte oder in Formulare, aber nicht in Daten.
Anzeige
natürlich konstruiert
28.01.2020 10:49:45
Daniel
schließlich braucht man für einen Geschwindigkeitstest eine definierte, für alle Tests gleiche Vorlage.
auch wenn sie "konstruiert" ist, sie entspricht ja genau deinen Vorgaben, nur Daten, keine Formeln keine Formate.

a) meine Lösung ist im Code viel klarer und kürzer und ist als Blocklösung für "einmalig-jeweiliges" Satzlöschen zu sehen.

das ist ein sehr eingeschränkter und meiner Erfahrung nach in der Praxis selten vorkommender Einsatzzweck.
bei der Bearbeitung von Daten müssen häufig viele Zeilen in in großen Datenmengen gelöscht werden.
das das du hier beschreibst, trifft ehr auf das Arbeiten in Formularen zu (aber das willst du ja genau nicht)
Die Leistungsfähigkeit Deiner Lösung sei damit nicht bestritten, und sie ist auch das richtige Vorgehen in Excel bei gegebenen Vorgaben nicht perfekter Daten.
das klang in deiner ersten Bewertung meiner Lösungsvorschläge aber noch ganz anders. Hast du deine Meinung gändert?
Immerhin quälst Du meine Lösung ja auch vielhundertfach in eine Blockzuweisung, wo der einzige Schwachpunkt der Variantzuweisung liegt. Der Sinn einer Variantverwendung liegt aber darin, nach Zuweisung an das Variant vielfach innerhalb des Variants zu arbeiten und erst am Ende das manipulierte Variant an die Tabelle zurückzugeben.
nunja, dein Hauptargument für deine Lösung lag in der Geschwindigkeit (du schriebst was von "Quantensprung") und um die Geschwindigkeit eine Methode zu testen, wendet man sie am besten in großer Häufigkeit an.
Außerdem ist beim Bearbeiten von Daten 500 noch keine große Anzahl.
Ich habe deine Methode ürigens so eingesetzt wie du sie vorgeschlagen hast. von eine Bearbeitung innerhalb des Arrays hast du nichts geschrieben.
Das zeigt (wieder mal), dass Du immer nur wörtlich Vorschläge anderer aufnimmst
was soll ich auch anderes tun? ich bin kein Hellseher
(die von denen einfach aus Unlust nicht zu Ende dargestellt wurden, weil sie sich nicht so wichtig nehmen)
sorry, ich kann nur das verwenden, was du schreibst, wenn du zu faul bist, deine Methode korrekt zu beschreiben, kann ich nichts dafür.
Vornehm ist es hingegen, die Gegner-Lösung auch zu verteidigen und deren Vorzüge hervorzuheben.
was ich explizit getan habe. die erste Hälfte meiner Antwort an Georg beschäftigt sich mit den Vorteilen deiner Lösung und den Voraussetzungen, unter denen man sie am sinnvollsten einsetzt.
Inklusive einer ausführlichen Begründug. War vielleicht etwas viel Text für dich zum Lesen, warhscheinlich hast du es deswegen übersehen.
hingegen kann ich in deiner Kommentierung meiner Lösungvorschläge keine "Verteidigung" oder das "Hervorheben der Vorzüge". Du trampelst nur auf meinen Vorschlägen herum und das auch noch Begründungen, die falsch sind.
Aber da kommst Du in Deinem Leben und mit Deiner fehlenden Empathie nicht mehr hin: "Ich mach mir die Welt so, wie sie mir gefällt, widdewiddewitt juchheirassa".
sachlich diskutieren ist nicht so dein Ding. Trifft das nicht eher auf dich zu?
b) bei mehrfachem oder vielfachem regelmäßigem Löschen kann man das mit manuellen Sub-Zählern in Schleifen erledigen: http://xxcl.de/0052.htm ("Anwendungsbeispiel", ist sehr schnell in Excel 2000, müsste aber zugegeben für neueres Excel optimiert werden)

mag sein, aber das hat nichts mit dem zu tun, was du vorgeschlagen hast.
und wenn man diese Methode für das Löschen von Zeilen anwendet, dann wird der Code ja deutlich länger und unübersichtlicher und verliert damit die von dir beschriebenen Vorteile.
c) es bleibt dabei, dass man nur Werte in Daten derart manipulieren muss. Formeln, Rahmen und Formate haben da nichts verloren. Rahmen gehören in Berichte oder in Formulare, aber nicht in Daten.
das mag sein, allerdings liegen die Vorteile deiner Methode im Bearbeiten von Berichten oder Formulare.
und auch wenn du ein Gegner davon bist, viele Trennen halt nicht Daten und Formular und das hat ja auch nicht nur Nachteile.
Anzeige
AW: Quantensprünge im Speed per Variantzuweisungen
27.01.2020 13:05:28
Daniel
Hi
prinzipell sollte man in VBA vermeiden, Zellen einzeln zu bearbeiten sondern wenn möglich, Bearbeitungsschritte immer als Block für mehrere Zellen gleichzeitig durchzuführen.
so dauert beispielsweise ein Rows(1).Delete genauso lang wie ein Rows("1:10000").Delete
hier ist es dann oft hilfreich bei großen Datenmengen, die Listen so zu sortieren, dass dies möglich ist.
ggf kann es auch hilfreich sein, die zu löschenden Zeilen per Formel in einer Hilfsspalte zu kennzeichnen, um dies tun zu können.
gleiches auch bei Kopieren und einfügen.
wenn möglich, lückenlos zusammenhängende Zellen immer als Block bearbeiten und niemals einzeln.
so ist hier beispeilsweise die Schleife über die Spalten Unsinn:
         For i = 2 To lastRowWks1
For j = 7 To 15
If .Cells(i, 7).Value  Wks2.Cells(i, 7) Then
.Cells(i, j).Copy Destination:=Wks2.Cells(i, j)
End If
Next j
Next i

das müsste reichen:
         For i = 2 To lastRowWks1
If .Cells(i, 7).Value  Wks2.Cells(i, 7) Then
.Cells(i, 7).Resize(1, 9).Copy Destination:=Wks2.Cells(i, 7)
End If
Next i
Gruß Daniel
Anzeige
AW: hallo Daniel, vielen Dank, hab ..
27.01.2020 13:13:26
Georg
..glaube ich das Prinzip verstanden. Gruß G

Beliebteste Forumthreads (12 Monate)

Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Anzeige