Warum noch ein Access-Buch?
Für wen ist das Buch?
Jetzt bestellen
+ direkter Download des eBooks!
Nur EUR 59,95!
Fehler gefunden?
Bitte melden!
Wünsche an das Buch?
Her damit!
Was denken die Leser über dieses Buch?
Lesen Sie aktuelle Rezensionen!
Kapitel des noch nicht veröffentlichten Buchs zum Downloaden, Probelesen und Kommentieren
Beispieldatenbanken
Zusätzliches Material

Das Buch im HTML-Format

Für unbestimmte Zeit bieten Addison-Wesley und André Minhorst den kompletten Inhalt des Buchs als Download an. Schauen Sie rein und informieren Sie sich über den Inhalt! Und wenn Ihnen das Buch nützlich erscheint und Sie glauben, dass Sie etwas gelernt haben oder durch das Gelesene sogar etwas Zeit und somit Geld bei Ihrer Arbeit einsparen konnten, können Sie sich ja beim Autor und beim Verlag revanchieren - beispielsweise durch den Kauf dieses Buchs.

Am schönsten wäre es natürlich, wenn Sie das Buch direkt hier bestellen - Sie erhalten das Buch dann direkt vom Verlag, und der Autor und Verlag haben dann noch mehr davon, als wenn Sie es anderswo kaufen.

Danke für Ihr Interesse!

4.7.1 Eingabe von Daten ohne Detaildatensatz

4.7.2 Undo in Haupt- und Unterformular

Viele Formulare zeigen nicht nur selbst Daten an, sondern enthalten auch noch ein Unterformular zur Bearbeitung von Daten aus verknüpften Tabellen. Wie in gebundenen Formularen üblich, gilt auch hier: Wechselt man den Datensatz, wird er auch in der zugrunde liegenden Tabelle gespeichert. Bis dahin lassen sich Änderungen am aktuell bearbeiteten Datensatz noch relativ leicht durch Auslösen des Undo-Ereignisses rückgängig machen, etwa durch Betätigen der Esc-Taste.

Viele Formulare enthalten eine Implementierung einer Undo-Funktion in Form einer Abbrechen-Schaltfläche. Den unbedarften Benutzer täuscht man freilich damit, denn diese Schaltfläche macht lediglich die Änderungen an dem im Hauptformular angezeigten Datensatz rückgängig. Die Änderungen im Unterformular sind und bleiben gespeichert.

Abbildung 4.59 zeigt, wie solch ein Formular aussieht. Es handelt sich um das bereits weiter oben hergeleitete Formular mit zunächst zwei (sichtbaren) Erweiterungen: einer OK- und einer Abbrechen-Schaltfläche.

Abbildung 4.59: Formular mit Unterformular und Abbrechen-Funktion (»frmProjektzeiten_Undo«)

Der Code, der durch das Beim Klicken-Ereignis der jeweiligen Schaltfläche ausgelöst wird, sieht etwa wie folgt aus:

Private Sub cmdOK_Click()

    'Formular schließen
    DoCmd.Close acForm, Me.Name

End Sub

Private Sub cmdAbbrechen_Click()

    'Prüfen, ob Datensatz seit letzter Speicherung geändert wurde
    If Me.Dirty = True Then
        'Falls ja, Änderungen rückgängig machen
        Me.Undo
    End If

    'Formular schließen
    DoCmd.Close acForm, Me.Name

End Sub

Listing 4.30: Ereignisprozeduren der OK- und der Abbrechen-Schaltfläche

Eine Änderung im Unterformular wird auf jeden Fall gespeichert, da das Verlassen des Unterformulars das Speichern des aktuellen Datensatzes zur Folge hat.

Wenn Sie nun einmal eine Korrektur an den Projektzeiten eines Projekts vornehmen und dabei aus Versehen einige Datensätze löschen, weil Sie sich in einem anderen Projekt wähnten, gibt es keine Undo-Funktion: Solche Änderungen führen Sie ohne Netz und doppelten Boden aus.

In den folgenden Abschnitten erfahren Sie, wie Sie den Benutzern Ihrer Datenbank (und vielleicht auch sich selbst) das Leben in dieser Hinsicht erleichtern können. Dabei machen Sie Gebrauch von einer Transaktion, die bei der ersten Änderung an einem Datensatz des Hauptformulars oder der verknüpften Datensätze im Unterformular gestartet und mit Speichern des Datensatzes im Hauptformular (etwa durch Betätigen der OK-Schaltfläche oder den Wechsel zu einem anderen Datensatz) beendet wird - was zum endgültigen Speichern der Änderungen im Haupt- und Unterformular führt. Auch die Abbrechen-Schaltfläche kann die Transaktion beenden - allerdings sollen dabei alle seit Beginn der Transaktion durchgeführten Änderungen verworfen werden.

Normalerweise ist eine Transaktion ein gängiges Mittel, um mehrere Datenbankoperationen zu bündeln und je nach Verlauf der Operationen komplett durchzuführen oder zu verwerfen. Das kann doch bei den Aktionen innerhalb eines Formulars nicht viel anders sein: Also startet man die Transaktion einfach beim Öffnen des Formulars und beendet sie mit Betätigen der OK- oder der Abbrechen-Schaltfläche. Oder doch nicht? Nein, ganz so einfach ist es nicht. Access führt nämlich die in Zusammenhang mit gebundenen Formularen anfallenden Datenbankzugriffe nicht im Kontext des aktuellen Workspace aus. Wenn Sie also einen Datensatz ändern und speichern, bekommt die Transaktion davon überhaupt nichts mit.

Abhilfe schafft überhaupt erst die mit Access 2000 eingeführte Recordset-Eigenschaft von Formularen. Damit lässt sich ein Formular an ein zuvor erstelltes Recordset-Objekt binden, das wiederum sehr wohl unter die Kontrolle einer Transaktion fallen kann.

