Formulare sind oft völlig überfrachtet mit Steuerelementen zur Anzeige und Auswahl von Daten und Schaltflächen. Das lässt sich zumindest teilweise ändern, indem Sie einige Elemente aus dem Formular in ein Ribbon auslagern, das dann beim Erscheinen des Formulars eingeblendet wird. Bei einfachen Schaltflächen ist das noch recht einfach, aber sobald die Steuer-elemente etwa abhängig von den angezeigten Daten ein- oder ausgeblendet werden sollen, wird es interessant. In diesem Beitrag schauen wir uns an, wie das gelingt.
Konkret nehmen wir uns das Beispiel aus dem Beitrag Datenblatt: Reihenfolge mehrerer Einträge ändern (www.access-im-unternehmen.de/1198) vor. Hier finden wir in einem Formular ein Unterformular in der Datenblattansicht vor (siehe Bild 1). Dieses enthält vier Schaltflächen, mit denen Sie die Reihenfolge der Einträge des Datenblatts über die Werte des Feldes ReihenfolgeID manipulieren können. Im Falle dieses Beispiels enthält das Datenblatt nicht so viele Felder, dass diese nicht auf das Formular passen würde.
Bild 1: Ausgangsformular
Wenn dies allerdings der Fall wäre, würde man sich die Schaltflächen an einer anderen Position wünschen. Am Besten, damit diese gar nicht mehr im Weg sind, direkt im Ribbon. Und genau das ist Thema des vorliegenden Artikels: Wir wollen zeigen, wie Sie die Schaltflächen aus einem Formular in das Ribbon übertragen und dabei alle vorgegebenen Funktionen beibehalten.
In unserem Fall betrifft das vor allem das Aktivieren und Deaktivieren der Schaltflächen in Abhängigkeit der angezeigten Daten. Das heißt, dass die Schaltflächen zum Verschieben der Elemente nach oben nur aktiviert sein sollen, wenn die Elemente auch nach oben verschoben werden können. Das gleiche gilt für die Schaltflächen zum Verschieben nach unten – diese sollen nur aktiviert werden, wenn die Elemente auch nach unten verschoben werden können. Außerdem sollen die Schaltflächen natürlich die im Klassenmodul des Formulars gespeicherten Ereignisprozeduren aufrufen.
Eine weitere Anforderung ist, dass das Ribbon nur in Zusammenhang mit der Anzeige dieses Formulars angezeigt werden soll. Um dieses zu öffnen, fügen wir der Anwendung noch ein Start-Ribbon hinzu, das beim Start angezeigt wird und das Öffnen des Formulars frmMehrfachreihenfolgeDatenblatt erlaubt. Wir könnten theoretisch auch direkt das Unterformular in der Datenblattansicht öffnen, aber das würde bedeuten, dass wir den kompletten Code des Hauptformulars in das Klassenmodul des Unterformulars übertragen und anpassen müssten. Diesen Schritt wollen wir erst einmal nicht gehen. Daher maximieren wir einfach das Unterformular innerhalb des Hauptformulars und sorgen dafür, dass das Hauptformular mit dem Unterformular beim Anklicken des entsprechenden Ribbon-Eintrags angezeigt wird. Das Ribbon-Tab für das Formular frmMehrfachreihenfolgeDatenblatt soll dann rechts neben dem Startribbon erscheinen.
Start-Ribbon erstellen
Um das erste Ribbon zu erstellen, fügen wir zunächst eine neue Tabelle namens USysRibbons zur Datenbank hinzu. Dieser Tabelle fügen Sie die drei folgenden Felder hinzu (siehe Bild 2):
Bild 2: Entwurf der Tabelle USysRibbons
- ID: Autowertfeld mit Primärschlüsselindex
- RibbonName: Textfeld/Kurzer Text
- RibbonXML: Memofeld/Langer Text
USysRibbons wieder einblenden
Wenn Sie nicht die Anzeige von Systemobjekten und ausblendeten Objekten deaktiviert haben, verschwindet die Tabelle allerdings direkt nach dem Speichern aus dem Navigationsbereich.
Um diese wieder sichtbar zu machen, klicken Sie mit der rechten Maustaste auf die Titelzeile des Navigationsbereichs und wählen aus dem Kontextmenü den Eintrag Navigationsoptionen… aus.
Im nun erscheinenden Dialog Navigationsoptionen aktivieren Sie die beiden Optionen Ausgeblendete Objekte anzeigen und System-Objekte anzeigen (siehe Bild 3). Danach erscheint die Tabelle USysRibbons wieder im Navigationsbereich.
Bild 3: Die Navigationsoptionen von Access
Ribbon-Definition für das Start-Ribbon
Danach fügen wir dem Feld RibbonName der Tabelle den Wert Main und dem Feld RibbonXML den XML-Code aus Listing 1 hinzu.
<xml version="1.0"> <customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"> <ribbon> <tabs> <tab id="tabBeispiele" label="Beispiele"> <group id="grpFormulare" label="Formulare"> <button imageMso="AccessFormDatasheet" label="Mehrfachreihenfolge Datenblatt" id="btnMehrfachreihenfolgeDatenblatt" onAction="onAction" size="large"/> </group> </tab> </tabs> </ribbon> </customUI>
Listing 1: XML-Code für das Start-Ribbon
Hier definieren wir die ineinander verschachtelten Elemente customUI, ribbon, tabs, tab, group und schließlich button. Das button-Element erhält schließlich über das Attribut imageMso den Namen eines eingebauten Icons, eine Beschriftung, eine ID, den Wert large für das Attribut size und den Wert onAction für das Attribut onAction. Das bedeutet, dass wir an irgendeiner Stelle – in diesem Fall in einem Standardmodul – eine Prozedur namens onAction bereitstellen müssen, die bestimmten syntaktischen Anforderungen genügt. Die Tabelle sieht danach wie in Bild 4 aus.
Bild 4: Ribbon-Definition für das Start-Ribbon
Code für die Schaltfläche zum Öffnen des Formulars
Die oben genannte Prozedur onAction erstellen wir schließlich so:
Sub onAction(control As IRibbonControl) DoCmd.OpenForm "frmMehrfachreihenfolgeDatenblatt" End Sub
Die Prozedur öffnet also dann das gewünschte Formular.
Ribbonfehler anzeigen
Damit die Benutzeroberfläche Fehler beim Verwenden der benutzerdefinierten Ribbons anzeigt, müssen wir noch eine Access-Option aktivieren. Dazu öffnen Sie über den Eintrag Datei|Optionen zunächst den Optionen-Dialog von Access. Hier finden Sie im Bereich Client-ein-stel-lun-gen|Allgemein die Option Fehler von Be-nut-zer-ober-flächen-Add-Ins anzeigen. Diese aktivieren Sie und schließen den Dialog mit der Schaltfläche OK (siehe Bild 5).
Bild 5: Ribbon-Option zum Anzeigen von Ribbon-Fehlern
Abschließende Schritte
Nun müssen wir nur noch drei Schritte erledigen:
- Die Anwendung schließen und wieder öffnen.
- Die Option Name des Menübands auf die durch das Schließen und Öffnen nun verfügbaren Eintrag Main einstellen (siehe Bild 6).
- Die Anwendung erneut schließen und wieder öffnen, um das Ribbon nun anzuzeigen.
Bild 6: Start-Ribbon für die Anwendung einstellen
Nun erscheint das Ribbon wie in Bild 7. Hier klicken Sie auf den Tab namens Beispiele und erhalten die Schaltfläche zum Öffnen des Formulars.
Bild 7: Das Start-Ribbon
Schaltflächen ins Ribbon
Um die Funktionen der vier Schaltflächen nun über das Ribbon ausführen zu können, legen wir zunächst ein neues Ribbon mit einem eigenen Tab für das Formular frmMehrfachreihenfolgeDatenblatt an.
Der XML-Code für dieses Ribbon sieht zunächst wie in Listing 2 aus und bildet das Grundgerüst, das wir gleich noch ausbauen. Erstmal möchten wir überhaupt ein Ribbon mit dem Formular einblenden. Diesen XML-Code fügen Sie in einem zweiten Datensatz in die Tabelle USysRibbons ein, und zwar mit dem Eintrag Reihenfolge im Feld RibbonName.
<xml version="1.0"> <customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"> <ribbon> <tabs> <tab id="tabReihenfolge" label="Reihenfolge"> <group id="grpReihenfolgeAendern" label="Reihenfolge ändern"> <button imageMso="ShapeUpArrow" label="Ganz nach oben" id="btnTop" size="large"/> <button id="btnUp" imageMso="ShapeUpArrow" label="Nach oben" size="large"/> <button id="btnDown" imageMso="ShapeDownArrow" label="Nach unten" size="large"/> <button id="btnBottom" imageMso="ShapeDownArrow" label="Ganz nach unten" size="large"/> </group> </tab> </tabs> </ribbon> </customUI>
Listing 2: XML-Code für das Ribbon zum Formular
Damit dies gelingt, stellen wir die Eigenschaft Name des Menü-bands des Hauptformulars auf den Namen des neu erstellten Ribbons ein – allerdings erst, nachdem wir nach dem Einfügen des neuen Eintrags zur Tabelle USysRibbons die Anwendung geschlossen und wieder geöffnet haben (siehe Bild 8). Nur dadurch werden neu hinzugefügte Ribbon-Namen auch in den Auswahlfeldern der jeweiligen Eigenschaften sichtbar.
Bild 8: Menüband festlegen
Ribbon für das Unterformular
Wenn wir das Formular nun über den Ribbon-Befehl des Start-Ribbons öffnen, erscheint zwar das Formular, aber das Tab-Element aus dem zugeordneten Ribbon wird nicht angezeigt (siehe Bild 9). Warum das Ganz einfach: Die Schaltflächen sind zu Beginn deaktiviert, damit bleibt das Unterformular das einzige Steuer-element, das den Fokus erhalten kann. Und das Unterformular hat genau wie das Formular eine eigene Eigenschaft namens Name des Menübands. Wir haben nun zwei Möglichkeiten:
Bild 9: Kein neues Ribbon für das Formular
- Wir stellen diese Eigenschaft einfach auf das gleiche Ribbon ein wie die für das Hauptformular.
- Wir fügen eine Ereignisprozedur für das Hauptformular hinzu, dass dem Unterformular das Ribbon des Hauptformulars zuweist.
Wir entscheiden uns für die zweite Variante, da wir dann gegebenenfalls nur das Ribbon für das Hauptformular ändern müssen:
Private Sub Form_Load() Me!sfm.Form.RibbonName = Me.RibbonName End Sub
Damit erhalten wir nun beim Öffnen des Formulars frmMehrfachreihenfolgeDatenblatt zwar das neue Ribbon-Tab, allerdings wird dieses nicht aktiviert (siehe Bild 10).
Bild 10: Das Reihenfolge-Ribbon wird nicht aktiviert.
Dazu gibt es wiederum drei Möglichkeiten:
- Wir aktivieren das Ribbon-Tab per VBA-Code.
- Wir definieren das Ribbon-Tab als kontextsensitives Ribbon-Tab.
- Wir stellen die Eigenschaft startFromScratch des ribbon-Elements auf true ein. Damit werden alle übrigen Elemente ausgeblendet.
Wir schauen uns alle drei Varianten an.
Ribbon-Tab per VBA-Code aktivieren
Für diesen Fall benötigen wir zunächst einen Verweis auf die Bibliothek Microsoft Office 14.0 Object Library, wobei wir diesen über den Verweise-Dialog hinzufügen.
Diesen öffnen Sie über den VBA-Editor mit dem Menübefehl Extras|Verweise. Dort fügen Sie dann den genannten Eintrag hinzu (siehe Bild 11).
Bild 11: Verweis auf die Office-Bibliothek
Nun fügen wir dem Ribbon-Element customUI das Attribut onLoad hinzu:
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" onLoad="onLoad_Reihenfolge">
Die hier angegebene Ereignisprozedur onLoad_Reihenfolge hinterlegen wir wieder im Modul mdlRibbons. Die Prozedur weist lediglich der Variablen objRibbon_Reihenfolge einen Verweis auf das per Parameter mitgelieferte Objekt IRibbonUI zu:
Sub onLoad_Reihenfolge(ribbon As IRibbonUI) Set objRibbon_Reihenfolge = ribbon End Sub
Diese Variable müssen wir nun noch deklarieren, was wir im gleichen Modul erledigen:
Public objRibbon_Reihenfolge As IRibbonUI
Nun bietet dieses Objekt verschiedene Methoden an, darunter auch die ActivateTab-Methode, die den Namen des zu aktivierenden Tab-Elements entgegennimmt. Wann und wie aber wollen wir diese Methode aufrufen Eigentlich sollte dies gleich beim Öffnen des Formulars geschehen, also etwa in der Ereignisprozedur für eine der Ereigniseigenschaften Beim Öffnen oder Beim Laden.
Wenn wir aber etwa für die Ereignisprozedur Form_Load die folgende Anweisung anlegen, gelingt das nicht:
Private Sub Form_Load() objRibbon_Reihenfolge.ActivateTab "tabReihenfolge" End Sub
Wir erhalten dann nämlich die Fehlermeldung aus Bild 12, der dadurch ausgelöst wird, dass die Objektvariable noch nicht mit dem Verweis auf das customUI-Objekte gefüllt wurde. Das versuchen wir zu umgehen, indem wir das Aktivieren des Tab-Elements ein wenig verzögern. Dazu stellen wir die Eigenschaft Zeitgeberintervall des Hauptformulars auf den Wert 500 ein (für 500 Millisekunden) und für die Ereigniseigenschaft Bei Zeitgeber hinterlegen wir die folgende Ereignisprozedur:
Bild 12: Fehler beim Versuch, die ActiveTab-Methode zu nutzen
Private Sub Form_Timer() objRibbon_Reihenfolge.ActivateTab "tabReihenfolge" Me.TimerInterval = 0 End Sub
Allerdings erhalten wir hier den gleichen Fehler. Woran liegt das Wir könnten annehmen, dass die Prozedur onLoad_Reihenfolge erst ausgeführt wird, wenn das Ribbon-Tab aus dieser Ribbon-Definition angezeigt wird. Allerdings scheint auch dies nicht der Fall zu sein. Wir können ja zwischendurch immer prüfen, ob objRibbon_Reihenfolge einen Wert hat – und zwar mit der folgenden VBA-Anweisung, abgesetzt im Direktbereich des VBA-Editors:
objRibbon_Reihenfolge Is Nothing
Dies liefert aber aktuell immer den Wert True, objRibbon_Reihenfolge ist also leer. Die Lösung für dieses Problem war: Wir haben das Formular mehrfach aufgerufen und bereits zuvor dafür gesorgt, dass On_Load aufgerufen wurde. Damit war objRibbon_Reihenfolge gefüllt. Allerdings haben wir anschließend vermutlich durch einen Laufzeitfehler dafür gesorgt, dass die Variable wieder geleert wurde. Da On_Load aber bereits ausgeführt war, wurde sie nicht erneut gefüllt … Es gilt also zu beachten: Entweder Sie verhindern Laufzeitfehler durch entsprechend stabile Programmierung mit Fehlerbehandlungen, oder Sie müssen zwischendurch die Anwendung einmal neu laden, damit alle Ribbons et cetera wieder korrekt geladen werden können.
Ende des frei verfügbaren Teil. Wenn Du mehr lesen möchtest, hole Dir ...
den kompletten Artikel im PDF-Format mit Beispieldatenbank
diesen und alle anderen Artikel mit dem Jahresabo