FAQ

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_97.mdb

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

Schreibe einen Kommentar

FAQ

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 achten Teil lernen Sie die Lösungen zu den häufigsten Problemen im Zusammenhang mit dem Finden, Sortieren und Speichern von Daten in Formularen kennen.

Hinweis

Die Beispieldatenbanken zu FAQ8_A97.mdb für Access 97 und FAQ8_A00.mdb für Access 2000 und höher. Sie finden die Datenbanken auf der Heft-CD oder im Internet unter http://www.access-im-unternehmen.de (Shortlink 281).

Suchfunktionalitäten lassen sich in zwei große Kategorien einteilen: Filtern oder Springen. Die häufigste Aufgabenstellung bei der Sprungvariante ist der Wunsch, in ein Text- oder Kombinationsfeld einen Suchbegriff eingeben zu können und damit zum passenden Datensatz zu springen. Dafür bietet VBA zwei verschiedene Lösungsmöglichkeiten, die beide sowohl im Einzel- als auch im Endlosformular funktionieren.

Bild 1: Suche mit FindRecord oder Bookmark

In der Beispieldatenbank zu diesem Artikel finden Sie das Formular frmArtikelSuche (siehe Bild 1), in dem beide Techniken vorgeführt werden. Ob Sie sich zur Suche eines Kombinationsfeldes oder eines normalen Textfeldes bedienen, ist für den reinen Suchcode unerheblich.

Im Beispielformular ist es ein Kombinationsfeld, dessen erste und gebundene Spalte die eindeutige ArtikelId enthält, die zweite Spalte enthält die Artikelbezeichnung.

Die Spaltenbreite der ID-Spalte steht auf 0, damit sie nicht sichtbar ist. Der Anwender gibt also den Suchtext für die aussagekräftige Artikelbezeichnung ein, gesucht wird aber mittels der gebundenen Spalte, die die eindeutige ID enthält.

Die erste Methode, FindRecord, ist sehr einfach und erfordert nur drei Zeilen VBA-Code im Ereignis Nach Aktualisierung des Such-Kombinationsfeldes.

If IsNull(Me!cboSuche1) Then Exit Sub
Me!ArtikelId.SetFocus
DoCmd.FindRecord Me!cboSuche1

Die erste Zeile dient dazu, die Prozedur gleich wieder zu verlassen, falls das Kombinationsfeld leer ist. Ansonsten würde FindRecord eine unnötige Fehlermeldung liefern. Die zweite Codezeile setzt den Fokus auf das Textfeld ArtikelId, die dritte führt die eigentliche Such- und Sprungaktion aus, indem nach dem FindRecord-Befehl der Parameter für den Suchvergleich angegeben wird. In diesem Fall ist das der Inhalt des Such-Kombinationsfeldes. Die Methode FindRecord bietet darüber hinaus noch interessante weitere Parameter zum Beispiel zur Unterscheidung zwischen Groß- und Kleinschreibung, zur Angabe einer Suchrichtung oder zur Suche in allen Feldern eines Datensatzes. Die Methode ist also die Umsetzung des normalen Suchdialogs von Office und bietet auch alle entsprechenden Möglichkeiten. Sie sind recht gut in der Online-Hilfe erläutert.

Der große Nachteil dieser Methode ist, dass das Feld, in dem gesucht werden soll, im Formular sichtbar und aktiviert sein muss, damit es den Fokus erhalten kein und FindRecord weiß, wo gesucht werden soll. Das ist oft nicht erwünscht, so wie im Beispielfall, in dem die Anzeige einer nicht aussagekräftigen und nicht änderbaren ArtikelId keinen Sinn macht. Für diesen Fall eignet sich eher der Umweg über den RecordsetClone des Formulars, wie er im zweiten Such-Kombinationsfeld des Beispielformulars gezeigt wird. Der Code im Ereignis Nach Aktualisierung des Kombinationsfeldes lautet:

If IsNull(Me!cboSuche2) Then Exit Sub
Dim rst As DAO.Recordset
Set rst = Me.RecordsetClone
rst.FindFirst "ArtikelId = " _    & Me!cboSuche2
If Not rst.NoMatch Then
    Me.Bookmark = rst.Bookmark
End If
Set rst = Nothing

Es wird also ein DAO-Recordset deklariert und mit dem Clone des Formular-Recordsets belegt. In diesen Daten wird mit der FindFirst-Methode von DAO nach dem Datensatz gesucht, der dem Suchbegriff entspricht. Falls etwas gefunden wurde, setzt FindFirst den Zeiger auf diesen gefundenen Datensatz und anschließend wird die Bookmark-Eigenschaft des Formulars auf jene des RecordsetClones gesetzt. Das hat zur Folge, dass im Formular der gefundene Datensatz zum aktuellen wird. Was ist der Grund dafür

