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

Rechnen sehr langsam

Rechnen sehr langsam
kerschl
Hallo Kollegen.
Heute habe ich ein Problem mit einem an sich sehr einfachen Makro. Nur ist leider die Laufzeit mit knapp 10 Minuten indiskutabel.
Evtl. könnt ihr mir helfen. Hier die Vorgeschichte:
Ich erhalte eine csv-Datei, die ich in Excel einspiele. Anschließend möchte ich mit dem folgenden Makro alle Werte eines Gruppen-Kriteriums aufsummieren. Dazu lese ich in einer Schleife so lange, wie das Kriterium (Spalte D) gleich ist. Erkenne ich einen Gruppenwechsel, füge ich eine Spalte ein und addiere alle Werte darüber in einer Summe auf. Im Anschluß lösche ich die Detailzeilen und übernehme die festen Werte in der Summenzeile (keine Formeln mehr).
Alles ziemlich einfach. Ich denke auch, daß der Makro so schlecht nicht ist. Ich habe Selects vermieden und die Berechnung ausgeschaltet. Dennoch läuft das Programm 10 Minuten und die Datei hat eine Größe von 3 MB. Und das bei nur 537 Datensätzen.
Könnt ihr euch das mal ansehen? Vielleicht überseh ich was...

Sub Gruppe_Opal()
Dim bereich As String
Dim gruppe As String
Dim summe As Range
Dim S1 As Integer
Dim sgroup As String
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
erster = 3	'ist die erste Zeile mit einem Wert
sgroup = "D"	'Spalte mit den Gruppen-Kriterien
'Liste sortieren nach dem Wert, nach dem gruppiert werden soll
j = Range("A65536").End(xlUp).Row
Rows(erster & ":" & j).Select
bereich = sgroup & erster
Selection.Sort Key1:=Range(bereich), Order1:=xlAscending, Header:=xlNo, _
OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom
'Summenzeilen berechnen. Gruppenbegriff sgroup steht in Spalte D (FP-Nr)
gruppe = Cells(erster, sgroup).Value
z = erster
y = 0		'y = die Anzahl der Zeilen mit gleichem Gruppen-Kriterium
Do Until z > j + 2
'Suchen, bis wann die Gruppe gleich bleibt
If Cells(z, sgroup).Value = gruppe Then
y = y + 1
'wenn Gruppenwechsel, dann aufaddieren aller Spalten
Else
'z = aktuelle Zeile der Gruppe, y = Anzahl der Zeilen der Gruppe
'wenn y =1, dann gar nix machen, weil die summen eh passen
If y = 1 Then GoTo skip
'summenzeile einfügen und die Zellen darüber addieren
Rows(z - 1 & ":" & z - 1).Copy
Rows(z & ":" & z).Insert Shift:=xlDown
On Error GoTo fehler:
'Spalten I bis AM mit der Summenformel belegen
Set summe = Range("I" & z & ":AM" & z)
summe.Formula = "=SUM(R[-" & y & "]C:R[-1]C)"
Calculate
'als Festwerte wegkopieren.
summe.Copy
summe.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Application.CutCopyMode = False
'Detailzeilen immer löschen
bereich = z - y & ":" & z - 1
Rows(bereich).Rows.Delete
z = z - y
skip:
j = j + 1
gruppe = Cells(z + 1, sgroup).Value
y = 0
End If
z = z + 1
Loop
Exit Sub
fehler:
MsgBox "Fehler beim Aufaddieren! (evtl. Textfeld gewählt)", vbCritical, "Fehler"
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub

AW: Rechnen sehr langsam
13.08.2009 21:26:55
Daniel
Hi
naja, es ist halt doch etwas umständlich programmiert.
es könnte aber auch irgenwie ein Bug mit viel Datenmüll drin sein, die Grösse scheint mir bei der Anzahl der Datensätze unangemessen.
außerdem sind deine Variablen nicht vollständig deklariert. verwendest du "Option Explicit" standardmäßig?
wenn nein, erstmal das hier lesen, verstehen und umsetzen: http://www.online-excel.de/excel/singsel_vba.php?f=4
ansonsten, probier mal diese Variante.
der Vorteil ist, die Summen werden am Ende eingefügt und dann die Detailzeilen auf einen Schlag gelöscht, daß ist immer schneller als einzeln zu löschen.
Sub test()
Dim Z1 As Long, Z2 As Long
Dim ZSummen As Long, ZStart As Long, ZEnde As Long
Dim gruppe As String
ZStart = 3
ZEnde = Cells(Rows.Count, 4).End(xlUp).Row
ZSummen = ZEnde + 1
With Range(Rows(ZStart), Rows(ZEnde))
.Sort Key1:=.Cells(1, 4), Order1:=xlAscending, Header:=xlNo
End With
Z1 = ZStart
gruppe = Cells(ZStart, 4)
For Z2 = ZStart + 1 To ZEnde + 1
If Cells(Z2, 4)  gruppe Then
ZSummen = ZSummen + 1
Cells(ZSummen, 4).Value = gruppe
With Range(Cells(ZSummen, "I"), Cells(ZSummen, "AM"))
.FormulaR1C1 = "=Sum(R" & Z1 & "C:R" & Z2 - 1 & "C)"
.Formula = .Value
End With
Z1 = Z2
gruppe = Cells(Z2, 4)
End If
Next
Range(Rows(ZStart), Rows(ZEnde + 1)).Delete
End Sub
Gruß,Daniel
Anzeige
AW: Rechnen sehr langsam
13.08.2009 21:35:05
BoskoBiati
Hallo,
hier noch eine Anfängervariante. Das Summieren erfolgt direkt im Makro, so dass die Formel wegfallen kann:
Option Explicit
Sub Gruppe_Opal()
Dim Bereich As Range
Dim loLetzte As Long
Dim lngA As Long
Dim lngB As Long
Dim lngC As Long
Dim lngD As Long
Dim lngSumme(38) As Variant
lngD = 1
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
loLetzte = Range("A65536").End(xlUp).Row
Set Bereich = Range("A3:AM" & loLetzte)
Bereich.Sort Key1:=Range("D3"), Order1:=xlAscending, Header:=xlNo, _
OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom
For lngA = loLetzte To 3 Step -1
For lngB = 0 To 2
lngSumme(lngB) = lngSumme(lngB) + Cells(lngA, lngB + 1)
Next
lngSumme(3) = Cells(lngA, 4)
For lngB = 4 To 38
lngSumme(lngB) = lngSumme(lngB) + Cells(lngA, lngB + 1)
Next
If Cells(lngA - 1, 4)  Cells(lngA, 4) Then
Rows(loLetzte).Insert shift:=xlDown
For lngB = 0 To 38
Cells(loLetzte + 1, lngB + 1) = lngSumme(lngB)
lngSumme(lngB) = 0
Next
For lngC = loLetzte To lngA Step -1
Rows(lngC).Delete shift:=xlUp
Next
loLetzte = Range("A65536").End(xlUp).Row - lngD
lngD = lngD + 1
lngA = loLetzte - 1
End If
Next
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub
Gruß
Bosko
Anzeige
AW: Rechnen sehr langsam
13.08.2009 21:34:51
Christian
Hallo Michael,
ohne jetzt tiefer in deinen Code einzutauchen kann ich dir für deine Schleife Folgendes empfehlen:
- vermeide zusammengesetze Strings bei der Festlegung von Ranges, Formeln, etc.
- vermeide kopieren und Werte einfügen
- vermeide Anweisungen wie dein Calculate innerhalb von Schleifen
- ...
statt dessen:
- verarbeite die Ergebnisse intern mit Hilfe von Arrays, Collections oder Dictionaries (Hashes). Mit Letzerem könntest du dann auch auf die Sortierung verzichten.
- Anschließend schreibst du die Ergebnisse deiner interenen Kalkulation auf einen Schlag in die Tabelle.
Was noch auffällt:
- du sagst, du hast "select" vermieden ... na ja, nicht wirklich. Mit 'ner sauberen Referenzierung wäre das nicht passiert.
- Erzwinge die Variablen-Deklaration mit Option Explizit - das hilft nicht zuletzt bei der Fehlersuche.
So sollten imho die Ergebnisse für deine 537 Datensätze innerhalb von Millisekunden berechnet werden können.
Grüße
Christian
Anzeige
Kannst Du bitte eine CSV-Datei hochladen ?
13.08.2009 21:44:54
NoNet
Hallo Michael,
mir erscheinen alle bisher geposteten Codes sehr umständlich !
Könntest Du bitte mal eine DEMO-CSV hochladen (Werte müssen keine Originalwerte sein !) und URL hier posten ?
Ich bin sicher, das Makro kann wesentlich einfacher "gestrickt"sein und zudem deutlich schneller !
Gruß, NoNet
AW: Kannst Du bitte eine CSV-Datei hochladen ?
13.08.2009 23:33:40
Daniel
Hi
das ist mal einfacher und erzeugt das gleiche Ergebnis:
bei Makrostart muss das Blatt mit den CSV-Daten aktiv sein, es wird ein neues Blatt erstellt, in dem die Auswertung erfolgt. Das Blatt mit den CSV-Daten wird anschließend gelöscht.
Sub Test()
Dim shQuelle As Worksheet
Dim shAuswertung As Worksheet
Set shQuelle = ActiveSheet
Set shAuswertung = Sheets.Add
With shQuelle
.Range(.Cells(2, 4), .Cells(Rows.Count, 4).End(xlUp)).AdvancedFilter _
action:=xlFilterCopy, copytorange:=shAuswertung.Cells(2, 4), unique:=True
.Range("1:2").Copy Destination:=shAuswertung.Cells(1, 1)
End With
With shAuswertung
With Intersect(Range(.Cells(3, 4), .Cells(Rows.Count, 4).End(xlUp)).EntireRow, .Range("i:AM" _
))
.FormulaR1C1 = "=Sumif('" & shQuelle.Name & "'!C4,RC4,'" & shQuelle.Name & "'!C)"
.Formula = .Value
End With
End With
Application.DisplayAlerts = False
shQuelle.Delete
Application.DisplayAlerts = True
End Sub

