Performance Probleme
18.12.2013 12:49:04
Sebastian
ich habe eine komplexe Funktion erstellt zu deren Berechnung ein Breiten- und Höhenmaß als Bezug zu je einem Tabellenfeld als Eingabewerte benötigt werden.
In der Funktion wird jedoch ein Tabellenblatt mit derzeit 100 Zeilen und 7 Spaltenwerten durchsucht und die in jeder Zeilen enthaltenen Werte in der Funktion berechnet. Die Berechnung erfolgt nach Kriterien und durchläuf insgesamt pro Zeile je 4 If-Schleifen. Im Prinzip wird um einen Ausgabewert der Funktion zu erhalten, eine komplette Stückliste pro Funktionsverwendung berechnet. Ändert man nun einen der EingabeWerte der Funktion, werden natürlich alle Funktionen durchgerechnet, sofern ide Arbeitsmappe auf Automisches Berechnen eingestellt ist. In einer Preistabelle können schon mal 90-150 Funktionen mit unterschiedlichen Eingabewerten stehen. Das bedeutet eine entsprechende Anzahl von Berechnungen.
Ich bin auf folgende Überlegung gestoßen: 150 x 100 x 4 = 60.000 Berechnungen für ein Tabellenupdate.
Selbst mit 4 Prozessoren dauert so ein Update ca. 3-4 Minuten. Und es werden noch einige den Tabellen nachgestellte Berechnungen in die Arbeitsmappe eingebaut werden.
Ich habe die Berechnng der Tabelle bereits auf "manuell" im VBA Code gestellt.
In einem Thread hier im Forum habe ich jetzt gelesen, dass man die Berechnungszeit beschleunigen könnte, wenn ich die Daten, die in dem Tabellenblatt der Stückliste stehen, in ein Array einlese. Wie bekomme ich denn einen Bereich eines Tabellenblatts in ein Array und wie lese ich die Daten dort wieder aus?
Hier mal der Code der beiden Funktionen
Function KREUZWERT(Breite, Hoehe)
KREUZWERT = 0
For i = 1 To 100
'Datenzeile Einsammeln
For j = 1 To 10
DatenZeile(j) = Sheets(StueckL).Cells(i + 1, j).Text
Next j
'Werte korrekt Umwandeln
If DatenZeile(1) "" Then
DatCaLBool = CInt(DatenZeile(1)) ' Berechnung Ja Nein = 1.Spalte
Else
GoTo ENDE:
End If
If DatenZeile(3) "" Then
DatStueck = CDec(DatenZeile(3)) ' Anzahl der Teile Einlesen
Else
GoTo KeinWert:
End If
If DatenZeile(4) "" Then
DatRaB = CDec(DatenZeile(4)) ' Anzahl der Teile pro Rahmenbreite einlesen
Else
GoTo KeinWert:
End If
If DatenZeile(5) "" Then
DatOperand = CStr(DatenZeile(5)) ' Operand einlesen
Else
GoTo KeinWert:
End If
If DatenZeile(6) "" Then
DatRaH = CDec(DatenZeile(6)) ' Anzahl der Teile pro Rahmenhöhe einlesen
Else
GoTo KeinWert:
End If
If DatenZeile(7) "" Then
DatEHT = CStr(DatenZeile(7)) ' Berechnungseinheit "ST" "LM", "M2" - "M3" geht _
_
_
nicht, weil die Dimensionen nicht zur Verfügung stehen
Else
GoTo KeinWert:
End If
If DatenZeile(8) "" Then
DatPReis = CDec(DatenZeile(8)) ' Anzahl der Teile pro Rahmenhöhe einlesen
Else
GoTo KeinWert:
End If
'Berechnungsformel Aufrufen
a = Berechnung(DatCaLBool, DatStueck, DatRaB, DatOperand, DatRaH, DatEHT, DatPReis, _
Breite, Hoehe)
KREUZWERT = KREUZWERT + a
a = 0
KeinWert:
Next i
ENDE:
End Function
Function Berechnung(CALBOOL, STUECK, RaB, OPERAND, RaH, EHT, PREIS, BerBReite, BerHoehe)
'Checken, ob überhaupt berechnet wird
If CALBOOL = 0 Then
Berechnung = 0
GoTo BerEnde:
End If
'Checken, obe es wirklich eine Addition ist
If OPERAND = "ADD" And EHT = "ST" Then
Berechnung = (STUECK * RaB + STUECK * RaH) * PREIS
End If
If OPERAND = "ADD" And EHT = "LM" Then
Berechnung = (STUECK * RaB * BerBReite / 1000 + STUECK * RaH * BerHoehe / 1000) * PREIS
End If
If OPERAND = "MUL" And EHT = "M2" Then
Berechnung = STUECK * RaB * (BerBReite / 1000) * RaH / (BerHoehe / 1000) * PREIS
End If
BerEnde:
End Function
Ich habe bisher nur immer mit Bezügen auf Tabellenblätter gearbeitet, weil ich mir das besser Vorstellen kann.
Noch eine Anmerkung: Ich habe das Programmieren mir selbst beigebracht.... vielleicht ist der Code deswegen nicht perfekt und nach "Regeln aufgebaut"... eher Spaghetti-CODE... wer also Optimierungen für mich hat... gerne lerne ich etwas...
Freue mich über jeden Tipp. Vielen Dank!