Home > Artikel > Ausgabe 1/2017 > Ribbons, Teil III: Interaktion im Ribbon

Ribbons, Teil III: Interaktion im Ribbon

Achtung: Sie sind nicht angemeldet. Wenn Sie Abonnent sind und sich anmelden, lesen Sie den kompletten Artikel, laden das PDF herunter oder probieren die Beispieldatenbank aus (sofern vorhanden).

Das Ribbon lässt sich nicht so einfach programmieren wie es bei Menüleisten, Symbolleisten oder Kontextmenüs der Fall war. Diese Elemente ließen sich nach Wunsch mit Objektvariablen referenzieren und zum Beispiel aktivieren oder deaktivieren. Das Ein- oder Ausblenden von Menüs war auch recht einfach. Beim Ribbon gibt es einen alternativen Programmieransatz, bei dem der XML-Code zur Beschreibung des Aussehens des Ribbons und der VBA-Code für seine Steuerung interagieren sollen. Welche Vorbereitungen dazu notwendig sind und wie die Programmierung im Detail aussieht, zeigt dieser Artikel.

Beispieldatenbank

Die Beispiele dieses Artikels finden Sie in der Datenbank 1701_Ribbon.accdb.

Voraussetzungen

Beachten Sie, wie im ersten Teil dieser Artikelreihe beschrieben, dass Sie einen Verweis auf die Bibliothek Microsoft Office x.0 Object Library benötigen, um das Ribbon zu programmieren.

Eigenschaften dynamisch gestalten

Die Ribbon-Elemente haben eine ganze Reihe von Attributen, die Sie gleich in der XML-Definition des Ribbons festlegen – zum Beispiel den Namen, die Beschriftung, die Größe bei Schaltflächen, den Namen eventuell ausgelöster Callback-Prozeduren und viele mehr. Attribute, die Sie per XML definieren, können Sie später nicht mehr ändern. In vielen Fällen ist das auch sinnvoll. Wer möchte schon den nur intern verwendeten Namen eines Ribbon-Elements ändern?

Bisher haben wir allerdings noch nicht darüber gesprochen, dass sich einige Eigenschaften von Ribbon-Elementen auch zur Laufzeit ändern lassen können beziehungsweise dass Sie deren Werte nicht gleich bei der XML-Definition des Ribbons anlegen, sondern dass die Werte von Attributen auch erst beim Erstellen des Ribbons beziehungsweise beim ersten Anzeigen mithilfe von VBA-Funktionen ermittelt werden können.

Die Attribute, die das dynamische Abfragen von Werten zur Laufzeit ermöglichen, beginnen in der Regel mit dem Präfix get... gefolgt vom Namen des statischen Attributs. Schauen wir uns dies am Beispiel des button-Elements an, das wohl das häufigste Ziel von dynamischen Einstellungen sein dürfte – allein, um dieses zu aktivieren oder deaktivieren oder ein- und auszublenden. Hier gibt es etwa die Attribute label, visible oder enabled. Diese können Sie bereits in der XML-Definition festlegen. Wenn Sie dies allerdings erst beim Anzeigen des jeweiligen Elements erledigen wollen, verwenden Sie die Attribute getLabel, getVisible oder getEnabled und hinterlegen für diese den Namen der Callback-Funktion, welche den Wert für das entsprechende Attribut liefert.

Schauen wir uns dies an einem Beispiel an. Die folgende Ribbon-Definition enthält in einem tab-Element ein group-Element mit zwei untergeordneten button-Elementen. Das erste hat eine statische Bezeichnung, die wir mit dem label-Attribut eingestellt haben. Die zweite verwendet das Attribut getLabel und gibt dafür den Callback-Namen getLabel an:

<customUI ...>

  <ribbon>

    <tabs>

      <tab id="tabInteraktion" label="Interaktion">

        <group id="grpInteraktion" label="Beispiele">

          <button label="Statisches Label" id="btnLabelStatisch"/>

          <button getLabel="getLabel" id="btnLabelDynamisch"/>

        </group>

      </tab>

    </tabs>

  </ribbon>

</customUI>

Die VBA-Prozedur, die beim Auslösen des Callback-Ereignisses getLabel aufgerufen werden soll, sieht so aus:

Sub getLabel(control As IRibbonControl, ByRef label)

label = "Dynamisches Label"

End Sub

Sie erwartet zwei Parameter, von denen der zweite namens label in diesem einfachen Beispiel der wichtigere ist: Er nimmt schlicht die Zeichenkette entgegen, die als Bezeichnung angezeigt werden soll. Dementsprechend füllen wir die Variable label mit dem Wert Dynamisches Label. Das Ergebnis finden Sie in Bild 1.

Zwei Label mit verschiedenen Beschriftungen

Bild 1: Zwei Label mit verschiedenen Beschriftungen

Wann erfolgt der Aufruf?

Wie schon weiter oben erwähnt, werden die Callback-Ereignisse, deren Name mit get... beginnt, bei der Anzeige der jeweiligen Elemente ausgelöst. Um dies zu belegen, haben wir ein zweites tab-Element hinzugefügt, dass ein button-Element mit dem Wert getLabel für das Attribut getLabel aufweist:

<tab id="tabMehrInteraktion" label="Mehr Interaktion ...">

  <group id="grpBeispiele" label="Beispiele">

    <button getLabel="getLabel" id="btnDynamisch2"/>

  </group>

</tab>

Außerdem müssen wir nun der Anforderung gerecht werden, dass wir nicht mehr nur eine einzige Schaltfläche haben, von der aus das Callback-Ereignis getLabel ausgelöst wird, sondern zwei.

In diesem Fall kommt der erste Parameter der Callback-Prozedur zum Zuge, der mit dem Parameter control einen Verweis auf das auslösende Steuerelement liefert. control enthält eine Eigenschaft namens ID, mit der wir auf den Wert des Attributs id der button-elemente zugreifen können. Diese prüfen wir in einer Select Case-Anweisung und weisen verschiedene Bezeichnungen über den Rückgabeparameter label zu:

Sub getLabel(control As IRibbonControl, ByRef label)

    Select Case control.ID

        Case "btnLabelDynamisch"

            label = "Dynamisches Label"

        Case "btnDynamisch2"

            label = "Dynamisches Label 2"

    End Select

End Sub

Wenn Sie nun die Datenbank komprimieren und reparieren (schnellster Weg, die Datenbank zu schließen und wieder zu öffnen) und einen Haltepunkt in die erste Zeile der Prozedur setzen, landen Sie beim Anzeigen des Ribbon-Tabs Interaktion in dieser Prozedur und dort im Case-Zweig für den Wert btnLabelDynamisch (siehe Bild 2).

Ansteuern eines Haltepunktes in einer Callback-Prozedur

Bild 2: Ansteuern eines Haltepunktes in einer Callback-Prozedur

Wechseln Sie danach zum zweiten tab-Element des Beispiels, wird getLabel wieder ausgelöst – diesmal allerdings für das Element btnDynamisch2.

Label während der Laufzeit aktualisieren

Damit haben wir allerdings nur gezeigt, wie wir eine Callback-Eigenschaft beim erstmaligen Anzeigen aufrufen, um ein Attribut zur Laufzeit mit einem Wert zu versehen. Wenn Sie anschließend weitere Male zwischen den beiden tab-Elementen hin- und herwechseln, wird die Callback-Prozedur getLabel nicht mehr aufgerufen.

Wenn Sie dies erreichen wollen, um beispielsweise einen regelmäßig aktualisierten Wert wie die Uhrzeit anzuzeigen, müssen Sie den Wert der per get...-Prozedur zugewiesenen Attribute ungültig machen. Welche Voraussetzungen dafür erforderlich sind und wie dies gelingt, zeigt der folgende Abschnitt.

Referenz auf das Ribbon speichern

Der wichtigste Schritt, um ein Attribut ungültig zu machen, ist das Speichern einer Objektreferenz auf die aktuell angezeigte Ribbon-Definition. In diesem Fall wollen wir die Uhrzeit in einem label-Element in einem weiteren Tab anzeigen, das wir wie folgt definieren:

<customUI ... onLoad="OnLoad_Interaktiv">

  <ribbon>

    <tabs>

    ...

      <tab id="tabDynamisch" label="Dynamische Werte">

        <group id="grpUhrzeit" label="Uhrzeit">

          <labelControl getLabel="getLabel" id="lblUhrzeit"/>

        </group>

      </tab>

    </tabs>

  </ribbon>

</customUI>

Entscheidend ist hier, dass wir für das customUI-Element das Attribut onLoad mit dem Wert onLoad_Interaktiv füllen (Interaktiv ist der Name, unter dem wir das Ribbon in der Tabelle USysRibbons gespeichert haben):

