Anzeige
Archiv - Navigation
1856to1860
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

For-Schleife nicht performant

For-Schleife nicht performant
22.11.2021 17:09:22
Florian
HI Leute,
dieser Code-Ausschnitt läuft bei mir ziemlich unperformant. Wenn ich damit 10.000 Zeilen durchlaufen lasse, dauert es ca. 6-7 MInuten.

For lngAktuelleZeileZiel = 3 To lngZeilenBuchungen
strZuordnung = wksZieldatei.Cells(lngAktuelleZeileZiel, 29).Value
Set rngQuelle = wksQuelldatei.Columns(29).Find(What:=strZuordnung, LookIn:=xlValues)
If Not rngQuelle Is Nothing Then
lngAktuelleZeileQuelle = rngQuelle.Row
wksZieldatei.Range("N" & lngAktuelleZeileZiel & ":S" & lngAktuelleZeileZiel).Value = wksQuelldatei.Range("N" & lngAktuelleZeileQuelle & ":S" & lngAktuelleZeileQuelle).Value
End If
Next lngAktuelleZeileZiel
Kann man das irgendwie beschleunigen?
Wenn ihr den ganzen Code braucht, sagt Bescheid ;)
Danke euch!

12
Beiträge zum Forumthread
Beiträge zu diesem Forumthread

Betreff
Datum
Anwender
Anzeige
AW: For-Schleife nicht performant
22.11.2021 17:50:11
ChrisL
Hi Florian
Ich interpretiere den Code-Schnipsel im weitesten Sinne als SVERWEIS().
In etwa das hier:
https://www.herber.de/forum/archiv/1856to1860/1857404_Spalten_vergleichen_und_sortieren.html
Womöglich bist du schneller, wenn du per VBA die SVERWEIS-Formel einsetzt und dann in Werte umwandelst. Oder du verwendest ein Array/Datenfeld.
Speziell bei grossen Datenmengen kann ich dir aber Power-Query speziell empfehlen. Ich denke hier braucht es ein JOIN, also der Klassiker bei Abfragen. Siehe z.B.
https://excelhero.de/power-query/power-query-ganz-einfach-erklaert/
cu
Chris
Anzeige
AW: For-Schleife nicht performant
22.11.2021 17:59:19
Florian
Mit SVERWEIS kann ich mal probieren.
PowerQuery etc. kommt nicht in Betracht, da es sich um ein Tool handelt, das von vielen Personen mit verschiedenen Datensätzen genutzt wird. Ich denke das wird in der Anwendung zu kompliziert.
Was meinst Du mit Array/Datenfeld? Wie kann man das umsetzen?
AW: For-Schleife nicht performant
22.11.2021 18:40:36
ChrisL
Hi
Power-Query würde ich noch nicht gleich verwerfen. Theoretisch könnte man da mit Parametern arbeiten, welche der User selber ändern kann. Aber so genau kenne ich deine Ausgangslage nicht.
Für eine Array-Lösung solltest du eine Excel-Beispieldatei posten. Anonymisiert, gekürzte Anzahl Zeilen und Ist- sowie Soll-Zustand dargestellt. Danach bitte die Frage als offen kennzeichnen.
Etwas Array-mässig hinzuwursteln würde ich zwar hinbekommen, aber ich lasse gerne den Vortritt. Mein aktuelles Steckenpferd ist eher Power-Query ;)
Abstrakt könntest du dich bereits mit dem Thema auseinander setzen: https://de.wikipedia.org/wiki/Feld_(Datentyp)
Oder konkret z.B. mit "VBA Array erklärt" in der Suchmaschine deiner Wahl.
cu
Chris
Anzeige
AW: For-Schleife nicht performant
22.11.2021 18:39:57
{Boris}
Hi,
vielleicht reicht es auch schon, wenn Du zu Beginn des Codes die Bildschirmaktualisierung ab- sowie die Berechnung auf manuell schaltest und am Ende wieder einschaltest.
Also:

Sub Test()
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
'hier Dein weitere Code
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub
VG, Boris
AW: For-Schleife nicht performant
22.11.2021 18:59:19
Daniel
HI
wenn du öfters sowas pogrammieren willst, solltest du dich mit dem Dicktionary-Objekt beschäftigen.
Das Dictionary-Objekt ist im Prinzip ein eindimensionales Array, bei dem der Index nicht über Zahlen wie bei einem normalen Array gebildet wird, sondern ein beliebiger Freitext sein darf.
wenn man dann mal so ein Dictionary erstellt hat, wird dieser Freitext-Index dann auch sehr schnell gefunden, so dass man damit solche Zuordnungen über ID-Nummern (deine Spalte 29) sehr schnell durchführen kann.
Der Code dazu könnte so aussehen:

