Home > Artikel > Ausgabe 8/2011 > Fehlerbehandlung in Formularen

Fehlerbehandlung in Formularen

Achtung: Sie sind nicht angemeldet. Wenn Sie Abonnent sind und sich anmelden, lesen Sie den kompletten Artikel, laden das PDF herunter oder probieren die Beispieldatenbank aus (sofern vorhanden).

In den Artikeln Fehler unter VBA und Fehlerbehandlung unter VBA (Teil I und II) haben Sie fast schon alles über Fehler und ihre Behandlung erfahren. Es gibt jedoch ein paar Fälle, in denen zwar Fehlermeldungen erscheinen, Sie aber keine Chance haben, auf diese zu reagieren. Dies geschieht beispielsweise, wenn Sie per Formular einen Wert zwei Mal in ein Feld mit eindeutigem Index eingeben. In diesem Artikel erfahren Sie, wie Sie solche Fehler ebenfalls abfangen und eine eigene Fehlerbehandlung dafür implementieren – gegebenenfalls auch mit benutzerdefinierter Fehlermeldung.

Beispieldatenbank

Die Beispiele dieses Artikels finden Sie in der Datenbank 11_08_FehlerbehandlungInFormularen.mdb.

Benutzerdefinierte Fehlermeldungen

Nichts ist ärgerlicher, als wenn der Benutzer einer Anwendung Fehlermeldungen angezeigt bekommt, die er nicht interpretieren kann, weil diese schlicht nicht aussagekräftig genug ist. In solchen Fällen sollten Sie immer eine benutzerdefinierte Meldung bereithalten und entsprechend auf den Fehler reagieren (gegebenenfalls gelingt dies ja auch, ohne dass der Benutzer überhaupt eine Fehlermeldung zu Gesicht bekommt ...). Wie Sie dies für Fehler durchführen, die durch VBA-Anweisungen in den Ereignisprozeduren ausgelöst werden, erfahren Sie unter Fehlerbehandlung unter VBA und Fehlerbehandlung in der Praxis.

Die Fehler, von denen wir hier sprechen, sind in den meisten Fällen keine Fehler, sondern lediglich Meldungen, die auf Verletzungen etwa der Datenintegrität hinweisen – meist werden diese durch die Jet-Engine verursacht, die für den Zugriff und das Bearbeiten der in den Tabellen gespeicherten Daten verantwortlich ist. Beispiele hierfür sind die folgenden:

  • Eingabe eines Textes in ein Zahlenfeld,
  • Speichern eines Datensatzes, der noch nicht gefüllte Pflichtfelder enthält,
  • Gültigkeitsmeldungen oder
  • Eingabe eines bereits vorhandenen Wertes in ein Feld, das als eindeutiges Feld indiziert ist.

Restriktionen durch den Datentyp

Das erste Beispiel zeigt die grundlegende Vorgehensweise beim Abfangen von Fehlern in Formularen, die nicht durch den Code selbst ausgelöst werden. Das Beispielformular heißt frmArtikel und verwendet die Tabelle tblArtikel als Datenherkunft. Diese Tabelle enthält beispielsweise ein Feld namens Einzelpreis, das den Datentyp Währung aufweist. Dementsprechend darf der Benutzer nur Zahlenwerte eingeben. Wenn er hier etwa einen Text eingibt, weil er der Ansicht ist, man müsste neben der Preisangabe noch die Zeichenkette EURO ausschreiben, löst dies die Meldung aus Bild 1 aus.

Dieser Meldung erscheint beim Eingeben von Text in numerische Felder.

Bild 1: Dieser Meldung erscheint beim Eingeben von Text in numerische Felder.

Der Meldungstext ist eigentlich aussagekräftig, aber wir können ihn dennoch durch eine eigene Meldung ersetzen. Dazu verwenden Sie eine spezielle Ereignisprozedur namens Bei Fehler, die nur bei Fehlern ausgelöst wird, die nichts mit dem Code des Formulars zu tun haben. Aktivieren Sie dazu in der Entwurfsansicht des Formulars das Eigenschaftsfensters und wechseln Sie zur Registerseite Ereignis. Dort finden Sie, sofern das Formular selbst aktiviert ist, den Eintrag Bei Fehler. Wählen Sie hier den Wert [Ereignisprozedur] aus (siehe Bild 2) und klicken Sie auf die Schaltfläche mit den drei Punkten. Es erscheint der VBA-Editor, der das Grundgerüst der Prozedur zeigt, mit der Sie die oben erwähnten Fehler abgreifen können:

