Select und Activate

Oder: Geschwindigkeit ist keine Hexerei

Als ich meine ersten Gehver­suche in der Excel-Pro­gram­mierung machte, da gab es nur Makros. „Richtige” Makros, also eine mehr oder weniger große Menge an Excel-Befehlen, die in deutsch­er (!) Namensge­bung untere­inan­der geschrieben und dann nacheinan­der abgear­beit­et wur­den. VBA gab es noch nicht, und mein­er Erin­nerung nach auch keinen Makrorecorder. Mit Ein­führung der VBA-Sprache (Visu­al Basic for Appli­ca­tions) kam dann auch der Makrorecorder und erle­ichterte so manch­es.

In Excel gibt es ihn heute noch und er ist bei­des: Segen und Fluch. Ein Segen, weil schnell und unkom­pliziert ein (meist) lauf­fähiger Code erstellt wer­den kann. Ein Fluch, weil fast immer alles, aber auch wirk­lich alles aufgeze­ich­net wird. Und das macht einen Code sehr oft langsam, unüber­sichtlich, bläht ihm fast immer unnötig auf und macht ihn vielfach auch fehler­an­fäl­lig.

Nichts gegen das aufze­ichen eines Codes, das mache sog­ar ich auch mitunter. Aber es gibt da für mich drei „Gold­ene Regeln”: Nachar­beit­en, nachar­beit­en und noch ein­mal nach­ar­bei­ten. Die bei­den größten „Bösewichte” sind dabei das Select und an zweit­er Stelle das Acti­vate. Bei­de Anweisun­gen sind in über 99% aller Fälle von aufge­zeich­ne­tem Code vol­lkom­men über­flüs­sig. Und bei der Pro­gram­mierung „zu Fuß” fast auch immer. Ich stelle Ihnen hier ein­mal zwecks Demon­stra­tion ein kleines Beispiel vor. Und um Ihnen den Zeitun­ter­schied deut­lich zu machen, lasse ich die Rou­tine 250 Mal durch­laufen. Fol­gen­des passiert in dem Code: Aus Tabelle1 sollen vier Bere­iche nach Tabelle2 kopiert wer­den. Vor dem ein­fü­gen in Tabelle2 soll der Inhalt des Blattes kom­plett gelöscht wer­den. Der per Makrorecorder aufgeze­ich­nete 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 lauf­fähig und macht exakt das, was weit­er oben als Ziel vorge­ge­ben ist. Das geht auch einiger­maßen rasch und außer etwas Bild­schir­mge­flim­mer wer­den Sie bezüglich der Geschwindigkeit nichts auszuset­zen haben. Auf meinem Rech­n­er braucht der Code etwa eine halbe Sekunde. Für genau 1 Durch­lauf, klar.

Zu Demon­stra­tionszweck­en soll ja das Pro­gramm mehrere Durch­läufe absolvieren, um den Unter­schied deut­lich zu machen. Und damit unser Zeit­ge­fühl und keinen Stre­ich spie­len kann, lasse durch Excel die Zeit messen. Nach den 250 Durch­läufen wird dann in ein­er Mes­sage­Box die benötigte Zeit aus­gegeben. Das Work­book mit den Dat­en und den bei­den Tabel­len­blät­tern und natür­lich dem Code kön­nen Sie hier herunter laden. Zum testen sor­gen Sie erst ein­mal dafür, dass Makros (sprich VBA) auch aus­ge­führt wer­den kön­nen und dann AltF8 und führen Sie bitte Makro1 aus. Und ja, das Flim­mern macht auch mich nervös bis aggres­siv, ist aber durch die Form der Aufze­ich­nung und man­gels Nach­bear­beitung nor­mal. „Augen zu und durch …”. 🙁 

Diese eigentlich sehr lange Bear­beitungszeit liegt ganz klar daran, dass der Select – Befehl ein­fach Zeit braucht. Und zwar nicht wenig. Dazu kommt dann auch noch, dass zum selek­tierten Blatt oder zu der Zelle „gesprun­gen” wer­den muss. In der zweit­en Ver­sion des Makros ist prak­tisch kom­plett auf Select verzichtet wor­den. Nur zum Schluss wurde es genutzt, um auf jeden Fall Tabelle2 zum aktuellen Blatt zu machen und den Cur­sor auf A1 zu set­zen. Die bei­den Makros Makro2a und Makro2b unter­schei­den sich nur mar­gin­al. Dadurch, dass Makro2a in einem all­ge­meinen Mod­ul liegt muss erst ein­mal dafür Sorge getra­gen wer­den, dass Tabelle1 auf jeden Fall die Quelle für die Dat­en ist. Der Code des Makro2b liegt bere­its in Tabelle1 und dadurch ist der „Umweg” nicht erforder­lich.

Sie wer­den erken­nen, dass der Geschwindigkeits­gewinn bedeu­tend ist. Und das Ganze ohne die Selectier­erei. Die Nachar­beit per Hand hat sich gelohnt und es sind auch erhe­blich weniger Zeilen Code. Etwas Zeit­gewinn kön­nen Sie noch her­aus­holen, wenn Sie kom­plett auf die Bild­schir­mak­tu­al­isierung verzicht­en und auch noch die Neu­be­rech­nung des Tabel­len­blattes bei jed­er Änderung verzicht­en. Das geschieht in Makro3.

Unter Umstän­den lässt sich noch mehr an Geschwindigkeits­gewinn erzie­len. Aber das passt ein­fach nicht zum Haupt-The­ma, dem weit­ge­hen­den Verzicht auf das Select und Acti­vate. – Selb­stver­ständlich ist bei jeglichem Code in diesem Blog auf diese unnöti­gen Anweisun­gen verzichtet wor­den. Und genau so selb­stver­ständlich sollte es sein, dass sich dieser Verzicht auf jeglichen Code bezieht, ob nun per Makrorecorder aufgeze­ich­net oder von Hand geschrieben.

[NachOben­Let­zte Verweis=„T&T: Select u. Acti­vate”]
Dieser Beitrag wurde unter Coding / Programmieren, Downloads, Tipps und Tricks abgelegt und mit , , , , , verschlagwortet. Setze ein Lesezeichen auf den Permalink.