Das Ribbon, in der deutschen Version von Office auch Menüband genannt, ist die Menüleiste für Office-Anwendungen und somit auch für Access. Sie können die Befehle im Ribbon jedoch nicht nur während der Entwicklung von Access-Anwendungen nutzen, sondern dieses für eigene Anwendungen so anpassen, dass der Benutzer die Funktionen dieser Anwendung darüber aufrufen kann. Dabei können Sie die eingebauten Elemente sogar weitgehend ausblenden, sodass man Ihrer Anwendung nur noch an wenigen Stellen ansieht, dass es sich überhaupt um eine Access-Anwendung handelt. Diese Artikelreihe liefert alle Informationen, die Sie für die Arbeit mit dem Ribbon und für seine Anpassung und Programmierung benötigen. Dabei lernen Sie auch alle Steuerelemente und ihre Eigenschaften kennen.
Beispieldatenbank
Die Beispiele dieses Artikels finden Sie in der Datenbank 2106_RibbonAnpassen.accdb.
Das dynamicMenu-Element
Dieses Element nimmt eine besondere Rolle unter den Ribbonelementen ein, denn Sie können nicht nur einzelne Attribute mit get…-Attributen manipulieren, sondern Sie können den gesamten Inhalt des Menüs per VBA im XML-Format zusammensetzen und an ein spezielles Callbackattribut zurückgeben.
Das Beispiel finden Sie in der Tabelle USysRibbons unter dem Namen Beispiel dynamicMenu. Der Code befindet sich im Modul mdlRibbonsDynamicMenu.
Das Attribut zum Füllen des Elements heißt getContent und wir betten dieses wie folgt in das dynamicMenu-Element ein:
<group id="grp0" label="Beispiel dynamicMenu"> <dynamicMenu id="dyn" label="Dynamic Menu:" getContent="getContent" /> </group>
Eine sehr einfache Variante der dadurch aufgerufenen Callbackprozedur getContent sieht wie in Listing 1 aus.
Sub getContent(control As IRibbonControl, ByRef content) Dim strXML As String Dim i As Integer strXML = "<menu xmlns=""http://schemas.microsoft.com/office/2009/07/customui"">" For i = 1 To 10 strXML = strXML & "<button id=""btn" & i & """ label=""Button " & i & """/>" Next i strXML = strXML & "</menu>" content = strXML End Sub
Listing 1: Beispiel für ein dynamicMenu-Element
Die Prozedur erhält einen Verweis auf das auslösende dynamicMenu-Element als Parameter und erhält einen weiteren Parameter namens content, der den Inhalt des dynamicMenu-Elements entgegennimmt.
Sie füllt sukzessive eine Variable namens strXML. Die erste Zeile enthält das menu-Element:
<menu xmlns="http://schemas.microsoft.com/office/2009/07/customui">
Sie durchläuft eine Schleife von 1 bis 10, in der Sie Einträge wie die folgenden zu der ersten Zeile hinzufügt:
<button id="btn1" label="Button 1"/> <button id="btn2" label="Button 2"/> <button id="btn3" label="Button 3"/> ... <button id="btn10" label="Button 10"/>
Schließlich hängt die Prozedur noch die abschließende Zeile mit dem schließenden menu-Element an:
</menu>
Schließlich gibt die Prozedur das in strXML zusammengestellte Ergebnis mit dem Parameter content zurück. Das Ergebnis dieses Beispiels finden Sie in Bild 1.
Bild 1: dynamicMenu-Element
dynamicMenu-Element aus der Datenbank füllen
Genau wie über eine Schleife können Sie das dynamicMenu-Element auch mit den Daten einer Tabelle aus der Datenbank füllen. Um den Spaß zu erhöhen, machen wir das gleich mal mit zwei Ebenen – Kategorien und Artikeln. Das Ergebnis soll wie in Bild 2 aussehen und ein Klick auf einen der Artikel soll auch noch ein Formular öffnen, das diesen Artikel anzeigt.
Bild 2: dynamicMenu-Element mit Kategorien und Artikeln
Das Beispiel finden Sie in der Tabelle USysRibbons unter dem Namen Beispiel dynamicMenu aus Datenbank. Der Code befindet sich im Modul mdlRibbonsDynamicMenu.
Die Prozedur, die durch das Callbackattribut getContent ausgelöst wird, finden Sie in Listing 2. Die Prozedur referenziert mit der Variablen db das aktuelle Database-Objekt und mit rstKategorien ein Recordset auf Basis der Tabelle tblKategorien. Sie erstellt dann zunächst das umschließende menu-Element und steigt dann in eine Do While-Schleife über alle Kategorien ein. Darin fügt sie zunächst für jede Kategorie ein neues menu-Element hinzu und legt seine Attribute fest. id erhält den Buchstaben k und die KategorieID, label erhält den Kategorienamen und image den Wert folder.
Sub dynKategorienUndArtikel_getContent(control As IRibbonControl, ByRef content) Dim db As DAO.Database Dim rstKategorien As DAO.Recordset Dim rstArtikel As DAO.Recordset Dim strXML As String Dim i As Integer Set db = CurrentDb Set rstKategorien = db.OpenRecordset("SELECT * FROM tblKategorien", dbOpenDynaset) strXML = "<menu xmlns=""http://schemas.microsoft.com/office/2009/07/customui"">" & vbCrLf Do While Not rstKategorien.EOF strXML = strXML & " <menu id=""k" & rstKategorien!KategorieID & """ label=""" & rstKategorien!Kategoriename _ & """ image=""folder"">" & vbCrLf Set rstArtikel = db.OpenRecordset("SELECT * FROM tblArtikel WHERE KategorieID = " & rstKategorien!KategorieID, dbOpenDynaset) Do While Not rstArtikel.EOF strXML = strXML & " <button id=""a" & rstArtikel!ArtikelID & """ label=""" & rstArtikel!Artikelname _ & """ onAction=""btnArticle_onAction"" tag=""" & rstArtikel!ArtikelID & """ image=""form""/>" & vbCrLf rstArtikel.MoveNext Loop strXML = strXML & " </menu>" & vbCrLf rstKategorien.MoveNext Loop strXML = strXML & "</menu>" content = strXML End Sub
Listing 2: Beispiel zum Füllen eines dynamicMenu-Elements aus den Daten einer Datenbank
Danach erstellt die Prozedur ein Recordset, das alle Datensätze der Tabelle tblArtikel enthält, die zur aktuellen Kategorie aus der übergeordneten Schleife gehören. Diese durchläuft die Prozedur ebenfalls in einer Do While-Schleife. Hier legt sie jeweils ein button-Element für den aktuellen Artikel an. Die id erhält den Buchstaben a und die Artikel-ID, das label den Artikelnamen und das Attribut onAction den Prozedurnamen btnArticle_onAction. Und damit wir beim Anklicken des button-Elements wissen, welchen Artikel der Benutzer überhaupt angeklickt hat, hinterlegen wir für das tag-Attribut noch den Primärschlüsselwert des jeweiligen Artikels.
Sind alle Artikel einer Kategorie durchlaufen, fügt die Prozedur das schließende menu-Element hinzu und schreitet mit der nächsten Kategorie voran. Auf diese Weise werden alle Kategorien und Artikel eingefügt, bevor das schließende menu-Element folgt und die Prozedur den Inhalt von strXML mit dem Parameter content zurückgibt.
Das Ergebnis sieht in gekürzter Form wie in Listing 3 aus.
<menu xmlns="http://schemas.microsoft.com/office/2009/07/customui"> <menu id="k1" label="Getränke" image="folder"> <button id="a1" label="Chai" onAction="btnArticle_onAction" tag="1" image="form"/> <button id="a2" label="Chang" onAction="btnArticle_onAction" tag="2" image="form"/> ... </menu> <menu id="k2" label="Gewürze" image="folder"> <button id="a3" label="Aniseed Syrup" onAction="btnArticle_onAction" tag="3" image="form"/> <button id="a4" label="Chef Anton's Cajun Seasoning" onAction="btnArticle_onAction" tag="4" image="form"/> ... </menu> ... </menu>
Listing 3: Der von der Prozedur dynKategorienUndArtikel_getContent erzeugte XML-Ausdruck (gekürzt)
Anzeigen des Formulars mit dem gewählten Artikel
Für das Callbackattribut btnArticle_onAction hinterlegen wir die folgende Prozedur:
Sub btnArticle_onAction(control As IRibbonControl) Dim lngArtikelID As Long lngArtikelID = control.Tag DoCmd.OpenForm "frmArtikel", WhereCondition:="ArtikelID = " & lngArtikelID End Sub
Diese Prozedur ermittelt aus der Eigenschaft tag des Parameters control den Primärschüsselwert des Artikels, den der Benutzer angeklickt hat. Diesen fügen wir dann über die Variable lngArtikel als Vergleichswert in die WhereCondition der DoCmd.OpenForm-Methode ein.
Sie können auch Menü-Einträge zum Hinzufügen neuer Kategorien oder Artikel hinzufügen – hier ergeben sich eine Menge neuer Ideen!
dynamicMenu zur Laufzeit aktualisieren
Bisher wird das dynamicMenu-Element beim ersten Aufruf per VBA zusammengestellt. Was aber, wenn der Benutzer bei der Arbeit mit der Datenbank neue Kategorien oder neue Artikel anlegt oder die vorhandenen Daten ändert oder löscht Dann sollte auch das Menü beim nächsten Aufruf neu zusammengestellt werden.
Was wir dazu brauchen, ist wiederum ein Attribut namens onLoad für das customUI-Element und dafür eine Ereignisprozedur, welche die Ribbondefinition per IRibbonUI-Variable referenziert.
Für diese können wir dann zu gegebener Zeit die Invalidate– oder die InvalidateControl-Methode aufrufen.
Also erweitern wir customUI um das onLoad-Attribut:
<customUI ... loadImage="loadImage" onLoad="onLoad_dynamicMenu">
Die Callbackprozedur implementieren wir wie folgt:
Sub onLoad_dynamicMenu(ribbon As IRibbonUI) Set objRibbon_DynamicMenu = ribbon End Sub
Die Deklaration der benötigten Variablen lautet:
Public objRibbon_DynamicMenu As IRibbonUI
Um das Ribbon beispielsweise nach dem Ändern eines Datensatzes im Formular frmArtikel neu zu laden, fügen wir für das Ereignis Nach Aktualisierung des Formulars die folgende Ereignisprozedur hinzu:
Private Sub Form_AfterUpdate() objRibbon_DynamicMenu.Invalidate End Sub
Damit wird das dynamicMenu nach Änderungen an einem Artikel im Formular frmArtikel neu gefüllt.
Das gallery-Element
Mit dem gallery-Element können Sie Elemente nicht nur untereinander, sondern unter- und nebeneinander anzeigen. Dazu teilen Sie dem gallery-Element mit den Attributen columns und rows mit, wie die enthaltenen Elemente dargestellt werden sollen.
Das Beispiel finden Sie in der Tabelle USysRibbons unter dem Namen Beispiel gallery. Der Code befindet sich im Modul mdlRibbonsGallery.
Hier ist ein Beispiel für ein sehr einfaches gallery-Element mit zwei mal zwei Elementen:
<group id="grp0" label="Beispiel gallery"> <gallery id="gal" label="Galerie" rows="2" columns="2"> <item id="itm1" label="Element 1" /> <item id="itm2" label="Element 2" /> <item id="itm3" label="Element 3" /> <item id="itm4" label="Element 4" /> </gallery> </group>
Dieses sieht wie in Bild 3 aus. Die Elemente werden also zuerst zeilenweise hinzugefügt und dann untereinander. Dabei geben die Werte für die beiden Attribute rows und columns lediglich an, wie groß der Platz für das gallery-Element berechnet wird. Sie legen damit keine Obergrenze für die anzeigbaren Elemente fest. Wenn Sie mehr Elemente hinzufügen, also in dem durch rows und columns festgelegten Platz angezeigt werden können, erscheint eine Bildlaufleiste und die übrigen Elemente werden unten angehängt (siehe Bild 4).
Bild 3: gallery-Element
Bild 4: gallery-Element mit Bildlaufleiste
Das gallery-Element hat noch zwei interessante Eigenschaften:
- itemHeight: Gibt die Höhe der Bilder im gallery-Element an.
- itemWidth: Gibt die Breite der Bilder im gallery-Element an.
Diese treten jedoch nur in Erscheinung, wenn für die Elemente überhaupt Bilder hinterlegt sind. Dies ist etwa in folgendem Beispiel der Fall:
<customUI ... loadImage="loadImage"> ... <group id="grp0" label="Beispiel gallery"> <gallery id="gal" label="Galerie" rows="2" columns="2" itemHeight="32" itemWidth="32"> <item id="itm1" label="Element 1" image="apple" /> <item id="itm2" label="Element 2" image="lemon" /> <item id="itm3" label="Element 3" image="hamburger"/> <item id="itm4" label="Element 4" image="banana" /> </gallery> </group>
Das Ergebnis sehen Sie in Bild 5.
Bild 5: gallery-Element mit Bildern
gallery-Element immer neu laden
Genau wie das comboBox-Element weist auch das gallery-Element das Attribut invalidateContentOnDrop auf. Stellen Sie dieses auf true ein, wird der Inhalt des Elements immer wieder neu geladen.
Dazu benötigen wir aber zunächst die notwendigen Attribute, die zum dynamischen Laden der Elemente notwendig sind.
Diese hinterlegen wir in der Definition aus Listing 4. Diese Definition finden Sie in der Tabelle USysRibbons unter dem Namen Beispiel gallery dynamisch. Den Code finden Sie im Modul mdlRibbonsGallery.
<xml version="1.0"> <customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" loadImage="loadImage"> <ribbon> <tabs> <tab id="tab" label="Beispiel Menüs" insertBeforeMso="TabHomeAccess"> <group id="grp0" label="Beispiel gallery"> <gallery id="gal" label="Galerie" itemHeight="32" itemWidth="32" getItemLabel="gal_getItemLabel" getItemImage="gal_getItemImage" getItemID="gal_getItemID" getItemCount="gal_getItemCount" invalidateContentOnDrop="true"/> </group> </tab> </tabs> </ribbon> </customUI>
Listing 4: Beispiel für ein gallery-Element, das aus der Datenbank befüllt wird
Wir haben in diesem Beispiel wieder die beiden Attribute columns und rows entfernt, da diese nicht dynamisch gesetzt werden können – es gibt kein get…-Attribute für diese Eigenschaften. Wenn wir diese weglassen, teilt das Ribbon die Elemente gleichmäßig auf Zeilen und Spalten auf.
Wir wollen in diesem Beispiel einmal alle Bilder, die in der Tabelle MSysResources gespeichert sind, in einem gallery-Element auflisten. Dazu benötigen wir wieder die Attribute getItemCount, getItemLabel und getItemID. Außerdem wollen wir zu jedem Element das Bild anzeigen und nutzen dazu das Attribut getItemImage.
Die folgende Array-Variable soll die einzelnen Einträge in der Prozedur für das Attribut getItemCount erfassen:
Public strGallery() As String
Die Prozedur aus Listing 5 ermittelt die Anzahl der Elemente und stellt die wichtigsten Informationen zu diesen im Array strGallery zusammen. Dazu durchläuft diese Prozedur alle Datensätze eines Recordsets basierend auf der Tabelle MSysResources. Wir haben diese gefiltert nach Elementen, deren Feld Type den Wert img enthält.
Sub gal_getItemCount(control As IRibbonControl, ByRef count) Dim db As DAO.Database Dim rst As DAO.Recordset Dim i As Integer Set db = CurrentDb Set rst = db.OpenRecordset("SELECT * FROM MSysResources WHERE Type = 'img'", dbOpenDynaset) Do While Not rst.EOF ReDim Preserve strGallery(1, i) As String strGallery(0, i) = rst!ID strGallery(1, i) = rst!Name i = i + 1 rst.MoveNext Loop count = i End Sub
Listing 5: Code zum Ermitteln der Anzahl der Elemente für das gallery-Element aus der Tabelle MSysResources
Beim Durchlaufen des Recordsets in einer Do -While-Schleife erweitern wir das zweidimensionale Array jeweils um eine Zeile und fügen der ersten Spalte des neu hinzugefügten Elements die ID und der zweiten den Namen aus der Tabelle hinzu. Dabei erhöhen wir die Zählervariable i jeweils um 1. Der Wert von i entspricht anschließend der Anzahl der einzulesenden Elemente und wird mit dem Parameter count zurückgegeben.
Entsprechend dieser Anzahl ruft das Ribbon anschließend die Prozeduren für die drei Attribute getItemLabel, getItemImage und getItemID auf. Die Prozedur gal_getItemLabel gibt als Bezeichnung des Elements den Wert des Feldes Name zurück, der im Array in der zweiten Spalte enthalten ist:
Sub gal_getItemLabel(control As IRibbonControl, _ index As Integer, ByRef label) label = strGallery(1, index) End Sub
Die Prozedur gal_getItemID holt den Wert aus der ersten Spalte des Arrays und gibt diese mit dem Parameter ID zurück:
Sub gal_getItemID(control As IRibbonControl, _ index As Integer, ByRef ID) ID = strGallery(0, index) End Sub
Schließlich fehlt noch die Prozedur gal_getItemImage. Diese liefert einen Verweis auf das auslösende Steuerelement für den Parameter control und den aktuellen index, also den Wert für das aktuell zu füllende Element. Der Parameter image erwartet ein StdPicture-Element mit dem Bild, das im gallery-Element für diesen Eintrag angezeigt werden soll. Dazu ermitteln wir aus dem Array strGallery den Namen aus der zweiten Spalte, welcher dem Bildnamen entspricht. Danach können wir die Funktion PicFrom-SharedResource_Ribbon nutzen, um das Bild aus der Tabelle MSysResources zu diesem Namen einzulesen und mit dem Parameter image zurückzugeben:
Sub gal_getItemImage(control As IRibbonControl, _ index As Integer, ByRef image) Dim strImage As String strImage = strGallery(1, index) Set image = _ PicFromSharedResource_Ribbon(CStr(strImage)) End Sub
Das Ergebnis sieht schließlich wie in Bild 6 aus.
Bild 6: gallery-Element mit zur Laufzeit geladenen Bildern
Da wir das Attribut invalidateContentOnDrop auf den Wert true eingestellt haben, können wir zur Laufzeit weitere Elemente zur Tabelle MSysResources hinzufügen und diese werden direkt beim nächsten Aufklappen vom gallery-Element angezeigt.
Das splitButton-Element
Dieses Element ist vermutlich eines der eingebauten Elemente, das Sie ständig verwenden: Bei dem Element zum Ändern der Ansicht eines Objekts handelt es sich nämlich um ein splitButton-Element (siehe Bild 7). Damit wählen Sie einen der Einträge Formularansicht, Datenblattansicht, Layoutansicht oder Entwurfsansicht aus der Aufklappliste aus, wobei einer der Einträge immer schon als sofort anklickbares Element erscheint.
Bild 7: Das wohl meistgenutzte eingebaute splitButton-Element
Dieses Element können wir ebenfalls selbst zu unseren Ribbons hinzufügen. Der XML-Code für dieses Element ist dabei genauso aufgebaut, wie es auch zu sehen ist: Es enthält ein button-Element sowie ein menu-Element mit den button-Elementen für die aufklappbare Liste.
Das Beispiel finden Sie in der Tabelle USysRibbons unter dem Namen Beispiel splitButton.
Der Code für ein benutzerdefiniertes splitButton-Element sieht wie in Listing 6 aus. Die Größe für das Icon im immer sichtbaren button-Element stellen Sie bereits für das splitButton-Element ein. Dieses stellt als eines der wenigen Elemente nicht das Attribut label zur Verfügung. Unterhalb des splitButton-Elements ordnen wir das button-Element an, das die immer sichtbare Schaltfläche anzeigt, sowie ein menu-Element mit weiteren button-Elementen – eben jenen, die erst beim Aufklappen erscheinen.
<group id="grp0" label="Beispiel splitButton"> <splitButton id="spb" size="large"> <button id="btnBanane" label="Banane" image="banana" /> <menu id="spbMenu" itemSize="large"> <button id="spbLemon" label="Zitrone" image="lemon" /> <button id="spbApfel" label="Apfel" image="apple" /> <button id="spbBanane" label="Banane" image="banana" /> <button id="spbAnanas" label="Pineapple" image="pineapple" /> <button id="spbOrange" label="Orange" image="orange" /> </menu> </splitButton> </group>
Listing 6: Code für ein splitButton-Element
Die Größe für die Icons der button-Elemente stellen wir wiederum nicht für die button-Elemente selbst ein, sondern für das Element menu – und zwar mit dem Attribut itemSize. Für die einzelnen button-Elemente könnten wir nun beispielsweise noch das onAction-Attribut festlegen und Prozeduren hinzufügen, die durch die jeweiligen Schaltflächen ausgelöst werden. Das hier definierte Ribbon sieht wie in Bild 8 aus.
Bild 8: Ein benutzerdefiniertes splitButton-Element
Das splitButton-Element lässt sich im Gegensatz zu den anderen aufklappbaren Elementen nicht zur Laufzeit über get…-Attribute mit Daten füllen.
Das control-Element
Sie können auch die eingebauten Ribbonelemente an beliebiger Stelle in Ihren eigenen Ribbondefinitionen einfügen. Dazu benötigen Sie das control-Element. Für dieses legen Sie mit dem Attribut idMso fest, welches Steuerelement es abbilden soll. Die idMso finden Sie am einfachsten über den Bereich Menüband anpassen in den Access-Optionen (Ribboneintrag Datei|Optionen).
Angenommen, Sie möchten den Befehl Datenbank komprimieren und reparieren in Ihre Ribbondefinition aufnehmen. Sie wissen, dass sich dieser Befehl im Backstagebereich befindet, den Sie über den Datei-Reiter öffnen. Also wechseln Sie unter Menüband anpassen unter Befehle auswählen zunächst zu Registerkarte “Datei”. Die darunter befindliche Liste listet nun alle Befehle auf, die unter bestimmten Konstellationen in diesem Bereich erscheinen können. Darunter finden wir auch den Befehl Datenbank komprimieren und reparieren. Der Trick ist nun, den Mauszeiger über diesem Befehl zu positionieren. Es erscheint ein ToolTip-Text, der am Ende in Klammern den englischen Namen für die idMso anzeigt – in diesem Fall FileCompactAndRepairDatabase (siehe Bild 9).
Bild 9: Ermitteln der idMso eines Elements über die Access-Optionen
Auf diese Weise können Sie mit ein wenig Detektivarbeit die idMso für alle gewünschten Elemente ausfindig machen.
Weiter unten stellen wir noch ein Formular vor, mit dem Sie noch schneller an die gewünschten idMso-Werte kommen – auch für tab– und group-Elemente.
Wie aber fügen Sie das gewünschte Element nun zu Ihrer eigenen Ribbondefinition hinzu Hier kommt das control-Element ins Spiel. Dieses bildet exakt das Steuerelement ab, dessen idMso Sie angeben.
Im folgenden Beispiel (siehe Tabelle USysRibbons unter Beispiel control) fügen wir die Schaltfläche Datenbank komprimieren und reparieren hinzu. Dabei überschreiben wir mit der Eigenschaft label auch gleich noch die Beschriftung mit dem Text Komprimieren:
<control idMso="FileCompactAndRepairDatabase" size="large" label="Komprimieren" />
Dies hätten wir auch erreichen können, wenn wir einfach ein button-Element mit der gleichen idMso verwendet hätten:
<button idMso="FileCompactAndRepairDatabase" size="large" label="Komprimieren" />
Welchen Vorteil bietet uns nun das control-Element, sodass wir dieses nutzen sollten Dieser Vorteil tritt erst in Erscheinung, wenn wir komplexere Steuerelemente abbilden wollen. Wollen Sie beispielsweise das splitButton-Element zum Einstellen der Ansicht des aktuell geöffneten Objekts zum benutzerdefinierten Ribbon hinzufügen, brauchen Sie auch hier einfach nur die idMso anzugeben – hier ViewsModeMenu:
<control idMso="ViewsModeMenu" size="large" />
Dies bildet dann das Element exakt ab (siehe Bild 10). Sie brauchen sich also nicht um den Elementtyp zu kümmern, sondern tragen einfach nur die idMso ein.
Bild 10: Beispiel für eingebaute Elemente im benutzerdefinierten Ribbon
Das dialogBoxLauncher-Element
Bei manchen eingebauten group-Elementen finden Sie unten rechts eine kleine Schaltfläche mit einem nach rechts unten zeigenden Pfeil (siehe Bild 11). Diese öffnet in der Regel einen Dialog mit weiteren Optionen. Auch dieses Element können Sie zu Ihren eigenen benutzerdefinierten group-Elementen hinzufügen. Dazu verwenden Sie das dialogBoxLauncher-Element.
Bild 11: Schaltfläche zum Anzeigen weiterer Optionen
Das Beispiel finden Sie in der Tabelle USysRibbons unter Beispiel dialogBoxLauncher und den VBA-Code im Modul mdlRibbonsDialogBoxLauncher.
Das dialogBoxLauncher-Element fügen Sie der Gruppe hinzu, in der es angezeigt werden soll. Das Element hat keinerlei Attribute. Sie können lediglich ein button-Element als Unterelement hinzufügen. Dieses legt mit dem on-Action-Attribut die Prozedur fest, die beim Anklicken ausgelöst werden soll.
Außerdem wollen wir, damit der Benutzer weiß, was ein Klick auf dieses Element auslöst, einen Hilfstext für das Attribut screentip hinterlegen:
<group id="grp0" label="Beispiel dialogBoxLauncher"> <dialogBoxLauncher> <button id="dbl" onAction="dbl_onAction" screentip="Weitere Optionen anzeigen ..." /> </dialogBoxLauncher> </group>
Das Ergebnis sehen Sie in Bild 12.
Bild 12: Beispiel für den dialogBoxLauncher
Für das Callbackattribut hinterlegen wir einfach eine Prozedur, die ein Meldungsfenster anzeigt. Normalerweise könnten Sie hier beispielsweise ein Formular mit weiteren Optionen anzeigen:
Sub dbl_onAction(control As IRibbonControl) MsgBox "Weitere Optionen ..." End Sub
Formular zur einfachen Suche von tab-, group- und control-Elementen und ihren idMso-Werten
Für die folgenden Beispiele benötigen Sie den Wert des Attributs idMso des tab– oder group-Elements, in das Sie die Elemente integrieren wollen.
Diese lassen sich normalerweise nicht so einfach ermitteln, denn im Gegensatz zu den Elementen innerhalb der Gruppen finden Sie die Werte für das Attribut idMso nicht wie weiter oben beschrieben in den Access-Optionen im Bereich Menüband anpassen.
Als Unterstützung bei der Suche nach idMso-Werten von verschiedenen Elementen, die Sie für die Beispiele in den folgenden Abschnitten benötigen, haben wir Ihnen in der Beispieldatenbank ein Formular namens frmRibbonControls hinzugefügt.
Mit diesem fragen Sie Informationen über die tab-, group– und control-Elemente ab – und es gibt auch eine Suchfunktion, mit der Sie nach den Werten der idMso und nach den deutschen Bezeichnungen suchen können.
Das Formular sieht wie in Bild 13 aus. Hier finden Sie zunächst zwei Textfelder, mit denen Sie nach der englischen Bezeichnung für die Eigenschaft idMso suchen können und/oder nach der Beschriftung im Ribbon in der deutschsprachigen Version von Access. Außerdem können Sie hier angeben, ob Sie nach dem Namen von tab-, group-, control– oder gallery-Elementen suchen wollen.
Bild 13: Das Formular zum Suchen von Ribbon-Elementen
Schließlich legen Sie unter Optionen noch fest, ob die Suchergebnisse mit dem angegebenen Suchausdruck beginnen sollen, ob dieser irgendwo enthalten sein soll oder ob Sie eine exakte Übereinstimmung wünschen.
Das Suchergebnis wird nach der Eingabe eines jeden Buchstaben in die beiden Textfelder oder nach dem Aktualisieren der Kontrollkästchen oder der Optionsgruppe aktualisiert. Im Beispiel aus dem Screenshot suchen wir nach allen Elementen, deren Wert für die Eigenschaft idMso mit Table beginnt.
Im Ergebnis sehen Sie die idMso, die deutsche Beschriftung sowie den Elementtyp. Damit haben Sie eine gute Ergänzung zu der Suchmöglichkeit über die Access-Optionen (siehe weiter oben), die auch die Namen von tab– und group-Elementen umfasst.
Benutzerdefinierte Elemente in eingebauten tab- und group-Elemente einbauen
Sie müssen Ihre benutzerdefinierten Elemente nicht unbedingt in jeweils neu angelegte tab– und group-Elemente einbauen. Sie können diese auch einfach in die eingebauten tab– und group-Elemente integrieren.
Nachdem Sie den Namen des gesuchten tab– oder group-Elements mithilfe des oben beschriebenen Formulars oder auf andere Weise gefunden haben, können Sie diesen eingebauten Elementen benutzerdefinierte Elemente hinzufügen.
Wir wollen wie in Bild 14 eine Gruppe mit einer Schaltfläche zum Ribbon-Tab Externe Daten hinzufügen. Dazu ermitteln wir über das Formular frmRibbonControls den Wert der Eigenschaft idMso, indem wir für das Feld Beschriftung den Text Externe Daten eingeben. Dies liefert direkt den Wert TabExternalData für die idMso des tab-Elements.
Bild 14: Einbau einer benutzerdefinierten Gruppe in ein eingebautes tab-Element
Diesen Wert nutzen wir dann, um das tab-Element wie in der folgenden Ribbondefinition zu referenzieren und darin ein neues group-Element mit einem button-Element anzulegen:
<xml version="1.0"> <customUI ... loadImage="loadImage" > <ribbon> <tabs> <tab idMso="TabExternalData"> <group id="grp0" label="Beispiel benutzerdefinierte Gruppe"> <button id="btn" label="Benutzerdefinierter Button" image="apple" size="large" /> </group> </tab> </tabs> </ribbon> </customUI>
Benutzerdefiniertes group-Element an bestimmter Stelle in eingebauten tab-Elementen platzieren
Wenn Sie nun nicht möchten, dass das neue group-Element ganz rechts steht, sondern an einer anderen Position, können Sie die folgenden Attribute nutzen:
- insertAfterMso: Geben Sie für diese Attribut den idMso-Wert des group-Elements an, hinter dem Sie das einzufügende group-Element platzieren wollen.
- insertBeforeMso: Geben Sie für diese Attribut den idMso-Wert des group-Elements an, vor dem Sie das einzufügende group-Element platzieren wollen.
Wenn Sie das group-Element also beispielsweise ganz vorn platzieren wollen, verwenden Sie insertBeforeMso und geben als Wert dieses Attributs die idMso der Gruppe Importieren und Verknüpfen an. Auch diese idMso finden wir schnell mit dem Formular frmRibbonControls heraus. Sein Name lautet GroupImport. Die neue Definition für das Element group würde nun wie folgt lauten:
<group id="grp0" label="Beispiel benutzerdefinierte Gruppe" insertBeforeMso="GroupImport"> <button id="btn" label="Benutzerdefinierter Button" image="apple" size="large" /> </group>
Bild 15 zeigt das Ergebnis. Auf die gleiche Weise gehen Sie mit den anderen Positionen vor.
Bild 15: Einbau einer benutzerdefinierten Gruppe an den Beginn eines eingebauten tab-Elements
Benutzerdefinierte Elemente in eingebauten group-Elementen platzieren
Benutzerdefinierte Elemente können Sie nicht in eingebauten group-Elementen platzieren. Wollen Sie dies dennoch tun, könnten Sie die eingebaute Gruppe ausblenden und die Gruppe in einer benutzerdefinierten Gruppe nachbilden, der Sie dann noch Ihre eigenen Elemente hinzufügen.
Um die Gruppe auszublenden, fügen wir ein group-Element hinzu, das die idMso der auszublenden Gruppe aufweist. Damit diese ausgeblendet wird, stellen wir ihr Attribut visible auf den Wert false ein (siehe Listing 7). Dann fügen wir eine neue, benutzerdefinierte Gruppe hinzu, welche die gleiche Beschriftung erhält und deren Position wir mit dem Attribut insertBeforeMso einstellen.
<xml version="1.0"> <customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" loadImage="loadImage" > <ribbon> <tabs> <tab idMso="TabCreate"> <group idMso="GroupCreateTables" visible="false" /> <group id="grpGroupCreateTables" insertBeforeMso="GroupCreateClientQuery"> <button idMso="CreateTable" size="large" /> <button idMso="CreateTableInDesignView" size="large" /> <button idMso="DatabaseMoveToSharePoint" size="large" /> <button id="btn" label="Benutzerdefinierter Button" image="apple" size="large" /> </group> </tab> </tabs> </ribbon> </customUI>
Listing 7: Code für den Nachbau einer eingebauten Gruppe mit benutzerdefiniertem button-Element
In dieser legen wir dann zunächst die drei eingebauten Elemente CreateTable, CreateTableInDesignView und DatabaseMoveToSharePoint an und stellen size auf large ein, damit diese in der gleichen Größe wie im Original erscheinen.
Schließlich fügen wir die benutzerdefinierte Schaltfläche hinzu, die dann wie in Bild 16 aussieht.
Bild 16: Nachbau einer eingebauten Gruppe mit neuem button-Element
Eingebaute Elemente an anderer Stelle einbauen
Vielleicht möchten Sie auch eingebaute Elemente an einer Stelle einbauen, wo diese für Sie besser zugreifbar sind. Oder Sie möchten einfach die vorhandenen Elemente umarrangieren, etwa weil diese zu klein oder zu groß angezeigt werden. Mir ist beispielsweise immer die Anzeige der Steuerelemente im Bereich Steuerelemente im tab-Element Entwurf ein Dorn im Auge. Es ist schlicht unergonomisch, wenn man nur acht Steuerelemente direkt anklicken kann und für alle übrigen erst noch ein Menü aufklappen muss wie in Bild 17.
Bild 17: Die meisten Schaltflächen für das Hinzufügen der Steuerelemente erst durch Aufklappen einer Liste zu erreichen.
Möchten Sie weiterlesen? Dann lösen Sie Ihr Ticket!
Hier geht es zur Bestellung des Jahresabonnements des Magazins Access [basics]:
Zur Bestellung ...
Danach greifen Sie sofort auf alle rund 400 Artikel unseres Angebots zu - auch auf diesen hier!
Oder haben Sie bereits Zugangsdaten? Dann loggen Sie sich gleich hier ein: