Datensatzänderungen im Formular anzeigen

15.07.2006 von Helma  Spona
Es bleibt nicht aus, dass bei der Bearbeitung von Formulardaten versehentlich einmal Daten überschrieben werden. Um die alten Daten wiederherstellen zu können, müsste man sie kennen. Sie werden nun nicht mehr angezeigt und sind auch endgültig weg, wenn man den Datensatz wechselt. Die nachfolgende Lösung zeigt, wie Sie ein Formular so gestalten, dass dem Benutzer nach einer Änderung des Formularfeldes der alte Wert angezeigt wird.

Wenn Sie einen neuen Wert in ein Steuerelementeingeben, speichert Access den alten Wert automatisch in der Eigenschaft OldValue des Steuerelements. Das können Sie sich zunutze machen, um dem Benutzer die Möglichkeit zu geben, die alten Werte zu sehen und bei Bedarf die Änderungen rückgängig zu machen.

Vorbereitungen und Voraussetzungen

Um das zu realisieren, genügt ein Formular, das standardmäßig in der Formularansicht angezeigt wird. Sie können es einfach mit dem Assistenten erstellen oder auch manuell erzeugen.

Neben den gebundenen Formularfeldern fügen Sie dann zusätzlich für jedes Feld, dessen vorheriger Wert dem Benutzer angezeigt werden soll, ein zusätzliches Eingabefeld mit Labelfeldzur Beschriftung ein. Idealerweise sollte das Eingabefeld den gleichen Namen wie das gebundene Feld des Formulars haben, dessen alten Wert es anzeigt. Nach dem Namen geben Sie ein einheitliches Suffix oder vor dem Namen ein einheitlichesPräfix an. Heißt das gebundene Feld beispielsweise ID, könnten Sie das einzufügendeFeld IDAlt nennen. Auf diese Weise haben Sie es wesentlich einfacher, wenn Sie den Code für größere Formulare erstellen möchten.

Damit der Benutzer in die Eingabefelder nichts eingeben kann und er auch gar nicht erst auf diese Idee kommt, sollten Sie für die Eingabefelder die Rahmen- und Füllfarbe auf Transparent setzen. Dadurch wirken sie wie Labelfelder. Zusätzlich sollten Sie noch die Eigenschaften Enabled (Aktiviert) und Visible (Sichtbar) auf False setzen. Damit die Felder dann nicht deaktiviert dargestellt werden, setzen Sie noch die Eigenschaft Gesperrt auf True.

Bei Änderung die alten Werte anzeigen

Nun müssen Sie natürlich dafür sorgen, dass bei Änderung eines Wertes der alte Wert im Eingabefeld angezeigt wird. Dazu erstellen Sie für jedes gebundene Steuerelement des Formulars eine Ereignisprozedur für das Ereignis Bei Geändert (Dirty). Innerhalb der Prozedur setzen Sie dann die Visible-Eigenschaft des Steuerelements auf True und weisen ihm den Wert des gebundenen Steuerelements zu (Listing 1).

Private Sub Geburtstag_Dirty(Cancel As Integer)
Me.GeburtstagAlt.Value = Geburtstag.OldValue
Me.GeburtstagAlt.Visible = True
End Sub
Private Sub ID_Dirty(Cancel As Integer)
Me.IDAlt.Value = ID.OldValue
Me.IDAlt.Visible = True
End Sub
Private Sub Nachname_Dirty(Cancel As Integer)
Me.NachnameAlt.Value = Nachname.OldValue
Me.NachnameAlt.Visible = True
End Sub
Private Sub Vorname_Dirty(Cancel As Integer)
Me.VornameAlt.Value = Vorname.OldValue
Me.VornameAlt.Visible = True
End Sub
Private Sub Geburtstag_Change()
Me.GeburtstagAlt.Value = Geburtstag.OldValue
Me.GeburtstagAlt.Visible = True
End Sub
Private Sub ID_Change()
Me.IDAlt.Value = ID.OldValue
Me.IDAlt.Visible = True
End Sub
Private Sub Nachname_Change()
Me.NachnameAlt.Value = Nachname.OldValue
Me.NachnameAlt.Visible = True
End Sub
Private Sub Vorname_Change()
Me.VornameAlt.Value = Vorname.OldValue
Me.VornameAlt.Visible = True
End Sub

