Autor: Peter Haserodt --- Aus Excel VBA - Gruppe:
GrundlagenAchtung Makrorekorder oder Wer selektiert denn da?
Autor: Peter Haserodt - Erstellt: -- - Letzte Revision: --
Der Makrorekorder: Freund und Feind
oder:
Bitte kein Select
Vorbemerkung:
Ich gehe davon aus, dass Sie zumindest rudimentär mit dem Makrorekorder umgehen können,
es wird sicherlich auch dazu nochmal einen Artikel geben.
Zumindest wohin er aufzeichnet und der Unterschied zwischen realtiven und absoluten Aufzeichnung setze ich voraus.
Dieser Artikel soll Ihnen helfen, den Makrorekorder zu hinterfragen und den aufgezeichneten Code zu entschlacken.
Weiterhin soll er mit diesem unsäglichem Select und Activate aufräumen.
Nehmen Sie sich eine leere Arbeitsmappe mit 3 Tabellenblättern Tabelle1 bis Tabelle3 (Also standard)
Bevor ich loslege, zeichnen Sie bitte etwas auf:
Dafür markieren Sie zuerst die Zelle A1 im Tabelle1.
Starten Sie nun den Makrorekorder und wählen die absolute Aufzeichnung (Schaltfläche hervorgehoben)
Markieren Sie nun Zelle B3 und schreiben dort eine 1 hinein, dann Zelle B4 und eine 2, dann Zelle B5 und das Wort Haus,
dann die Zelle B6.
Stoppen Sie dann den Makrorekorder.
Folgender Code sollte nun vorhanden sein.
(Mit einem kleinen Unterschied, von wem aufgezeichnet)
Sub Makro1()
'
' Makro1 Makro
' Makro am 20.05.2005 von PH aufgezeichnet
'
'
Range("B3").Select
ActiveCell.FormulaR1C1 = "1"
Range("B4").Select
ActiveCell.FormulaR1C1 = "2"
Range("B5").Select
ActiveCell.FormulaR1C1 = "Haus"
Range("B6").Select
End Sub
Dieser Code funktioniert, ist aber völlig absurd.
Es ist ganz wichtig zu verstehen, dass der Makrorekorder nicht vorher wissen kann, was Sie erreichen wollen (nämlich die Werte in die Zellen zu schreiben) und das er mit standardisierten Eigenschaften arbeitet.
Was macht er?
Er zeichnet genau Ihre Bewegungen auf und Ihre Eingaben.
Er kann nicht wissen ob Sie nur die Zelle füllen wollen oder ob Sie auch dorthingehen wollen.
Er benutzt eine Eigenschaft (FormulaR1C1) des Rangeobjektes, die für alle möglichen Eingaben von ihm genutzt werden kann. Er standardisiert also.
(Jedem ist klar, dass keine Formel eingegeben wurde, trotzdem benutzt er die Formula Eigenschaft und zwar in einer ganz besonderen Form, mehr dazu später)
Damit wir aber überhaupt verstehen können, wie wir den ganzen Müll entsorgen können, wird ein kleiner Ausflug notwendig, der uns über Namen, verschiedene Bezeichnungen für ein und dasselbe näher bringt:
Der Malermeister und sein Geselle
Malermeister PinselGut und sein Geselle JawollChef stehen in der Küche in einer Wohnung.
Nun möchte PinselGut, dass JawollChef das Wohnzimmer blau streicht.
Wenn er jetzt sagen würde: Streiche DasZimmerInDemDuBist blau, müsste die Küche darunter leiden.
Will er also die Bezeichnung: DasZimmerInDemDuBist benutzen, muss er JawollChef erst ins Wohnzimmer dirigieren,
damit dies zum DasZimmerInDemDuBist wird.
Somit habe ich schon zwei Bezeichnungen für das Wohnzimmer: Nämlich der Name selbst und DasZimmerInDemDuBist, wenn die angesprochene Person sich darin befindet.
In unserem Codebeispiel ist z.B. Range("B2") das Wohnzimmer und ActiveCell DasZimmerInDemDuBist.
Eine weitere Option für die Wohnung wäre z.B. das alle Zimmer eine Nummer hätten (auf einem Grundriss).
Hat das Wohnzimmer die Nummer 5 könnte PinselGut dies auch mit : Raum 5 bezeichnen.
Sie sehen, nun haben wir schon 3 Möglichkeiten, auf das Wohnzimmer zuzugreifen, jeweils unter anderen Bezeichnungen aber immer ist dasselbe Zimmer gemeint.
(Das dritte Beispiel soll jetzt schon vorbereiten, dass ich eine Zelle auch über eine Aufzählung ansprechen kann)
Betrachten wir nun nochmal das ganze von der Excelseite:
Ich habe eine Zelle, z.B. die Zelle B3.
Ich kann Sie ansprechen über den Namen, nämlich Range("B3").
Habe ich sie markiert und selektiert, ist es die Aktive Zelle und und ich kann sie über ActiveCell ansprechen.
Ich kann ich sie auch über eine Aufzählung: Cells(3,2) ansprechen, wobei hier zuerst die Reihe und dann die Spalte genannt wird.
Zum Teufel mit dem selektieren.
PinselGut wird aber bestimmt nicht zu seinem Gesellen sagen:
Gehe ins Wohnzimmer und streiche dann das ZimmerInDemDuBist blau, sondern: Streiche das Wohnzimmer blau.
Eigentlich ist das Beispiel noch etwas unglücklich, den VBA technisch gesehen (wenn wir davon ausgehen, dass es nur um die Wände geht) müsste er in etwa sagen: Gib den Wänden des Wohnzimmers die Eigenschaft blau.
Analysieren wir 2 Zeilen unseres Codes:
Range("B3").Select
ActiveCell.FormulaR1C1 = "1"
Hier habe ich genau das unerwünschte Szenario: Anstatt direkt das Zimmer zu bezeichnen, mache ich einen Umweg.
Ich sage: Selektiere Range("B3"), mache es dadurch zur aktiven Zelle, damit ich es mit dem Namen ActiveCell ansprechen kann.
Und schon können wir das ganze lösen:
Range("B3").FormulaR1C1 = "1"
Löschen Sie den Tabelleninhalt, ändern Sie den Code und führen Sie ihn aus.
Es funktioniert. Wir haben die Zelle B3 direkt gefüllt ohne zu selektieren.
Merksatz:
Zu 99,9 Prozent ist das markieren, selektieren, aktivieren nicht nur völlig überflüssig, sondern auch völlig unsinnig.
Es kostet Rechenzeit, kann zu Bildschirmflackern führen (auch wenn man dies ausstellen kann) und und und ...
Ändern Sie nun Ihren Code dahingehend komplett, dass alle Selektiererei verschwindet,
schmeißen Sie auch noch die letzte Zeile raus, denn nach B6 wollen wir doch gar nicht.
Starten Sie dann den Code und Sie sehen, die Markierung bleibt an der aktuellen Zelle und trotzdem wird gefüllt.
Der Code könnte so aussehen:
Sub MeinMakro()
Range("B3").FormulaR1C1 = "1"
Range("B4").FormulaR1C1 = "2"
Range("B5").FormulaR1C1 = "Haus"
End Sub
Die "falsche" Eigenschaft
Ein weiteres Manko des Makrorekordes ist seine Standardisierung auf FormulaR1C1, beim schreiben in eine Zelle.
Eine Zelle hat viele Eigenschaften (z.B. Schriffarbe, Füllfarbe) , die ich je nachdem, was ich tun will, ansprechen muss.
Um etwas in eine Zelle zu schreiben, gibt es einige Eigenschaften, die ich ansprechen kann.
Will ich Formeln in eine Zelle schreiben, muss ich eine Eigenschaft benutzen, die mit Formula beginnt.
Davon gibt es aber einige und sind hier:
Formeln in Zellen schreiben
erklärt.
In unserem Beispielcode schreiben wir aber keine Formeln, sondern nur Inhalte.
Deswegen sollte dafür auch die Eigenschaft Value benutzt werden.
Sub MeinMakroNeu()
Range("B3").Value = 1
Range("B4").Value = 2
Range("B5").Value = "Haus"
End Sub
Tatsächlich könnte ich auch das .Value weglassen, da es die Default Eigenschaft ist.
Ein Geselle geht auf Reisen
Bis jetzt haben wir nur im aktiven Tabellenblatt gearbeitet.
Dies wollen wir nun ändern.
Markieren Sie wieder Zelle A1 in Tabelle1 und starten Sie den Makrorekorder.
Gehen Sie dann zur Tabelle2 markieren dort die Zelle B2 und schreiben dort 5 hinein,
dann gehen Sie zur Tabelle3 markieren dort C4 und schreiben Maus.
Gehen Sie dann wieder zu Tabelle 1 und markieren A1.
Beenden Sie nun die Aufzeichnung.
Der Code sollte dann in etwa so aussehen (hier nur die interessanten Zeilen):
Sheets("Tabelle2").Select
Range("B2").Select
ActiveCell.FormulaR1C1 = "5"
Sheets("Tabelle3").Select
Range("C4").Select
ActiveCell.FormulaR1C1 = "Maus"
Sheets("Tabelle1").Select
Range("A1").Select
Malermeister PinselGut will diesmal, dass sein Geselle nicht in der Wohnung, in welcher er sich befindet, etwas arbeitet, sondern in einer anderen Wohnung des Hauses.
Er würde vielleicht sagen:
Streiche das Wohnzimmer im Erdgeschoss blau
Und nicht:
Gehe ins Erdgeschoss, gehe dort ins Wohnzimmer, streiche DasZimmerInDemDuBist blau.
Es reicht hier nicht, einfach Wohnzimmer zu sagen, da sonst der Geselle davon ausgehen muss, dass er das Wohnzimmer der aktuellen Wohnung bearbeiten soll.
Nein, ich muss es näher bezeichnen mit : Erdgeschoss.Wohnzimmer
In Excel VBA kann ich ein Tabellenblatt über Sheets("DerName") z.B. ansprechen.
(Auch hier arbeitet der Makrorekorder wieder unsauber, da es präziser Worksheets heißen müsste aber alles können wir hier nicht behandeln)
Mittlerweile sind wir aber schon geübt und können wunderbar das ganze zusammenziehen:
Sheets("Tabelle2").Select
Range("B2").Select
ActiveCell.FormulaR1C1 = "5"
wird zu:
Sheets("Tabelle2").Range("B2").Value = 5
Ich bezeichne mein Ziel genauer, indem ich noch die Tabelle hinzunehme.
Der ganze Code reduziert sich auf:
Sheets("Tabelle2").Range("B2").Value = 5
Sheets("Tabelle3").Range("C4").Value = "Maus"
Testen Sie es.
Und dies zieht sich noch weiter fort.
Wenn JawollChef sogar in ein anderes Haus soll, wird PinselGut sagen:
Streiche das Wohnzimmer im Erdgeschoss in Haus Sonnenschein blau.
Können Sie sich vorstellen, was dem in Excel entspricht?
Ganz einfach, Sie haben eine andere Arbeitsmappe noch geöffnet und wollen dort per Code hineinschreiben.
Dies überlasse ich nun Ihnen, einen solchen Code aufzuzeichen und zu bearbeiten.
Zwischenbemerkung
Wir sehen, der Makrorekorder zeichnet viel unnötiges auf.
Aber er hilft uns auch. Z.B. konnten wir sehen, wie man ein anderes Tabellenblatt anspricht, er hat uns mit Sheets bekannt gemacht (und wer sich an das letzte Experiment gewagt hat, lernte dort Workbooks kennen)
Aber wenn ich vernünftigen Code schreiben will, benutze ich auf keinen Fall den aufgezeichneten Code, sondern schreibe ihn selber, wobei ich mir fehlende Informationen mit Hilfe des Makrorekorders hole.
Arbeiten mit Bereichen und mehr ...
Gehen Sie nun wieder in Tabelle1 auf A1 und starten Sie den Makrorekorder.
Markieren Sie nun die Zellen B2 bis D5.
Geben Sie ihnen die Hintergrundfarbe gelb.
Markieren Sie wieder A1.
Beenden Sie die Aufzeichnung, der Code:
Range("B2:D5").Select
With Selection.Interior
.ColorIndex = 6
.Pattern = xlSolid
End With
Range("A1").Select
Diesmal bietet der Makrorekorder mir etwas anderes an, nämlich Selection.
Er arbeitet in solchen Fällen immer mit dem Selectionobjekt, für uns aber schon kein Problem mehr.
Wir sehen: Range("B2:D5").Select und schon können wir erahnen, dass wir Selection einfach mit der Bezeichnung ersetzen können, also geschwind den ganzen Code geändert in:
Sub Farbe()
With Range("B2:D5").Interior
.ColorIndex = 6
.Pattern = xlSolid
End With
End Sub
Hier kommt aber noch mehr dazu.
Auf einmal kommt ein With Konstrukt.
Damit kann man wunderbar mehrere Unterpunkte eines Objektes einfassen.
Der Makrorekorder hat mit folgende Information gegeben:
Um einem Bereich die Hintergrundfarbe Gelb zu geben empfiehlt er:
Benutze die Eigenschaft Interior und deren Untereigenschaft ColorIndex,
und um sicherzustellen, dass dies auch ausgefüllt ist,
benutze die Eigenschaft Interior und deren Untereigenschaft Pattern (und setze die auf solid)
Mein Code könnte auch so aussehen:
Sub Farbe()
Range("B2:D5").Interior.ColorIndex = 6
Range("B2:D5").Interior.Pattern = xlSolid
End Sub
Mit dem With Konstrukt kann ich aber das "Überobjekt" mehrfach ansprechen, also in unserem Fall
Range("B2:D5").Interior
Schlussbemerkung:
Uups, dies ist ja ganz schön lang geworden.
(und könnte durchaus noch länger sein aber selbst herausfinden macht schön
)
Dieser Artikel kann Ihnen nur ansatzweise aufzeigen, wie man vom Makrorekorder aufgezeichneten Code nutzt, um dann daraus vernünftigen Code zu machen.
Selbstverständlich müssen Sie sich intensiv mit den Objekten beschäftigen und einiges studieren.
Was ich aber hoffentlich erreicht habe, ist, dass Sie in Zukunft jedes Select und Activate hinterfragen.
Leider gibt es Buchautoren, die in ihren Büchern solch einen Rekordermüll schreiben und damit dem Leser vorgaukeln,
so müsse es sein. (Ich denke mal, weil sie es selber glauben)
Deswegen zum Abschluss nochmals:
Select und Activate sind zu 99,9 Prozent überflüssig.
Weitere Artikel der Gruppe: Grundlagen Aus Excel VBA
Nach oben