Live-Forum - Die aktuellen Beiträge
Anzeige
Archiv - Navigation
1056to1060
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

Zwei Codes mit gleicher Funktion im Vergleich

Zwei Codes mit gleicher Funktion im Vergleich
05.03.2009 23:54:08
Richard


Guten Abend,
ich will mich so langsam von der Makro-Orientierten Programmierung trennen, dabei ist mir aufgefallen, dass sie trotz ein paar Codezeilen mehr dennoch viel schneller ist. Und daher nutzte ich sie immer noch zu Genüge.
Dazu habe ich mal nachfolgend 2 Varianten geschrieben, wo ihr mir bestimmt sofort mit Sicheheit sagen könnt, wo mein Denkfehler liegt.
Zur Aufgabe:
Ich habe In 20000 Zeilen per Zufall irgendwelche Werte in den ersten beiden Spalten (A,B) eingefügt. In Spalte C will ich die Summe auf alle 20000 Zeilen berechnen lassen. Dabei will ich am Ende nur reine Werte haben (also nicht als Formel). In der 1. Variante habe ich mir den Makrorekorder zur Hilfe genommen den Code anschließend etwas modifiziert. De Facto habe ich mit Formeln und anschließenden Kopier- u. Einfügmethoden gearbeitet.
Variante 1:


iRow = Cells(Rows.Count, 1).End(xlUp).Row
Cells(1, 3).FormulaR1C1 = "=SUM(RC[-2]:RC[-1])"
Cells(1, 3).Copy
Range("C1:C" & iRow).Select
ActiveSheet.Paste
Selection.Copy
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, _
SkipBlanks:=False, Transpose:=False
Application.CutCopyMode = False


In der 2. Variante habe ich zwar einen funktionierenden und Codezeilen sparenderen Code ohne Makrorekorder verwendet. Dieser ist bei mir auf dem Rechner aber mindestens 30 mal langsamer als der erste. Was sollte ich eurer Meinung nach besser machen? Gibt es evtl. andere Möglichkeiten?


iRow = Cells(Rows.Count, 1).End(xlUp).Row
For i = 1 To iRow
Cells(i, 3).Value = Cells(i, 1).Value + Cells(i, 2).Value
Next i


Vielen Dank für eure Hilfe!
Mit freundlichen Grüßen
Richard E.

23
Beiträge zum Forumthread
Beiträge zu diesem Forumthread

Betreff
Datum
Anwender
Anzeige
AW: Zwei Codes mit gleicher Funktion im Vergleich
06.03.2009 00:21:57
Daniel
Hi
also der erste Code lässt sich auch noch deutlich optimieren (sowohl in bezug auf Länge, als auch in Bezug auf Geschwindigkeit):

iRow = Cells(Rows.Count, 1).End(xlUp).Row
With Range("C3:C" & iRow)
.FormulaR1C1 = "=SUM(RC[-2]:RC[-1])"
.Formula = .Value
End With


eine Zweite Möglichkeit wäre, die Daten in ein Array zu lesen, dort zu aufzuaddieren und dann zurückzurschreiben.


dim Summanden
dim Ergebnis
dim iRow as long
dim i as long
iRow = Cells(Rows.Count, 1).End(xlUp).Row
Summanden = Range("A1:B" & iRow).Value
Ergebnis = Range("C1:C" & iRow).Value
For i = 1 to iRow
Ergebnis(i, 1) = Summanden(i, 1) + Summanden(i, 2)
next
Range("C1:C" & iRow).Value = Ergebnis


im Prinzip gibt es 2 Möglichkeiten, mit Excel schnell und effektiv zu arbeiten:
1. du arbeitest wie gezeigt möglichst schleifenfrei und nutzt sehr intensiv FORMELN und die angebotenen Excel-Funktionen (z.B. SpecialCells, Replace)
2. du kopierst die zu bearbeitenden Werte in Array-Variablen und bearbeitest diese in Schleifen und legst das Ergebnis ebenfalls in Array-Variablen ab. diese Array-Variablen schreibst du am Ende in die Excelzellen zurück
hier werden zwar Schleifen verwendet, diese sind aber sehr schnell.
was du unbedingt vermeiden solltest, ist die Excel-Objekte RANGE und CELLS in Schleifen zu verwenden, da Excel hier sehr langsam arbeitet. Auch der Makrorecorder liefert in der Regel ineffizienten Code, dh. man kann ihn verwenden, um die Syntax und die Parameter von bestimmten Excelfunktionen komfortabel herauszufinden, ohne lange in der Hilfe zu suchen, aber der aufgezeichnete Code muss noch überarbeitet werden, um wirklich schnell zu sein.
Gruß, Daniel

