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_OnLoad und 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 long wird zu Dim 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 Foo ergänzt die fehlenden Klammern zu Sub Foo(), schreibt End Sub darunter und setzt den Cursor eingerückt dazwischen, ebenso bei If … Then, For, Do, With, Select Case, Function, Property, Type und Enum. Geschlossen wird nur, wenn der Abschluss wirklich noch fehlt — in einer fertigen Prozedur passiert nichts. Ein einzeiliges If x Then Exit Sub schließt sich in VBA selbst und bekommt deshalb kein End If. End If, Else, Case und Next rü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 F12 oder Strg-Klick, und Umbenennen mit F2 — beides für Prozeduren, die in diesem Modul deklariert sind. Liegt die Prozedur woanders, zeigt der Mauszeiger-Hinweis Signatur und Herkunft.

  • Option Explicit wird 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 korrekter Sub-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.19 rechnet dann in eine Variable, die niemand liest, und das Ergebnis bleibt einfach falsch. Mit Option Explicit meldet 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. Public ist dabei der Normalfall: ohne Schlüsselwort ist ein Sub in 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 Public ist. 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. ActiveSheet und Selection meinen 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.