Wir erweitern nun noch die Prozedur getLabel, um dem Label lblUhrzeit beim Anzeigen die aktuelle Uhrzeit zuzuweisen (mit der Time-Funktion):

Sub getLabel(control As IRibbonControl, ByRef label)

    Select Case control.ID

        Case "btnLabelDynamisch"

            label = "Dynamisches Label"

        Case "btnDynamisch2"

            label = "Dynamisches Label 2"

        Case "lblUhrzeit"

            label = Time

    End Select

End Sub

Außerdem müssen wir noch die Prozedur hinzufügen, die durch das Attribut onLoad ausgelöst wird und die wie folgt aussieht:

Sub onLoad_Interaktiv(ribbon As IRibbonUI)

    Set objRibbon_Interaktiv = ribbon

End Sub

Die Prozedur liefert mit dem Parameter ribbon einen Verweis auf das zuvor definierte IRibbonUI-Objekt, was alle mit der XML-Definition benutzerdefiniert angepassten Elemente des Ribbons umfasst. Diesen Verweis speichern wir in einer öffentlich deklarierten Variablen im gleichen Modul, und zwar unter dem Namen objRibbon_Interaktiv:

Public objRibbon_Interaktiv As IRibbonUI

Viele andere Quellen verwenden hier einfach den allgemeinen Bezeichner objRibbon und füllen diesen von jeder neu angewendeten Ribbon-Definition aus. Das kann jedoch problematisch werden, wenn Sie tatsächlich mehrere Ribbon-Definitionen gleichzeitig laden – etwa eine als Hauptribbon und eine als Formularribbon. Dann sollten Sie sauber zwischen den beiden Definitionen trennen und für jede eine eigene Objektvariable zum Speichern der Ribbon-Definition vorhalten. Wir verwenden dazu die Schreibweise auf objRibbon, einem Unterstrich und dem Namen der Ribbon-Definition, also etwa objRibbon_Interaktiv.

Wenn Sie das Ribbon nun anzeigen, liefert dieses die aktuelle Uhrzeit (siehe Bild 3). Allerdings ändert sich diese nicht, wenn Sie zu einem anderen Tab und wieder zurück zum Tab mit der Uhrzeit wechseln. Was soll das nun wieder?

Uhrzeit in einem label-Element

Bild 3: Uhrzeit in einem label-Element

Nun, wir erwähnten ja bereits, dass man das betroffene Element für das erneute Auslösen der Callback-Prozedur erst »ungültig« machen muss. Und hier kommt die Objektvariable objRibbon_Interaktiv ins Spiel: Diese bietet nämlich unter anderem drei Methoden an, welche die aktuell mit dem get...-Attributen dynamisch ermittelten Werte ungültig macht (siehe Bild 4).

Verschiedene Invalidate-Methoden

Bild 4: Verschiedene Invalidate-Methoden

Die Methode Invalidate macht dabei alle Elemente des mit objRibbon_Interaktiv referenzierten Ribbons ungültig. Das heißt, dass alle get...-Attribute nach dem Aufruf dieser Methode neu ausgeführt werden müssen, sobald diese aus- und wieder eingeblendet werden.

Setzen Sie einmal den folgenden Befehl im Direktbereich des VBA-Editors ab:

objRibbon_Interaktiv.Invalidate

Dadurch, dass Sie objRibbon_Interaktiv als öffentliche Variable in einem Standardmodul deklariert haben, können Sie von überall, also auch vom Direktbereich aus, auf seine Methoden zugreifen. Wenn Sie während des Aufrufs das tab-Element mit dem label-Element zur Anzeige der Uhrzeit anzeigen, wird die Anzeige nun auf die aktuelle Uhrzeit geändert.

Wenn Sie gezielt nur ein einzelnes Element ungültig machen wollen, damit seine get...-Attribute erneut eingelesen werden, dann verwenden Sie die Methode InvalidateControl und übergeben den Namen des Elements, also den Inhalt des Attributs id, mit dem Aufruf als Parameter. Das sieht beispielsweise wie folgt aus:

Sie haben das Ende des frei verfügbaren Teil dieses Artikels erreicht!

Wenn Sie mehr lesen und auf viele weitere Artikel zugreifen möchten, melden Sie sich als Abonnent unter Login an. Falls nicht, bestellen Sie doch einfach ein Jahresabonnement!