Vor sehr langer Zeit (2003) gab es für die Office-Anwendungen noch die Möglichkeit, Menüleisten, Symbolleisten und Kontextmenüs über die Benutzeroberfläche anzupassen. Die Menüleisten und Symbolleisten sind seit der Version 2007 Geschichte, und damit ist auch der Editor für die Gestaltung dieser Elemente verschwunden. Allerdings gibt es noch die Kontextmenüs, und diese lassen sich auch noch anpassen – zum Beispiel, um eigene Befehle hinzuzufügen. Diese könnten beispielsweise Teil von Add-Ins, COM-Add-Ins oder auch von Dokumenten sein. In diesem Artikel zeigen wir, wie man vorhandene Kontextmenüs bearbeitet oder eigene Kontextmenüs anlegt und diese bei Bedarf aufruft.
Unterschiede zwischen Outlook und den übrigen Office-Anwendungen
Zwischen Outlook und den übrigen Office-Anwendungen gibt es einen entscheidenden Unterschied für die individuelle Anpassungen von Kontextmenüs: Während wir unter Word, Excel, Access oder PowerPoint das Objektmodell aus der Bibliothek Microsoft Office x.0 Object Library nutzen können, um die gewünschten Anpassungen vorzunehmen, ist dies in Outlook nicht möglich. Hier sind die Kontextmenüs bereits Bestandteil des Ribbons. Änderungen der Kontextmenüs müssen wir in Outlook daher über die Ribbondefinition vornehmen, und zwar über die Einträge im Unterelement contextMenus. Dieses Thema behandeln wir im vorliegenden Artikel nicht, aber wir gehen im Detail darauf in einem weiteren Artikel namens Kontextmenüs in Outlook anpassen (www.vbentwickler.de/369) ein.
Beispieldateien
Da die CommandBars sich in den verschiedenen Office-Anwendungen Access, Excel und Word leicht unterschiedlich verhalten, haben wir jeweils eine Beispieldatei für jede Anwendung bereitgestellt:
- Access: KontextmenuesPerVBA.accdb
- Excel: KontextmenuesPerVBA.xlsm
- Word: KontextmenuesPerVBA.docm
Objektmodell verfügbar machen
Um die Kontextmenüs anzupassen, benötigen wir Elemente der Bibliothek Microsoft Office x.0 Object Library. Diese ist in beispielsweise in den VBA-Projekten von Word und Excel bereits referenziert, nicht jedoch unter Access oder in anderen Projekten auf Basis von Visual Studio oder twinBASIC. Damit wir die Bibliothek etwa in Access unter Einsatz von IntelliSense nutzen können, fügen wir einen Verweis auf diese Bibliothek hinzu. Dazu öffnen wir zunächst den VBA-Editor der jeweiligen Anwendung, beispielsweise mit der Tastenkombination Alt + F11. Im VBA-Editor zeigen wir mit dem Menübefehl Extras|Verweise den Verweise-Dialog an. Hier selektieren Sie den Eintrag aus Bild 1 und fügen diese so hinzu.
Bild 1: Aktivieren des Verweises auf die Bibliothek Microsoft Office x.0 Object Library
Das Objektmodell zum Anpassen von Kontextmenüs
Zeigen wir nun mit F2 den Objektkatalog an, können wir dort die Bibliothek Office auswählen und finden dort beispielsweise die Auflistung CommandBars vor (siehe Bild 2). Diese bietet bereits einige interessante Elemente an. Unter anderem können wir damit die Anzahl aller aktuell verfügbaren CommandBar-Elemente ausgeben:
Bild 2: Die CommandBars-Auflistung im Objektkatalog
Debug.Print "Anzahl Commandbars: " _
& Application.CommandBars.Count
Das liefert beispielsweise für Access die Anzahl von 247 CommandBar-Elemente, unter Excel immerhin noch 199 Einträge. Ob es sich dabei ausschließlich um Kontextmenüs handelt, finden wir gleich heraus. Unter Access können wir direkt auf die CommandBars-Auflistung zugreifen, unter Excel und Word müssen wir einen Verweis auf die Application-Klasse voranstellen. Bei dem Zugriff von COM-Add-Ins aus ist dies ohnehin obligatorisch, mehr dazu zeigen wir in einem Beispiel in einem weiteren Artikel namens Kontextmenü per COM-Add-In anpassen (www.vbentwickler.de/370).
CommandBar-Elemente durchlaufen
Mit den folgenden Zeilen aus der Prozedur CommandBarsDurchlaufen geben wir die Namen aller CommandBar-Elemente im Direktbereich des VBA-Editors aus:
Dim cbr As CommandBar For Each cbr In Application.CommandBars Debug.Print cbr.Name Next cbr
Das Gleiche gelingt auch per For…Next-Schleife über den 1-basierten Index:
Dim cbr As CommandBar Dim i As Integer For i = 1 To Application.CommandBars.Count Set cbr = Application.CommandBars.Item(i) Debug.Print cbr.Name Next i
Die Ausgabe können wir noch verfeinern, indem wir zwei weitere Eigenschaften ausgeben lassen:
Debug.Print cbr.Name, cbr.Type, cbr.BuiltIn
Typ eines CommandBar-Elements ermitteln
Die erste hier verwendete Eigenschaft lautet Type. Type kann einen der folgenden drei Werte liefern:
- 0 (msoBarTypeNormal): Das CommandBar-Element ist eine Symbolleiste.
- 1 (msoBarTypeMenuBar): Das CommandBar-Element ist eine Menüleiste.
- 2 (msoBarTypePopup): Das CommandBar-Element ist ein Kontextmenü.
Die ersten beiden Typen sind für unsere Zwecke nicht relevant. Bei diesen handelt es sich um die Typen der bis Office 2003 verwendeten Elemente, die dort angezeigt wurden, wo jetzt das Ribbon erscheint. Interessant wird es, wenn die Eigenschaft Type den Wert 2 liefert. Geben wie also nun alle Kontextmenüs aus und lassen uns, da wir deren Anzahl nicht über die Count-Eigenschaft bestimmen können, mit der Zählervariablen i den Index ausgeben:
Dim cbr As CommandBar Dim i As Integer For Each cbr In Application.CommandBars If cbr.Type = msoBarTypePopup Then i = i + 1 Debug.Print i, cbr.Name, cbr.BuiltIn End If Next cbr
Lassen wir die Prozedur unter Access laufen, erhalten wir 138 Kontextmenüs, unter Excel nur 67.
Eingebaute oder benutzerdefinierte Kontextmenüs
Mit der bereits verwendeten Eigenschaft BuiltIn können wir einen Boolean-Wert ausgeben, der angibt, ob es sich um ein eingebautes Kontextmenü handelt. Damit können wir die eingebauten Kontextmenüs von denen unterscheiden, die wir selbst per VBA hinzufügen.
Wozu die eingebauten Kontextmenüs nutzen?
Wozu sollten wir überhaupt wissen wollen, welche eingebauten Kontextmenü die jeweiligen Anwendungen anbieten? Weil es geschehen kann, dass wir nicht gleich ein vollständiges Kontextmenü mit neuen Funktionen hinzufügen wollen, sondern nur einzelne Funktionen, die in bestehenden Kontextmenüs angezeigt werden sollen.
Wenn wir beispielsweise unter Excel eine Funktion hinzufügen wollen, die nur im Zusammenhang mit einer Zelle angezeigt werden soll – also wenn der Benutzer mit der rechten Maustaste auf eine Zelle klickt – dann müssen wir den Namen dieses Kontextmenüs herausfinden und passen dann dieses Kontextmenü an.
Namen eines Kontextmenüs herausfinden
Den Namen eines Kontextmenüs kann man auf mehrere Arten ermitteln. Die erste ist die Ausgabe der Namen aller Kontextmenüs der jeweiligen Anwendung. Dazu führen wir die obige Prozedur zum Durchlaufen aller Kontextmenüs in der jeweiligen Anwendung aus. In vielen Fällen können wir schon am Namen des Kontextmenüs erkennen, wann dieses angezeigt wird.
Im Falle von Excel und einem Kontextmenü für eine Zelle werden wir schnell fündig – das Kontextmenü heißt Cell (siehe Bild 3).
Bild 3: Ausgabe der Kontextmenüs von Excel
Unter anderen Anwendungen wie Access ist es teilweise schwierig, das richtige Kontextmenü aufgrund der Benennung zu finden. In diesem Fall kommt eine zweite Technik zum Zuge.
Beispielkontextmenüs in den anderen Anwendungen
Unter Excel nutzen wir zu Beispielzwecken wie beschrieben die Kontextmenüs Cell oder Column. In der Beispieldatei für Word schauen wir uns in den Beispielen das Kontextmenü Text an, das beim Rechtsklick auf normalen Text im Dokument erscheint. In der Beispieldatei für Access verwenden wir das Kontextmenüs eines Elements des Navigationsbereichs namens Navigation Pane object Pop-up.
Name des Kontextmenüs in das Kontextmenü schreiben
Dabei greifen wir einer Technik vor, die wir weiter unten noch genauer erläutern. Wir fügen jedem Kontextmenü eine Schaltfläche hinzu, für deren Beschriftung wir den Namen des CommandBar-Elements festlegen. Dabei durchlaufen wir wieder alle Elemente der CommandBars-Auflistung und rufen jeweils für die Controls-Auflistung die Add-Methode auf. Dieser übergeben wir als ersten Parameter den Typ des zu erstellenden Steuerelements, in diesem Fall msoControlButton für eine Schaltfläche. Außerdem hinterlegen wir für den letzten Parameter Temporary den Wert True. Dies sorgt dafür, dass die angelegten Steuerelemente nur für die aktuelle Session der jeweiligen Anwendung angezeigt werden und bei einem weiteren Start nicht erneut erscheinen:
Public Sub NameInKontextmenuesSchreiben() Dim cbr As CommandBar Dim cbb As CommandBarButton Dim i As Integer For Each cbr In Application.CommandBars If cbr.Type = msoBarTypePopup Then Set cbb = cbr.Controls.Add( _ msoControlButton, , , , True) cbb.Caption = cbr.Name End If Next cbr End Sub
Führen wir diese Prozedur aus und zeigen mit der rechten Maustaste eines der Kontextmenüs der Anwendung an, liefert dieses in einem neuen Eintrag den Namen des Kontextmenüs (siehe Bild 4).
Bild 4: Name eines CommandBar-Elements als Schaltflächenbeschriftung
Mit dem Namen eines Kontextmenüs können wir gezielt auf das jeweilige Kontextmenü zugreifen und dessen Elemente bearbeiten oder neue Elemente hinzufügen.
Elemente von Kontextmenüs ausgeben
Wir schauen uns dies zunächst beim Ausgeben der Steuerelemente eines Kontextmenüs an. Die folgende Prozedur referenziert das Kontextmenü Column von Excel (wenn Du den in einer anderen Anwendung ausprobieren möchtest, gib den Namen eines dort vorhandenen Steuerelements an). Dann durchläuft die Prozedur alle Elemente der Controls-Auflistung des CommandBar-Elements. Wichtig ist, dass wir die Laufvariable ctl mit dem Typ Object deklarieren. Der Hintergrund ist, dass die Controls-Auflistung verschiedene Steuerelementtypen enthalten kann. Deshalb geben wir im Folgenden direkt den Wert der Eigenschaft Type des jeweiligen Steuerelements aus. Noch eine bessere Methode, um den Typ zu ermitteln, ist die Ausgabe von TypeName(ctl):
Public Sub ElementeEinesKontextmenuesAusgeben() Dim cbr As CommandBar Dim ctl As Object Set cbr = Application.CommandBars("Column") For Each ctl In cbr.Controls Debug.Print ctl.Caption, ctl.Type, TypeName(ctl) Next ctl End Sub
Die Ausgabe für das Column-Kontextmenü lautet:
Auss&chneiden 1 CommandBarButton K&opieren 1 CommandBarButton Einfü&gen 1 CommandBarButton Inhalte einfü&gen... 1 CommandBarButton Tabelle e&infügen 1 CommandBarButton &Datentyp 10 CommandBarPopup Zellen &einfügen 1 CommandBarButton Zellen l&öschen 1 CommandBarButton Inhal&te löschen 1 CommandBarButton Zellen &formatieren... 1 CommandBarButton Spalten&breite... 1 CommandBarButton &Ausblenden 1 CommandBarButton Einb&lenden 1 CommandBarButton &Links entfernen 1 CommandBarButton Änderun&gen anzeigen 1 CommandBarButton
Es gibt eine ganze Reihe von Steuerelementtypen, die Du im Objektkatalog unter der Auflistung msoControlType einsehen kannst. Wir können jedoch nur einige wenige nutzen. Unter den eingebauten Steuerelementen finden wir eine ganze Reihe verschiedener Typen, aber wir können nur drei davon mit der Add-Methode zur Controls-Auflistung hinzufügen:
- 1 (msoControlButton): Schaltfläche
- 4 (msoControlComboBox): Kombinationsfeld
- 10 (msoControlPopup): Untermenü
Das erledigen wir beispielhaft mit der folgenden Prozedur. Hier fügen wir nicht nur die drei verschiedenen Typen hinzu, sondern zeigen gleich noch das angepasste Kontextmenü mit der Methode ShowPopup an:
Public Sub ElementeAnlegen() Dim cbr As CommandBar Dim ctl As Object Set cbr = Application.CommandBars("Column") Set ctl = cbr.Controls.Add(1, , , , True) ctl.Caption = "msoControlButton" Set ctl = cbr.Controls.Add(4, , , , True) ctl.Caption = "msoControlComboBox" Set ctl = cbr.Controls.Add(10, , , , True) ctl.Caption = "msoControlPopup" cbr.ShowPopup End Sub
Möchten Sie weiterlesen? Dann lösen Sie Ihr Ticket!
Hier geht es zur Bestellung des Jahresabonnements des Magazins Visual Basic Entwickler:
Zur Bestellung ...
Danach greifen Sie sofort auf alle rund 200 Artikel unseres Angebots zu - auch auf diesen hier!
Oder haben Sie bereits Zugangsdaten? Dann loggen Sie sich gleich hier ein: