Dynamische Beschriftungen auf Ribbons

Die neuen Ribbons in Office 2007 sehen nicht nur toll aus, sie bieten auch viele neue Möglichkeiten. So können die Elemente auf den neuen Office 2007-Ribbons weitaus dynamischer sein, als es bisherige Menüs oder Symbolleisten zuließen. Allerdings ist die dabei verwendete Technik auch komplett anders als bisher, denn es gibt kein Objektmodell zum VBA-Zugriff auf die Ribbons.

∅ 4.6 / 7 Bewertungen

Die neuen Ribbons in Office 2007 sehen nicht nur toll aus, sie bieten auch viele neue Möglichkeiten. So können die Elemente auf den neuen Office 2007-Ribbons weitaus dynamischer sein, als es bisherige Menüs oder Symbolleisten zuließen. Allerdings ist die dabei verwendete Technik auch komplett anders als bisher, denn es gibt kein Objektmodell zum VBA-Zugriff auf die Ribbons.

Office 2007 verfügt über eine neue Benutzeroberfläche (Office Fluent). Die Menüs und Funktionen wurden in eine Multifunktionsleiste (Ribbon) integriert. Im Beitrag "Ribbons erstellen in Word 2007" bzw. in "Ribbons erstellen in Excel 2007" finden Sie die grundsätzlichen Tipps zur Erstellung und Programmierung der Ribbons und was dabei zu beachten ist.

Auch wenn die Beispiele hier für Word 2007 beschrieben wurden, funktionieren sie grundsätzlich genauso in den anderen Programmen von Office 2007.

Die einzige Chance, ein Ribbon zur Aktualisierung zu veranlassen, besteht im Invalidate-Befehl. Dieser nötigt das Ribbon, sich selbst erneut einzulesen. Es gibt noch eine "Sparversion" davon mit InvalidateControl, damit nur ein Element statt des ganzen Ribbons eingelesen wird, aber das war's dann auch schon.

Das Ribbon selbst muss in der XML-Beschreibung alle benötigten VBA-Prozeduren kennen, die für seine Darstellung sorgen. Diese werden beim Invalidate aufgerufen.

Lösungsdatei

Laden Sie zum Vergleich die Lösungsdatei Invalidate01.docm herunter.

Erstellen Sie zum Testen ein neues leeres Word 2007-Dokument mit Makros im *.docm- oder *.dotm-Format. Schließen Sie die Datei in Word.

Öffnen Sie diese dann im Custom UI Editor und fügen Sie den folgenden Code ein:

<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" onLoad="OnLoadRibbon">
	<ribbon startFromScratch="false">
		<tabs>
			<tab id="tabTest" label="akademie">
				<group id="grpTest" label="Dynamisch">
					<button id="btnUhrzeit" label="Uhrzeit" onAction="OnActionButton" />
                                        <labelControl id="lblUhrzeit" getLabel="GetLabel" />
				</group>
			</tab>
		</tabs>
	</ribbon>
</customUI>
60195_invalidate_xml01.png

Der XML-Code für die dynamische Anzeige

Wenn Sie diese Datei in Word öffnen, erhalten Sie sofort eine Fehlermeldung. Klicken Sie auf OK.

60196_invalidate_word01.png

Der VBA-Code müsste schon beim Öffnen ausgeführt werden.

Bisher waren Fehler erst beim Klick auf eine Schaltfläche gemeldet worden, weil das der erste Anlass gewesen war, ein onAction-Attribut auszuführen. Jetzt steht aber bereits im <customUI>-Element ein onLoad-Attribut und dessen VBA-Code soll auch direkt ausgeführt werden.

Ergänzen Sie daher im VBA-Editor in Word in einem neuen Modul die folgenden Prozedur-Rümpfe, wie sie für die XML-Beschreibung gebraucht werden:

Option Explicit

'Callback for customUI onLoad
Sub OnLoadRibbon(ribbon As IRibbonUI)
End Sub

'Callback for btnUhrzeit onAction
Sub OnActionButton(control As IRibbonControl)
End Sub

'Callback for lblUhrzeit getLabel
Sub GetLabel(control As IRibbonControl, ByRef returnedVal)
End Sub
60197_invalidate_vba01.png

Die Prozedur-Rümpfe noch ohne Inhalt

