Komfortable Dropdown-Listenfelder

15.01.2006 von Helma  Spona
Listenfelder sind aus komplexen Formularen kaum wegzudenken, da sie eine effiziente Möglichkeit bieten, Daten zu erfassen und auszuwählen. Wie Sie Dropdown- Listenfelder noch komfortabler gestalten, zeigt Ihnen der vorliegende Beitrag

Am schnellsten und für den Entwickler einfachsten lassen sich Dropdown-Listenfelder per SQLAbfrage oder direkt mit einer Tabelle oder Abfrage füllen. Das ist im Hinblick auf die Benutzerfreundlichkeit jedoch nicht der optimale Weg. Sie haben damit nämlich keinerlei Möglichkeiten, Einträge auszusparen, umzuformulieren oder zusätzliche Einträge hinzuzufügen. Das ist aber wichtig, wenn Sie komfortable Dropdown-Listenfelder verwenden möchten.

Aufbau der Beispieldatenbank

Dem nachfolgend erläuterten Code liegt eine Datenbank bestehend aus zwei Tabellen zugrunde, die der Speicherung von Übersetzungen von Tier- und Pflanzennamen dienen. Für eine einfachere Suche in den Daten sind diese Namen nach Bereichen gruppiert. Die Gruppennamen und IDs werden in der Tabelle Gruppen verwaltet (Bild 1).

Bild 1: Aufbau der Datenbank.

Das beschriebene Kombinationslistenfeld soll es nun ermöglichen, bei Eingabe eines neuen Worts in die Tabelle Woerter die Gruppe zuzuordnen und gegebenenfalls auch eine neue zu erstellen.

Listenfelder manuell füllen

Zunächst einmal wird das Listenfeld manuell gefüllt. Am einfachsten geht das mit Hilfe einer Funktion, die diese Aufgabe übernimmt (Listing 1). Wenn Sie ihr neben der SQL-Anweisung, die die Daten liefert, auch das zu füllende Dropdown- Listenelement sowie den Standardwert für das Listenelement übergeben, können Sie die Funktion für beliebige Formulare verwenden. Wichtig ist dann allerdings, dass Sie darauf achten, die SQL-Anweisung so zu formulieren, dass das erste zurückgegebene Feld die ID des Datensatzes ist. Standardmäßig wird dieses Feld nicht angezeigt, da seine Spaltenbreite auf 0 gesetzt wird.

Sub Listefuellen(objLFeld As ComboBox, strSQL As String, Optional lngWert = 0)
Dim objRS As ADODB.Recordset
Dim strTemp As String
Dim lngI As Long
Set objRS = New ADODB.Recordset

objRS.Open strSQL, Application.CurrentProject.Connection, adOpenStatic
objRS.MoveFirst
'Listenfeld leeren
Do While objLFeld.ListCount > 0
objLFeld.RemoveItem objLFeld.ListCount - 1
Loop
Do While Not (objRS.EOF)
'Listenfeld füllen
strTemp = ""
For lngI = 0 To objRS.Fields.Count - 1
strTemp = strTemp & objRS.Fields(lngI) & ";"
Next lngI
'letztes Semikolon abschneiden
strTemp = Mid(strTemp, 1, Len(strTemp) - 1)
'Eintrag hinzufügen
objLFeld.AddItem strTemp
objRS.MoveNext
Loop
'Zusätzlichen Datensatz anhängen
objLFeld.AddItem "0;[neuer Eintrag ...]"
'Formatierungen
objLFeld.BoundColumn = 1
objLFeld.ColumnCount = objRS.Fields.Count
If objLFeld.ColumnWidths = "" Then
objLFeld.ColumnWidths = "0;3cm"
End If
objLFeld.Value = lngWert
objRS.Close
Set objRS = Nothing
End Sub

Sie können allerdings die Spaltenbreiten individuell an Ihre Bedürfnisse anpassen, indem Sie die Eigenschaft Spaltenbreiten des Steuerelements setzen. Die Prozedur ersetzt diese Einstellung nicht, sondern legt nur Spaltenbreiten von 0;3cm fest, wenn die Eigenschaft nicht gesetzt wurde.

Die Prozedur Listefuellen führt zunächst die angegebene SQL-Anweisung aus und löscht dann alle vorhandenen Einträge im Listenfeld. Danach durchläuft sie das Ergebnis der Abfrage. Für jeden Datensatz erzeugt sie dann einen Eintrag, in dem alle Feldwerte nacheinander angegeben und durch Semikolons getrennt werden. Die Semikolons sorgen dafür, dass jeder Feldwert in einer eigenen Spalte innerhalb des Dropdown-Listenfeldes dargestellt wird.

Wenn auf diese Weise alle Datensätze abgearbeitet wurden, wird ein zusätzlicher Eintrag mit der ID 0 und dem Text "[neuer Eintrag ...]" eingefügt. Anschließend erfolgt die Formatierung der Liste. Mit der Eigenschaft BoundColumn wird die Spalte festgelegt, deren Wert als Wert des Kombinationslistenfeldes verwendet wird. Anschließend wird die Spaltenanzahl auf die Anzahl Felder in der Datenbankgruppe festgelegt, die als Ergebnis der SQL-Anweisung geliefert wurde. Danach wird die Feldbreite festgelegt, falls die Eigenschaft ColumnWidths eine leere Zeichenfolge als Wert hat. Ganz zum Schluss wird noch der übermittelte Parameter lngWert als Wert für das Listenfeld ausgewählt, um den gewünschten Listeneintrag auszuwählen.

Damit das Listenfeld jedoch gefüllt wird, müssen Sie die Funktion noch aufrufen. Außerdem benötigen Sie neben dem ungebundenen Kombinationslistenfeld ein gebundenes Textfeld, das den aktuellen Wert des Feldes Gruppe anzeigt. Damit ist es dann ganz einfach möglich, den korrekten Wert im Listenfeld anzeigen zu lassen. Das Textfeld (im Beispiel heißt es Gruppe) können Sie mit Hilfe der Sichtbar-Eigenschaft des Steuerelements ausblenden. Die Prozedur Listefuellen rufen Sie dann beim Öffnen des Formulars auf, indem Sie eine Ereignisprozedur für das Open-Ereignis erstellen (Listing 2).

Listing 2: Die Prozedur beim Laden des Formulars ausführen
Private Sub Form_Open(Cancel As Integer)
Listefuellen Me.cmbGruppe, _
"SELECT ID, Gruppe FROM Gruppen ORDER BY Gruppe ASC", _
Me.Gruppe.Value
End Sub

Außerdem müssen Sie nun noch dafür sorgen, dass beim Auswählen eines neuen Eintrags der Wert des Listenfeldes in das Textfeld Gruppe geschrieben und umgekehrt beim Wechseln des Datensatzes das Kombinationslistenfeld aktualisiert wird. Dazu erstellen Sie Ereignisprozeduren für das Change-Ereignis des Kombinationslistenfeldes und das Current-Ereignis des Formulars (Listing 3).

Private Sub cmbGruppe_Change()
Me.Gruppe.Value = Me.cmbGruppe.Value
End Sub
Private Sub Form_Current()
If Not (IsNull(Me.Gruppe.Value)) Then
Me.cmbGruppe.Value = Me.Gruppe.Value
Else
Me.cmbGruppe.Value = 0
End If
End Sub

Neue Datensätze für das Listenfeld erfassen

Mit diesen Maßnahmen haben Sie nun, bis auf den zusätzlichen Listeneintrag, nur das realisiert, was sich durch Zuweisung einer Tabelle oder Abfrage als Datenquelle auch erreichen ließe. Für den gewünschten Komfort sollten Sie aber dafür sorgen, dass bei Auswahl des Listeneintrags mit dem Wert 0 in der ersten Spalte ein Formular angezeigt wird, über das der Benutzer eine neue Gruppe erfassen kann.

Bild 2: Das Dropdown-Listenfeld mit zusätzlichem Eintrag.

Zu diesem Zweck reicht zunächst ein ganz normales Formular für die Eingabe von Daten in die Tabelle Gruppen, das Sie über den Formularassistenten erstellen können. In das Formular fügen Sie eine Schaltfläche ein, über die der Benutzer das Formular schließen kann. Dazu deaktivieren Sie den Schließen-Button des Fensters, indem Sie die Eigenschaft Schließen-Schaltfläche auf Nein setzen. Im Beispiel heißt dieses Formular frmGruppen und die Schaltfläche bttSchliessen.

Für die Schaltfläche erstellen Sie eine Click-Ereignisprozedur, die das Formular schließt. Innerhalb dieser Ereignisprozedur rufen Sie die Close- Methode des DoCmd-Objekts auf. Für das Formular erzeugen Sie eine Ereignisprozedur für das Close-Ereignis. In dieser speichern Sie den Wert des Feldes ID in der Variablen lngErgebnis (Listing 4).

Private Sub bttSchliessen_Click()
lngDatensatz = 0
DoCmd.Close acForm, Me.Name, acSaveYes
End Sub
Private Sub Form_Close()
lngErgebnis = Me.ID.Value
End Sub
Private Sub Form_Open(Cancel As Integer)
'Variable lngDatensatz abfragen, um zu ermitteln,
'welcher Datensatz angezeigt werden soll.
If lngDatensatz = -1 Then
'Neuen Datensatz anzeigen
DoCmd.GoToRecord acDataForm, Me.Name, acNewRec
End If
End Sub

Auch beim Öffnen müssen Sie noch Code ausführen. Da es natürlich auch möglich ist, dass der Benutzer das Formular zur Erfassung der Gruppen separat aufruft, darf natürlich nicht automatisch zu einem neuen Datensatz gesprungen werden. Sie sollten daher prüfen, ob das Formular über das Listenfeld aufgerufen wurde. Das geht am einfachsten, indem Sie den aktuellen Wert des Listenfeldes in der Variablen lngDatensatz speichern. Problematisch ist dies allerdings, weil eine nicht initialisierte numerische Variable auch den Wert 0 bekommt. Somit können Sie nicht unterscheiden, ob die Variable keinen Wert hat oder den Wert 0. Daher wird hier vom Wert des Listeneintrags noch der Wert 1 abgezogen. Das bedeutet dann, dass Sie innerhalb der Open- Ereignisprozedur prüfen müssen, ob der Wert der Variablen -1 ist. In diesem Fall springen Sie zu einem neuen Datensatz.

Schließen des Formulars

Beim Schließen des Formulars, also in der Close- Ereignisprozedur, muss nun noch die ID des neu erzeugten Datensatzes zurückgegeben werden. Dazu benötigen Sie eine zweite Variable lngErgebnis, der Sie den Wert des Feldes ID zuweisen.

Damit der Datenaustausch zwischen den beiden Formularen funktioniert, müssen Sie die beiden Variablen in einem normalen Modul mit dem Schlüsselwort public definieren (Listing 5).

Listing 5: Notwendige Variablen
Public lngDatensatz As Long
Public lngErgebnis As Long

Im Formular mit dem Dropdown-Listenfeld müssen Sie noch etwas Code ergänzen, damit die ID des erzeugten Datensatzes übernommen und der neue Eintrag im Dropdown-Listenfeld angezeigt wird (Listing 6). Sie benötigen dazu eine Ereignisprozedur für das Activate-Ereignis des Formulars. Sie sorgt dafür, dass der Code ausgeführt wird, wenn das Formular aktiviert wird.

Private Sub Form_Activate()
If lngErgebnis > 0 Then
Listefuellen Me.cmbGruppe, _
"SELECT ID, Gruppe FROM Gruppen ORDER BY Gruppe ASC", lngErgebnis
Me.Gruppe.Value = lngErgebnis
lngDatensatz = lngErgebnis
lngErgebnis = 0
End If
End Sub
Private Sub cmbGruppe_Change()
Me.Gruppe.Value = Me.cmbGruppe.Value
If Me.cmbGruppe.Value = 0 Then
'Eintrag [Neuer Eintrag ...] wurde gewählt
lngDatensatz = Me.cmbGruppe.Value - 1
DoCmd.OpenForm "frmGruppen", acNormal, , , acFormAdd
End If
End Sub

Beim Aktivieren rufen Sie den Wert der Variablen lngErgebnis ab. Ist er größer als 0, wurde ein Wert aus dem Eingabeformular zurückgegeben nd die Liste wird neu gefüllt. Der zurückgegebene ert wird dann als neuer Wert des Dropdown- istenfeldes übergeben. Anschließend ürfen Sie natürlich nicht vergessen, den Wert uch mit Me.Gruppe.Value=lngErgebnis als Wert ür das versteckte Textfeld zu speichern.

Den Wert der Variablen lngDatensatz setzen ie dann auf den zurückgegebenen Wert und danach ie Variable lngErgebnis auf 0. Das ist wichtig, amit im Formular frmGruppen zur Eingabe er Gruppen nicht ein neuer Datensatz erzeugt ird, falls der Benutzer es unabhängig vom dropdown-Listenfeld öffnet.

Außerdem müssen Sie noch die Change-Er- eignisprozedur für das Formular ergänzen und dort prüfen, ob der Eintrag mit dem Wert 0 ausgewählt´wurde. In diesem Fall zeigen Sie das Formular zur Eingabe der Gruppe an. Der Aufruf mit

DoCmd.OpenForm "frmGruppen", acNormal, , , acFormAdd

sorgt dafür, dass der Benutzer nur Datensätze hinzufügen kann und automatisch ein leerer Datensatz angezeigt wird.

Das Listenfeld aufklappen

Benutzer, die vornehmlich die Tastatur zum Bedienen des Formulars verwenden, empfinden es als angenehm, wenn das Listenfeld automatisch aufklappt, sobald es den Fokus bekommt. Aufklappen lassen sich Dropdown-Listenfelder durch den Aufruf der steuerelementeigenen Dropdown-Methode. Dazu wird für das Ereignis Bei Fokuserhalt (onFocus) eine Ereignisprozedur erstellt. Diese Ereignisprozedur wird dann noch´durch den Methodenaufruf ergänzt (Listing 7).

Private Sub cmbGruppe_GotFocus()
Me.cmbGruppe.dropdown
End Sub

Auswahl über den numerischen Wert

Bei sortierten Listeneinträgen kann der Benutzer die Listeneinträge über den Anfangsbuchstaben des Eintrags auswählen. Dafür sorgt Access. Tippt der Benutzer beispielsweise ein T ein, springt Access automatisch zu dem Eintrag mit dem Anfangsbuchstaben T. Durch Eingabe weiterer Zeichen kann der Benutzer auch aus mehreren Einträgen mit gleichem Anfangsbuchstaben wählen. Damit die Auswahl aber dann auch in das versteckte Textfeld übernommen wird, müssen Sie für das Exit-Ereignis des Dropdown- Listenfeldes eine Ereignisprozedur erstellen (Listing 8). Das ist notwendig, weil das Change-Ereignis nur dann eintritt, wenn der Benutzer einen Listeneintrag mit der Maus auswählt, nicht wenn er den Eintrag über die Tastatur aktiviert.

Private Sub cmbGruppe_Exit(Cancel As Integer)
Me.Gruppe.Value = Me.cmbGruppe.Value
End Sub

Diese Auswahl funktioniert aber auch nur innerhalb der ersten sichtbaren Spalte. Gibt es darüber hinaus eine gebundene Spalte, die nicht sichtbar ist und die eine numerische ID des Datensatzes enthält, ist es normalerweise nicht´möglich, durch Eingabe der numerischen ID einen Eintrag zu wählen.

