Ribbon für VBA – Dynamischer Mehrwert

Seit der letzten Bastelei verhält sich das Ribbon ja schon ziemlich gut und aktualisiert sich brav selbst. Nun sollte ja noch abhängige Funktionalität dazu, nämlich ein Ribbon was nur mit einer bestimmten Vorlage angezeigt wird. Gucken wir doch mal was sich machen lässt.

Briefgeschichten

Als erste Aktion separieren wir mal die „normalen“ Templates von denen mit VBA-Code intus. Dann wird einfach ein leeres Dokument geöffnet und das ganze als neue brief.dotx in das templates Verzeichnis gelegt.

Mit Ribbon X Editor kann jetzt der XML-Code in die Briefvorlage integriert werden. Grundsätzlich sieht das dem VBACore sehr ähnlich aus, allerdings wird kein onLoad Ereignis hinterlegt. Es wird aber trotzdem auf die zentrale VBA-Methode für das Klicken verwiesen.

<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui">
  <ribbon>
    <tabs>
      <tab id="VBACore" label="Mein VBA" >
        <group id="Brief" label="Briefkram">
            <button   id="BriefButton" 
                    label="Brief groß"
                    size="large"
                    screentip="Hiermit machst du:"
                    supertip="tolle Dinge in einem Brief"
                    onAction="vbaCoreRibbonButton_Click" />
        </group>
    </tab>
    </tabs>
</ribbon>
</customUI>

OK speichern wir mal das ganze und öffnen die Briefvorlage per Doppelklick – mal sehen was wir bekommen. Wir bekommen das Ribbon doppelt, das wollten wir zwar nicht aber immerhin taucht es schon auf. Dafür funktioniert der Button und sagt, dass er nicht belegt ist. Damit wird also tatsächlich die zentrale Methode ausgeführt ohne das wir eine Zeile VBA-Code in der Briefvorlage haben.

Geteiltes Leid

OK wie erklären wir denn jetzt Word, dass die beiden Ribbons zusammengefügt werden sollen. Das ist recht simpel, wir benutzen ein zusätzliches Attribut in der customUI Zeile und sagen dann noch was zusammengefasst wird..

<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" xmlns:shared="VBACore">
  <ribbon>
    <tabs>
      <tab idQ="shared:VBACore" label="Mein VBA" >

Mit dem xmlns:shared="VBACore" definieren wir einen eindeutigen Namen für unser Projekt, einen Namespace. In diesem Namensraum ist unser Ribbon zu Hause und lässt sich eindeutig zuordnen. Der Tab im Ribbon bekommt ebenfalls mit idQ="shared:" die Information das er aus mehreren Gruppen aus unterschiedlichen Vorlagen zusammengesetzt werden soll. Gucken wir doch mal was jetzt passiert.

Fantastisch, so wollten wir das doch. Wenn die Briefvorlage geöffnet wird, dann wird die Gruppe mit dem Brief-Button eingeblendet. Wird jedoch einfach so Word ohne direkte Vorlage geöffnet (unten), dann wird dieser Teil des Ribbons nicht eingeblendet.

Unter der Haube

Diskutieren wir mal noch ein Dinge die einem so in den Sinn kommen könnten.

Wenn das Ribbon in der Vorlage ist, dann sieht ja jemand anders auch das Ribbon wenn er ein Brief-Dokument öffnet was ich mit dieser Vorlage erstellt habe. Das will ich nicht.

Nein, dem ist nicht so. Das hängt mit der Art und Weise zusammen wie Word funktioniert. An jedem Dokument hängt in Word eine Vorlage aus der Formatierungen oder zusätzliche Elemente wie Bausteine oder eben das Ribbon kommen kann. Wenn diese Vorlage nicht gefunden wird, dann benutzt Word schlichtweg die integrierte Vorlage Normal.dotm. Und dort gibt es das Ribbon nicht.

Das bedeutet im Umkehrschluss aber auch, dass man das Ribbon selber auch „kaputt“ machen kann. Nehmen wir an das Dokument kommt bearbeitet zurück und man bearbeitet das selbst weiter. Zwar gibt es bei einem selbst den Pfad, aber das Dokument hat schon die Normal.dotm hinterlegt. Dann muss man leider zwangsläufig wieder das Template anfügen in dem die Funktionalität (Ribbon) liegt. Ab dann taucht es wieder auf. Deshalb gibt es in IOX eine Gruppe die sich genau um solche Probleme kümmert und es dem Anwender leichter macht eine Vorlage zu verwalten.


Könnte man das auch anders umsetzen als ein Ribbon in einer Vorlage zu haben? Ja das geht, bei VSTO – also einer .net Framework Umgebung – muss man das sogar. Im Prinzip lässt man sich den Vorlagennamen des aktuellen Dokuments ermitteln. Wenn der einem bestimmten Kriterium entspricht, dann lässt man die gesamte Gruppe im Ribbon XML einblenden. Dafür muss im XML dann ein Callback für die Sichtbarkeit als getVisible="..." hinterlegt sein. Diese Gruppe muss dann bei den passenden Ereignissen geprüft werden wie im vorherigen Artikel gezeigt wurde. Es muss nicht zwingend SelectionChange sein, es ginge auch DocumentOpen. Also immer wenn das Dokument geöffnet wird.


Zum Ende dieses Artikels muss ich noch auf die etwas geänderte Denkweise hinweisen. Da es keinen VBA-Code in der Briefvorlage gibt, muss man immer zu Beginn einer Funktion das gerade aktuelle Dokument ermitteln. Das was ein Makro Rekorder erzeugt wird also nicht sehr belastbar sein und womöglich falsche Ergebnisse liefern.