Beim öffnen eines Formulars weist Access jedem angezeigten Datensatz einen eindeutigen Wert zu, das so genannte Lesezeichen oder Bookmark in VBA. Der RecordsetClone ist nichts anderes als eine Kopie der Daten im Formular und verwendet dieselben Bookmarks. Deshalb kann man sie in beiden Richtungen aufeinander abstimmen.

Noch ein Warnhinweis, falls Sie Access 97 verwenden: Sie sollten ein aktuelles JET-Update für Access 97 installiert haben und/oder das Service Release 2 für Office 97. Wenn nicht, sollten Sie vor der ersten Verwendung des RecordsetClones schreiben:

Me.RecordsetClone.Requery

Ansonsten könnte der legendäre Bookmark-Bug wirksam werden, der in älteren Access-Versionen manchmal dafür sorgt, dass die Anzeige im Formular nicht richtig mit dem dahinter liegenden Recordset synchronisiert wird und somit Datenänderungen nicht im aktuell sichtbaren Datensatz des Formulars vorgenommen werden, sondern in irgendeinem anderen. Das war einer der schwersten Fehler, die Access jemals hatte, weil dadurch ohne Schuld des Anwenders falsche Daten erzeugt wurden. Microsoft hat diesen Bug erst mit den oben angeführten Updates gefixt.

Zum Sortieren gibt es die zwei einfach und klar zu bedienenden Schaltflächen in der Formular-Symbolleiste. Es kommt aber vor, dass man entweder keine Symbolleisten anzeigen, die Sortier-Funktion auf das Klicken einer selbst erstellten Schaltfläche legen oder nach mehr als einem Feld sortieren möchte. Für all diese Varianten brauchen Sie die Sortierung per VBA. Dafür gibt es wiederum zwei Varianten mit Vor- und Nachteilen. Die erste Variante ist das Erzeugen oder ändern des SQL-Strings, der als Datenherkunft des Formulars dient. Entscheidend für die Sortierung der Daten ist dabei die Klausel ORDER BY von SQL. Angenommen Sie haben eine Tabelle tblKunden, die standardmäßig nach dem Primärschlüsselfeld KundenId sortiert wird, und Sie möchten auf Knopfdruck nach den Feldern Nachname und Vorname sortieren. Der Code im Ereignis Beim Klicken einer Schaltfläche könnte so aussehen:

Dim strSQL As String
strSQL = "SELECT tblKunden.* " _    & "FROM tblKunden " _    & "ORDER BY tblKunden.Nachname, " _    & " tblKunden.Vorname;"
Me.RecordSource = strSQL

Die Neuzuweisung der RecordSource (Datenherkunft) an das Formular bewirkt immer auch gleich eine Aktualisierung der Anzeige. Mehr ist also nicht zu tun.

Diese Sortier-Methode über das SQL-Statement des Formulars ist sehr flexibel, weil Sie nicht nur die Sortierung, sondern auch alle anderen die Daten betreffenden Einstellungen über das SQL-Statement vornehmen können. Wenn Sie nicht besonders SQL-erfahren sind, ist das beste Vorgehen, eine Abfrage mit dem Abfrage-Editor zu erstellen, in die SQL-Ansicht zu wechseln und das Statement von dort per Zwischenablage zu übernehmen. Auch Profis verwenden oft diese Technik und verbessern gegebenenfalls noch das Statement des Assistenten, weil es schneller und weniger fehleranfällig ist als das Tippen des kompletten Statements samt Feldnamen und so weiter.

Der große Nachteil dieser Methode ist, dass die Daten komplett neu abgerufen werden, was bei langsamer Verbindung oder großen Datenmengen ein Performance-Problem darstellen kann. Die zweite Methode ist die Verwendung der Eigenschaft Sortiert nach des Formulars:

Me.OrderBy = "Nachname, Vorname"
Me.OrderByOn = True

Für eine absteigende Sortierung müssten Sie übrigens genau wie in SQL auch hier das Schlüsselwort DESC verwenden. Zum Beispiel absteigend nach Nachname und Vorname sortiert:

Me.OrderBy = _    "Nachname DESC, Vorname DESC"
Me.OrderByOn = True

Diese Methode hat den Vorteil, dass die Datenherkunft des Formulars nicht neu geladen wird. Sie hat aber den Nachteil, dass Access die letzte Sortierung speichert. Das passiert auch, wenn Sie diese Eigenschaft nicht per VBA, sondern im Eigenschaftsfenster einstellen. Wenn Sie verhindern möchten, dass die Daten beim nächsten öffnen nach der zuletzt verwendeten Einstellung sortiert werden, können Sie im Ereigniscode Beim öffnen des Formulars schreiben:

Me.OrderBy = ""

In vielen Situationen müssen Sie zum Aktualisieren der Daten eines Formulares die Requery-Methode verwenden. Ein typisches Beispiel ist das Auswahlformular, das nach dem öffnen eines Detailformulars alle geänderten und neuen Datensätze anzeigen soll und die gelöschten nicht mehr. Das Problem mit Requery ist, dass die Methode bei der erwünschten Neuabfrage der Datenherkunft zum ersten Datensatz des Formulars springt. Um das sauber zu beheben, ist einiges an Code erforderlich. Bild 2 zeigt die Formulare frmArtikelAuswahl und frmArtikelAktualisierung aus der Datenbank zum Artikel.

