Grundlagen des Fehlermanagements

By , 17. Juli 2009

Fehlermanagement im VBA-Code ist keine lästige Pflichtübung für den Entwickler, sondern essentiell wichtig für eine funktionierende Access-Anwendung und liefert wichtige Informationen zur Korrektur und Optimierung von VBA-Code.

Softwarefehler
Befassen wir uns erst mal mit dem Begriff des Fehlers. Wie üblich gibts in Deutschland auch dafür eine allgemeine Norm: Nach DIN EN ISO 8402 ist ein Fehler gleichzusetzen mit der Nichterfüllung einer festgelegten Forderung. Man könnte einen Fehler auch als eine Nicht-Konformität bezeichnen.

Und da fängt es an spannend zu werden. Forderungen können z.B. vom Kunden in Form von Lastenheften existieren. Das wäre auch der Idealfall, da dann die Forderungen exakt umrissen sind und der Entwickler zielgerichtet diese erfüllen kann. Was aber wenn kein Lastenheft existiert? Das ist ein Dilemma in das sich dann jeder Entwickler begibt. Er bekommt dann meist scheibchenweise die benötigten Informationen, mal als Email oder per Post und im schlechtesten Fall mündlich per Telefon oder in einem Gespräch mitgeteilt. Da heißt es dann nur: „wer schreibt der bleibt“, also mitprotokollieren und am besten vom Gesprächspartner gegenzeichnen lassen.

Auftretende Fehler bei der VBA Programmierung lassen sich grob in 5 Kategorien einteilen:

  • Fehlerhafter VBA-Code, z.b. ein Überlauf durch falschen Variablentyp
  • Fehlerhafte Interaktion des Benutzers, z.B. fehlende oder fehlerhafte Eingabe
  • Fehler durch Wechselwirkung mit der Hardware, z.B. defekte Speicherbausteine
  • Fehler durch Wechselwirkung mit Software, z.B. Virenscanner, Firewall etc.
  • Und zuletzt noch Fehler durch Versionsänderung benuzter Komponenten, z.B. ActiveX Komponenten


Gerade zum letzten Punkt gibt es ein aktuelles Beispiel. Als für Access 2002 das Service Pack 3 heraus kam, führte das zu zahlreiche Fehlern in den verschiedensten Access-Anwendungen.

Risikoanalyse
Zur Entwicklungszeit sollte der Entwickler sowas wie eine Risikoanalyse durchführen. D.H. man betrachtet jede Prozedur und überlegt welche Fehler auftauchen können, wie wahrscheinlich das Auftreten ist, und wie schwerwiegend das Auftreten des Fehlers ist. Daraus könnte man dann Kennzahlen bilden und bei überschreiten eines best. Wertes entsprechende Maßnahmen einleiten.

Beispiel:
Function Foo (Bar1 As Integer, Bar2 As Long) As Integer
Foo = Bar1 + Bar2
End Function

Möglicher Fehler:
1. Bar1 könnte den Wertebereich des Integers überschreiten. Der Fehler würde in einer aufrufenden Prozedur auftreten und müsste dort auch behandelt werden.
2. Rückgabewert Foo könnte den Wertebereich des Integers überschreiten

Angenommene Auftretenswahrscheinlichkeit (dass der Fehler mind. 1x auftritt): 80% (8)
Schwere des Fehlers: Programmunterbrechung könnte zu Produktionsunterbrechung führen. Angenommene Schwere: 60% (6) ergäbe eine Kennzahl von 8×6 = 48.

Bilden wir mal einen willkürlichen Schwellenwert: geringe Auftretenswahrscheinlichkeit (2) x geringe Schwere (2) ergäbe einen Wert von 4. D.H. wir liegen mit 48 deutlich darüber und müssen hier eine Maßnahme einleiten. Für den relativ unwahrscheinlichen Fall dass der Fehler trotzdem eintritt sollte dieser Fehler nicht dazu führen den Kunden zu irritieren oder den Ablauf zu unterbrechen. Wir brauchen also eine Fehlerbehandlung.

Bei einer Fehlerbehandlung muss man immer prüfen ob denn vor dem Fehlerzeitpunkt eine Neuanlage oder Manipulation eines Datensatzes stattgefunden hat, und ob dieser Fehler Einfluss auf die Datenkonsistenz und -Integrität hat. Wird diese Frage mit Ja beantwortet, dann müssen Sie zwangsweise über Transaktionen nachdenken und über Rollback-Szenarien.

Eine ähnliche Frage ist die nach gesetzten Variablen. Eventuell müssen Sie Variablen auf einen Standardwert zurücksetzen, oder Objektvariablen auf Nothing setzen, oder geöffnete Recordsets schließen etc.

Man sieht also, das Thema Fehlerbehandlung ist komplexer als man zuvor angenommen hat.

Das Fehler Objekt Err:
Microsoft Access stellt in der VBA Umgebung ein Objekt zur Verfügung, mit dem auftretende Fehler ausgewertet werden können. Dieses Objekt ist das „Err“ Objekt.

Das Err Objekt ist Global verfügbar und braucht nicht extra deklariert werden. Das Objekt wirkt singulär. d.h. mit jedem neuen auftreten eines Fehlers werden die im Objekt gehaltenen Informationen überschrieben.

Das Err Objekt besitzt folgende Eigenschaften:

Eigenschaft Inhalt
Err.Number gibt einen numerischen Wert zurück, der für einen speziellen Fehler oder einen Fehlertyp steht
Err.Description gibt eine Zeichenkette zurück die den aufgetretenen Fehler beschreibt.
Err.Source gibt einen Objektnamen oder Anwendungsnamen zurück durch den der Fehler ursprünglich ausgelöst wurde.
Err.HelpContext Wenn eine Hilfedatei angegeben ist kann man hier die Context-Nummer angeben um eine spezielle Hilfeseite anzuzeigen.
Err.HelpFile Hier kann eine Windows-Hilfedatei angegeben werden, sie wird dann automatisch aufgerufen, wenn man im Dialogfeld der Fehlermeldung die Schaltfläche Hilfe betätigt oder die F1-Taste drückt.
Err.LastDllError Bei einem 32-Bit Windows gibt diese Eigenschaft nur den den Systemfehler-Code vom letzten DLL Aufruf zurück.

Die Standard-Eigenschaft des Err Objektes ist Err.Number, d.h. wenn man mit einer MsgBox das Objekt ausgibt, erhält man die Fehlernummer: Msgbox Err
Ist zu diesem Zeitpunkt kein Fehler aufgetreten, ist Err = 0

Das Err Objekt besitzt außerdem noch folgende Methoden:

Methode Funktion
Err.clear Bewirkt dass das Fehlerobjekt zurückgesetzt wird und alle Werte gelöscht werden.
Err.raise Bei Err.raise wird der Programmablauf unterbrochen, und man erhält Informationen zum Fehler im Err Objekt. Ein mit Err.Raise erzeugter Fehler unterscheidet sich formal nicht von einem intern ausgelösten Fehler – er kann wie ein interner Fehler per Errorhandler ausgewertet werden.

Tritt nun während des Ablaufes der Anwendung ein sog. Laufzeitfehler ein, werden die Eigenschaften des Err-Objektes automatisch gesetzt. Bei einem erneuten Auftretens eines Fehlers werden diese allerdings wieder überschrieben.
Tritt nun während der Laufzeit ein Fehler auf, wird dieser als einen schwerwiegenden Fehler behandelt und der Programmablauf wird unterbrochen. So ein Verhalten sollte man keinem Anwender zumuten – er wäre damit sicherlich überfordert. Also brauchen wir eine spezielle Routine zur Behandlung von solchen Fehlern – also eine Fehlerbehandlungsroutine.

Fehlerbehandlungsroutine
Die Fehlerbehandlungsroutine befindet sich immer am Ende einer Prozedur, und beginnt mit einer Sprungmarke (Label). Der Name der Sprungmarke ist beliebig, meist wird aber eine Kombination aus dem Wort „Error“ und dem Namen der Prozedur verwendet, z.B. BerichtAusdrucken_Error:
Der Doppelpunkt am Ende macht den Text erst zur Sprungmarke.

Eine Fehlerbehandlungsroutine könnte z.B. so aussehen, wobei die Fehlernummer hier willkürlich gewählt wurde:

    If Err.Number = 4711 Then
        MsgBox "Bitte füllen Sie Papier im Drucker nach"
    Else
        MsgBox "Ein Fehler ist aufgetreten, bitte Admin unterrichten!" & _
               vbCrLf & "Fehlercode: " & Err.Number
    End If

Damit nun aber, wenn die Prozedur ohne Fehler durchläuft, nicht in diese Fehlerbehandlungsroutine eingesprungen wird, muss man noch ein bisschen mehr machen. Z.B. direkt vor der Fehlerbehandlungsroutine ein Exit Sub (Exit Function) schreiben.
Oder ebenfalls davor eine weitere Sprungmarke setzen, nach der dann ein Exit Sub (Exit Function) steht. Dann kann nämlich von der Fehlerbehandlungsroutine per Sprungbefehl zu dieser Sprungmarke gesprungen werden.

Damit aber nun im Fehlerfalle in die Routine gesprungen wird benötige wir noch einen speziellen Sprungbefehl:
On Error GoTo Sprungmarke

Beispiel

Private Sub Beispiel()
    On Error GoTo Beispiel_Error

    'Hier kommt dann der Inhalt der Prozedur

Exit_Beispiel:
    Exit Sub

Beispiel_Error:
    MsgBox "Folgender Fehler ist aufgetreten:" & vbCrLf & Err.Description & _
           vbCrLf & "Bitte Admin informieren!"
    Resume Exit_Beispiel
End Sub

Zu Beginn der Prozedur steht die Sprungmarke für den Fehlerfall. Danach kommt der eigentliche Prozedurinhalt. Nach diesem eine Sprungmarke die danach den Befehl zur Beendigung der Prozedur beinhaltet. Am Schluss dann die Fehlerbehandlungsroutine in der eine MsgBox ausgegeben wird. Danach wird mit Resume zur Sprungmarke Exit_Beispiel gesprungen und die Prozedur beendet.

Es gibt noch weit mehr Aspekte auf die ich hier eingehen könnte, z.B. die Auslagerung der Fehlerbehandlung in eine zentrale Funktion in einem Modul oder die undokumentierte Funktion ERL, mit der man die Fehlerzeile ermitteln kann etc. Doch davon mehr in einem anderen Artikel.

Hier noch ein paar Links zum Thema Fehlerbehandlung:
Err Objekt: http://msdn.microsoft.com/de-de/library/…
Fehlerbehandlung: http://www.dbwiki.de/wiki.php?…

AV 2009

Leave a Reply

You must be logged in to post a comment.

OfficeFolders theme by Themocracy