Oder: Geschwindigkeit ist keine Hexerei
Als ich meine ersten Gehversuche in der Excel-Programmierung machte, da gab es nur Makros. „Richtige” Makros, also eine mehr oder weniger große Menge an Excel-Befehlen, die in deutscher (!) Namensgebung untereinander geschrieben und dann nacheinander abgearbeitet wurden. VBA gab es noch nicht, und meiner Erinnerung nach auch keinen Makrorecorder. Mit Einführung der VBA-Sprache (Visual Basic for Applications) kam dann auch der Makrorecorder und erleichterte so manches.
In Excel gibt es ihn heute noch und er ist beides: Segen und Fluch. Ein Segen, weil schnell und unkompliziert ein (meist) lauffähiger Code erstellt werden kann. Ein Fluch, weil fast immer alles, aber auch wirklich alles aufgezeichnet wird. Und das macht einen Code sehr oft langsam, unübersichtlich, bläht ihm fast immer unnötig auf und macht ihn vielfach auch fehleranfällig.
Nichts gegen das aufzeichen eines Codes, das mache sogar ich auch mitunter. Aber es gibt da für mich drei „Goldene Regeln”: Nacharbeiten, nacharbeiten und noch einmal nacharbeiten. Die beiden größten „Bösewichte” sind dabei das Select und an zweiter Stelle das Activate. Beide Anweisungen sind in über 99% aller Fälle von aufgezeichnetem Code vollkommen überflüssig. Und bei der Programmierung „zu Fuß” fast auch immer. Ich stelle Ihnen hier einmal zwecks Demonstration ein kleines Beispiel vor. Und um Ihnen den Zeitunterschied deutlich zu machen, lasse ich die Routine 250 Mal durchlaufen. Folgendes passiert in dem Code: Aus Tabelle1 sollen vier Bereiche nach Tabelle2 kopiert werden. Vor dem einfügen in Tabelle2 soll der Inhalt des Blattes komplett gelöscht werden. Der per Makrorecorder aufgezeichnete Code sieht so aus:
Sub Makro1() ' ' Makro1 Makro ' Per Makrorecorder aufgezeichneter Code Sheets("Tabelle2").Select Cells.Select Selection.ClearContents Sheets("Tabelle1").Select Range("A1:B5").Select Selection.Copy Sheets("Tabelle2").Select Range("A1").Select ActiveSheet.Paste Sheets("Tabelle1").Select Range("A16:B20").Select Application.CutCopyMode = False Selection.Copy Sheets("Tabelle2").Select Range("A16").Select ActiveSheet.Paste Sheets("Tabelle1").Select Range("D1:F5").Select Application.CutCopyMode = False Selection.Copy Sheets("Tabelle2").Select Range("D1").Select ActiveSheet.Paste Sheets("Tabelle1").Select Range("C10:F15").Select Application.CutCopyMode = False Selection.Copy Sheets("Tabelle2").Select Range("C10").Select ActiveSheet.Paste Application.CutCopyMode = False Sheets("Tabelle1").Select Range("A1").Select End Sub
Der Code ist genau so lauffähig und macht exakt das, was weiter oben als Ziel vorgegeben ist. Das geht auch einigermaßen rasch und außer etwas Bildschirmgeflimmer werden Sie bezüglich der Geschwindigkeit nichts auszusetzen haben. Auf meinem Rechner braucht der Code etwa eine halbe Sekunde. Für genau 1 Durchlauf, klar.
Zu Demonstrationszwecken soll ja das Programm mehrere Durchläufe absolvieren, um den Unterschied deutlich zu machen. Und damit unser Zeitgefühl und keinen Streich spielen kann, lasse durch Excel die Zeit messen. Nach den 250 Durchläufen wird dann in einer MessageBox die benötigte Zeit ausgegeben. Das Workbook mit den Daten und den beiden Tabellenblättern und natürlich dem Code können Sie hier herunter laden. Zum testen sorgen Sie erst einmal dafür, dass Makros (sprich VBA) auch ausgeführt werden können und dann AltF8 und führen Sie bitte Makro1 aus. Und ja, das Flimmern macht auch mich nervös bis aggressiv, ist aber durch die Form der Aufzeichnung und mangels Nachbearbeitung normal. „Augen zu und durch …”. 🙁
Diese eigentlich sehr lange Bearbeitungszeit liegt ganz klar daran, dass der Select – Befehl einfach Zeit braucht. Und zwar nicht wenig. Dazu kommt dann auch noch, dass zum selektierten Blatt oder zu der Zelle „gesprungen” werden muss. In der zweiten Version des Makros ist praktisch komplett auf Select verzichtet worden. Nur zum Schluss wurde es genutzt, um auf jeden Fall Tabelle2 zum aktuellen Blatt zu machen und den Cursor auf A1 zu setzen. Die beiden Makros Makro2a und Makro2b unterscheiden sich nur marginal. Dadurch, dass Makro2a in einem allgemeinen Modul liegt muss erst einmal dafür Sorge getragen werden, dass Tabelle1 auf jeden Fall die Quelle für die Daten ist. Der Code des Makro2b liegt bereits in Tabelle1 und dadurch ist der „Umweg” nicht erforderlich.
Sie werden erkennen, dass der Geschwindigkeitsgewinn bedeutend ist. Und das Ganze ohne die Selectiererei. Die Nacharbeit per Hand hat sich gelohnt und es sind auch erheblich weniger Zeilen Code. Etwas Zeitgewinn können Sie noch herausholen, wenn Sie komplett auf die Bildschirmaktualisierung verzichten und auch noch die Neuberechnung des Tabellenblattes bei jeder Änderung verzichten. Das geschieht in Makro3.
Unter Umständen lässt sich noch mehr an Geschwindigkeitsgewinn erzielen. Aber das passt einfach nicht zum Haupt-Thema, dem weitgehenden Verzicht auf das Select und Activate. – Selbstverständlich ist bei jeglichem Code in diesem Blog auf diese unnötigen Anweisungen verzichtet worden. Und genau so selbstverständlich sollte es sein, dass sich dieser Verzicht auf jeglichen Code bezieht, ob nun per Makrorecorder aufgezeichnet oder von Hand geschrieben.
[NachObenLetzte Verweis=„T&T: Select u. Activate”]