Anzeige
AW: Zwei Codes mit gleicher Funktion im Vergleich
06.03.2009 08:50:16
Richard
Moin allesamt,
entschuldigt, dass ich mich jetzt erst melde. Vorab herzlichen Dank für euer Feedback. Aber nun nochmal zum Thread von mir.
Ich habe die Versionen von Daniel und die Version von Uwe einmal getestet. Ich habe versucht irgendwie einen Geschwindigkeitsmessung einzubauen, sicherlich nicht sehr ideal aber dennoch lieferte Excel mir Wert aus denen man Schlussfolgerungen ziehen kann.
Seht euch das selbst bitte einmal an:
https://www.herber.de/bbs/user/60033.xls
Ich habe vor jeder Variante eine Startzeit erfasst und nach jedem Code eine Endzeit, die Differenz lasse ich mir dann direkt im Sheet anzeigen. Damit ich vergleichbare Werte geliefert bekomme, durchlaufe ich jeden Code 10x mit einer For...Next-Schleife.
Platzierung ( laut meinen Test ):
1. Uwes Code
2. Mein Code (Variante 1 - Makroversion)
3. Daniels Code (Variante 2 - Arrayversion)
4. Daniels Code (Variante 1 - verkürzte Makroversion)
5. Mein Code (Variante 2 - Schleifenversion)
Testet es selbst und schreibt zurück!
Mit freundlichen Grüßen
Richard E.
Anzeige
AW: Zwei Codes mit gleicher Funktion im Vergleich
06.03.2009 00:22:13
Uwe
Hi Richard,
ich hätte da eine Alternative, die ziemlich schnell ist, wenn sie auch ein bisschen seltsam daher kommt:

Columns("B:B").Copy
Columns("C:C").PasteSpecial xlPasteAll, xlPasteSpecialOperationNone, False, False
Columns("A:A").Copy
Columns("C:C").PasteSpecial Paste:=xlAll, Operation:=xlAdd, SkipBlanks:=False _
, Transpose:=False
Application.CutCopyMode = False


Teste das mal gegen Deine anderen Lösungen.
Allgemein ist zu sagen, dass bei großen Datenmengen die copy / paste Methode wesentlich schneller ist als die ... .value = ... .value Methode.
Gruß
Uwe
(:o)

Anzeige
AW: Interessante Lösung, aber
06.03.2009 00:47:34
Daniel
die möglichen Berechnungen beschränken sich auf die 4 Grundrechenarten
Gruß, Daniel
AW: Stimmt. Aber immerhin schnell
06.03.2009 00:52:37
Uwe
Hi Daniel,
es war mir klar, dass das eine ganz spezielle Lösung ist. Deshalb auch die allgemeine Nachbemerkung.
Gruß
Uwe
(:o)
AW: Zwei Codes mit gleicher Funktion im Vergleich
06.03.2009 00:24:12
Uduuh
Hallo,
beide Quatsch.
cells(rows.count,1).end(xlup).offset(1)=application.sum(Range(cells(2,1),cells(rows.count,1).end(xlup)))
Gruß aus’m Pott
Udo

AW: Zwei Codes mit gleicher Funktion im Vergleich
06.03.2009 00:35:53
Uwe
Hi Udo,
genau: Quatsch (;-).
Wenn Du Dir Richards Code angesehen hättest, hättest Du gesehen, dass er die Summen zeilenweise haben will.
Gruß
Uwe
(:o)
Anzeige
kürzer
06.03.2009 00:30:52
Uduuh
Hallo,

Sub tt()
Cells(Rows.Count, 1).End(xlUp).Offset(1) = Application.Sum(Columns(1))
End Sub


Gruß aus’m Pott
Udo

AW: kürzer und fälscher
06.03.2009 00:41:38
Daniel
der Code macht doch was völlig anderes, als die Codebeispiele von Richard
Gruß, Daniel
noch schneller
06.03.2009 08:49:17
Tino
Hallo,
noch schneller geht’s mit Area trotz schleife. ;-)
Sub Test()
Dim Ar1, Ar2
Dim Bereich As Range
Dim A As Long
Dim i As Single
i = Timer
Set Bereich = _
Range("A1", IIf(IsEmpty(Cells(Rows.Count, 1)), Cells(Rows.Count, 1).End(xlUp), Cells(Rows.Count, 1)))

