Das mit Access 2007 neu eingeführte Ribbon kommt mit einer Menge interessanter Steuerelemente. Zur Auswahl von Daten gibt es gleich mehrere Kandidaten, von denen wir uns diejenigen ansehen, die sich dynamisch etwa mit den Daten aus Tabellen füllen lassen: Zwei verschiedene Kombinationsfelder und zusätzlich auch noch ein dynamisch zu füllendes Menü, das sich prima für die Datenauswahl zweckentfremden lässt. Dieser Beitrag zeigt, wie Sie Daten aus Tabellen und sonstigen Quellen in diese Steuerelemente füllen und sie zur Anwendungssteuerung benutzen können.
Die Vision hinter dem Ribbon und seinen Möglichkeiten ist eindeutig: Durch die viel größere Zahl verschiedener Steuerelemente und die flexibleren gestalterischen Möglichkeiten erlaubt Access dem Benutzer das Auslagern wesentlicher Funktionen der Entwicklungsoberfläche in das Ribbon.
Neben dem üblichen Aufruf von Formularen, Berichten oder Funktionen über einfache Schaltflächen, wie sie in den Menü- und Symbolleisten älterer Access-Versionen gängig waren, können Sie nun viel einfacher weitere Funktionen auf das Ribbon übertragen. An welchen Stellen macht dies Sinn Zum Beispiel dort, wo der Benutzer nicht nur einfache Formulare zur Anzeige von Daten öffnet, sondern zuvor noch die gewünschten Daten auswählen muss. Dies geschieht in der Regel in folgenden Schritten:
- Öffnen eines Auswahlformulars, das beispielsweise eine Liste der Daten zur Auswahl bereitstellt
- Auswahl des gewünschten Eintrags etwa per Doppelklick auf einen Listeneintrag
- Anzeige des Eintrags im Detailformular
Alternativ enthält das Detailformular gleich ein Steuerelement zur Auswahl des gewünschten Datensatzes – beispielsweise ein Kombinationsfeld. Normalerweise wird hier aber immer direkt beim Öffnen irgendein Datensatz angezeigt, zum Beispiel das erste Element der Datenherkunft.
Das ist genau der richtige Einstiegspunkt für die drei Ribbon-Elemente, die in diesem Beitrag genauer beleuchtet werden. Es geht um die Elemente zur Darstellung von Listen, und hier speziell um solche, die dynamisch mit Daten gefüllt werden können. Davon gibt es insgesamt vier – das gallery-Element schauen wir uns aber noch einmal in einem späteren Beitrag an:
- comboBox
- dropDown
- dynamicMenu
Rahmenwerk
Um Platz zu sparen, finden Sie in Listing 1, das ein Beispiel für ein statisches comboBox-Element zeigt, letztmalig für diesen Beitrag die Ribbon-Elemente, die für den Aufbau des tab-Elements und der group-Elemente verantwortlich sind – wir haben diese fett gedruckt, um die betroffenen Elemente hervorzuheben. Einige Erläuterungen zu diesen Basiselementen:
Listing 1: Beispiel für ein statisches comboBox-Steuerelement
<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" onLoad="OnLoad_Beispiel" loadImage="loadImage"> <ribbon startFromScratch="true"> <tabs> <tab id="tab0" label="Beispiele für Kombinations- und Auswahlfelder"> <group id="grpSamplesComboBox" label="Beispiele ComboBox"> <comboBox id="cboStatic" label="ComboBox statisch"> <item id="item1" image="chart_area.png" label="Eintrag 1"/> <item id="item2" image="printer.png" label="Eintrag 2"/> </comboBox> </group> <group id="grpSampleDropDown" label="Beispiele DropDown"/> <group id="grpSampleDynamicMenu" label="Beispiel DynamicMenu"/> </tab> </tabs> </ribbon> </customUI>
- Die onLoad-Callback-Funktion OnLoad_Beispiel sorgt dafür, dass ein Verweis auf das Ribbon in einer Variablen namens objRibbon_Beispiel gespeichert wird und für spätere Zugriffe bereitsteht.
- Die loadImage-Callback-Funktion loadImage sorgt dafür, dass alle für die einzelnen Steuerelemente definierten Bilder aus einer Tabelle namens USysImages eingelesen und im Ribbon angezeigt werden. Die übrigen dafür notwendigen Funktionen finden Sie im Standardmodul mdlRibbonImages. Zum Verständnis dieses Beitrags sind die dort enthaltenen Routinen nicht relevant. Detaillierte Informationen zu Bildern im Ribbon finden Sie in einem späteren Beitrag.
- Das Attribut startFromScratch sorgt mit dem Wert true dafür, dass nur die in unserer Definition enthaltenen Elemente angezeigt und die eingebauten Elemente ausgeblendet werden.
Grundlagen zu den oben genannten Elementen finden Sie unter anderem im Beitrag Dynamische Ribbons (Shortlink 657).
Das comboBox-Element
Das comboBox-Element zeigt eine Liste von Elementen an. Gleich in Bild 1 sehen Sie ein Feature, das es vom Access-Kombinationsfeld abhebt: Es kann nämlich pro Eintrag ein Icon anzeigen. Der Code für dieses einfache comboBox-Element sieht wie in Listing 1 aus. Schauen wir uns die Definition dieses Elements genauer an: Wenn Sie es statisch definieren, also nicht mit den Daten aus einer Tabelle füllen möchten, können Sie die einzelnen Einträge mit dem item-Element anlegen.
Bild 1: Ein einfaches statisches comboBox-Element
Inhalt der comboBox auswerten
Damit Sie den Inhalt des comboBox-Elements nach der Auswahl auswerten können, müssen Sie für das Attribut onChange eine Callback-Funktion festlegen und diese in einem Standardmodul, in unserem Beispiel mdlRibbon, definieren.
Die erste Zeile des comboBox-Elements sieht dann so aus:
<comboBox id="cboStatic" label="ComboBox statisch" onChange="onChange">
Die folgende Callback-Funktion gibt den Namen des auslösenden Steuerelements sowie den Inhalt der comboBox aus:
Sub onChange(control As IRibbonControl, _ text As String) MsgBox "Steuerelement: " & control.ID _ & vbCrLf & "text: " & text End Sub
comboBox dynamisch füllen
Schauen wir uns gleich an, wie wir statt der beiden statischen Einträge einige Datensätze einer Datenbanktabelle im comboBox-Element unterbringen. Die Beispieldatenbank enthält eine Tabelle namens tblAdressen, die ein paar Daten zum Experimentieren liefert. Das comboBox-Element soll schlicht die Nachnamen aus dieser Tabelle anzeigen. Dazu sind mindestens zwei Callback-Funktionen nötig, und zwar getItemLabel und getItemCount. Die Definition eines solchen Elements sieht so aus:
<comboBox id="cboDynamic" label="comboBox dynamisch" getItemCount="getItemCount" getItemLabel="getItemLabel" onChange="onChange"/>
Die Callback-Funktion getItemCount wird einmal beim Initialisieren des comboBox-Elements aufgerufen, die Callback-Funktion getItemLabel entsprechend der Anzahl, die Sie mit dem Parameter count der Callback-Funktion getItemCount zurückgeben. Die Hauptarbeit erledigt dabei die Routine getItemCount. Sie speichert die anzuzeigenden Daten in einem Array, das Sie im Kopf des Moduls wie folgt deklarieren:
Dim strAdressen() As String
Die Routine getItemCount liefert mit dem Parameter control einen Verweis auf das aufrufende Steuerelement. Diesen müssen Sie auswerten, wenn mehrere Steuerelemente die Funktion getItemCount aufrufen und Sie diesen Steuerelementen unterschiedliche Daten zurückliefern möchten. Das Prinzip zeigen wir gleich in einer anderen Callback-Funktion.
Die einfache Variante von getItemCount geht davon aus, dass alle Aufrufe von unserem Steuerelement mit dem Wert cboDynamic für das Attribut id kommen. Sie deklariert ein Database– und ein Recordset-Objekt, die anschließend instanziert und als Quelle für die anzuzeigenden Daten herhalten werden.
Beim Durchlaufen der Datensätze passiert Dreierlei: Das Array strAdressen wird jeweils um ein Feld erweitert, dieses wird mit dem Nachnamen des aktuellen Datensatzes gefüllt und schließlich wird die Zählervariable i, die in beiden Fällen als Index dient, um eins erhöht. Nach dem Durchlaufen aller Datensätze enthält die Zählervariable gleichzeitig die Anzahl der anzuzeigenden Elemente, weshalb die Funktion diesen Wert dem Parameter count zuweisen und dem Ribbon übergeben kann.
Sub 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 Nachname FROM tblAdressen", dbOpenDynaset) Do While Not rst.EOF ReDim Preserve strAdressen(i + 1) As _ String strAdressen(i) = rst!Nachname i = i + 1 rst.MoveNext Loop count = i End Sub
Die Anzahl der Aufrufe der zweiten Callback-Funktion namens getItemLabel entspricht genau diesem Wert. Die Funktion erhält neben dem obligatorischen Verweis auf das Steuerelement (control) noch einen Wert für den Parameter index, der beim ersten Aufruf eins beträgt und sich dann mit jedem Aufruf um eins erhöht. Das ist praktisch, denn so lassen sich leicht die anzuzeigenden Daten aus dem Array strAdresssen auslesen und dem Rückgabewert label zuweisen.
Sub getItemLabel(control As IRibbonControl, _ index As Integer, ByRef label) label = strAdressen(index) End Sub
Das Ribbon sieht dann mit der Tabelle aus Bild 2 als Ausgangsmaterial wie in Bild 3 aus.
Bild 2: Datenherkunft für die Beispiele dieses Beitrags
Bild 3: Beispiel für eine comboBox, die mit Daten aus einer Tabelle gefüllt wurde
Werte aus dem comboBox-Element auslesen
Das schönste Steuerelement hilft nicht weiter, wenn man nicht per Code auf Benutzereingaben reagieren kann. Wer die Arbeit mit dem Access-Kombinationsfeld gewohnt ist, wird nicht gerade mit Begeisterung auf die beschränkten Möglichkeiten des comboBox-Steuerelements reagieren: Es bietet zwar eine Callback-Funktion, die ausgelöst wird, wenn der Benutzer einen Eintrag auswählt, aber dieser liefert als Parameter lediglich den in der comboBox angezeigten Text.
Diesen werten Sie beispielsweise mit dieser Routine aus, wobei die für dieses Steuerelement relevanten Zeilen fett gedruckt sind (die übrigen zeigen, wie Sie unbehandelte Aufrufe anderer Steuerelemente erkennen und behandeln können):
Sub onChange(control As IRibbonControl, _ text As String) Select Case control.id Case "cboDynamic" MsgBox text Case Else MsgBox "Steuerelement: " _ & control.id & vbCrLf _ & "text: " & text End Select End Sub
Normalerweise möchte man an dieser Stelle etwas mit den ausgewählten Daten tun, also etwa den gewünschten Datensatz in einem Formular anzeigen. Dazu braucht man, um auf Nummer sicher zugehen, die ID des entsprechenden Datensatzes.
Wenn die im comboBox angezeigten Texte eindeutig sind, ist dies kein Problem – Sie müssen einfach nur die ID mit einer entsprechenden DLookup-Anweisung ermitteln und können dann damit weiterarbeiten. Unnötig ist dieser zusätzliche Schritt dennoch – und problematisch wird es zudem, wenn die Einträge der comboBox nicht eindeutig sind.
Aktualisieren des comboBox-Elements
Ein Vorteil des comboBox-Elements ist sicher die Eigenschaft invalidateContentOnDrop. Stellen Sie diese auf true ein, liest comboBox die anzuzeigenden Daten bei jedem Aufklappen neu ein. Gerade bei Daten, die sich oft ändern und deren Menge überschaubar ist, macht diese Einstellung Sinn. Wenn Sie den Zeitpunkt der Aktualisierung selbst steuern möchten, verwenden Sie die Invalidate– oder die InvalidateControl-Methode. Mehr dazu erfahren Sie weiter unten unter Aktualisieren des dropDown-Elements; die Vorgehensweise ist bei beiden Steuerelementen gleich.
Texteingabe im comboBox-Element
Im Gegensatz zum gleich beschriebenen dropDown-Element kann der Benutzer nicht nur die Einträge des comboBox-Elements auswählen, sondern auch eigene Texte eingeben. Die anschließende Betätigung der Eingabetaste führt zum Auslösen der onChange-Callback-Funktion, die im Parameter text den neu eingegebenen Wert liefert.
Eintrag im comboBox-Element auswählen
Sie können im comboBox-Element keinen Eintrag in dem Sinne vorauswählen, wie es etwa im Access-Kombinationsfeld möglich ist. Stattdessen erlaubt die Callback-Funktion getText die Übergabe eines Textes, der beim Anzeigen des comboBox-Elements in diesem erscheint. Das Attribut fügen Sie wie folgt ein:
<comboBox id="cboDynamic" label="comboBox dynamisch" ... getText="getText"/>
Die Callback-Routine liefert schließlich den gewünschten Ausdruck zurück – hier der Wert des Feldes Nachname des ersten Datensatzes der Tabelle tblAdressen:
Sub getText(control As IRibbonControl, _ ByRef text) text = DLookup("Nachname", "tblAdressen") End Sub
Das dropDown-Element
Schauen wir uns nun an, was das andere Ribbon-Steuerelement mit Kombinationsfeld-Charakter, das dropDown-Element, besser oder weniger gut kann als das comboBox-Element.
Bei einem statischen Beispielexemplar fällt zunächst einmal auf, dass man dem dropDown-Element nicht nur item-Elemente, sondern auch button-Elemente unterordnen kann. Die folgende Definition ergibt beispielsweise das dropDown-Element aus Bild 4 (in diesem Fall kommen eingebaute Ribbon-Icons zum Einsatz, bei denen Sie einfach nur die imageMso angeben müssen):
Bild 4: Beispiel für ein statisches dropDown-Element mit zusätzlicher Schaltfläche
<dropDown id="drpStatic" label="dropDown statisch"> <item id="itm1" imageMso="_3DExtrusionDepth72Classic" label="Eintrag 1"/> <item id="itm2" imageMso="_3DSurfaceMetalClassic" label="Eintrag 2"/> <button id="btn1" imageMso="_3DLightingClassic" label="Button 1"/> </dropDown>
dropDown-Element dynamisch füllen
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