Dim z As Long
Dim x As Long
Dim s As Long
Dim arrQuelleWerte
Dim arrQuelleID
Dim arrZielWerte
Dim arrZielID
Dim dic As Object
Dim rngQuelleWerte As Range
Dim rngQuelleID As Range
Dim rngZielWerte As Range
Dim rngZielID As Range
Set rngQuelleID = wksQuelldatei.UsedRange.Columns(29)
Set rngQuelleWerte = wksQuelldatei.UsedRange.Range("N:S")
Set rngZielID = wksZieldatei.UsedRange.Columns(29)
Set rngZielWerte = wks.Zieldatei.UsedRange.Range("N:S")
arrQuelleWerte = rngQuelleWerte.Value
arrQuelleID = rngQuelleID.Value
arrZielWerte = rngZielWerte.Value
arrZielID = rngZielID.Value
Set dic = CreateObject("Scripting.Dictionary")
For z = 1 To UBound(arrQuelleID, 1)
dic(arrQuelleID(z, 1)) = z
Next
For z = 3 To UBound(arrZielID, 1)
If dic.exists(arrZielID(z, 1)) Then
x = dic(arrZielID(z, 1))
For s = 1 To UBound(arrQuelleWerte, 2)
arrZielWerte(z, s) = arrQuelleWerte(z, s)
Next
End If
Next
rngZielWerte.Value = arrZielWerte
Gruß Daniel
Anzeige
AW: For-Schleife nicht performant
23.11.2021 08:42:56
Florian
Ich habe es jetzt mal so versucht und in meinen Code eingebaut. Allerdings werden keine Werte gefunden und ich steige noch nicht ganz durch, wo ich suchen muss oder prüfen kann, woran es hängt.
Es sollen die Werte in den Spalten AC der Quelldatei und AC der Zieldatei verglichen werden. Dann sollen die Werte der Spalten N-S aus der Quelldatei in die Zieldatei in die entsprechende Zeile übernommen werden.

Sub DatenuebernahmeQuelldatei(strTabelleJahr As String)
Dim ialngIndex As Long
Dim wksBuchungenPruefen As Worksheet, wksQuelldatei As Worksheet
Dim strZuordnung As String
Dim lngZeilenQuelldatei As Long
Dim avntValuesBuchungenPruefen As Variant, avntValuesQuelldaten As Variant
Dim objDictionary As Object
Dim Dateiname
Dateiname = Application.GetOpenFilename(filefilter:="xlsm-Dateien (*.xlsm), *.*)", Title:="Quelldatei auswählen")
If Dateiname = "Falsch" Then
MsgBox "Keine Datei ausgewählt!"
Else
If Dateiname  False Then
Application.ScreenUpdating = False
Workbooks.Open (Dateiname)
Set wksQuelldatei = ActiveWorkbook.Sheets(strTabelleJahr)
'Autofilter in Quelldaten löschen
If wksQuelldatei.FilterMode Then
wksQuelldatei.ShowAllData
End If
'Zuordnung Datenübernahme in Quelldatei schreiben
wksQuelldatei.Unprotect Password:=p_strPasswort
lngZeilenQuelldatei = wksQuelldatei.Cells(Rows.Count, 1).End(xlUp).Row
wksQuelldatei.Range("AC3:AC" & lngZeilenQuelldatei).Formula = "=A3&B3&C3&D3&E3&F3&G3&I3"
wksQuelldatei.Protect userinterfaceonly:=True, AllowFiltering:=True, Password:=p_strPasswort
End If
Application.ScreenUpdating = False
'Tabellenblatt Buchungen prüfen setzen
Set wksBuchungenPruefen = ThisWorkbook.Worksheets(strTabelleJahr)
'Autofilter in Buchungen prüfen löschen
If wksBuchungenPruefen.FilterMode Then
wksBuchungenPruefen.ShowAllData
End If
'Autofilter in Quelldaten löschen
If wksQuelldatei.FilterMode Then
wksQuelldatei.ShowAllData
End If
With wksBuchungenPruefen
avntValuesBuchungenPruefen = .Range(.Cells(3, 1), .Cells(.Cells(Rows.Count, 1).End(xlUp).Row, 9)).Value
End With
With wksQuelldatei
avntValuesQuelldaten = .Range(.Cells(3, 14), .Cells(Rows.Count, 29).End(xlUp)).Value
End With
Set objDictionary = CreateObject(Class:="Scripting.Dictionary")
For ialngIndex = LBound(avntValuesQuelldaten) To UBound(avntValuesQuelldaten)
objDictionary.Item(Key:=avntValuesQuelldaten(ialngIndex, 16)) = avntValuesQuelldaten(ialngIndex, 1)
Next
With wksBuchungenPruefen
For ialngIndex = LBound(avntValuesBuchungenPruefen) To UBound(avntValuesBuchungenPruefen)
strZuordnung = avntValuesBuchungenPruefen(ialngIndex, 1) & avntValuesBuchungenPruefen(ialngIndex, 2) & _
avntValuesBuchungenPruefen(ialngIndex, 3) & avntValuesBuchungenPruefen(ialngIndex, 4) & _
avntValuesBuchungenPruefen(ialngIndex, 5) & avntValuesBuchungenPruefen(ialngIndex, 6) & _
avntValuesBuchungenPruefen(ialngIndex, 7) & avntValuesBuchungenPruefen(ialngIndex, 9)
If objDictionary.Exists(strZuordnung) Then .Cells(ialngIndex + 2, 14).Value = objDictionary.Item(Key:=strZuordnung)
Next
End With
wksQuelldatei.Parent.Close False
Application.ScreenUpdating = True
Set objDictionary = Nothing
Set wksBuchungenPruefen = Nothing
Set wksQuelldatei = Nothing
End If
End Sub