Mit nur ein paar Zeilen Code ist das leicht realisiert. Im einfachsten Fall prüfen Sie, ob der eingegebene Wert numerisch ist, wenn ja, übernehmen Sie den Wert als Wert des Listenfeldes und als Wert des versteckten gebundenen Textfeldes. Das Ganze bringen Sie in der Ereignisprozedur für das Ereignis Bei Taste ab (Keydown)unter (Listing 9). Wichtig ist dabei, dass Sie zuerst den Wert im Textfeld speichern und dann dem Listenfeld zuweisen. Andernfalls würde die Text-Eigenschaft des Listenfeldes den Text des Eintrags anzeigen, der durch die Nummer gewählt´wurde, und diesen Wert können Sie dann natürlich nicht dem gebundenen Textfeld zuweisen, der einen numerischen Wert erwartet.

Private Sub cmbGruppe_KeyDown(KeyCode As Integer, Shift As Integer)
If IsNumeric(Me.cmbGruppe.Text) Then
Me.Gruppe.Value = Me.cmbGruppe.Text
Me.cmbGruppe.Value = Me.cmbGruppe.Text
End If
End Sub

Nachteile

Diese Lösung hat aber mehrere Nachteile. Sie eignet sich nur für sehr kleine Listen, bei denen es keine zwei- oder mehrstelligen IDs gibt. Durch Eingabe einer Ziffer würde nämlich der alte Wert ersetzt, so dass Zahlen wie 11, 120 und so weiter nicht eingegeben werden können. Zudem können Sie so nicht prüfen, ob es die ID überhaupt gibt. Falls sie nicht vorhanden ist, wird kein Listeineintrag gewählt und so ein ungültiger Wert im Feld gespeichert.

Wenn Sie das Dropdown-Listenfeld so eingestellt haben, dass nur Listeneinträge ausgewählt werden können, erhalten Sie außerdem eine Fehlermeldung. Diese Lösung ist also definitiv nicht optimal.

Bild 3: Werte im Dropdown-Listenfeld auf Listeneinträge beschränken.

Besser ist, Sie schreiben sich eine Funktion, die die Liste durchläuft, den Wert überprüft, den passenden Eintrag markiert, die Liste schließt und das nächste Steuerelement aktiviert. Um diese Prozedur möglichst einfach aufrufen zu können,´sollten Sie für das Dropdown-Listenfeld die Eigenschaft Nur Listeneinträge auf True setzen. Dann tritt bei Eingabe eines Wertes, der nicht in der ersten sichtbaren Spalte vorkommt, das Ereignis NotInList ein. Mit Hilfe einer Ereignisprozedur für dieses Ereignis können Sie dann die Funktion aufrufen (Listing 10).

Private Sub cmbGruppe_NotInList(NewData As String, Response As Integer)
Listedurchsuchen Me.cmbGruppe, NewData, 1, Me.ID
Response = acDataErrContinue
End Sub

Wichtig ist dabei, dass Sie am Ende der Ereignisprozedur deren Parameter Response auf den Wert der Konstanten acDataErrContinue setzen. Das verhindert, dass eine Fehlermeldung angezeigt wird. Sie müssen dann aber natürlich selbst afür sorgen, dass ein gültiger Wert eingegeben ird. Über den Parameter NewData können Sie en eingegebenen Wert ermitteln.

Die Prozedur Listedurchsuchen definieren Sie einem beliebigen Modul, so dass Sie sie auf verschiedene Listenfelder anwenden können. Die Prozedur erwartet vier Parameter. Als Erstes das Dropdown-Listenfeld als Objekt, dann den zu suchenden Wert, die Spalte, in der dann der anzuzeigende Text steht, und das Steuerelement, dass als nächstes den Fokus bekommen soll.

Sub Listedurchsuchen(objLFeld As ComboBox, strWert As String, _
intSpalte As Integer, objFolgeControl As Control)
Dim lngI As Long
'Liste nach Wert durchsuchen
For lngI = 0 To objLFeld.ListCount - 1
If objLFeld.ItemData(lngI) = strWert Then
'Wert gefunden
objLFeld.Value = strWert
objLFeld.Text = objLFeld.Column(intSpalte, lngI)
objFolgeControl.SetFocus
Exit Sub
End If
Next lngI
End Sub

