Manchmal wird die Liste der Tabellen, Abfragen, Formulare und Co. im Navigationsbereich etwas unübersichtlich. Da wünscht sich der eine oder andere, dass die wichtigsten Elemente einer Datenbank schnell zur Verfügung stehen. Eine Möglichkeit, das zu erledigen, ist das Ribbon. Wie Sie die dort anzuzeigenden Elemente auswählen und diese dort hinzufügen, zeigt der vorliegende Beitrag.
Zwar verstummen allmählich die Stimmen, die eine Rückkehr des Datenbankfensters fordern, aber dass der Navigationsbereich nicht gerade die übersichtlichste Variante ist, um Datenbankobjekte anzuzeigen, ist offensichtlich (siehe Bild 1). Auf vielfachen Leserwunsch schauen wir uns daher einmal an, welche Möglichkeiten es gibt, Elemente wie Tabellen, Abfragen, Formulare, Berichte, Makros und Module über das Ribbon zugänglich zu machen.
Bild 1: Navigationsbereich
Als Erstes benötigen wir eine Tabelle, in die wir die Elemente des Navigationsbereichs einlesen und der wir ein Feld hinzufügen, mit dem wir angeben, ob das jeweilige Element zusätzlich zur Anzeige im Navigationsbereich noch im Ribbon erscheinen soll. Dann stellen wir ein Formular zusammen, mit dem wir die Elemente anzeigen und die Möglichkeit bieten, diese für die Anzeige im Ribbon auszuwählen. Schließlich gibt es verschiedene Varianten, um Daten wie die beschriebenen Objekte im Ribbon anzuzeigen. Wir schauen uns die verschiedenen Varianten an und prüfen die Machbarkeit und Vor- und Nachteile.
Objekte in Tabelle
Zum Speichern der Objekte wollen wir die Tabelle tblObjekte-In-Ribbon verwenden, die im Entwurf wie in Bild 2 aussieht.
Bild 2: Tabelle zum Speichern der Objekte
Die Tabelle verwendet neben dem Primärschlüsselfeld ID das Feld Objektname, in das wir den Namen der Tabelle, Abfrage et cetera eintragen. Für das Feld Objektname legen wir über die Eigenschaft Indiziert mit dem Wert Ja (Ohne Duplikate) einen eindeutigen Index fest. Damit stellen wir sicher, dass jedes Objekt nur einmal zur Tabelle hinzugefügt wird.
Das Feld ObjekttypID ist verknüpft mit der Tabelle tblObjekttypen, in der wir die sechs Objekttypen aufführen (siehe Bild 3). Das letzte Feld heißt InRibbon und hat den Datentyp Ja/Nein. Mit diesem Feld legen wir fest, ob das Objekt im Ribbon angezeigt werden soll oder nicht.
Bild 3: Die verschiedenen Objekttypen in der Tabelle tblObjekttypen
Achtung: Die Tabelle muss die Daten genau mit den Primärschlüsselwerten enthalten, wie sie hier abgebildet sind. Später verwenden wir im Code die Werte von 1 bis 6, um Elemente zu referenzieren, die zu einer der Objektkategorien gehören.
Prozedur zum Erfassen aller Objekte in der Tabelle
Schließlich benötigen wir eine Prozedur, mit der wir die Objekte der Datenbank durchlaufen und diese zur Tabelle tblObjekteInRibbon hinzufügen.
Diese sieht wie in Listing 1 aus. Die Prozedur deklariert die Variable db, die Sie mit einem Verweis auf das Database-Objekt der aktuellen Datenbank füllt. tdf und qdf haben die Typen TableDef und QueryDef und dienen zum Durchlauen der Tabellen und Abfragen.
Public Sub ObjekteInTabelleSchreiben() Dim db As DAO.Database Dim tdf As DAO.TableDef Dim qdf As DAO.QueryDef Dim objAccess As AccessObject Set db = CurrentDb On Error Resume Next For Each tdf In db.TableDefs db.Execute "INSERT INTO tblObjekteInRibbon(Objektname, ObjekttypID) VALUES('" & tdf.Name & "', 1)", dbFailOnError Next tdf For Each qdf In db.QueryDefs db.Execute "INSERT INTO tblObjekteInRibbon(Objektname, ObjekttypID) VALUES('" & qdf.Name & "', 2)", dbFailOnError Next qdf For Each objAccess In CurrentProject.AllForms db.Execute "INSERT INTO tblObjekteInRibbon(Objektname, ObjekttypID) VALUES('" & objAccess.Name _ & "', 3)", dbFailOnError Next objAccess For Each objAccess In CurrentProject.AllReports db.Execute "INSERT INTO tblObjekteInRibbon(Objektname, ObjekttypID) VALUES('" & objAccess.Name _ & "', 4)", dbFailOnError Next objAccess For Each objAccess In CurrentProject.AllMacros db.Execute "INSERT INTO tblObjekteInRibbon(Objektname, ObjekttypID) VALUES('" & objAccess.Name _ & "', 5)", dbFailOnError Next objAccess For Each objAccess In CurrentProject.AllModules db.Execute "INSERT INTO tblObjekteInRibbon(Objektname, ObjekttypID) VALUES('" & objAccess.Name _ & "', 6)", dbFailOnError Next objAccess End Sub
Listing 1: Prozedur zum Einlesen aller Access-Objekte in die Tabelle tblObjekteInRibbon
objAccess hat den Typ Access-Object und erlaubt das Durchlaufen der Auflistungen AllForms, AllReports, AllMacros und AllModules der CurrentProject-Klasse.
Die Fehlerbehandlung deaktivieren wir mit On Error Resume Next. Der Hintergrund ist, dass beim erneuten Einlesen der Objekte gegebenenfalls vorhandene Elemente gleichen Namens zu Fehlern führen können, da der eindeutige Index für das Feld Objektname verletzt wird. Dies wollen wir einfach ignorieren und Objekte, deren Namen bereits vorhanden sind, einfach nicht nochmals hinzufügen.
In der ersten For Each-Schleife durchläuft die Prozedur alle Elemente der TableDefs-Auflistung des Database-Objekts und trägt für jedes Element einen neuen Datensatz in die Tabelle tblObjekteInRibbon ein.
Dabei wird als Objektname der Wert der Eigenschaft Name des TableDef-Objekts und als ObjekttypID der Wert 1 eingetragen.
Die zweite For Each-Schleife erledigt das Gleiche für die Elemente der Auflistung QueryDefs. Hier fügt sie der Tabelle jedoch für das Feld ObjekttypID den Wert 2 hinzu.
Die dritte bis sechste For Each-Schleife der Prozedur verwendet die Auflistungen AllForms, AllReports, AllMacros und AllModules des CurrentProject-Objekts, um die Formulare, Berichte, Makros und Module der Datenbank zu ermitteln. Dabei nutzen wir jeweils die Name-Eigenschaft des AccessObject-Elements als Wert für das Feld Objektname. Für das Feld ObjekttypID tragen wir je nach Objekttyp die Werte 3, 4, 5 oder 6 ein. Das Ergebnis sieht wie in Bild 4 aus.
Bild 4: Die Tabelle tblObjekteInRibbon mit den Objekten der Datenbank
Formular zur Auswahl der anzuzeigenden Elemente
Nun benötigen wir ein Formular, dass die Elemente der Datenbank in alphabetischer Reihenfolge und nach Objekttyp aufgeteilt anzeigt und das Markieren der im Ribbon anzuzeigenden Objekte erlaubt. Dazu erstellen wir ein neues Formular namens frmObjekteInRibbon. Das Formular soll seine Daten in einem Register-Steuerelement mit sechs Registerseiten anzeigen, die jeweils ein Unterformular enthalten. Das Unterformular soll die Elemente des jeweiligen Objekttyps anzeigen. Da das Unterformular jeder Registerseite die Daten aus der gleichen Tabelle anzeigen soll, die nur unterschiedlich gefiltert werden, benötigen wir nur ein Formular, das dann in den sechs Unterformular-Steuerelementen angezeigt wird.
Wir legen als Erstes das Formular frmObjekteInRibbon an und fügen das Register-Steuerelement hinzu. Dann wählen wir aus dem Kontextmenü dieses Steuerelements so oft den Eintrag Seite einfügen aus, bis das Register-Steuerelement sechs Registerseiten enthält (siehe Bild 5). Die sechs Registerseiten beschriften wir über die Eigenschaft Beschriftung mit Tabellen, Abfragen, Formulare, Berichte, Makros und Module. Die Seiten erhalten die Namen pgeTabellen, pgeAbfragen, pgeFormulare, pgeBerichte, pgeMakros und pgeModule.
Bild 5: Hinzufügen von Registerseiten zum Register-Steuerelement
Das Unterformular sfmObjekteInRibbon statten wir mit einer Abfrage namens qryObjekteInRibbonNachObjektname als Datensatzquelle aus, welche alle Felder der Tabelle tblObjekteInRibbon enthält und diese nach dem Feld Objektname sortiert (siehe Bild 6).
Bild 6: Datensatzquelle des Formulars sfmObjekteInTabelle
Wir fügen dem Formular die beiden Felder InRibbon und Objektname der Datensatzquelle hinzu. Außerdem stellen wir die Eigenschaft Standardansicht auf Datenblatt ein.
Danach speichern und schließen Sie das Unterformular sfm-ObjekteInRibbon. Für das Formular frmObjekteInRibbon stellen wir noch die Eigenschaften Datensatzmarkierer, Navigationsschaltflächen und Bildlaufleisten auf Nein ein und die Eigenschaft Automatisch zentrieren auf Ja.
Dann folgt ein wenig Kleinarbeit: das Einfügen des Unterformulars in das Register-Steuerelement. Hier gibt es zwei Möglichkeiten:
- Entweder wir fügen auf jeder Registerseite ein neues Unterformular-Steuerelement ein, das wir dann jeweils nach dem Wert für das Feld ObjekttypID filtern, der die Objekte passend zur Beschriftung der Registerseite liefert.
- Oder wir platzieren ein Unterformular-Steuerelement in z-Reihenfolge vor dem Register-Steuerelement und ändern den Filter jeweils bei Änderung der ausgewählten Registerseite.
Wer schon einmal auf mehreren Registerseiten ein Steuer-element so eingefügt hat, dass es sich beim Blättern im Register immer an der gleichen Position befindet, weiß, dass das eine langweilige Arbeit ist. Also entscheiden wir uns für die zweite Variante mit nur einem Unterformular, das wir einfach vor dem Register-Steuerelement platzieren. Dazu fügen wir dieses zuerst unter oder neben dem Register-Steuerelement ein, entfernen das Beschriftungsfeld und schieben es dann über das Register-Steuerelement (siehe Bild 7).
Bild 7: Unterformular-Steuerelement über Register-Steuerelement
Damit sich beide beim Ändern der Formulargröße der Größe anpassen, stellen wir die Eigenschaften Horizontaler Anker und Vertikaler Anker jeweils auf Beide ein.
Nun müssen wir nur noch dafür sorgen, dass das Unterformular nur noch die Elemente anzeigt, die dem im Register-Steuerelement ausgewählten Objekttyp entsprechen. Dazu hinterlegen wir für die Ereigniseigenschaft Bei Änderung des Register-Steuerelements, das wir zuvor noch mit regObjekte benennen, die folgende Ereignisprozedur:
Private Sub regObjekte_Change() With Me!sfmObjekteInRibbon.Form .Filter = "ObjekttypID = " & Me!regObjekte.Value + 1 .FilterOn = True End With End Sub
Diese stellt die Eigenschaft Filter des Unterformulars auf einen Ausdruck ein, der den Wert der jeweils ausgewählten Registerseite ermittelt, eins hinzuaddiert und diesen mit dem Wert des Feldes ObjekttypID gleichsetzt. Dabei kommt dann etwa für die erste Registerseite das folgende Kriterium heraus:
ObjekttypID = 1
Wenn wir das Formular nun öffnen, erscheinen allerdings zunächst alle Elemente in der Liste (siehe Bild 8).
Bild 8: Das Unterformular zeigt noch alle Einträge an.
Wenn wir allerdings die Ereignisprozedur regObjekte_Change einmal beim Laden des Formulars aufrufen, erhalten wir auch direkt nach dem Öffnen die korrekt gefilterten Elemente (siehe Bild 9).
Bild 9: Objekte gefiltert nach Objekttyp, hier alle Tabellen
Die Ereignisprozedur, die durch das Ereignis Beim Laden ausgelöst wird, sieht dann so aus:
Private Sub Form_Load() regObjekte_Change End Sub
Verwalten der Objekte
Wir wollen noch ein paar weitere Elemente hinzufügen, damit der Benutzer die Objekte im Formular einfacher verwalten kann. Die dazu angelegten Schaltflächen sehen Sie in Bild 10. Damit die Schaltflächen nicht unter den anderen Steuerelementen verschwinden, wenn der Benutzer das Formular nach unten vergrößert, stellen wir die Eigenschaft Vertikaler Anker auf Unten ein.
Bild 10: Objekte verwalten mit zusätzlichen Schaltflächen
Alle Objekte löschen
Die Schaltfläche mit der Beschriftung Alle löschen heißt cmdAlleLoeschen und soll alle Datensätze aus der Tabelle tblObjekteInRibbon löschen. Auf diese Weise kann der Benutzer die Objekte nach umfangreicheren Änderungen anschließend wieder neu einlesen. Die Schaltfläche löst beim Anklicken die Ereignisprozedur aus Listing 2 aus. Diese zeigt zunächst noch eine Meldung an, die den Benutzer darauf hinweist, dass alle Datensätze gelöscht werden. Der Benutzer kann dies durch Betätigen der Nein-Schaltfläche abwenden. Ansonsten sorgt eine DELETE-Abfrage für das Löschen aller Datensätze der Tabelle tblObjekteInRibbon. Die folgende Anweisung aktualisiert die Anzeige der Daten im Unterformular.
Private Sub cmdAlleLoeschen_Click() Dim db As DAO.Database Set db = CurrentDb If MsgBox("Dies löscht alle Elemente. Diese müssen danach neu eingelesen werden.", vbYesNo) = vbYes Then db.Execute "DELETE FROM tblObjekteInRibbon", dbFailOnError Me!sfmObjekteInRibbon.Form.Requery End If End Sub
Listing 2: Beim Klicken-Prozedur der Schaltfläche cmdAlleLoeschen
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