Da Access 2000 das Dirty-Ereignis noch nicht kennt, sollten Sie zusätzlich auch Ereignisprozeduren für das Change-Ereignis mit dem gleichen Inhalt erstellen, damit die Anzeige auch in Access 2000 funktioniert.

Das Formular beim Datensatzwechselzurücksetzen

Beim Datensatzwechsel müssen Sie dafür sorgen, dass die vorher eingeblendeten Steuerelemente wieder ausgeblendet werden, damit sie nur dann sichtbar werden, wenn der Benutzer im zugehörigen Feld den Wert geändert hat. Dazu erstellen Sie eine Ereignisprozedur für das Current- Ereignis (Beim Anzeigen) des Formulars (Listing 2).

Private Sub Form_Current()
Me.IDAlt.Visible = False
Me.VornameAlt.Visible = False
Me.NachnameAlt.Visible = False
Me.GeburtstagAlt.Visible = False
End Sub

Ein Button zum Wiederherstellen der alten Daten

Schön wäre es jetzt, wenn Sie dem Benutzer noch eine Möglichkeit bieten könnte, wie er die alten Daten wieder in den Datensatz schreiben kann. Dazu fügen Sie einfach einen Button mit einer entsprechenden Aufschrift in das Formular ein und erstellen dafür eine Ereignisprozedur für das Click-Ereignis (Listing 3).

Bild 1: Das Formular zur Laufzeit nach Änderung der Felder Vorname und Nachname.

Private Sub bttWiederherstellen_Click()
Me.ID.Value = Me.IDAlt.Value
Me.Vorname.Value = Me.VornameAlt.Value
Me.Nachname.Value = Me.NachnameAlt.Value
Me.Geburtstag.Value = Me.GeburtstagAlt.Value
End Sub

Den Code optimieren

Der hier vorgestellte Code ist zwar korrekt und funktioniert, für Formulare mit sehr vielen Steuerelementen ist er jedoch sehr aufwändig zu erstellen, und es sind viele Anpassungen notwendig, wenn Sie Steuerelemente umbenennen, aus dem Formular löschen oder neue hinzufügen. Für komplexere Formulare ist es daher sinnvoller, die Steuerelemente in Schleifen zu bearbeiten (Listing 4). Sie benötigen dazu je eine Prozedur

Sub ausblenden(strSuffix As String, strPraefix As String)
Dim objContr As Control
Dim bytSuff As Byte
Dim lngI As Long
bytSuff = Len(strSuffix)
For lngI = 1 To Me.Controls.Count
On Error Resume Next
Set objContr = Me.Controls(lngI)
If (strSuffix <> "") Then
If Mid(objContr.ControlName, Len(objContr.ControlName) - _
bytSuff + 1) = strSuffix Then
'Name endet mit Suffix
objContr.Visible = False
End If
ElseIf (strPraefix <> "") Then
If InStr(1, objContr.ControlName, strPraefix) = 1 Then
'Name beginnt mit Präfix
objContr.Visible = False
End If
End If
Next lngI
End Sub
Sub einblenden(strSuffix As String, strPraefix As String)
Dim objContr As Control
Dim bytSuff As Byte
Dim lngI As Long
Dim strName As String
bytSuff = Len(strSuffix)
Dim strSuffixTemp As String
Dim strPraefixTemp As String
For lngI = 0 To Me.Controls.Count
On Error Resume Next
Set objContr = Me.Controls(lngI)
strSuffixTemp = Mid(objContr.ControlName, _
Len(objContr.ControlName) - bytSuff + 1)
strPraefixTemp = Mid(objContr.ControlName, 1, Len(strPraefix))
If ((strSuffix <> "") Or (strPraefix <> "")) Then
If (strSuffix <> "") And (strSuffixTemp <> strSuffix) Then
'Name endet nicht mit Suffix und beginnt nicht mit Präfix
'Prüfen, ob der alte Wert vom aktuellen abweicht
If objContr.Value <> objContr.OldValue Then
'Alten Wert anzeigen
strName = objContr.ControlName & strSuffix
Me.Controls(strName).Value = objContr.OldValue
Me.Controls(strName).Visible = True
Else
Me.Controls(strName).Visible = False
End If
ElseIf (strPraefix <> "") And ((strPraefixTemp <> strPraefix) _
And (strPraefixTemp <> "")) Then
If objContr.Value <> objContr.OldValue Then
strName = strPraefix & objContr.ControlName
'Alten Wert anzeigen
Me.Controls(strName).Value = objContr.OldValue
Me.Controls(strName).Visible = True
Else
Me.Controls(strName).Visible = False
End If
End If
End If
Next lngI
End Sub
Sub wiederherstellen(strSuffix As String, strPraefix As String)
Dim objContr As Control
Dim bytSuff As Byte
Dim lngI As Long
Dim strName As String
bytSuff = Len(strSuffix)
Dim strSuffixTemp As String
Dim strPraefixTemp As String
For lngI = 0 To Me.Controls.Count
On Error Resume Next
Set objContr = Me.Controls(lngI)
strSuffixTemp = Mid(objContr.ControlName, _
Len(objContr.ControlName) - bytSuff + 1)
strPraefixTemp = Mid(objContr.ControlName, 1, Len(strPraefix))
If ((strSuffix <> "") Or (strPraefix <> "")) Then
If (strSuffix <> "") And (strSuffixTemp <> strSuffix) Then
'Name endet nicht mit Suffix und beginnt nicht mit Präfix
'Prüfen, ob der alte Wert vom aktuellen abweicht
If objContr.Value <> objContr.OldValue Then
'Alten Wert wiederherstellen
strName = objContr.ControlName & strSuffix
objContr.Value = Me.Controls(strName).Value
Me.Controls(strName).Visible = True
Else
Me.Controls(strName).Visible = False
End If
ElseIf (strPraefix <> "") And ((strPraefixTemp <> _
strPraefix) And (strPraefixTemp <> "")) Then
If objContr.Value <> objContr.OldValue Then
strName = strPraefix & objContr.ControlName
'Alten Wert wiederherstellen
objContr.Value = Me.Controls(strName).Value
Me.Controls(strName).Visible = True
Else
Me.Controls(strName).Visible = False
End If
End If
End If
Next lngI
End Sub

