DAO, Teil 2: Recordsets in Aktion

Zusammenfassung

Erfahren Sie, wie Sie in Datensatzgruppen navigieren und die Inhalte manipulieren.

Techniken

VBA, DAO

Voraussetzungen

Access 97 und höher

Beispieldatei

DAO2.mdb

André Minhorst, Duisburg

Hat man einmal ein Recordset-Objekt erzeugt und mit den benötigten Daten gefüllt, möchte man auch damit arbeiten. Die Bibliothek DAO (Data Access Objects) greift einem dabei tüchtig unter die Arme – doch das Navigieren in Datensatzgruppen und das Anlegen, Bearbeiten oder Löschen von Datensätzen gerät damit zur Fleißarbeit.

Navigieren bedeutet in Zusammenhang mit Datensatzgruppen, dass man den Datensatzzeiger auf einen der Datensätze verschiebt. Nach dem öffnen befindet sich dieser Zeiger auf dem ersten Datensatz der Datensatzgruppe – sofern diese überhaupt einen Datensatz enthält.

Leere Datensatzgruppen führen manchmal zu Problemen, also erfahren Sie zunächst, wie Sie solche zuverlässig identifizieren. Der Datensatzzeiger kann im Falle einer leeren Datensatzgruppe ja theoretisch auch auf keinen Datensatz zeigen – was sich auch bemerkbar macht, wenn man nach dem öffnen eines leeren Recordsets versucht, den Inhalt des aktuellen Datensatzes zu lesen: Dann gibt es nämlich eine Fehlermeldung.

EOF und BOF

Das Recordset-Objekt hat keine spezielle Eigenschaft, mit der Sie den “leeren” Zustand testen können. Stattdessen benötigen Sie für diese Prüfung zwei Eigenschaften, die auf den ersten Blick gar nicht danach aussehen, also ob sie das Fehlen jeglicher Datensätze bestätigen könnten. Die beiden Eigenschaften heißen EOF und BOF und liefern einen Booleschen Wert. Im Falle der Eigenschaft EOF lautet dieser Wert True, wenn sich der Datensatzzeiger hinter dem letzten Datensatz befindet, und BOF liefert True, wenn der Datensatzzeiger vor dem ersten Datensatz ins Leere zeigt.

Das ganze kann man sich wie in Bild 1 vorstellen: Im ersten Kasten zeigt der Datensatzzeiger auf den ersten Datensatz, dementsprechend haben die beiden Eigenschaften EOF und BOF den Wert False. Verschiebt man den Datensatzzeiger von dort aus eine Position nach oben (oder nach vorne, je nach Sichtweise), befindet sich dieser vor dem ersten Datensatz – die Eigenschaft BOF liefert den Wert True zurück. Befindet sich der Datensatzzeiger hinter dem letzten Datensatz, hat wiederum EOF den Wert True.

Fehlt schließlich noch die Variante mit einer leeren Datensatzgruppe: Zugegebenermaßen fällt es hier schwer, eine Datensatzposition zu beschreiben. Laut Access nimmt der Datensatzzeiger direkt beide Positionen ein, die nicht auf einem Datensatz zeigen, denn BOF und EOF haben beide den Wert True.

Bild 1: Der Datensatzzeiger an verschiedenen Positionen im gefüllten und im leeren Recordset

Eine leere Datensatzgruppe weist man dementsprechend mit den fettgedruckten Anweisungen aus Quellcode 1 nach.

Quellcode 1: Diese Routine meldet eine leere Datensatzgruppe.

Public Sub Datensatzzeiger()
    Dim db As DAO.Database
    Dim rst As DAO.Recordset
    Set db = CurrentDb
    Set rst = db.OpenRecordset( _        "Artikel_Leer", dbOpenDynaset)
    If rst.EOF And rst.BOF Then
        MsgBox "Die Datensatzgruppe ist leer."
    End If
    rst.Close
    Set rst = Nothing
    Set db = Nothing
End Sub

Hinweis

In den folgenden Codebeispielen lassen wir häufig wiederkehrende Zeilen wie die Deklaration der Objektvariablen oder deren Freigabe aus Platzgründen weg. Die vollständigen Routinen finden Sie im Modul mdlDAO2 der Beispieldatenbank.

Move!