Ar1 = Bereich
Ar2 = Bereich.Offset(0, 1)

For A = 1 To Ubound(Ar1)
 Ar2(A, 1) = Ar1(A, 1) + Ar2(A, 1)
Next A

Bereich.Offset(0, 2) = Ar2

MsgBox Timer - i
End Sub


Gruß Tino

Anzeige
getestet mit 1048576 Zeilen 7 Sekunden ...oT.
06.03.2009 08:54:26
Tino
AW: getestet mit 1048576 Zeilen 7 Sekunden ...oT.
06.03.2009 09:16:15
Richard
Mit meiner Zeitmessung habe ich mich natürlich sehr lächerlich gemacht! ;-)
Die Timer-Lösung ist dagegen sehr viel kürzer, ganauer und elagenter. Wie dumm, dass ich da nicht selbst drauf gekommen bin.
Aber dennoch Tino, ist deine Lösung nicht die schnellste in dem von mir beschriebenen Fall.
Ranking:
1) Uwes Version
2) Meine 1. Version
3) deine Lösung
4) Daniels 2. Version (Array)
5) Daniels 1. Version
6) Meine 2. Version (Schleife)
Mit freundlichen Grüßen
Richard E.
p.s. Hier noch mal ein Datei-Upload: https://www.herber.de/bbs/user/60037.xls
Anzeige
AW: getestet mit 1048576 Zeilen 7 Sekunden ...oT.
06.03.2009 09:41:59
Tino
Hallo,
ist wohl auch von der Excelversion oder Rechnerkonfiguration abhängig (bei mir xl2007),
habe die Zeile mal aufgefüllt bis zur vorletzten.
Userbild
Gruß Tino
AW: getestet mit 1048576 Zeilen 7 Sekunden ...oT.
06.03.2009 10:08:21
Richard
Ja das mag wohl sein, dass es daran liegt, bestimmt sogar. Könnte mir aber trotzdem vorstellen, dass gerade dein Code viel Sinn macht, wenn man sehr viele Zeilen berechnen muss. Bei weniger Werten (z.B. 1000) ist vielleicht eine andere Lösung deutlich schneller.
Ein Summe zu berechnen ist ja noch relativ einfach, die Sache wird bestimmt schon ganz anders aussehen, wenn man mit komplexeren Formeln arbeitet.
Mir ging es in erster Linie darum, den goldenen Mittelweg zu finden, d.h. möglichst ohne Rekorder zu arbeiten, möglichst wenig Code zu schreiben und dennoch sehr schnell. Immerhin will ich mir beim erlernen der Programmiersprache keine Sauklaue angewöhnen.
Mit freundlichen Grüßen
Richard E.
Anzeige
AW: getestet mit 1048576 Zeilen 7 Sekunden ...oT.
06.03.2009 10:21:42
Tino
Hallo,
"...beim erlernen der Programmiersprache..."
Dann empfehle ich sowieso sich unter anderem mit dem Thema Area zu befassen,
wird oft gebraucht und ist sehr nützlich.
Gruß Tino
noch schneller?
06.03.2009 10:27:10
Klaus
… auf dem Mac ist das die schnellste Variante:

Sub Rechnen()
'Application.ScreenUpdating = False
Dim BEREICH As Range
iRow = Cells(Rows.Count, 1).End(xlUp).Row
x = Timer
Set BEREICH = Range("C1:C" & iRow)
With BEREICH
.FormulaR1C1 = "=SUM(RC[-2]:RC[-1])"
.Value = .Value
End With
Range("K30").Value = Timer - x
'Application.ScreenUpdating = True
Set BEREICH = Nothing
End Sub


Gruß
Klaus

