Startseite
» PC-Tipps
»
Beschleunigen Sie Calc-Makros durch das Lesen und Schreiben von Daten in Stapeln
Beschleunigen Sie Calc-Makros durch das Lesen und Schreiben von Daten in Stapeln
Die zuverlässigste erste Möglichkeit zur Beschleunigung eines langsamen Calc-Makros besteht darin, wiederholte zellenweise Lese- und Schreibvorgänge durch einen Bereichslesevorgang, eine Schleife im Arbeitsspeicher und einen Bereichsschreibvorgang zu ersetzen. Dadurch werden die Aufrufe zwischen Basic und Calc reduziert; eine feste Geschwindigkeitssteigerung ist jedoch nicht garantiert, da Formeln, Formatierung, Dateigröße und die Makrologik die Laufzeit ebenfalls stark beeinflussen können. Das folgende Beispiel ändert eine Statusspalte und zeigt, wie Geschwindigkeit und Korrektheit gemessen werden können. Die API-Details wurden am 9. Oktober 2026 anhand der LibreOffice-Dokumentation 26.8 überprüft.
Was sollte verbessert werden und wie werden Sie das messen?
Führen Sie das aktuelle Makro auf einer Kopie der Arbeitsmappe aus und notieren Sie die verstrichene Zeit. Verwenden Sie für das alte und das überarbeitete Makro jeweils eine neue Kopie mit denselben Ausgangsdaten oder stellen Sie die Eingabedaten zwischen den Ausführungen wieder her; andernfalls kann die zweite Ausführung weniger Ergebnisse liefern. Halten Sie die Zeilenanzahl, die Berechnungseinstellungen und die Ausgabebedingungen unverändert. Wiederholen Sie jede Ausführung und vergleichen Sie die durchschnittliche Laufzeit, anstatt sich auf eine ungewöhnlich schnelle Ausführung zu verlassen. Prüfen Sie, ob das Ergebnis Ihrer erwarteten Regel entspricht. Ein Makro, das zwar schneller fertig ist, aber die falschen Zeilen ändert, stellt keine Verbesserung dar.
Die Funktion von LibreOffice Basic Timergibt die seit Mitternacht gespeicherten Sekunden aus. Weisen Sie diese LongFunktion Variablen zu, um numerische Sekunden zu erhalten. Bei kurzen Messreihen erfassen Sie einen Start- und einen Endwert und subtrahieren diese. Ist der Endwert niedriger, hat die Messreihe Mitternacht überschritten. Addieren Sie in diesem Fall 86.400 Sekunden zur Differenz. Der Timer gibt ganze Sekunden aus. Verwenden Sie den ScriptForgeTimer-Dienst für Millisekundenpräzision. Weitere Informationen finden Sie in der Dokumentation zum LibreOffice Basic Timer und im ScriptForge Timer-Dienst . Führen Sie das Öffnen, Speichern und die manuelle Überprüfung von Arbeitsmappen außerhalb des Messintervalls durch, es sei denn, diese Vorgänge sind Teil der eigentlichen Aufgabe.
Verwenden Sie für jeden Zeitmesslauf denselben zusammenhängenden Datenbereich und dieselben Arbeitsmappenbedingungen.
Warum verlangsamen große Calc-Makros die Ausführung?
Eine Schleife, die wiederholt einzelne Zelleneigenschaften aufruft getCellByPosition()oder liest und schreibt, veranlasst Calc, für jede Operation die Schnittstelle zwischen Basic und Calc zu verwenden. Bei vielen Zeilen und Spalten können sich diese Aufrufe summieren, selbst wenn die Transformation selbst einfach ist. Eine Schleife über ein Array im Arbeitsspeicher durchläuft zwar weiterhin jede Zeile, vermeidet aber einen separaten API-Aufruf für jeden Wert.
Entfernen Sie zunächst Operationen, die das Ergebnis nicht beeinflussen: Vermeiden Sie die Auswahl oder Aktivierung von Zellen innerhalb der Schleife, führen Sie keine wiederholten Neuberechnungen oder Formatierungen einer Zelle durch, wenn eine abschließende Bereichsoperation ausreicht, und verarbeiten Sie keine ganzen Spalten, wenn nur ein begrenzter Datenblock benötigt wird. Diese Änderungen helfen, den eigentlichen Engpass zu identifizieren, bevor Sie weitere Steuerelemente hinzufügen.
Wie verarbeitet man einen Bereich als Array?
Verwenden Sie einen rechteckigen Bereich, der nur die Werte enthält, die Ihr Makro ändern soll. Das Beispiel geht von einem Tabellenblatt mit dem Namen „<Tabellenblattname>“ Data, einer Kopfzeile in Zeile 1 und Statuswerten in Spalte C aus. Passen Sie den Tabellenblattnamen und den Bereich an Ihre Arbeitsmappe an. Die API getDataArray()gibt den Bereich als Zeilen mit Werten zurück; das setDataArray()Makro schreibt ein gleich großes Array zurück in diesen Bereich.
Lesen Sie den benötigten rechteckigen Bereich einmal vor der In-Memory-Schleife ein.
Sub UpdateStatuses
Dim oSheet As Object
Dim oRange As Object
Dim aData As Variant
Dim i As Long
oSheet = ThisComponent.Sheets.getByName("Data")
oRange = oSheet.getCellRangeByName("A2:C10001")
aData = oRange.getDataArray()
For i = LBound(aData) To UBound(aData)
If aData(i)(2) = "pending" Then
aData(i)(2) = "review"
End If
Next i
oRange.setDataArray(aData)
End Sub
Das Zeilenarray ist nullbasiert: aData(i)(2)Es adressiert die dritte Spalte jeder Zeile. Hier ist das Spalte C, da der ausgewählte Bereich bei A beginnt. Die äußere Sequenz des Arrays repräsentiert die Zeilen, die innere Sequenz die Spalten. Der übergebene Bereich setDataArray()muss dieselben Dimensionen wie das Array haben; andernfalls wird ein Fehler ausgelöst. Weitere Informationen finden Sie in der LibreOffice XCellRangeData API-Referenz und der LibreOffice ScriptForge-Array-Dokumentation .
Wende die Regel im Speicher an und schreibe dann das fertige Array in einem einzigen Aufruf in Calc.
Formelzellen von reinen Wertaktualisierungen ausschließen
getDataArray()Gibt Zellwerte als Zahlen oder Zeichenketten zurück, nicht den ursprünglichen Formeltext. Wenn Sie einen Bereich mit Formeln lesen und dieses Array mit `XCellRangeFormula()` zurückschreiben setDataArray(), können diese Formeln durch ihre aktuellen Ergebnisse ersetzt werden. Beschränken Sie die Wertarray-Methode auf Eingabe-/Ausgabezellen, die Werte enthalten sollen. Wenn ein Makro Formeln beibehalten oder ändern muss, verwenden Sie die Formelarray-Methoden `XCellRangeFormula()` getFormulaArray()und setFormulaArray()`XCellRangeFormula()` oder arbeiten Sie nur mit dem Bereich ohne Formel. Die API-Referenz zu `XCellRangeFormula` dokumentiert diese separate Schnittstelle.
Wann sollten Sie die Berechnungs- oder Anzeigeeinstellungen ändern?
Testen Sie diese Optionen erst nach der Messung der Array-Version. Wenn die Formelneuberechnung einen Großteil der Laufzeit ausmacht, können Sie eine Abfrage durchführen isAutomaticCalculationEnabled(), die automatische Berechnung vorübergehend deaktivieren enableAutomaticCalculation(False)und anschließend die ursprüngliche Einstellung wiederherstellen und geänderte Zellen bei Bedarf neu berechnen. Platzieren Sie die Wiederherstellung in einem Bereinigungspfad, damit ein Fehler die Arbeitsmappe nicht im manuellen Berechnungsmodus belässt. Deaktivieren Sie die Berechnung nicht, wenn das Makro zwischen den Schritten aktuelle Formelergebnisse benötigt. LibreOffice dokumentiert dies calculate()als Neuberechnung geänderter Zellen; calculateAll()erzwingt eine vollständige Neuberechnung und kann selbst ressourcenintensiv sein. Siehe XCalculatable-API-Referenz .
lockControllers()Kann einige Benachrichtigungen für Anzeigeaktualisierungen unterbrechen, während ein Makro viele Zellen ändert. Kombinieren Sie jede Sperre mit `lock` unlockControllers(), auch wenn das Makro über eine Fehlerbehandlung beendet wird. Dies reduziert den Aufwand für Anzeigeaktualisierungen; Formelberechnungen werden nicht deaktiviert und die Logik pro Zelle wird nicht zu einer Massenoperation. Verwenden Sie es für einen gemessenen Engpass bei der Bildschirmaktualisierung, nicht als Ersatz für Bereichsarrays. Siehe XModel-API-Referenz .
Wie überprüft man die Änderung und wie erkennt man, wann man die Methode wechseln muss?
Führen Sie das überarbeitete Makro in einer Kopie der Arbeitsmappe aus und erfassen Sie die Laufzeit unter denselben Bedingungen wie in der Referenzversion. Vergleichen Sie die betroffenen und nicht betroffenen Zeilen, Formeln und wichtigen Summen. Speichern, schließen und öffnen Sie die Kopie erneut, falls der Produktionsworkflow das Speichern vorsieht. Dadurch können Probleme aufgedeckt werden, die bei einer kurzen Sichtprüfung übersehen wurden. Bei wiederholten Ausführungen sollte sich eine stabile Verbesserung zeigen, solange die Ausgabeprüfungen erfolgreich verlaufen.
Bestätigen Sie die transformierten Werte und erfassen Sie die gemessenen Zeiten, ohne im Voraus von einer Beschleunigung auszugehen.
Wenn das Makro weiterhin den Großteil seiner Zeit mit komplexen Formeln, Formatierung, Datei-E/A oder Sortierung verbringt, sollten Sie diese Phase separat profilieren; Bereichsarrays reduzieren lediglich wiederholte Zellzugriffe. Bei sehr großen Tabellenblättern kann ein vollständig im Arbeitsspeicher befindliches Array ebenfalls viel Speicherplatz beanspruchen. Verarbeiten Sie jeweils nur einige Spalten oder teilen Sie die Zeilen in messbare Blöcke auf, wenn der Speicherdruck steigt, und stellen Sie dabei sicher, dass jeder Block in den vorgesehenen Zeilen beginnt und endet. Wenn die Daten bereits in einer Datenbank vorhanden sind und die Aufgabe das Filtern, Gruppieren oder Aktualisieren von Datensätzen umfasst, ist es möglicherweise sinnvoller, diese Arbeit in eine Datenbankabfrage auszulagern, anstatt jeden Datensatz in Calc zu laden.