Live-Forum - Die aktuellen Beiträge
Anzeige
Archiv - Navigation
988to992
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
988to992
988to992
Aktuelles Verzeichnis
Verzeichnis Index
Verzeichnis Index
Übersicht Verzeichnisse
Inhaltsverzeichnis

Makrooptimierung

Makrooptimierung
30.06.2008 15:00:00
David
Hallo zusammen.
Ich habe mir folgendes Makro zusammengebastelt:

Sub new_month()
Application.ScreenUpdating = False
Dim Nmonth, Omonth As String
Dim x, y As Integer
Dim position, länge, inhalt As String
Nmonth = InputBox("Welcher Monat?")
Nmonth = Format(Nmonth, "00")
anfang = Time()
x = Cells.SpecialCells(xlLastCell).Row
y = Cells.SpecialCells(xlLastCell).Column
For i = 1 To 20 'x
For j = 1 To 12 'y
position = InStr(1, Cells(i, j).Formula, "!", vbTextCompare)
länge = Len(Cells(i, j).Formula)
inhalt = Right(Cells(i, j).Formula, länge - position)
Cells(i, j).Formula = "='L:\Finanz\monthend\2008\" & Nmonth & "\[SAP wages.xls]SAP wages'!" &  _
inhalt
Next
Next
ende = Time()
dauer1 = (ende - anfang) * 60 * 24 * 60
anfang = Time()
Omonth = Range("A1").Formula
Omonth = Replace(Omonth, "='L:\Finanz\monthend\2008\", "")
Omonth = Replace(Omonth, "\[SAP wages.xls]SAP wages'!C3", "")
Range("A1:L20").Replace What:=Omonth, Replacement:=Nmonth, LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
Application.ScreenUpdating = True
ende = Time()
dauer2 = (ende - anfang) * 60 * 24 * 60
MsgBox ("For-Next: " & dauer1 & " --- Replace: " & dauer2 & " --- Differenz: " & dauer2 -  _
dauer1)
End Sub


Ich habe die Zeitfunktionen zur Analyse der Schnelligkeit der beiden "Suchen-und-Ersetzen"-Funktionen eingebaut. Dabei habe ich festgestellt, dass die Zeiten der beiden Verianten sich ständig verändern. Mal ist eine Funktion 1 Sekunde, mal 2 Sekunden langsamer, mal sind beide gleich. Kann mir jemand erklären, warum?
Und was noch wichtiger ist: In dem Makro werden momentan nur die ersten 20 Zeilen bearbeitet. Das Blatt hat aber 2000 Zeilen, zukünftig evtl. noch mehr (bis zu 4000). Sieht jemand eine Möglichkeit, das zu beschleunigen? Im "günstigsten" Fall brauche ich sonst rund 8 Minuten.
Danke schon mal.
Gruß
David

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

Betreff
Datum
Anwender
Anzeige
AW: Makrooptimierung
30.06.2008 19:45:00
Gerd
Hallo David,
welche kompletten Formeln stehen drin, bevor der Code läuft?
In A1, A2, A20
In B1, B2, B20
In L1, L2, L20
Gruß Gerd

AW: Makrooptimierung
02.07.2008 11:57:45
David
A1: ='L:\Finanz\monthend\2008\06\[SAP wages.xls]SAP wages'!C3
A2: ='L:\Finanz\monthend\2008\06\[SAP wages.xls]SAP wages'!C4
...
A2000: ='L:\Finanz\monthend\2008\06\[SAP wages.xls]SAP wages'!C2002
B1: ='L:\Finanz\monthend\2008\06\[SAP wages.xls]SAP wages'!D3
...
B2000: ='L:\Finanz\monthend\2008\06\[SAP wages.xls]SAP wages'!D2002
usw. Sozusagen immer die Pfadangabe und dann der Bezug auf eine bestimmte Zelle in der Quelldatei. Der Pfad ändert sich halt jeden Monat, so daß ich die Monats-Zahl austauschen muss. Theoretisch könnte ich da ja auch mit INDIREKT realisieren, aber da kommen Fehlermeldungen bei nicht geöffneter Datei und das will ich weitestgehend vermeiden, da auch andere User die Datei öffnen könnten.
Gruß
David

Anzeige
AW: Makrooptimierung
01.07.2008 00:03:00
Daniel
Hi
wenn du Laufzeiten von Makros ermitteln willst, dann ist die Funktion TIMER vielleicht geeigneter als TIME
TIMER gibt dir die aktuelle Zeit in Sekunden ab Mitternacht,die einheit für Sekunden ist 1, und dürfte daher etwas genauer sein als Time, wenn es um Sekundenbruchteile geht.
Variablen, die mit Timer arbeiten, sollten als SINGLE deklariert sein.
Außerdem halte ich deine Versuchsmenge noch nicht gross genug, um signifikante Laufzeitunterschiede festzustellen.
des weiteren könnte es sein, daß gar nicht das Makro (welches auch immer) zeitbestimmend ist, sondern, da du mit Fernbezügen arbeitest, die Neuberechnung der Fernbezüge.
aber um dazu eine Aussage machen zu können, müsste man deine Formeln und die referenzierten Daten besser kennen.
meiner Erfahrung nach dürfte bei grossen Datenmengen das 2. Makro schneller sein, da hier nicht von VBA selbst gerechnet wird, sondern die in Excel eingebauten Funktionen verwendet werden.
Das ist in den meisten Fällen die schnellste Lösung.
das erste Makro ist langsam, weil VBA grundsätlich langsam ist, wenn mit den Excel-Objekten RANGE oder CELLS in Schleifen gearbeitet wird.
hier ist dann oft die bessere Methode, die Inhalte der Zellen in eine Feld-Variable (Array) zu kopieren, dann diese Feldvariable zu bearbeiten und dann die Werte in die Zellen zurückzuschreiben.
der Code dazu könnte so aussehen:

Sub new_month()
Application.ScreenUpdating = False
Dim Nmonth, Omonth As String
Dim x, y As Integer
Dim position, länge, inhalt As String
Dim arr
Nmonth = InputBox("Welcher Monat?")
Nmonth = Format(Nmonth, "00")
anfang = Time()
x = Cells.SpecialCells(xlLastCell).Row
y = Cells.SpecialCells(xlLastCell).Column
arr = Cells(1, 1).Resize(x, y).FormulaLocal
For i = 1 To 20 'x
For j = 1 To 12 'y
position = InStr(1, arr(i, j), "!", vbTextCompare)
länge = Len(arr(i, j))
inhalt = Right(arr(i, j), länge - position)
arr(i, j) = "='L:\Finanz\monthend\2008\" & Nmonth & "\[SAP wages.xls]SAP wages'!" & _
inhalt
Next
Next
Cells(1, 1).Resize(x, y).FormulaLocal = arr
ende = Time()
dauer1 = (ende - anfang) * 60 * 24 * 60
anfang = Time()
Omonth = Range("A1").Formula
Omonth = Replace(Omonth, "='L:\Finanz\monthend\2008\", "")
Omonth = Replace(Omonth, "\[SAP wages.xls]SAP wages'!C3", "")
Range("A1:L20").Replace What:=Omonth, Replacement:=Nmonth, LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
Application.ScreenUpdating = True
ende = Time()
dauer2 = (ende - anfang) * 60 * 24 * 60
MsgBox ("For-Next: " & dauer1 & " --- Replace: " & dauer2 & " --- Differenz: " & dauer2 - _
dauer1)
End Sub


(nicht getestet, da keine Beispieldaten vorhanden)
die Änderungen habe ich fett oder kursiv gekennzeichnet.
mit diesen beiden Makros sollten eigentlich auch grössere Datenmengen kein Problem sein.
wenn allerdings wie schon erwähnt die neuberechnung des Externen Bezugs das Problem ist, dann würde dir nur helfen, die Dateien , auf die sich die alten und neuen Fernbezüge beziehen zu öffnen, und dann das Makro für diese Situation neu zu schreiben (kein Pfadangaben in den Externen Bezügen).
bei geöffneten Dateien ist das Berechnen der externen Bezüge wesentlich schneller, als bei geschlossenen Dateien. Daher ist es auf jeden Fall lohnenswert, diese Dateien zu öffnen.
Gruß, Daniel

Anzeige
AW: Makrooptimierung
02.07.2008 11:52:19
David
Danke für deine ausführlichen Erläuterungen, werde ich mal testen.
Gruß
David

AW: Makrooptimierung
02.07.2008 13:08:00
David
Ich habe einen Test mit der Funktion Timer() gemacht und den Bereich auf 100 Zeilen ausgewertet. Das Ergebnis widerspricht deiner Vermutung, dass die VBA-Berechnung langsamer ist.
Userbild
Gruß

AW: Makrooptimierung
02.07.2008 13:36:00
David
Im Makro ist ein Fehler. Es muss nur '.Formula' heißen statt '.FormulaLocal', der Code steigt sonst aus und liefert innerhalb der Schleife auch falsche Werte.
Gruß
David

Anzeige
AW: Makrooptimierung
02.07.2008 20:59:44
Daniel
Hi
ohne Beispieldatei kann man seinen Code leider nicht testen.
Gruß, Daniel

AW: Makrooptimierung
03.07.2008 08:12:01
David
Klar, das war auch nicht als Kritik gemeint, sondern nur als Hinweis, falls mal jemand den Beitrag im Archiv liest.
Auf jeden Fall hat dein Vorschlag mit dem Array was gebracht. Ich habe das Makro entsprechend umgestellt und es braucht jetzt für die 2000 Zeilen á 12 Spalten nur ca. 75 Sek. gegenüber vorher 10 Minuten.
Also Danke nochmal.
Gruß
David

AW: Makrooptimierung
03.07.2008 23:21:45
Gerd
Hallo David,
pobier mal, ob Du damit hinkommst.

Sub holen2()
Const Standard As String = "L:\Finanz\monthend\2008\|\[SAP wages.xls]SAP wages'!C3:D2002"
Dim Neuer_Bezug As String
Dim Nmonth
Nmonth = InputBox("Welcher Monat?")
Nmonth = Format(Nmonth, "00")
Neuer_Bezug = "='" & Replace(Standard, "|", Nmonth, , 1)
With ActiveSheet.Range("A1:B2000")
.ClearContents
.FormulaArray = Neuer_Bezug
End With
End Sub


Gruß Gerd

Anzeige
AW: Makrooptimierung
04.07.2008 09:03:00
David
Hallo Gerd,
nicht schlecht, das dauert nur eine Sekunde. Was das komische daran ist, das die Quelldateien in der "Session" mindestens einmal geöffnet sein mussten, da es sonst BEZUG-Fehler gibt. Ob sie dann anschließend offen sind, ist egal. Wenn ich den Verweis auf einen Monat setze, dessen Datei ich noch nicht geöffnet habe, kommen die Fehler.
Ok, aber ich denke damit kann ich leben, indem ich im Makro einfach die Datei vorher öffne und wieder schließe.
Vielen Dank für die Hilfe.
Gruß
David

AW: Makrooptimierung
04.07.2008 09:56:00
Gerd
Hallo David,
dies konnte ich bei meinem Rechner nicht feststellen.
Ich hatte den Code allerdings nur auf dem Festplatten-Laufwerk "lokal" getestet.
Nun bin ich nicht der Spezialist für das "Verschieben/Kopieren" von Daten zwischen Dateien.
Evtl. sieht jemand eine Möglichkeit, dieses Verhalten zu beheben oder zu erklären.
Stelle daher auf noch offen.
Gruß Gerd

Anzeige
AW: Makrooptimierung
04.07.2008 10:23:49
David
Ist schon ok, ich habe das Makro jetzt soweit, dass es problemlos läuft und nur 1-2 Sekunden dauert, also kein weiteres Kopfzerbrechen notwendig.
Nochmals vielen Dank.
Gruß
David

Links zu Excel-Dialogen

Beliebteste Forumthreads (12 Monate)

Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Anzeige