Anzeige
und wieder anders oT.
06.03.2009 10:40:07
Tino
AW: getestet mit 1048576 Zeilen 7 Sekunden ...oT.
06.03.2009 10:07:56
Tino
Hallo,
habe es jetzt mehrmals hintereinander getestet (außer Variante 2)
Die Lösung von Uwe und die von mir wechseln sich im Rang in unregelmäßigen Zyklen ab.
Wird wohl an irgendeiner Speicherauslastung liegen. (keine Ahnung)
Ich komme zu dem Fazit, alle Versionen können ruhig verwendet werden bis auf die Version 2,
auf eine Sekunde mehr oder weniger wird es bei diesen Datenmengen nicht ankommen.
Gruß Tino
AW: getestet mit 1048576 Zeilen 7 Sekunden ...oT.
06.03.2009 11:57:13
Uwe
Hi Tino,
ich komme mir zwar ein bisschen kindisch vor, aber:
Wenn ich meinen Code durch Application.ScreenUpdating = False/ True ergänze, dann ist er bei mir fast doppelt so schnell wie Deiner (;-).
Allerdings ist klar das mein Code nur sehr beschränkte Möglichkeiten bietet und die Lösung über Arrays auf jeden Fall vorzuziehen ist.
Ich versuche zur Zeit auch möglichst oft mit Arrays zu arbeiten, um da mehr Routine zu bekommen.
Gruß
Uwe
(:o)
Anzeige
AW: getestet mit 1048576 Zeilen 7 Sekunden ...oT.
06.03.2009 12:23:38
Tino
Hallo,
ist nicht kindisch, finde ich zumindest, man kann sich ruhig mal über sowas austauschen.
Stimmt damit kann man noch was raus kitzeln.
Gruß Tino
AW: auf jeden Fall ist es mal interessant
06.03.2009 20:57:02
Daniel
die Verschiedenen Lösungsmöglichkeiten nebeneinander im direkten Vergleich zu sehen.
die Zeitunterschiede sind, bis auf die eine Variante ja eher klein, so daß es keinen eindeutigen Sieger gibt.
welche die Lösung die bessere ist, hängt wahrscheinlich vom konkreten Einzelfall ab.
allerdings favorisiere ich momentan eher die Formellösung als die Array-Schleifen, und zwar aus folgenden Gründen:
- als Excelanwender bin ich natürlich mit Formeln besser vertraut als mit "echter" Programmierung
- die Formeln lassen sich unabhängig vom Makro entwickeln und testen. Das hat Vorteile bei komplexen Makros, die zum Testen u.U. immer vollständig durchlaufen müssen
- ein Array ist immer eine Kopie der Exceldaten, dh die Datenmenge verdoppelt sich, was bei sehr grossen Datenmengen ein Problem sein kann
- in den Formeln lassen sich auch sehr komplexe Berechungen in einer VBA-Zeile abbilden. Der notwenige Makrocode ist dadurch sehr kompakt.
Grundsätzlich gilt meiner Ansicht nach für eine effiziente Programmierung in Excel:
man sollte immer erst mal nachdenken, wie das Problem ohne VBA nur mit Excel-Funktionen und Formeln am schnellsten und einfachsten lösbar wäre. Wenn man dann diese Vorgehensweise im Makro umsetzt, hat man auf jeden Fall eine gute bis sehr gute Lösung.
Gruß, Daniel
AW: auf jeden Fall ist es mal interessant
06.03.2009 21:26:42
Tino
Hallo Daniel,
Grundsätzlich gebe ich Dir Recht.
Kommt eben wirklich darauf an,
für komplexe Berechnungen, würde ich soweit es mein Kenntnisstand zulässt
Excelformeln heranziehen. (für mich in VBA oft einfacher umzusetzen)
Aber wie in diesem Fall, wo es eigentlich ganz einfach ist und
ich als Rückgabe sowieso einen festen Wert haben möchte,
würde ich persönlich doch eher zur VBA Version über Array neigen.
Muss man eben von Fall zu Fall entscheiden wie man vorgeht.
Gruß Tino
AW: Zwei Codes mit gleicher Funktion im Vergleich
06.03.2009 16:11:34
mpb
Hallo,
bei meinem Test am besten war:

Sub addieren()
Z = Range("A65536").End(xlUp).Row
Range("C1").Formula = "=Sum(A1:B1)"
Range("C1").Copy Destination:=Range(Cells(2, 3), Cells(Z, 3))
'Columns("C:C").Copy
'Columns("C:C").PasteSpecial Paste:=xlPasteValues
End Sub


Falls das Ergebnis Werte und nicht Formeln sein sollen, die beiden auskommentierten Zeilen mit durchlaufen lassen, dann wird der Code geringfügig langsamer.
Gruß
Martin

286 Forumthreads zu ähnlichen Themen

Anzeige
Anzeige
Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Anzeige