Anders als bisher ist auch im <labelControl>-Element nicht einfach das label-Attribut mit einem statischen Text genannt, sondern stattdessen ein getLabel-Attribut mit der Angabe einer GetLabel-Prozedur. Beide Attribute in einem Element gleichzeitig sind nicht zulässig.

Das hat zur Folge, dass über den returnedVal-Parameter die Beschriftung immer aus der GetLabel-Prozedur geholt wird, auch schon direkt beim ersten Laden. Weil das noch nicht geklappt hat, ist die Beschriftung unterhalb der Schaltfläche mit dem Text "Laden" auch noch nicht zu sehen:

60198_invalidate_word02.png

Das Bezeichnungsfeld ist noch unbeschriftet

Wenn Sie den Code für GetLabel wie folgt ergänzen, liefert die Prozedur jeweils die gewünschte Uhrzeit als Beschriftung:

Option Explicit

'Callback for customUI onLoad
Sub OnLoadRibbon(ribbon As IRibbonUI)
End Sub

'Callback for btnUhrzeit onAction
Sub OnActionButton(control As IRibbonControl)
End Sub

'Callback for lblUhrzeit getLabel
Sub GetLabel(control As IRibbonControl, ByRef returnedVal)
    Select Case LCase(control.ID)
    Case "lbluhrzeit": returnedVal = "Uhrzeit: " & Time()
    Case Else
    End Select
End Sub
60199_invalidate_vba02.png

Die GetLabel-Prozedur gibt eine Uhrzeit zurück

Das ist nach dem Schließen und erneuten Öffnen des Dokuments auch auf dem Ribbon zu sehen:

60200_invalidate_word03.png

Die Uhrzeit wird angezeigt

Allerdings soll die Aktualisierung auch ohne erneutes Öffnen möglich sein, nämlich mit der Schaltfläche darüber. Diese Schaltfläche muss nun lediglich ein Invalidate für das Ribbon-Objekt auslösen. Leider existiert kein Ribbon-Objekt, Sie müssen es selbst verwalten.

Die einzige Chance, eine VBA-Referenz auf ein Ribbon anzulegen, besteht in der OnLoadRibbon-Prozedur, bei der Word als Parameter eine IRibbonUI-Variable übergibt. Nur hier und nur zu diesem Zeitpunkt können Sie einen Verweis anlegen.

Also deklarieren Sie eine Modul-öffentliche Variable m_ribAkademie und weisen dieser den übergebenen Parameter zu:

Option Explicit

Dim m_ribAkademie As IRibbonUI

'Callback for customUI onLoad
Sub OnLoadRibbon(ribbon As IRibbonUI)
    Set m_ribAkademie = ribbon
End Sub

'Callback for btnUhrzeit onAction
Sub OnActionButton(control As IRibbonControl)
    m_ribAkademie.InvalidateControl "lblUhrzeit"
End Sub
60201_invalidate_vba03.png

Die Modul-öffentliche Variable m_ribAkademie enthält den Verweis

Dann können Sie diese in onActionButton mit Invalidate als Ganzes oder wie hier mit InvalidateControl für das genannte Objekt dazu veranlassen, den entsprechenden Ribbon-Teil erneut einzulesen und damit zu aktualisieren.

Das funktioniert, wie Sie in Word prüfen können. Allerdings wird OnLoadRibbon nur beim Öffnen des Dokuments ausgeführt, sodass Sie es nochmals schließen und wieder öffnen müssen:

60202_invalidate_word04.png

Die Uhrzeit lässt sich nun dynamisch aktualisieren.

IRibbonUI-Variable geht regelmäßig verloren

Sobald ein Laufzeit-Fehler auftritt und Sie die Ausführung stoppen müssen, werden alle Variablen zurückgesetzt. Das ist bei normaler VBA-Programmierung nicht weiter tragisch, denn alle Objekte werden von Word wieder aktualisiert.

Hier ist das anders, denn die OnRibbonLoad-Prozedur kann nur beim Öffnen der Datei ausgeführt werden, die Datei ist aber schon offen. Damit steht die m_ribAkademie-Variable auf Nothing. Es bleibt Ihnen nichts anderes übrig, als das Dokument zu schließen und wieder zu öffnen.

Wenn Sie ein Word-AddIn erstellen, ist das noch lästiger, denn Word hält das Dokument auch nach dem manuellen "Schließen" geöffnet. Da müssen Sie nach jedem Laufzeitfehler Word komplett beenden.