Code und Callbacks
Wo dein VBA landet, wie es aufgerufen wird und was du nicht wissen musst.
Jedes Steuerelement kann VBA hinterlegt haben. Du schreibst es im Editor rechts, im selben Feld, in dem auch die Snippet-Bibliothek einfügt.
Was generiert wird
Aus deinem Projekt entstehen zwei Module:
- Callbacks enthält
Ribbon_OnLoadund die Verteiler, die Excel aufruft. - UserCode enthält deinen Code, unverändert, ein Block pro Steuerelement.
Der Verteiler schaut sich die Id des geklickten Elements an und ruft deine
Prozedur. Du musst dich um IRibbonControl nicht kümmern, es sei denn, du
willst.
Dein Code beginnt mit einer Prozedur:
Sub ExportStarten()
MsgBox "Export läuft"
End Sub
Steht darunter weiterer Code, bleibt er erhalten. Aufgerufen wird die erste deklarierte Prozedur, sofern du unter Einstiegspunkt nichts anderes angibst.
Warum die Prozedurnamen ein Anhängsel haben
Im VBE siehst du Namen wie Ribbon_OnLoad_40YQU2. Das ist Absicht.
Excel löst einen Ribbon-Callback nicht innerhalb deines Add-Ins auf, sondern über alle geladenen VBA-Projekte, und der erste Treffer gewinnt. Zwei Add-Ins mit gleichnamigen Verteilern würden sich gegenseitig abfangen: der Klick in Add-In A landet im Verteiler von B, der die Id nicht kennt, und es passiert nichts. Ohne Fehlermeldung.
Das Anhängsel wird aus Projektname und Struktur berechnet. Es bleibt gleich, solange sich am Projekt nichts ändert, und ist zwischen zwei Projekten verschieden.
Deine eigenen Prozedurnamen bleiben unangetastet.
Eigene Module
Unter Module legst du vollwertige VBA-Module an, die im Projekt
landen. Alles, was dort Public ist, kannst du aus jedem Steuerelement heraus
aufrufen. Umbenannt wird über den Stift neben dem Namen, in der Liste und
im Kopf des Editors. Erlaubt sind Buchstaben A–Z, Ziffern und _, ohne
Umlaute und Leerzeichen; passt ein Name nicht, steht darunter, warum.
Zwei Regeln, die die Validierung durchsetzt: Modulnamen müssen eindeutig sein,
auch gegen Formularnamen, und ein Public Sub oder eine Public Const darf es
im ganzen Projekt nur einmal geben. VBA kompiliert sonst nicht, und die
Meldung zeigt dann auf eine ganz andere Stelle.
Eine dritte Regel betrifft die Ids der Steuerelemente: Das erzeugte VBA benennt
den Sub eines Knopfs nach seiner Id. Heißt ein Knopf wie ein Public Sub in
einem Modul, etwa weil du ihn nach seinem Makro benannt hast, gäbe es zwei
gleichnamige Subs, und Excel meldet beim ersten Aufruf „Mehrdeutiger Name“. Die
Validierung nennt beide Stellen vorab. Die Ids, die der Editor selbst vergibt
(btn_…), stoßen damit nicht zusammen.
Aufrufe vervollständigen
Im Code-Editor schlägt der Editor beim Tippen die Prozeduren vor, die von genau dieser Stelle aus aufrufbar sind. Dahinter steht derselbe Parser, mit dem die Validierung nach doppelten Namen sucht; was hier angeboten wird, existiert also auch wirklich.
Nach Call öffnet sich die Liste von selbst. Von Hand: Strg+Umschalt+Leertaste,
auf dem Mac Cmd+Umschalt+Leertaste. Monacos eigenes Strg+Leertaste geht
auch — auf dem Mac allerdings nur, wenn dort nicht die Umschaltung der
Eingabequelle daraufliegt, was der Standard ist, sobald man mehr als eine hat.
Übernommen wird mit Tab, nicht mit Enter — wie in der VBE. Enter
beendet immer die Zeile. Andersherum kostet es eine Taste, sobald die Liste
offensteht, während man die Zeile fertig schreibt: der erste Enter nimmt dann
einen Vorschlag an, der meist gar nichts sichtbar ändert, und erst der zweite
bricht die Zeile um.
Auf dem Kopf einer Prozedur wird nichts vorgeschlagen. Dort vergibst du einen neuen Namen, statt einen vorhandenen zu rufen — und der Name, den du gerade tippst, steht selbst schon im Index, sobald er lesbar ist.
Was der Editor sonst noch aus der VBE kennt
-
Schlüsselwörter werden großgeschrieben, sobald du die Zeile verlässt:
dim x as longwird zuDim x As Long. Das ist zugleich eine Prüfung — was nicht großgeschrieben wird, ist nicht das Schlüsselwort, für das du es gehalten hast. Deine eigenen Namen bleiben unangetastet, ebenso alles in Zeichenketten und Kommentaren. -
Blöcke schließen sich selbst und rücken ein. Enter hinter
Sub Fooergänzt die fehlenden Klammern zuSub Foo(), schreibtEnd Subdarunter und setzt den Cursor eingerückt dazwischen, ebenso beiIf … Then,For,Do,With,Select Case,Function,Property,TypeundEnum. Geschlossen wird nur, wenn der Abschluss wirklich noch fehlt — in einer fertigen Prozedur passiert nichts. Ein einzeiligesIf x Then Exit Subschließt sich in VBA selbst und bekommt deshalb keinEnd If.End If,Else,CaseundNextrücken beim Tippen von selbst wieder aus. -
Parameterhilfe: beim Tippen der Argumente steht die Signatur da, der Parameter, an dem du gerade bist, ist hervorgehoben.
-
Zur Deklaration springen mit
F12oder Strg-Klick, und Umbenennen mitF2— beides für Prozeduren, die in diesem Modul deklariert sind. Liegt die Prozedur woanders, zeigt der Mauszeiger-Hinweis Signatur und Herkunft. -
Option Explicitwird in eigenen Modulen als Hinweis über dem Code angeboten, wenn die Zeile fehlt — mit einer Schaltfläche, die sie einfügt. Bewusst kein Marker im Code: es ist ein Rat, kein Fehler, das Modul kompiliert auch ohne, und eine Markierung müsste auf irgendeine Zeile zeigen. Sie landete auf Zeile 1 und färbte, was da stand — meist ein völlig korrekterSub-Kopf. Der Grund für den Rat ist trotzdem unangenehm: ohne sie legt VBA bei einem Tippfehler im Variablennamen still eine neue, leere Variable an, statt einen Fehler zu melden.gesmat = gesamt * 1.19rechnet dann in eine Variable, die niemand liest, und das Ergebnis bleibt einfach falsch. MitOption Explicitmeldet Excel beim Kompilieren „Variable nicht definiert". In den Modulen, die addin.studio selbst erzeugt, steht die Zeile bereits. In deinen Code – Knopf-Code und Formular-Code – setzt der Export sie nur, wenn du sie selbst oben hinschreibst. Code, der in deiner Mappe ohne die Zeile lief, läuft so auch im Add-in. -
Nicht deklarierte Namen werden markiert — gelb hinterlegt, mit dem Namen in der Meldung. Dieselbe Prüfung, die Excel beim Kompilieren macht, nur sofort. Hinterlegt statt unterstrichen: eine Wellenlinie unter sechs Buchstaben bei 12 px sieht schlicht niemand.
Die beiden Stufen sehen deshalb verschieden aus, nicht nur verschieden farbig: ein Hinweis ist ein hinterlegter Name, ein Fehler eine rote Wellenlinie. Beides zugleich hiesse zweimal dasselbe sagen — und Bernstein auf Bernstein liest sich bei 12 px wie ein wütendes Rot. Der Editor kennt dafür deine Deklarationen, die Prozeduren des Projekts, seine öffentlichen Konstanten und Variablen, die Modulnamen und das ganze Excel-Objektmodell samt Konstanten.
Wichtig dabei: er sieht immer das ganze generierte Modul, nicht nur den Ausschnitt vor dir. Der Code aller Steuerelemente landet in einem Modul, die Ereignisse eines Formulars in dessen Klassenmodul — was du an einer Stelle deklarierst, gilt auch an der anderen.
Nicht dabei ist alles, was einen laufenden Interpreter braucht: Haltepunkte, Direktfenster, Lokal- und Überwachungsfenster. Dafür müsste Excel im Browser laufen.
Vorgeschlagen wird nur, was VBA an dieser Stelle auch findet:
- Alles Public aus den eigenen Modulen, überall im Projekt.
Publicist dabei der Normalfall: ohne Schlüsselwort ist einSubin einem Modul öffentlich. - Private nur im eigenen Modul. Das ist die ganze Bedeutung von
Private: die Prozedur existiert für ihr Modul und für sonst niemanden — nicht versteckt, sondern von außen schlicht nicht auffindbar. - Der Code aller Steuerelemente liegt zusammen in einem einzigen
generierten Modul. Ein
Private Sub, das du unter einem Knopf schreibst, kannst du deshalb aus jedem anderen Knopf aufrufen — aus einem eigenen Modul dagegen nicht. - Ein Formular ist ein Klassenmodul. Was dort steht, gilt nur innerhalb
dieses Formulars, auch wenn es
Publicist. Umgekehrt sieht das Formular alles Öffentliche aus dem Projekt.
Nach Call wird mit Klammern eingefügt (Call Foo(a, b)), ohne Call ohne
(Foo a, b) — beides ist gültiges VBA, aber nicht austauschbar.
Excel selbst vervollständigen
Nach einem Punkt schlägt der Editor die Member des Objekts vor, auf dem du
stehst — ws. zeigt die Eigenschaften und Methoden eines Worksheets, mit der
Beschreibung aus Microsofts eigener Dokumentation.
Damit das stimmt, liest der Editor mit, was du deklariert hast: Dim ws As Worksheet reicht. Ohne Deklaration hilft nur der Name selbst — die globalen
Namen sind bekannt (Application, ActiveSheet, ThisWorkbook, Selection,
Range, Cells und ein paar mehr).
Auch Ketten funktionieren, solange die Dokumentation den Rückgabetyp nennt:
Dim ws As Worksheet
ws.Range("A1").Interior.
zeigt die Interior-Member, weil Range ein Range zurückgibt und Interior ein
Interior. Nennt die Dokumentation keinen Typ, hört die Kette dort auf und es
kommt nichts — lieber keine Vorschläge als die des falschen Objekts.
Dazu die Konstanten: ab zwei getippten Zeichen stehen xlUp, xlValues
und die übrigen 2244 in der Liste, mit ihrer Aufzählung und ihrem Wert.
Abgedeckt sind 46 Objekte mit rund 2200 Membern — die, die in Add-In-Code tatsächlich vorkommen, nicht das vollständige Modell mit seinen 344 Objekten.
Bibliothek
Wiederkehrende Routinen speicherst du einmal als Snippet und fügst sie überall ein. Snippets gehören dir allein, niemand sonst sieht sie.
Keine Passwörter in den Code
Schreib keine Passwörter, API-Schlüssel oder Zugangsdaten direkt ins VBA. Zwei Gründe:
- Im fertigen Add-in steht der Code im Klartext. Jeder, der die
.xlam-Datei bekommt, öffnet den VBA-Editor und liest mit. Ein VBA-Projektkennwort hält davon nicht ab, dafür gibt es frei verfügbare Werkzeuge. - Dein Projekt liegt bei uns in der Datenbank. Dort ist es an dein Konto gebunden und für andere Nutzer unsichtbar, aber nicht Ende-zu-Ende verschlüsselt. Was wir mit dem Zugriff machen und was nicht, steht in der Datenschutzerklärung.
Besser: den Wert zur Laufzeit abfragen (InputBox, ein Anmeldedialog) oder
aus einer Datei bzw. Umgebungsvariable lesen, die nur auf dem Rechner des
Anwenders liegt. Serverpfade und Laufwerksbuchstaben sind unkritischer, aber
auch die verraten etwas über die Umgebung, in der das Add-in läuft.
Code-Tester
In der Steuerelement-Palette gibt es den Code-Tester als fertigen Baustein:
ein großer Knopf, der im Add-in ein Fenster öffnet. Dort tippst oder kopierst
du VBA hinein und startest es mit Ausführen oder Strg+Enter. Gestartet
wird das erste Sub ohne Parameter.
- Ausgeführt wird in einer unsichtbaren Hilfsmappe, die danach ungespeichert
geschlossen wird. Deine Arbeitsmappe bekommt also kein Modul.
ActiveSheetundSelectionmeinen trotzdem dein Blatt und deine Markierung. - Nach dem Ausführen öffnet sich das Fenster wieder, mit deinem Code und einer Statuszeile, damit du ändern und erneut starten kannst.
- Excel muss dafür den Zugriff auf das VBA-Projektobjektmodell erlauben: Datei › Optionen › Trust Center › Einstellungen für das Trust Center › Makroeinstellungen. Ist das aus, sagt der Tester genau das.
Der Code-Tester gehört zu den Plänen mit eigenem VBA (Free und Pro). Er gibt jedem, der das Add-in benutzt, die Möglichkeit, Code auszuführen — in ein Add-in für Kollegen gehört er deshalb nur, wenn das gewollt ist.