Sichtbar machen der alten Werte

Beiden Prozeduren übergeben Sie das für den Dateinamen verwendete Präfix oder Suffix. Innerhalb einer For-Schleife, die alle Steuerelemente durchläuft, prüfen Sie in einer Verzweigung, ob der Name des Steuerelements, den Sie über die ControlName-Eigenschaft abfragen können, mit dem Präfix beginnt oder mit dem Suffix endet. Ist das der Fall, blenden Sie das Steuerelement über die Visible-Eigenschaft aus.

In der Prozedur anzeigen, die dazu dient, die alten Werte sichtbar zu machen, müssen Sie hingegen nur die Steuerelemente durchlaufen, deren Name weder mit dem Präfix beginnt noch mit dem Suffix endet. Für diese Steuerelemente prüfen Sie, ob die OldValue-Eigenschaft einen anderen Wert als die Value-Eigenschaft hat. Falls ja, weisen Sie dem entsprechenden Steuerelement mit dem Präfix und Suffix im Namen den alten Wert zu und blenden es ein.

Die Prozedur wiederherstellen unterscheidet sich nur in wenigen Anweisungen. Statt dem ungebundenen Textfeld den alten Wert des gebundenen Feldes zuzuweisen, wird dem gebundenen Feld der Inhalt des ungebundenen zugewiesen, um den alten Wert wieder herzustellen.

Nun fehlt noch der Aufruf der drei Prozeduren. Das ist im Prinzip ganz einfach. Allerdings sollten Sie für die einzelnen Steuerelemente Ereignisprozeduren für das Exit-Ereignis erstellen. Im Unterschied zum vorherigen Code wird der alte Wert nämlich nur dann dem ungebundenen Steuerelement zugewiesen, wenn der Wert vom alten Wert abweicht. Der Wert wird aber immer erst dann geändert, wenn das Steuerelement nach der Eingabe verlassen wird. Solange es nach der Eingabe den Fokus behält, trifft diese Bedingung daher nicht zu.

Private Sub bttWiederherstellen_Click()
wiederherstellen "Alt", ""
End Sub
Private Sub Form_Current()
ausblenden "Alt", ""
End Sub
Private Sub Geburtstag_Exit(Cancel As Integer)
einblenden "Alt", ""
End Sub
Private Sub ID_Exit(Cancel As Integer)
einblenden "Alt", ""
End Sub
Private Sub Nachname_Exit(Cancel As Integer)
einblenden "Alt", ""
End Sub
Private Sub Vorname_Exit(Cancel As Integer)
einblenden "Alt", ""
End Sub