Das eine Formular ist eine nicht direkt änderbare Artikelliste, das andere ein Detailformular, in dem änderungen vorgenommen werden können. Das Detailformular enthält drei Schaltflächen, die die unterschiedlichen Auswirkungen auf das Auswahlformular demonstrieren, besonders wenn neue Datensätze hinzugefügt oder bestehende gelöscht wurden. Quellcode 1 ist der Code hinter dem Klick-Ereignis der untersten Schaltfläche, die nach dem Schließen des Detailformulars und dem Requery auf das Auswahlformular zum aktuellen Datensatz zurückkehrt.

Bild 2: Auswahl- und Detailformular mit Requery-Methode

Private Sub btnSchliessenMitDS_Click()
    On Error GoTo myError
    DoCmd.Close acForm, Me.Name
    Dim rs As DAO.Recordset
    Dim frm As Form
    Dim lngStore As Long
    Set frm = Forms!frmArtikelAuswahl
    Set rs = frm.RecordsetClone
    lngStore = frm!ArtikelId
    ''Bildschirmflackern reduzieren
    frm.Painting = False
    frm.Requery
    rs.FindFirst "ArtikelId = " & lngStore
    frm.Bookmark = rs.Bookmark
myExit:
    frm.Painting = True
    Exit Sub
myError:
    Select Case Err.Number
        Case 64519 ''Datensatz wurde gelöscht
            Resume Next
        Case Else
            MsgBox "Exception Nr. " & Err.Number _                & " " & Err.Description
            Resume myExit
    End Select
End Sub

Quellcode 1

Im Wesentlichen speichert der Code die ID des aktuellen Datensatzes im Auswahlformular in der Variable lngStore, führt die Requery-Methode aus und verwendet dann, wie im vorhergehenden Kapitel erläutert, Findfirst und die Bookmark-Eigenschaft, um zum aktuellen Datensatz zurückzukehren.

Mithilfe der Painting-Eigenschaft wird das Bildschirmflackern vermindert und in der Fehlerroutine wird der Fehler nach dem Löschen eines Datensatzes abgefangen und in diesem Fall nur das Requery zur Aktualisierung des Auswahlformulars durchgeführt.

Einen einzelnen markierten Datensatz in einem Endlosformular zu ermitteln, ist keine Kunst. Sie müssen dafür nur ein eindeutiges Feld auslesen, also zum Beispiel: Me!ArtikelId

Das funktioniert, weil der einzelne markierte Datensatz zugleich der aktuelle Datensatz des Formulars ist und alle Feld- oder Steuerelementbezüge auf den Detailbereich ihn betreffen. Wie aber können Sie, wenn Sie für weiterführende Zwecke mehrere Datensätze mithilfe des Datensatzmarkierers markiert haben, per Code ermitteln, um welche Datensätze es sich handelt

Hier helfen die Eigenschaften SelTop und SelHeight des Formulars. Das Formular frmArtikelMehrfachAuswahl in der Datenbank zum Artikel zeigt den Umgang mit diesen Eigenschaften (siehe Bild 3).

Bild 3: Mehrere markierte Datensätze ermitteln

An sich bekommt man mit einem einfachen Me.SelTop den ersten markierten Datensatz und mit Me.SelHeight die Anzahl der markierten Datensätze. Das Problem dabei ist, dass die Markierung sofort verschwindet, wenn ein anderes Steuerelement den Fokus erhält.

Es ist also nicht möglich, einfach eine Befehlsschaltfläche im Formular zu platzieren und bei deren Anklicken zum Beispiel einen Bericht mit den markierten Datensätzen zu drucken, weil die Markierung durch den Wechsel zur Schaltfläche bereits verloren gegangen ist.

Eine Möglichkeit, dieses Problem zu umgehen, ist, das Auslesen der Eigenschaften auf einen Menüpunkt oder einen Tastendruck zu legen, der die Markierung im Formular nicht beeinflusst. Ein solches Beispiel zeigt das Formular anhand der Funktionstaste F5. Dazu muss im Formular die Eigenschaft Tastenvorschau auf Ja eingestellt sein, damit immer zuerst die Tastatur-Ereignisprozedur des Formulars aufgerufen wird. Der Code beim Ereignis Bei Taste Ab des Formulars sieht so aus:

If KeyCode = vbKeyF5 Then
    MsgBox "Markierung beginnt bei " _        & "Datensatz " & Me.SelTop _        & vbCrLf & "Anzahl der " _        & "markierten Datensätze: " _        & Me.SelHeight
End If

Beim Drücken von F5 wird eine also eine Meldung ausgegeben, die mithilfe von SelTop und SelHeight den ersten markierten Datensatz ausgibt und die Anzahl der markierten Datensätze.

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

Schreibe einen Kommentar