Anlegen der Ereignisprozedur, die bei Fehlern im Formular ausgelöst wird

Bild 2: Anlegen der Ereignisprozedur, die bei Fehlern im Formular ausgelöst wird

Private Sub Form_Error(DataErr As Integer, _

                                Response As Integer)

End Sub

Diese Ereignisprozedur besitzt zwei Parameter:

  • Der erste heißt DataErr und ist mit der Eigenschaft Number des Err-Objekts identisch – er liefert also die Nummer des Fehlers, durch den die Form_Error-Ereignisprozedur ausgelöst wurde. Durch diesen Parameter können Sie auf die unterschiedlichen Fehler entsprechend reagieren.
  • Der zweite Parameter namens Response erwartet in dieser Prozedur einen von zwei Werten als Rückgabewert: acDataErrContinue bedeutet, dass die normalerweise von Access an dieser Stelle angezeigte Meldung nicht erscheinen soll, acDataErrDisplay legt fest, dass Access die Fehlermeldung wie gewohnt anzeigen soll.

Der Standardwert für Response lautet acDataErrDisplay. Das bedeutet, dass ohne weiteres Zutun Ihrerseits nach dem Anlegen der Ereignisprozedur einfach nur wie üblich die Access-Meldung erscheint. Soll dies nicht geschehen, stellen Sie Response auf den Wert acDataErrContinue ein:

Response = acDataErrContinue

Dadurch wird nun die Fehlermeldung unterdrückt. Der Benutzer kann das Feld aber nicht verlassen, ohne einen gültigen Wert einzugeben. Die folgende Anweisung teilt ihm dies mit:

MsgBox "Bitte geben Sie einen " _

& "Zahlenwert als Einzelpreis ein."

Dadurch wird nun eine entsprechende Meldung angezeigt. Den offensichtlich ungültigen Wert könnten Sie mit folgender Anweisung löschen:

Me!Einzelpreis.Undo

Fertig – wenn der Benutzer nun einen ungültigen Wert für das Feld Einzelpreis eingibt, erscheint eine benutzerdefinierte Meldung. Die eigentliche Meldung unterbleibt und das Feld wird zurückgesetzt.

Fehler differenzieren

Fast perfekt, oder? Nein, nicht ganz: Was geschieht denn, wenn ein anderer Fehler auftritt – beispielsweise beim Versuch, den Datensatz zu speichern, ohne das Pflichtfeld Artikelname zu füllen? Ganz einfach: Es erscheint genau die gleiche Fehlermeldung wie beim Eingeben eines Textes in das Währungsfeld Einzelpreis. Eigentlich sollte aber die Meldung erscheinen, die in Bild 3 abgebildet ist.

Fehlermeldung beim Speichern eines Datensatzes mit leeren Pflichtfeldern

Bild 3: Fehlermeldung beim Speichern eines Datensatzes mit leeren Pflichtfeldern

Moment – war da nicht was mit dem ersten Parameter DataErr? Der liefert doch für jeden Fehler eine entsprechende Fehlernummer! Also bauen wir diesen in die Ereignisprozedur Form_Error ein, um die jeweilige Fehlermeldung zu ermitteln.

Als erstes finden wir die Nummer des Fehlers heraus, der ausgelöst wird, wenn der Benutzer einen Text in ein numerisches Feld eingibt. Dazu tragen Sie als erste Zeile der Prozedur die folgende Anweisung ein:

MsgBox DataErr

Dann geben Sie 10 Euro in das Feld Einheitspreis ein und erhalten per Meldungsfenster die Fehlernummer für diesen Fehler, nämlich 2113. Damit können wir arbeiten und bauen ein Select Case-Konstrukt auf, dass diesen Fehler mit den oben bereits ermittelten Befehlen behandelt:

Select Case DataErr

     Case 2113 'Ungültige Zahl

         MsgBox "Bitte geben Sie einen Zahlenwert " _

             & "als Einzelpreis ein."

         Me!Einzelpreis.Undo

         Response = acDataErrContinue

     Case Else

         MsgBox DataErr

End Select

Die MsgBox-Anweisung verschieben Sie in den Case Else-Zweig, damit jeder weitere, nicht behandelte Fehler per MsgBox ausgeben wird, bevor seine eigentliche Fehlermeldung erscheint.

Leere Pflichtfelder

Beim Speichern des Artikel-Datensatzes mit nicht gefülltem Feld Artikelname löst dies beispielsweise den Fehler 3314 aus. Darauf reagieren wir ebenfalls mit einem eigenen Select Case-Zweig:

Case 3314 'Pflichtfeld leer

     MsgBox "Bitte geben Sie einen Wert für " _

         "'Artikelname' ein."

     Me!txtArtikelname.SetFocus

Response = acDataErrContinue

Neben der Meldung und dem Deaktivieren der eingebauten Fehlermeldung setzt dies auch noch den Fokus auf das Steuerelement txtArtikelname, damit der Benutzer gleich weiß, in welchem Steuerelement etwas schiefgelaufen ist. Dies ist nötig, weil Restriktionen wie etwa das Einstellen der Eigenschaft Eingabe erforderlich für ein Feld auf den Wert Ja erst beim Speichern des kompletten Datensatzes wirken.

Aber ist dieser Ansatz sinnvoll? In diesem Falle ausnahmsweise ja, denn Artikelname ist das einzige Feld, das nicht leer bleiben darf. Wenn Sie jedoch noch ein weiteres Pflichtfeld in der Tabelle hätten, könnten Sie beim Auslösen des Fehlers 3314 beim Speichern eines unvollständigen Datensatzes nur mit weiterem Code-Einsatz ermitteln, welches Feld denn nun unerlaubterweise leer geblieben ist. Besser wäre es an dieser Stelle vermutlich, für das Ereignis Vor Aktualisierung eine entsprechende Prüfung unterzubringen. Diese könnte beispielsweise so aussehen:

Private Sub Form_BeforeUpdate(Cancel As Integer)

     If IsNull(Me!txtArtikelname) Then

         MsgBox "Bitte geben Sie einen Wert für " _

             & "'Artikelname' ein."

         Me!txtArtikelname.SetFocus

         Cancel = True

     End If

End Sub

Dummerweise wird das Ereignis Bei Fehler vor dem Ereignis Vor Aktualisierung ausgelöst. Das ist aber auch nicht schlimm – Sie sorgen einfach dafür, dass die eingebaute Meldung beim Speichern eines Datensatzes nicht angezeigt wird und überlassen der benutzerdefinierten Validierung die Prüfung, ob die Pflichtfelder gefüllt wurden.

Der Case-Zweig für diesen Fall sieht dann einfach so aus:

Case 3314 'Pflichtfeld leer

Response = acDataErrContinue

Aber Vorsicht: Sie müssen dann in der Validierung alle Pflichtfelder prüfen und entsprechende Meldungen anzeigen, da der Benutzer sonst nicht erfährt, warum sein Datensatz nicht gespeichert werden kann.

Gültigkeitsregeln aushebeln

Wenn Sie einmal eine Gültigkeitsregel in der Bei Fehler-Ereignisprozedur ausheben wollen, können Sie dies auch tun. Die Tabelle tblArtikel besitzt eine Gültigkeitsregel, die verhindert, dass etwa für das Feld Lagerbestand negative Zahlen eingegeben werden. Die Verletzung einer Gültigkeitsregel löst den Fehler 3316 aus. Behandeln Sie diesen ebenfalls mit einem entsprechenden Case-Zweig:

Case 3316

     MsgBox "Bitte geben Sie eine positive Zahl " _

         "für den Lagerbestand ein."

Sie haben das Ende des frei verfügbaren Teil dieses Artikels erreicht!

Wenn Sie mehr lesen und auf viele weitere Artikel zugreifen möchten, melden Sie sich als Abonnent unter Login an. Falls nicht, bestellen Sie doch einfach ein Jahresabonnement!