Es sind also folgende Maßnahmen für die Verwendung einer Transaktion zur Zusammenfassung von Datenbankoperationen in einem Formular mit Unterformular notwendig:

  • Binden des Haupt- und des Unterformulars an Recordset-Objekte
  • Starten der Transaktion beim Ändern des Datensatzes im Hauptformular oder in einem der verknüpften Datensätze im Unterformular
  • Durchführen der Transaktion beim Klick auf die OK-Schaltfläche oder beim Wechseln des Datensatzes im Hauptformular
  • Verwerfen der Operationen der Transaktion beim Betätigen der Abbrechen-Schaltfläche
  • Die letzten beiden Punkte setzen voraus, dass die entsprechenden Prozeduren Informationen über den aktuellen Status haben - ist bereits eine Transaktion gestartet worden und wurde diese bereits beendet? Diese Information muss vom Haupt- und vom Unterformular aus schreib- und lesbar sein, da Datenbankoperationen in beiden Formularen eine Transaktion in Gang setzen können.

    Das ist deshalb wichtig, weil das Beenden einer Transaktion, die noch nicht gestartet wurde, zu einem Fehler führt. Genauso wichtig ist es, keine zweite Transaktion zu starten, wenn bereits eine Transaktion gestartet wurde. Dies würde als »verschachtelte« Transaktion gewertet werden; die Betätigung der OK- oder Abbrechen-Schaltfläche würde möglicherweise nur die innere von mehreren verschachtelten Transaktionen beenden und zu einem unvorhersehbaren Ergebnis führen.

    Öffentliche Variablen für den Transaktionsstatus

    Es gibt mehrere Möglichkeiten, den Status bezüglich der Transaktion zu speichern und in Haupt- und Unterformular zugänglich zu machen. Globale Variablen verwendet man besser nicht, da diese allzu leicht von einer anderen Stelle aus geändert werden können. Besser ist die Verwendung von Membervariablen in einem der beiden Formulare und ihre Veröffentlichung über entsprechende Property-Prozeduren.

    Der folgende Quellcode zeigt, wie der Kopf des Klassenmoduls des Hauptformulars aussieht:

    Option Compare Database
    Option Explicit

    Dim mDirtyForm As Boolean
    Dim mDeletedForm As Boolean
    Dim db As DAO.Database
    Dim wrk As DAO. Workspace

    Public Property Get DirtyForm() As Boolean
        DirtyForm = mDirtyForm
    End Property

    Public Property Let DirtyForm(bolDirtyForm As Boolean)
        mDirtyForm = bolDirtyForm
    End Property

    Listing 4.31: Kopf des Klassenmoduls des Formulars frmProjektzeiten_Undo

    Die Eigenschaft mDirtyForm machen Sie durch die nachfolgenden Property-Prozeduren von außerhalb schreib- und lesbar. Auf diese Weise können Sie auf die wichtigen Informationen über den Zustand der Transaktion vom Haupt- und auch vom Unterformular aus zugreifen.

    Die Verwendung von Property Get- und Property Let-Prozeduren ist ein kleiner Vorgriff auf Kapitel 15, »Objektorientierte Programmierung«. Weitere Informationen über die Verwendung dieser Prozeduren finden Sie in diesem Kapitel.

    Recordset-Objekt als Datensatzquelle

    Weiter oben wurde bereits erwähnt, dass Transaktionen von den Vorgängen im Formular und im Unterformular nur etwas mitbekommen, wenn die Datensatzquelle ein Recordset-Objekt ist.

    Für das Hauptformular weisen Sie diese Eigenschaft am besten direkt beim Öffnen zu. Die Prozedur, die durch die Ereigniseigenschaft Beim Öffnen ausgelöst wird, hat folgendes Aussehen:

    Private Sub Form_Open(Cancel As Integer)

        'Recordset-, Database- und Workspace-Objekt deklarieren
        Dim rst As DAO.Recordset
        Set db = DBEngine(0)(0)
        Set wrk = DBEngine.Workspaces(0)

        'Recordset-Objekt öffnen...
        Set rst = db.OpenRecordset("tblProjekte", dbOpenDynaset)

        '...und der entsprechenden Eigenschaft des Formulars zuweisen
        Set Me.Recordset = rst

    End Sub

    Listing 4.32: Ereignisprozedur Form_Open des Hauptformulars frmProjektzeiten_Undo

    Da Sie dem Formular nun dynamisch die Datensatzquelle zuweisen, können Sie die Eigenschaft Datensatzquelle leeren. Wichtig ist, dass die Felder weiterhin an die entsprechenden Felder der Datensatzquelle gebunden sind. Anderenfalls können diese natürlich nicht die gewünschten Daten anzeigen.

    Neben dem Zuweisen der Datensatzquelle per Recordset-Eigenschaft ist die Deklaration des Workspace-Objekts wrk die zweite Besonderheit in dieser Prozedur. Ein Workspace-Objekt können Sie anschaulich als Arbeitsbereich betrachten, in dem die aktuelle Access-Sitzung abläuft.

    Kein neues Formular-Recordset während einer Transaktion

    Wenn eine Transaktion einmal gestartet ist, können Sie dem Formular kein neues Recordset-Objekt zuweisen. Diese Regel bedeutet kein besonderes Problem, da Formular und Unterformular durchaus vor der ersten Änderung der Daten und damit dem Starten der Transaktion mit den benötigten Recordsets versehen werden können.

    Es ergibt sich nur eine Einschränkung: Sie können während einer Transaktion nicht den Datensatz im Hauptformular wechseln. Warum nicht? Weil bei der Anzeige eines neuen Datensatzes im Hauptformular auch die im Unterformular angezeigten Daten aktualisiert werden müssen. Und das geht wiederum nur durch das Zuweisen eines neuen Recordsets, das die mit dem Datensatz im Hauptformular korrespondierenden Daten enthält.

    Das ist aber nicht schlimm, denn dass beim Wechseln des Datensatzes die Daten des vorherigen Datensatzes gespeichert werden, sollte dem Benutzer klar sein. Die technische Umsetzung indes ist nicht ganz einfach. Fest steht nur, dass beim Wechsel des Datensatzes, der das Ereignis Beim Anzeigen des Hauptformulars auslöst, dem Unterformular ein neues Recordset zugewiesen werden muss. Um den Rest kümmern Sie sich später. Die Prozedur Form_Current sieht nun folgendermaßen aus:

    Private Sub Form_Current()

        Dim strSQL As String
        Dim rst As DAO.Recordset

        'Zusammenstellen des SQL-Strings für das Recordset    
        strSQL = "SELECT tblProjektzeiten.ProjektID, " _
            & "tblProjektzeiten.ProjektzeitID, " _
            & "tblProjektzeiten.MitarbeiterID, " _
            & "tblProjektzeiten.Datum, " _
            & "tblProjektzeiten.Zeit, " _
            & "tblMitarbeiter.Telefon " _
            & "FROM tblProjektzeiten INNER JOIN tblMitarbeiter " _
            & "ON tblProjektzeiten.MitarbeiterID = " _
            & " tblMitarbeiter.MitarbeiterID " _
            & "WHERE ProjektID = " & Nz(Me!ProjektID, 0)

            'Öffnen des Recordset
            Set rst = db.OpenRecordset(strSQL, dbOpenDynaset)

            'Zuweisen des Recordset an das Unterformular
            Set Me!sfmProjektzeiten_Undo.Form.Recordset = rst

    End Sub

    Listing 4.33: Quellcode der Prozedur Form_Current des Hauptformulars

    Alternativ können Sie auch die gespeicherte Abfrage qryProjektzeitenMitarbeiter verwenden (siehe Abbildung 4.44). Die Prozedur sähe dann folgendermaßen aus:

    Private Sub Form_Current()

        Dim rst As DAO.Recordset

        'Öffnen des Recordset
        Set rst = db.OpenRecordset("SELECT * FROM " _
            & "qryProjektzeitenMitarbeiter WHERE ProjektID = " _
            & Nz(Me!ProjektID, 0), dbOpenDynaset)

        'Zuweisen des Recordset an das Unterformular
        Set Me!sfmProjektzeiten_Undo.Form.Recordset = rst

    End Sub

    Listing 4.34: Vereinfachte und performantere Version der Prozedur Form_Current

    Dadurch, dass die im Unterformular angezeigten Datensätze ohnehin nach dem im Hauptformular angezeigten Projekt gefiltert werden, sind die beiden Eigenschaften Verknüpfen von und Verknüpfen nach im Unterformularsteuerelement nicht mehr notwendig. Leeren Sie also diese beiden Eigenschaften. Dadurch müssen Sie beim Anlegen neuer Datensätze im Unterformular dafür sorgen, dass diese Datensätze irgendwie mit der ProjektID des Datensatzes im Hauptformular versehen werden. Dazu jedoch später mehr.

    Sie kommen trotzdem nicht umhin, dafür zu sorgen, dass keine Datensätze im Unterformular angelegt werden, ohne dass sich ein Datensatz im Hauptformular befindet. Dazu können Sie die Routine aus Listing 4.29 verwenden.

    Transaktionen in Formularen

    Nun geht es an das eigentliche Problem: Das Einfassen von Änderungen im Haupt- und Unterformular in eine Transaktion, um getätigte Änderungen für Haupt- und Unterformular komplett revidieren zu können. Dazu veranschaulichen Sie sich zunächst, welche Datensatzänderungen überhaupt berücksichtigt werden müssen, und leiten davon ab, in welchen Ereignisprozeduren die Transaktion gestartet, durchgeführt oder abgebrochen wird.

  • Hinzufügen eines Datensatzes im Hauptformular: löst Form_Dirty im Hauptformular aus.
  • Ändern eines Datensatzes im Hauptformular: löst Form_Dirty im Hauptformular aus.
  • Löschen eines Datensatzes im Hauptformular: kann nicht rückgängig gemacht werden, da das Formular unmittelbar nach dem Löschen auf einen anderen Datensatz springt.
  • Hinzufügen eines Datensatzes im Unterformular: löst Form_Dirty im Unterformular aus.
  • Ändern eines Datensatzes im Unterformular: löst Form_Dirty im Unterformular aus.
  • Löschen eines Datensatzes im Unterformular: löst Form_Delete im Unterformular aus.
  • Damit stehen bereits die Ereignisse fest, die eine Transaktion starten sollen. Schauen Sie sich die dadurch ausgelösten Prozeduren an. Den Anfang macht die Prozedur Form_Dirty des Hauptformulars:

    Private Sub Form_Dirty(Cancel As Integer)

        'Wenn aktueller Datensatz noch nicht geändert...
        If Me. DirtyForm = False Then
            'Eigenschaft DirtyForm auf True setzen
            Me.DirtyForm = True
            'Transaktion starten
            wrk. BeginTrans
        End If

    End Sub

    Listing 4.35: Start einer Transaktion beim Ändern oder Hinzufügen eines Datensatzes im Hauptformular

    Im Unterformular muss die Prozedur Form_Dirty noch ein wenig mehr leisten. Sie sorgt nicht nur dafür, dass im Falle der ersten Änderung die Transaktion gestartet und die Eigenschaft DirtyForm des Hauptformulars auf True gesetzt wird. Zusätzlich prüft sie, ob es sich bei der Änderung um einen neuen Datensatz handelt. Wie weiter oben erwähnt, sind Haupt- und Unterformular nicht über die entsprechenden Werte für die Eigenschaften Verknüpfen von und Verknüpfen nach miteinander verknüpft.

    Der Wert des Verknüpfungsfeldes ProjektID wird nicht automatisch gefüllt. Die Prozedur übernimmt daher auch diese Aufgabe und weist dem Feld ProjektID des Unterformulars den entsprechenden Wert des Hauptformulars zu.

    Damit im Unterformular überhaupt eine Transaktion gestartet werden kann, sind noch einige Zeilen Code notwendig. So befindet sich im Modulkopf neben den obligatorischen Zeilen noch die Deklaration des Workspace-Objekts für das Unterformular:

    Option Compare Database
    Option Explicit
    Dim wrk As DAO.Workspace

    Dieses stellt das Form_Open-Ereignis des Unterformulars auf den gleichen Workspace wie im Hauptformular ein:

    Private Sub Form_Open(Cancel As Integer)
        Set wrk = DBEngine.Workspaces(0)
    End Sub

    Listing 4.36: Zuweisen des Workspace-Objekts

    Die Prozedur Form_Dirty ist eine von zwei Prozeduren, die vom Unterformular aus eine Transaktion starten können:

    Private Sub Form_Dirty(Cancel As Integer)

        'Wenn es sich um einen neuen Datensatz handelt,
        'Wert für die Herstellung der Verknüpfung über das
        'Feld ProjektID zuweisen
        If Me. NewRecord Then
            Me!ProjektID = Me. Parent!ProjektID
        End If

        'Wenn noch keine Änderung im Haupt- oder Unterformular
        'vorliegt, DirtyForm auf True setzen und Transaktion starten
        If Me.Parent. DirtyForm = False Then
            Me.Parent.DirtyForm = True
            wrk.BeginTrans
        End If

    End Sub

    Listing 4.37: Form_Dirty-Prozedur des Unterformulars sfmProjektzeiten_Undo

    Die Prozedur, die durch die Beim Löschen-Eigenschaft des Unterformulars ausgelöst wird, muss sich nicht um die ProjektID scheren. Sie startet lediglich die Transaktion, falls dies noch nicht geschehen ist:

    Private Sub Form_Delete(Cancel As Integer)

        'Wenn noch keine Änderung im Haupt- oder Unterformular...
        If Me.Parent.DirtyForm = False Then
            Me.Parent.DirtyForm = True
            wrk.BeginTrans
        End If

    End Sub

    Listing 4.38: Die Prozedur Form_Delete startet gegebenenfalls eine Transaktion

    Abbrechen der Transaktion

    Das Abbrechen der Transaktion erreichen Sie durch Betätigen der Abbrechen-Schaltfläche. Die dadurch ausgelöste Prozedur prüft, ob Änderungen im Haupt- oder Unterformular durchgeführt wurden und damit eine Transaktion gestartet wurde. Falls ja, werden die Änderungen durch die Rollback-Methode des Workspace-Objekts wieder verworfen.

    Private Sub cmdAbbrechen_Click()

        'Prüfen, ob Daten geändert wurden
        If Me.DirtyForm = True Then
            'Transaktion abbrechen
            wrk. Rollback
        End If

        'Formular schließen
        DoCmd.Close acForm, Me.Name

    End Sub

    Listing 4.39: Die Abbrechen-Schaltfläche verwirft alle Änderungen der aktuellen Daten des Haupt- und Unterformulars

    Durchführen der Transaktion

    Die Durchführung der Transaktion erfolgt durch Speichern des Datensatzes im Hauptformular. Dazu gibt es zum Beispiel folgende Möglichkeiten:

  • Schließen des Formulars mit der OK-Schaltfläche
  • Wechseln zu einem anderen Datensatz im Hauptformular
  • Schließen des Formulars auf anderem Wege (beispielsweise Betätigen des Schließen-Buttons oben rechts im Formular)
  • In diesem Beispiel werden nur die beiden ersten Möglichkeiten zum Speichern eines Datensatzes beschrieben. Zum Schließen des Formulars mit der OK-Schaltfläche ist die Prozedur verantwortlich, die durch das Ereignis Beim Klicken der Schaltfläche ausgelöst wird. Die Prozedur prüft anhand der Eigenschaft DirtyForm, ob überhaupt Änderungen im Haupt- oder Unterformular durchgeführt wurden und dementsprechend eine Transaktion gestartet wurde. Falls ja, schließt sie die Transaktion mit der Methode CommitTrans ab.

    Private Sub cmdOK_Click()

        'Speichern der Änderungen
        DoCmd.RunCommand acCmdSaveRecord

        'Wenn Änderungen vorliegen und damit eine
        'Transaktion gestartet wurde:
        If Me.DirtyForm = True Then
            'Transaktion durchführen
            wrk. CommitTrans
        End If

        'Formular schließen
        DoCmd.Close acForm, Me.Name

    End Sub

    Listing 4.40: Das Schließen des Formulars mit der OK-Schaltfläche bewirkt die Durchführung der Transaktion

    Der Wechsel zu einem anderen Datensatz im Formular löst das Ereignis Beim Anzeigen aus. Die erste Version dieser Prozedur (siehe Listing 4.33) sieht noch keine Funktion zum Abschließen einer Transaktion vor. Die folgende Variante holt dies nach:

    Private Sub Form_Current()

        'Wenn Daten geändert und Transaktion gestartet...
        If Me.DirtyForm = True Then
            'aktuellen Datensatz speichern
            DoCmd.RunCommand acCmdSaveRecord
            'Transaktion durchführen
            wrk.CommitTrans
            'Formular als "gespeichert" kennzeichnen
            Me.DirtyForm = False
        End If

        If mDeletedForm = False Then

            'Prozedur zum Aktualisieren des Unterformulars aufrufen
            UnterformularAktualisieren
        Else
            mDeletedForm = False
        End If

    End Sub

    Listing 4.41: Abschließen der Transaktion beim Datensatzwechsel im Hauptformular

    Die eigentliche Funktionalität zum Aktualisieren der Datensatzquelle des Unterformulars wird dabei in eine eigene Prozedur ausgegliedert, weil diese noch von einer weiteren Ereignisprozedur aufgerufen werden soll:

    Private Sub UnterformularAktualisieren()

        Dim strSQL As String
        Dim rst As DAO.Recordset

        'Zusammenstellen des SQL-Strings
        strSQL = "SELECT * FROM qryProjektzeitenMitarbeiter " _
            & "WHERE ProjektID = " & Nz(Me!ProjektID, 0)

        'Öffnen des Recordset
        Set rst = db.OpenRecordset(strSQL, dbOpenDynaset)

        'Zuweisen des Recordset an das Unterformular
        Set Me!sfmProjektzeiten_Undo.Form.Recordset = rst

    End Sub

    Listing 4.42: Prozedur zum Aktualisieren des Unterformulars

    Löschen des aktuellen Datensatzes im Hauptformular

    Bleibt noch ein Problem: Wenn Sie den aktuell im Hauptformular angezeigten Datensatz löschen möchten, erscheint der Fehler aus Abbildung 4.60. Das Merkwürdige ist, dass beim Löschen gar keine Transaktion per VBA gestartet wurde - woher kommt nun diese Transaktion? Offensichtlich schließt Access den Löschvorgang automatisch in eine Transaktion ein. Normalerweise würden Sie davon gar nichts mitbekommen, da innerhalb dieser Transaktion keine unerlaubten Aktionen erfolgen wie das hier bemängelte Zuweisen eines Recordset-Objekts an die entsprechende Eigenschaft.

    Hier liegt der Fall anders und bei genauer Betrachtung des Ablaufs der Ereignisse beim Löschen eines Datensatzes wird Einiges klarer. Die Ereignisse haben folgende Reihenfolge:

  • Form_Delete
  • Form_Current
  • Form_BeforeDelConfirm
  • Form_AfterDelConfirm
  • Dabei werden die beiden letzten Ereignisse nur ausgelöst, wenn die Einstellung Erweitert|Bearbeiten|Bestätigen|Datensatzänderungen in den Access-Optionen aktiviert ist.

    Abbildung 4.60: Fehler beim Löschen des Datensatzes im Hauptformular

    Wichtig ist zunächst, dass nach dem Delete-Ereignis der zu löschende Datensatz beziehungsweise die zu löschenden Datensätze zunächst temporär gespeichert werden, bis feststeht, dass der Löschvorgang nicht durch das Ereignis Vor Löschbestätigung des Formulars abgebrochen wird. Und genau dieses temporäre Speichern erledigt die Transaktion, die sich nicht mit dem Zuweisen des Recordset-Objekts zum Unterformular verträgt.

    Das Problem lösen Sie, indem Sie den Zeitpunkt der Zuweisung des Recordset-Objekts einfach nach hinten verschieben - vom Form_Current- ins Form_AfterDelConfirm-Ereignis. Dazu verwenden Sie die folgenden Prozeduren.

    Die Prozedur Form_Delete stellt die Eigenschaft mDeletedForm auf den Wert True ein. Diese Eigenschaft wird in der Prozedur Form_Current ausgewertet; wenn sie den Wert True enthält, wird das Aktualisieren des Unterformulars unterbunden (siehe auch Listing 4.41).

    Private Sub Form_Delete(Cancel As Integer)
        mDeletedForm = True
    End Sub

    Listing 4.43: Setzen einer Eigenschaft, an der andere Prozeduren den laufenden Löschvorgang erkennen können

    Die Prozedur Form_BeforeDelConfirm können Sie theoretisch auch weglassen. In diesem Fall unterbindet sie die Standardmeldung von Access beim Löschen des Datensatzes (siehe Abbildung 4.61).

    Private Sub Form_BeforeDelConfirm(Cancel As Integer, Response As Integer)
        Response = acDataErrContinue
    End Sub

    Listing 4.44: Verhindern der Rückfrage beim Löschen

    Abbildung 4.61: Standardmeldung von Access beim Löschen von Daten

    Die Prozedur Form_AfterDelConfirm ist wiederum sehr wichtig: Sie wird nur ausgelöst, wenn Sie wie in Listing 4.42 die Access-Meldung unterbinden oder wenn Sie den Löschvorgang im Fall der Anzeige bestätigen. Die Prozedur ruft die Routine auf, die das Unterformular aktualisiert, und holt damit genau den Vorgang nach, der durch Setzen der Variablen mDeletedForm im Form_Current-Ereignis unterbunden wurde.

    Private Sub Form_AfterDelConfirm(Status As Integer)
        UnterformularAktualisieren
    End Sub

    Listing 4.45: Aktualisieren des Unterformulars nach vollendetem Löschvorgang

    Restarbeiten

    Damit das Beispiel wie beschrieben funktioniert, brauchen Sie lediglich die Eigenschaften der Beziehungen zwischen den im Haupt- und Unterformular angezeigten Tabellen so anzupassen, dass beim Löschen des Datensatzes im Hauptformular direkt die entsprechenden Unterformulareinträge mitgelöscht werden. Dazu reicht das Setzen der Eigenschaft Löschweitergabe an verwandte Datensätze im Eigenschaftsfenster der passenden Beziehung (siehe Abbildung 4.62).

    Einsatz in eigenen Formularen

    Dem Einsatz dieser Technik in Ihren eigenen Formularen steht prinzipiell nichts im Wege. Sie müssen lediglich alle in den beiden Formularmodulen enthaltenen Deklarationen und Prozeduren in Ihre Formulare übertragen und einige Zeilen Code den Gegebenheiten Ihrer eigenen Datenbank anpassen - etwa die Datenherkünfte für Haupt- und Unterformular und die Zeile, die beim Anlegen eines neuen Datensatzes im Unterformular den Wert für den Fremdschlüssel festlegt (siehe Listing 4.35).

    Abbildung 4.62: Aktivieren der Löschweitergabe zwischen verknüpften Tabellen

    Nächster Abschnitt:

    4.8 Eingabe validierung

    © 2006-2008 André Minhorst Alle Rechte vorbehalten.