Wenn Sie sichergestellt haben, dass Sie es nicht mit einer leeren Datensatzgruppe zu tun haben, können Sie je nach der Art des Recordsets darin navigieren. Dabei kommt es darauf an, mit welchem Parameter für den Typ des Recordsets Sie beim öffnen angeben – mehr dazu im ersten Teil dieser Beitragsreihe (Shortlink 354). In der Regel setzt man die Option dbOpenDynaset ein – Sie können den Datensatzzeiger vorwärts und rückwärts durch solche Recordsets bewegen und in den meisten Fällen die enthaltenen Daten ändern.

Verantwortlich für die passenden Schritte sind die vier Methoden MoveNext, MovePrevious, MoveLast und MoveFirst.

Dabei ist die MoveNext-Methode die populärste. Das liegt daran, dass man meist ein komplettes Recordset Datensatz für Datensatz durchläuft – und zwar von vorne nach hinten (s. Quellcode 2).

Das Durchlaufen der Datensätze erfolgt meist innerhalb einer Do While-Schleife. Deren Abbruchbedingung lautet Not rst.EOF – sprich: solange der Datensatzzeiger sich nicht hinter dem letzten Datensatz befindet. Bekanntermaßen befindet sich dieser Zeiger nach dem öffnen des Recordsets auf dem ersten Datensatz (abhängig von der gewählten Sortierung). Innerhalb der Schleife sollte man also zunächst die Anweisungen einfügen, die die gewünschten Aktionen mit dem Datensatz durchführen, und vor dem Ende der Schleife den Datensatzzeiger weiterschieben (rst.MoveNext).

Quellcode 2: Alle Datensätze eines Recordsets durchlaufen

Public Sub DatensaetzeDurchlaufen()
    ''...
    Set rst = db.OpenRecordset("Personal", _        dbOpenDynaset)
    Do While Not rst.EOF
        ''etwas mit dem Datensatz tun
        rst.MoveNext
    Loop
    ''...

Vor und zurück

Wozu benötigt man die übrigen Move…-Methoden, wenn man doch mit MoveNext schon die komplette Datensatzgruppe durchlaufen kann Zum datensatzweisen Vor- und Zurückspringen jedenfalls sehr selten. Die MoveFirst-Methode kommt hin und wieder zum Einsatz, wenn man die gleiche Datensatzgruppe gleich mehrere Male hintereinander durchlaufen möchte. Dann springt man zwischen den Durchläufen mit dieser Methode wieder an die erste Stelle (s. Quellcode 3).

Quellcode 3: Eine Datensatzgruppe zwei Mal durchlaufen

Public Sub DatensaetzeZweiMalDurchlaufen()
    ''...
    Do While Not rst.EOF
        ''etwas mit dem Datensatz tun
        rst.MoveNext
    Loop
    rst.MoveFirst
    Do While Not rst.EOF
        ''etwas mit dem Datensatz tun
        rst.MoveNext
    Loop
    ''...

Datensätze zählen

Eine weitere Einsatzmöglichkeit für die MoveLast- und die MoveFirst-Methode ist das Zählen von Datensätzen. Prinzipiell gibt es dazu zwar die RecordCount-Eigenschaft von Datensätzen, allerdings arbeitet diese anders als erwartet. Die Routine aus Quellcode 4 gibt beispielsweise nicht wie erwartet den Wert 9 als Anzahl der Personal-Datensätze aus, sondern den Wert 1.

Quellcode 4: Falsches Zählen von Datensätzen

Public Sub DatensaetzeZaehlenFalsch()
    ''...
    Set rst = db.OpenRecordset("Personal", _        dbOpenDynaset)
    Debug.Print "Anzahl Datensätze: " _        & rst.RecordCount
    ''...

Der Grund ist, dass die RecordCount-Eigenschaft nur die Datensätze zählt, auf die die Routine bereits zugegriffen hat. Im vorliegenden Fall hat die Routine auf Anhieb nur den ersten Datensatz geladen – daher das Ergebnis 1. Wenn Sie vor dem Zählen per MoveNext auf den zweiten Datensatz springen, gibt die RecordCount-Eigenschaft den Wert 2 zurück. Sie müssen also zum letzten Datensatz springen, um mit RecordCount die korrekte Anzahl Datensätze zu ermitteln – das erledigt die MoveLast-Methode. Nach dem Zählen müssen Sie wieder zum ersten Datensatz springen, um wie gewohnt mit der Datensatzgruppe arbeiten zu können (s. Quellcode 5).

Quellcode 5: Korrektes Zählen der Datensätze eines Recordsets