Die Prozedur durchsucht alle Listeneinträge und vergleicht den Wert des gebundenen Feldes mit dem übermittelten Parameter strWert. Den Wert des gebundenen Feldes ermitteln Sie mit der Methode ItemData, der Sie den Zeilenindex übergeben. Dieser beginnt genau wie der Spaltenindex bei 0, so dass die Schleife von 0 bis zur Anzahl Listeneinträge (ListCount) abzüglich 1 läuft.

Findet die Prozedur einen übereinstimmenden Eintrag, wird der übermittelte Wert als Wert des Listenfeldes festgelegt und der Text auf den Wert in der entsprechenden Zeile gesetzt, der in der als intSpalte übermittelten Spalte steht. Anschließend sorgt die Methode SetFocus dafür, dass das definierte Folgesteuerelement den Fokus bekommt.
Falls der Benutzer einen Wert eingibt, für den keine Übereinstimmung gefunden wurde, wird die Prozedur einfach ohne Änderung verlassen. Das führt dann dazu, dass das Listenfeld geöffnet bleibt und der Benutzer nun einen Wert aus der Liste auswählen kann.

Alle Spalten nach Übereinstimmung durchsuchen

Ähnlich einfach ist es, mehrere Spalten zu durchsuchen. Nicht immer muss die Eingabe ja zwingend der ID entsprechen. Enthält ein Pulldown- Listenfeld mehr als zwei Spalten, könnte der eingegebene Wert beispielsweise einem Wert der dritten oder vierten Spalte entsprechen oder nur deren Anfang darstellen. Zusätzlich zu den Parametern der Prozedur Listedurchsuchen benötigen Sie nun einen Parameter mehr, mit dem sich bestimmen lässt, ob auch Teilzeichenfolgen akzeptiert werden. Ergänzen Sie den Prozedurkopf um einen booleschen Parameter. Geben Sie true an, prüft die Prozedur, ob irgendein Feld mit dem eingegebenen Text beginnt. Falls ja, wird dieser Eintrag ausgewählt. Damit aber exakte Übereinstimmungen Vorrang haben, erfolgt die Prüfung in drei Schritten. Zunächst wird in der gebundenen Spalte gesucht. Wird dort nichts gefunden, werden die übrigen Spalten nach exakten Übereinstimmungen durchsucht. Ist immer noch kein Wert gefunden, werden abhängig vom Wert des Parameters boolAnfang noch einmal alle Felder nach dem Wert als Feldanfang durchsucht (Listing 12).

Sub Listedurchsuchen2(objLFeld As ComboBox, strWert As String, _
intSpalte As Integer, objFolgeControl As Control, boolAnfang As Boolean)
Dim lngI As Long
Dim lngJ As Long
'Liste nach Wert durchsuchen
'Suchen in gebundener Spalte
For lngI = 0 To objLFeld.ListCount - 1
If objLFeld.ItemData(lngI) = strWert Then
'Wert gefunden
objLFeld.Value = strWert
objLFeld.Text = objLFeld.Column(intSpalte, lngI)
objFolgeControl.SetFocus
Exit Sub
End If
Next lngI
'Falls nichts gefunden wurde, suchen in den anderen Spalten
For lngI = 0 To objLFeld.ListCount - 1
For lngJ = 0 To objLFeld.ColumnCount - 1
If objLFeld.Column(lngJ, lngI) = strWert Then
'Wert gefunden
objLFeld.Value = objLFeld.ItemData(lngI)
objLFeld.Text = objLFeld.Column(intSpalte, lngI)
objFolgeControl.SetFocus
Exit Sub
End If
Next lngJ
Next lngI
'Falls immer noch nichts gefunden wurde, und boolAnfang den Wert True hat
'Nach dem Beginn der Felder suchen
For lngI = 0 To objLFeld.ListCount - 1
For lngJ = 0 To objLFeld.ColumnCount - 1
If InStr(1, objLFeld.Column(lngJ, lngI), strWert) = 1 Then
'Wert gefunden
objLFeld.Value = objLFeld.ItemData(lngI)
objLFeld.Text = objLFeld.Column(intSpalte, lngI)
objFolgeControl.SetFocus
Exit Sub
End If
Next lngJ
Next lngI
End Sub