Anzeige
AW: For-Schleife nicht performant
23.11.2021 11:56:20
Daniel
Das sieht irgendwie anders aus, als das was ich dir gezeigt habe.
Deswegen kann ich dazu nicht viel sagen.
Erklärt mal, was du da machst und warum du das machts.
Das einer Datei mit den beiden Tabellenblättern könnte auch nicht schaden, es können ja Dummydaten mit ein paar Zeilen sein, aber man muss sehen, wie die Daten vorliegen.
Gruß Daniel
AW: For-Schleife nicht performant
23.11.2021 13:00:40
Florian
Ja ich hatte es selbst mal versucht aufzubauen.
Hier mal eine Beispieldatei mit Code. Unterschied in meiner finalen Version wäre nur, dass ich dann die Quelldatei auswähle und Quelle und Ziel nicht in der gleichen Arbeitsmappe sind.
https://www.herber.de/bbs/user/149329.xlsm
Anzeige
AW: For-Schleife nicht performant
23.11.2021 17:29:05
Daniel
naja, mach mal nicht irgendwas, sondern das was ich dir gezeigt habe.
Gruß Daniel
AW: For-Schleife nicht performant
24.11.2021 08:57:14
Florian
Hab es gerade getestet. Es läuft durch und ich auch echt schnell.
Allerdings wird nicht anhand der Spalte AC geprüft, welche Zeilen von Quelle und Ziel zusammengehören, sondern einfach alles in gleicher Reihenfolge rüber kopiert.
Das ist mein finaler Code:

Sub DatenuebernahmeJahre(strTabelleJahr As String)
Dim Dateiname
Dim wksQuelldatei, wksZieldatei As Worksheet
Dim lngQuelleIndex, lngZielIndex, s As Long
Dim arrQuelleWerte, arrQuelleID
Dim arrZielWerte, arrZielID
Dim dic As Object
Dim rngQuelleWerte, rngQuelleID As Range
Dim rngZielWerte, rngZielID As Range
Dateiname = Application.GetOpenFilename(filefilter:="xlsm-Dateien (*.xlsm), *.*)", Title:="Quelldatei auswählen")
If Dateiname = "Falsch" Then
MsgBox "Keine Datei ausgewählt!"
Else
If Dateiname  False Then
Workbooks.Open (Dateiname)
Set wksQuelldatei = ActiveWorkbook.Sheets(strTabelleJahr)
Set wksZieldatei = ThisWorkbook.Sheets(strTabelleJahr)
'Autofilter in Quelldaten löschen
If wksQuelldatei.FilterMode Then
wksQuelldatei.ShowAllData
End If
Set rngQuelleID = wksQuelldatei.UsedRange.Columns(29)
Set rngQuelleWerte = wksQuelldatei.UsedRange.Range("N:S")
Set rngZielID = wksZieldatei.UsedRange.Columns(29)
Set rngZielWerte = wksZieldatei.UsedRange.Range("N:S")
arrQuelleWerte = rngQuelleWerte.Value
arrQuelleID = rngQuelleID.Value
arrZielWerte = rngZielWerte.Value
arrZielID = rngZielID.Value
Set dic = CreateObject("Scripting.Dictionary")
For lngQuelleIndex = 1 To UBound(arrQuelleID, 1)
dic(arrQuelleID(lngQuelleIndex, 1)) = lngQuelleIndex
Next
For lngQuelleIndex = 3 To UBound(arrZielID, 1)
If dic.exists(arrZielID(lngQuelleIndex, 1)) Then
lngZielIndex = dic(arrZielID(lngQuelleIndex, 1))
For s = 1 To UBound(arrQuelleWerte, 2)
arrZielWerte(lngQuelleIndex, s) = arrQuelleWerte(lngQuelleIndex, s)
Next
End If
Next
'Autofilter in Buchungen prüfen löschen
If wksZieldatei.FilterMode Then
wksZieldatei.ShowAllData
End If
rngZielWerte.Value = arrZielWerte
wksQuelldatei.Parent.Close False
End If
End If
End Sub

Anzeige
AW: For-Schleife nicht performant
24.11.2021 10:09:03
Daniel
Hi
ok da sind noch ein paar Indizes durcheinander geraten (ist mir auch passiert, ist halt so wenn man nix zum testen hat)
ändere mal die die beiden Schleifen so ab:

For lngQuelleIndex = 3 To UBound(arrQuelleID, 1)
If arrQuelleID(lngQuelleIndex, 1)  "" Then dic(arrQuelleID(lngQuelleIndex, 1)) = lngQuelleIndex
Next
For lngZielIndex = 3 To UBound(arrZielID, 1)
If dic.exists(arrZielID(lngZielIndex, 1)) Then
lngQuelleIndex = dic(arrZielID(lngZielIndex, 1))
For s = 1 To UBound(arrQuelleWerte, 2)
arrZielWerte(lngZielIndex, s) = arrQuelleWerte(lngQuelleIndex, s)
Next
End If
Next
noch zwei generelle Anmerkungen:
1. es gibt in VBA keine Gruppendeklarationen. Du musst jeder Variable ihren Typ einzeln zuweisen, wird die Variable nur aufgelistet, dann ist der Typ "Variant". In

Dim wksQuelldatei, wksZieldatei As Worksheet
wird nur wksZieldatei als Worksheet dimensionert und wksQuellDatei als Variant.
richtig wäre hier:

Dim wksQuelldatei As Worksheet, wksZieldatei As Worksheet
2. vermeide Formatierungen für ganze Spalten, vor allem wenn nicht wirklich ALLE Zeilen dieser Spalte die selbe Formatierung haben.
Excel reserviert Speicher normalerweise nicht für alle Zellen des Tabellenblatts, sondern nur für den Bereich, der tatsächlich genutzt wird.
Dabei zählt aber nicht nur Inhalt, sondern auch Formatierung (die ja auch irgendwo abgelegt werden muss).
Wenn du jetzt also die ganze Spalte formatierst, dann kann Excel auf die Idee kommen, dass du auch alle Zellen bis zur letzten Zeile benutzt und reserviert dann für alle Zellen Speicherplatz, und weil das ziemlich viele sind, verschlechtert das die Performance der Datei und viele Sachen dauern länger.
das fällt nicht sofort auf, denn wenn alle Zellen in der Spalte gleich sind, kann sich Excel auch die Formatierung für die Spalte merken.
sobald aber einige Zellen abweichen, muss es sich dann die Formatierung pro Zelle merken und dann hast du das Problem.
Also lieber Formatierungen über ganze Spalten oder Zeilen vermeiden.
Du erkennst das ganze auch an der Scrollbar. Wenn du diese nach ganz unten fährst, sollte immer noch die letzte Zeile der Tabelle sichtbar sein. Befindest du dich dann aber in der allerletzten Zeile (1,04 Mio), dann hast du das Problem.
Gruß Daniel
Anzeige
AW: For-Schleife nicht performant
28.11.2021 11:00:26
Florian
Danke für Deine mega ausführliche Antwort.
Ich teste das mal :)

Links zu Excel-Dialogen

Beliebteste Forumthreads (12 Monate)

Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Anzeige