Public Sub DatensaetzeZaehlen()
    ''...
    Set rst = db.OpenRecordset("Personal", _        dbOpenDynaset)
    rst.MoveLast
    Debug.Print "Anzahl Datensätze: " _        & rst.RecordCount
    rst.MoveFirst
    ''etwas mit dem Datensatz tun
    ''...

Wenn das Recordset nur eine einzige Tabelle als Datenherkunft hat, können Sie die RecordCount-Eigenschaft in Verbindung mit dem Parameter acOpenTable beim öffnen der Datensatzgruppe verwenden (s. Quellcode 6).

Quellcode 6: Datensätze zählen im Table-Recordset

Public Sub DatensaetzeZaehlenTable()
    ''...
    Set rst = db.OpenRecordset("Personal", _        dbOpenTable)
    Debug.Print "Anzahl Datensätze: " _        & rst.RecordCount
    ''...

Move individuell

Neben den bereits vorgestellten Methoden via MoveFirst und MoveLast gibt es noch eine weitere Variante, um den Datensatzzeiger zu bewegen: Die Methode Move hat zwei Parameter, die genau festlegen, auf welchen Datensatz der Zeiger positioniert werden soll.

Dabei legt der erste Parameter fest, um wieviel Datensätze der Datensatzzeiger vor- oder zurückspringen soll – hier sind nur positive oder negative Ganzzahlen zulässig. Der zweite Parameter legt den Startpunkt fest – dazu später mehr.

Die Routine aus Quellcode 6 lässt den zweiten Parameter der Move-Methode leer. Daher startet sie mit dem aktuellen (also dem ersten) Datensatz und springt dann solange um je fünf Datensätze weiter, bis sie das Ende des Recordsets erreicht.

Das bedeutet, dass der jeweils aktuelle Datensatz Ausgangspunkt für die nächste Bewegung ist.

Quellcode 6: Jeden fünften Datensatz eines Recordsets anspringen

Public Sub MoveInFuenferSchritten()
    ''...
    Set rst = db.OpenRecordset("Artikel", _        dbOpenDynaset)
    Do While Not rst.EOF
        ''etwas mit dem Datensatz tun
        rst.Move 5
    Loop
    ''...

Möchte man einen bestimmten Datensatz als Ausgangspunkt für die Move-Methode verwenden, muss man den Datensatz mit einem Lesezeichen (Bookmark) versehen und dieses als zweiten Parameter der Move-Methode angeben.

Um die Bookmark-Eigenschaft eines bestimmten Datensatzes zu speichern, muss man den Datensatzzeiger aber ohnehin auf diesen Datensatz setzen – und dann kann man den Datensatzzeiger auch direkt von dort per Move weiterbewegen.

Lesezeichen

Lesezeichen machen generell nur Sinn, wenn Sie sich einen Datensatz “merken” möchten, um später, wenn der Datensatzzeiger sich längst auf einer anderen Position befindet, zu dem gemerkten Datensatz zurückzukehren.

Die Bookmark-Eigenschaft eines Recordsets liefert einen Wert zurück, den Sie etwa in einer Variant-Variablen speichern können. Um später zu dem so “gemerkten” Datensatz zurückzukehren, weisen Sie der Bookmark-Eigenschaft diesen Variant-Wert erneut zu.

Die Routine aus Quellcode 7 zeigt, wie das funktioniert. Beachten Sie:

  • Der Inhalt der Eigenschaft Bookmark stimmt nicht mit der etwa in der Datenblattansicht angezeigten Datensatznummer überein.
  • Sie können die den Wert der Eigenschaft Bookmark für beliebig viele Datensätze in passenden Variablen speichern und diese anschließend durch Zuweisen eines der gespeicherten Werte wieder ansteuern.
  • Recordsets, die Daten aus verknüpften Tabellen anderer Datenbanksysteme enthalten, unterstützen nicht unbedingt die Bookmark-Eigenschaft. Das lässt sich aber leicht mit der Eigenschaft Bookmarkable prüfen.
  • Quellcode 7: Datensatz per Bookmark merken

    Public Sub BookmarkBeispiel()
        ''...
        Set rst = db.OpenRecordset("Artikel", _        dbOpenDynaset)
        ''zu einem beliebigen Datensatz navigieren
        ''...
        ''Datensatz mit Lesezeichen merken
        varBookmark = rst.Bookmark
        ''zu einem anderen Datensatz navigieren
        ''...
        ''zum gemerkten Datensatz zurück
        rst.Bookmark = varBookmark
        ''...

    Position des Datensatzzeigers verfolgen

    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