Per Mausklick ein Formular mit Datensatzdetails aufrufen

Das war aber noch nicht alles, was sie tun können, um dem Benutzer den Umgang mit dem Dropdown-Listenfeld zu erleichtern. Stellen Sie ihm bei vielen Spalten jetzt noch per Formular Informationen zum gewählten Listeintrag zur Verfügung.

Benötigt wird dazu ein Formular, das alle gewünschten Daten anzeigt. Im Beispiel handelt es sich dabei um das Formular frmGruppenKomplett, das den Namen und die ID der Gruppe anzeigt und darunter in einem Unterformular alle zugeordneten Datensätze auflistet. Beim Doppelklicken auf das Dropdown-Listenfeld soll dieses Formular angezeigt und nach der übermittelten Gruppen-ID gefiltert werden, die sich dem Wert des Dropdown-Listenfeldes entnehmen lässt.

Für den Aufruf des Formulars verwenden Sie wieder die OpenForm-Methode des DoCmd-Objekts. Als Filter übergeben Sie einen Ausdruck für die WHERE-Klausel einer SELECT-Anweisung (Listing 12). Im Beispiel erfolgt der Aufruf innerhalb der Ereignisprozedur für das DblClick-Ereignis. Die Prozedur wird ausgeführt, wenn der Benutzer doppelt auf das Dropdown-Listenfeld klickt.

Private Sub cmbGruppe_DblClick(Cancel As Integer)
DoCmd.OpenForm "frmGruppenKomplett", acNormal, , _
"Gruppen.ID=" & Me.cmbGruppe.Value, acFormReadOnly
End Sub
Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
If (Shift And acCtrlMask) And (KeyCode = vbKeyD) Then
DoCmd.OpenForm "frmGruppenKomplett", acNormal, , _
"Gruppen.ID=" & Me.cmbGruppe.Value, acFormReadOnly
End If
End Sub

Natürlich können Sie das Formular auch per Tastenkombination anzeigen lassen. Dazu wird eine Ereignisprozedur für das KeyDown-Ereignis erstellt (Listing 12). Innerhalb der Prozedur wird ermittelt, ob die gewünschten Tasten gedrückt wurden. Die gedrückten Tasten lassen sich über die Parameter KeyCode und Shift ermitteln. Key Code liefert den Code der gedrückten Taste. Allerdings ist dies nicht der ASCII-Code, sondern eine´vordefinierte VBA-Konstante. Die Namen der Konstanten finden Sie übrigens im Objektkatalog in den globalen Konstanten. Sie beginnen alle mit vbKey (Bild 5).

Bild 4: Nun kann der Benutzer auch Werte in der zweiten sichtbaren Spalte eingeben.
Bild 5: Anzeige der Konstanten für die Tastencodes über des Objektkatalog.

Der Parameter Shift liefert die Summe aller Tastencodes für die [Umsch]-, [Strg]- und [Alt]- Taste. Wenn Sie wissen möchten, ob die [Strg]- Taste gedrückt wurde, benötigen Sie dazu einen binären Vergleich. Der Ausdruck (Shift And acCtrlMask) ist beispielsweise WAHR, wenn in dem Wert des Parameters Shift der Tastencode der [Strg]-Taste enthalten ist.

Tabelle 1: Tastencodes des Shift-Parameters.

Konstante

Beschreibung

acShiftMask

Bitmaske für die [Umsch]-Taste.

acCtrlMask

Bitmaske für [Strg]-Taste.

acAltMask

Bitmaske für [Alt]-Taste.

Damit die Sache mit den Tastencodes aber auch funktioniert, sollten Sie die Eigenschaft Tastenvorschau des Formulars auf Ja setzen. Andernfalls wird der Tastendruck nur dann registriert, wenn kein Steuerelement den Fokus hat.