Zusammenfassung
Sie erhalten Antworten auf die meistgestellten Fragen zu Kombinations- und Listenfeldern.
Techniken
Formulare, Listenfelder, Kombinationsfelder, VBA
Voraussetzungen
Access 97 oder höher
Beispieldateien
FAQ9_00.mdb
Karl Donaubauer, Wien
In der Access-FAQ von Karl Donaubauer (www.donkarl.com) finden Sie die meistgestellten Fragen und Anworten zum Thema Microsoft Access. In dieser Beitragsreihe stellt Karl Donaubauer die wichtigsten Einträge im Detail vor und zeigt Ihnen entsprechende Lösungen anhand praxisnaher Beispiele. Im neunten Teil lernen Sie die Lösungen zu den häufigsten Problemen im Zusammenhang mit Kombinations- und Listenfeldern in Formularen kennen.
Es steht zwar nicht in der Online-Hilfe, aber die nicht änderbare maximale Zeilenanzahl für beide Steuerelemente beträgt in allen Access-Versionen 65536. Wenn die Datensatzherkunft mehr Datensätze enthält, werden die überzähligen ignoriert und nicht dargestellt. Sie sollten ohnehin niemals in diese Verlegenheit kommen, sondern dafür sorgen, dass nicht mehr als einige hundert oder wenige tausend Zeilen in einem Kombinationsfeld oder Listenfeld dargestellt werden. Der Grund ist die schlechte Performance bei sehr vielen Zeilen. Es ist fast immer möglich, große Datensatzmengen für die Verwendung sinnvoll vorzufiltern, sei es nach Anfangsbuchstabe, Gruppe, Bereich, Region oder ähnlich. Mehr dazu später in diesem Artikel.
Das Problem der oft schlechten Performance mit Kombinations- und Listenfeldern wird verschärft, wenn sich mehrere davon in einem Formular befinden. Das öffnen des Formulars kann dann sehr lange dauern und unzumutbar für den Benutzer werden. Die erste Maßnahme in solchen Fällen wäre natürlich die Reduzierung dieser Steuerelemente. Da sie aber großartige Funktionalität bieten und der Anwender dadurch leicht verwöhnt wird, ist das nicht immer möglich, vor allem, wenn sich erst im Laufe der Verwendung einer Datenbank die Datenmengen stark erhöhen und die Performance immer schlechter wird.
Teil des Performance-Problems ist, dass die Datensatzherkunft von Kombinations- und Listenfeldern immer schon beim öffnen des Formulars geladen wird, um die Steuerelemente zu füllen. Hier kann man lösungsmäßig ansetzen.
Lassen Sie einfach die Eigenschaft Datensatzherkunft leer, oder, wenn Sie unbedingt schon beim öffnen des Formulars Werte anzeigen müssen, belegen Sie sie standardmäßig mit stark einschränkenden Abfragen. Erst wenn der Anwender aktiv auf das Kombinations- oder Listenfeld zugreift, setzen Sie die Datensatzherkunft per VBA.
Dafür reichen drei Zeilen Code im Ereignis Beim Hingehen des Steuerelementes. Angenommen, Sie möchten das Kombinationsfeld cboOrte mit den Daten aus der Tabelle tblOrte füllen:
If Me!cboOrte.RowSource <> "tblOrte" Then Me!cboOrte.RowSource = "tblOrte" End If
Die Prüfung mit If vorneweg sorgt dafür, dass das Befüllen nicht unnötig wiederholt wird, wenn der Anwender erneut auf das bereits gefüllte Kombinationsfeld zugreift.
Ein häufig gewünschtes Feature für Klickfaule ist, dass sich die Auswahlliste eines Kombinationsfeldes beim Hingehen wie von Geisterhand öffnen möge, ohne dass der Anwender auf den entsprechenden Abwärtspfeil klicken muss.
In den ersten Versionen von Access konnte man das nur mit dem fehlerbehafteten Sendkeys-Befehl regeln, mit dem man eine der Windows-Tastenkombinationen zum öffnen von Auswahllisten, Alt + Pfeil nach unten oder F4, losschickte.
Heutzutage ist das eine Unsitte, die man aber immer noch entweder als Tipp oder in Anwendungen zu sehen bekommt. Bereits seit Access 95 gibt es für diesen Zweck die Methode Dropdown.
Zu ihrer Ausführung muss das Kombinationsfeld den Fokus haben. Sie müssen also entweder, wie im Beispielformular gezeigt (siehe Bild 1), zuerst den Fokus auf das Kombinationsfeld setzen oder das Ereignis Beim Hingehen des Kombinationsfeldes verwenden. Der Code ist dann einfach:
Me!cboOrte.Dropdown
Bild 1: Kombinationsfeld per Schaltfläche geöffnet
In der Eigenschaft Value eines Kombinations- oder Listenfeldes befindet sich immer nur der Wert aus der gebundenen Spalte. Den Zugriff auf die Werte anderer Spalten ermöglicht die Eigenschaft Column(Spalte, Zeile). Die Parameter für die Spalte und die Zeile sind beide nullbasierend. Den Wert der zweiten Spalte aus der zweiten Zeile erhalten Sie daher mit:
Me!cboOrte.Column(1,1)
Wenn Sie nur den ersten Parameter angeben, also jenen für die Spalte, zum Beispiel
Me!cboOrte.Column(1)
dann wird der Wert aus der aktuell ausgewählten Zeile zurückgeliefert.
Ein Bezug dieser Art wird auch gerne verwendet, um in ungebundenen Textfeldern eines Formulars die Werte aus den nicht gebundenen Spalten eines Kombinationsfeldes anzuzeigen. Wenn es nur um die Anzeige geht, reicht für das anzeigende Textfeld ein Steuerelementinhalt wie:
=[cboOrte].[Column](1)
Beispiele für die Verwendung von Column finden Sie ebenfalls im Formular frmKombinationsfeldOeffnen aus Bild 1.
Möchten Sie hingegen den Wert in einem gebundenen Textfeld speichern, so müssen Sie ihn, am besten im Ereigniscode Nach Aktualisierung des Kombinationsfeldes, per VBA zuweisen:
Me!MeinFeld = Me!cboOrte.Column(1)
Noch ein Hinweis auf einen Trick, um Column() auch in Bezügen in Abfragen verwenden zu können. Ein Bezug wie der folgende (in einer Zeile) in einem Abfragekriterium funktioniert nicht, weil JET mit der Column-Eigenschaft nichts anfangen kann:
Forms!MeinFormular!MeinListenFeld.Column(1)
Abhilfe bringt, wie so oft, die Verwendung der Funktion Eval(), die dafür sorgt, dass der Expression Service von JET den Bezug auswertet, bevor die Abfrage von der JET-Query-Engine weiter verarbeitet wird. Der Bezug in der Abfrage muss dafür lauten (in einer Zeile):
Eval("Forms!MeinFormular!MeinListenFeld.Column(1)")
Bild 2: Automatische Markierung bestimmter Zeilen
Eine häufige Anforderung an Kombinationsfelder und gelegentlich auch an Listenfelder ist ein voreingestellter Wert. Meistens geht es darum, den ersten oder letzten Wert aus der Liste automatisch auszuwählen.
Für diese Zwecke eignet sich am besten die Eigenschaft ItemData. Der Index von ItemData ist wieder nullbasierend, das heißt ItemData(0) ist die erste Zeile des Steuerelementes, ItemData(1) die zweite und so weiter.
Das Listenfeld lstOrte im Beispielformular (siehe Bild 2) ist so präpariert, dass beim öffnen des Formulars die erste Zeile vorausgewählt ist. Erreicht wird das durch folgenden Eintrag in der Eigenschaft Standardwert des Listenfeldes:
[lstOrte].[ItemData](0)
In Bild 2 sehen Sie auch mehrere Schaltflächen, die weitere Varianten vorführen. Der Code, um die erste Zeile eines Listenfeldes oder Kombinationsfeldes per VBA auszuwählen, lautet schlicht:
Me!lstOrte = Me!lstOrte.ItemData(0)
Etwas komplizierter ist das dynamische Weiterspringen um jeweils eine Zeile (ohne Zeilenumbruch):
Me!lstOrte = Me!lstOrte.ItemData(Me!lstOrte.ListIndex + 1)
Die aktuell ausgewählte Zeile wird dabei mithilfe der Eigenschaft ListIndex ausgelesen und um 1 erhöht. Der Code zum Auswählen der letzten Zeile lautet:
Me!lstOrte = Me!lstOrte.ItemData(Me!lstOrte.ListCount - 1)
Mithilfe der Eigenschaft ListCount wird dabei die Anzahl der Zeilen ermittelt und, da ItemData ja nullbasierend ist, 1 subtrahiert.
ListCount können Sie auch für andere nützliche Zwecke einsetzen. So kann es etwa für den Anwender eine sinnvolle Information sein, wenn er weiß, die wievielte Zeile von wie vielen vorhandenen er gerade ausgewählt hat. In Bild 2 sehen Sie unterhalb des Listenfeldes ein entsprechendes Textfeld mit folgendem Steuerelementinhalt:
=[lstOrte].[ListIndex]+1 & " / " & [lstOrte].[ListCount]
ListIndex ist wiederum eine nullbasierende Eigenschaft, die den aktuell gewählten Eintrag wiedergibt.
Es gibt mehrere Varianten, um den im Textteil eines Kombinationsfeldes eingegebenen Wert per VBA in seine Auswahlliste aufzunehmen. In der ersten hier demonstrierten Variante wird der Wert unmittelbar nach der Eingabe und ohne Nachfrage in die Liste aufgenommen.
Voraussetzung für den Zugriff per VBA ist, dass die Eigenschaft Nur Listeneinträge des Kombinationsfeldes auf Ja steht. Als Folge dieser Einstellung können Sie Code im Ereignis Bei nicht in Liste des Steuerelementes verwenden, um den Datensatz an die Datensatzherkunft anzufügen und das Kombinationsfeld zu aktualisieren.
Quellcode 1 zeigt den im Beispielformular frmKombiHinzufuegen verwendeten Code, um einen Eintrag an eine Artikeltabelle anzufügen.
In der ersten Codezeile wird der Parameter Response auf acDataErrAdded gesetzt. Standardmäßig bringt Access bei einem neuen Eintrag die schöne Meldung: „Der von Ihnen eingegebene Text ist kein Element der Liste.“
adDataErrAdded sorgt dafür, dass diese Standardmeldung unterbleibt und der neue Eintrag kommentarlos angefügt wird.
Quellcode 1: Anfügen eines Eintrags an eine Tabelle
Response = acDataErrAdded Dim db As DAO.Database Dim rs As DAO.Recordset Set db = CurrentDb Set rs = db.OpenRecordset("tblArtikel", dbOpenDynaset) rs.AddNew rs!Bezeichnung = NewData rs.Update rs.Close: Set rs = Nothing Set db = Nothing
Quellcode 2: öffnen eines Eingabeformulars
Response = acDataErrContinue If MsgBox("Dieser Artikel ist neu. " _ & "Möchten Sie ihn anlegen", vbYesNo) = _ vbYes Then DoCmd.OpenForm "frmArtikelNeu", , , , _ acFormAdd Forms!frmArtikelNeu!Bezeichnung = NewData Else Response = acDataErrContinue Me!cboArtikel2.Undo End If
Dazu wird ein DAO-Recordset auf Basis der dem Kombinationsfeld zugrunde liegenden Tabelle geöffnet. Der im Textfeld des Kombinationsfeldes neu eingegebene Begriff befindet sich im Parameter Newdata des NotInList-Ereignisses. Damit kann er dem passenden Feld im Recordset zugewiesen werden. Mit AddNew wird der neue Datensatz an die Tabelle angefügt.
Diese einfache Variante eignet sich nur für neue Einträge in Tabellen, bei denen keine weiteren Felder auszufüllen sind. Andernfalls ist das übliche Vorgehen, bei Eingabe eines neuen Begriffs in das Kombinationsfeld ein Eingabeformular für den Anwender zu öffnen, in das er alle nötigen weiteren Daten für den neuen Datensatz eintragen kann. Beim Schließen des Eingabeformulars wird dann der neue Eintrag in der Liste des Kombinationsfeldes hinzugefügt.
Quellcode 2 zeigt den Code im Beispielformular frmKombiHinzufuegen, der das Eingabeformular öffnet. Zuerst wird der Parameter Response auf adDataErrContinue gesetzt. Das ermöglicht eine selbst definierte Meldung anstelle der Access-Standardmeldung.
Dann erfolgt die Rückfrage an den Anwender, ob er den neuen Artikel wirklich anlegen möchte. Wenn er verneint, etwa im Falle eines Irrtums oder Tippfehlers, wird die Eingabe mit Undo rückgängig gemacht.
Wenn er hingegen bejaht, wird das Eingabeformular geöffnet und der neue Eintrag für die Artikelbezeichnung aus dem Kombinationsfeld in das entsprechende Textfeld im Eingabeformular übernommen (siehe Bild 3).
Bild 3: Eingabeformular zum Hinzufügen eines neuen Eintrags in die Auswahlliste eines Kombinationsfeldes
Der Anwender kann nun das Eingabeformular ausfüllen. Im Ereignis Beim Schließen des Eingabformulares wird dann mit den folgenden zwei Codezeilen dafür gesorgt, dass der neue Eintrag sofort in der Auswahlliste des Kombinationsfeldes sichtbar ist:
Forms!frmKombiHinzufuegen!cboArtikel2 _ = Me!ArtikelId
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