Gruß, Daniel
Anzeige
AW: Kannst Du bitte eine CSV-Datei hochladen ?
15.08.2009 19:36:33
kerschl
Hallo nochmal.
Ich hatte jetzt Zeit, die Datei und eure Lösungen zu überprüfen.
Als erstes habe ich den Hinweis von Daniel, daß es sich um Datenmüll handeln könnte, genau geprüft.
Und was soll ich sagen: Daniel hatte Recht!
Zuerst wollte ich die 537 Datensätze auf 100 reduzieren. Der Erfolg war erbärlich. Die Datei hatte im Anschluss 2,7 MB statt 3,0 MB. Klarer Hinweis auf Datenmüll. Danach habe ich die 537 Datenzeilen in eine neue Datei kopiert und habe damit die Grösse auf 96 KB reduziert.
Dann habe ich die Bosko-Variante laufen lassen. Lief leider auf Fehler.
Dann die von Daniel. Dauer nur noch gut eine Sekunde!
Dann meine eigene Version. Dauer ca. zwei Sekunden.
Bei so kurzen Laufzeiten hat die Option Explizit keinen Einfluss auf die Dauer. Dennoch werde ich es zukünftig nutzen.
Fehler lag also eindeutig an der Exportdatei, die ich aus unserem Firmensystem erhalten habe.
Euch allen ein dickes Dankeschön für die Lösungen und Hinweise. Hab viel dabei gelernt.
Gruß, Michael
Anzeige
AW: Kannst Du bitte eine CSV-Datei hochladen ?
15.08.2009 19:40:20
kerschl
Thema somit geklärt und abgeschlossen
AW: Kannst Du bitte eine CSV-Datei hochladen ?
16.08.2009 08:52:19
Hajo_Zi
Halo Michael,
wenn das Thema

geklärt und abgeschlossen
warum ist der Beitrag als offen gekennzeichnet?

AW: Kannst Du bitte eine CSV-Datei hochladen ?
16.08.2009 10:12:55
kerschl
habe Frage geschlossen.
AW: Kannst Du bitte eine CSV-Datei hochladen ?
16.08.2009 10:46:32
Hajo_Zi
Hallo Michael,
früher konnten Moderatoren Beiträge aus der Liste der offenen Beiträge entfernen, jetzt geht es nur mit einem neuen Beitrag.
Du darfst den Haken nicht bei offen machen, dann trägst Du ihn wieder ein.
Jetzt ist der Beitrag aus offen raus.
Gruß Hajo
Anzeige
AW: Rechnen sehr langsam
14.08.2009 18:32:07
kerschl
Hallo.
Vielen Dank für eure interessanten Antwoten und Mustercodes.
Zum Thema "Option Explizit": da bin ich etwas zu schlampig. Das mache ich sehr selten. Sollte ich ändern.
Zum Upload: die csv habe ich nicht verfügbar, aber die eingespielten Datensätze. Habe nur den Semicolon als Trennzeichen verwendet und die Daten als *.xls gespeichert. Leider kann ich die Datei nicht uploaden, weil sie 3MB hat. Ich schau mal, daß ich sie verkleinere.
Ansonsten werde ich eure Tipps noch dieses Wochenende testen und euch bescheid geben. Vielleicht war ja genau das Richtige dabei.
Bis hierher erstmal Danke. Ich melde mich mit dem Ergebnis.
Gruß, MIchael
Anzeige
AW: Schlampen mit Option Explicit
14.08.2009 18:42:39
Daniel
das muss nicht sein,
man kann ja im VBA-EDITOR unter EXTRAS - OPTIONEN - EDITOR das Häkchen bei "Variablendeklaration erforderlich" setzen, dann ist das immer drin.
Es gibt KEINEN Grund es nicht zu tun.
Gruß, Daniel
AW: Schlampen mit Option Explicit
14.08.2009 18:53:10
kerschl
Ok, danke für den Hinweis.
Ich werde mich bessern ;-)

Beliebteste Forumthreads (12 Monate)

Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Anzeige