Zur Hauptseite ... Zum Onlinearchiv ... Zum Abonnement ... Zum Newsletter ... Zu den Tools ... Zum Impressum ... Zum Login ...

Achtung: Dies ist nicht der vollständige Artikel, sondern nur ein paar Seiten davon. Wenn Sie hier nicht erfahren, was Sie wissen möchten, finden Sie am Ende Informationen darüber, wie Sie den ganzen Artikel lesen können.

Kompletten Artikel lesen?

Einfach für den Newsletter anmelden, dann lesen Sie schon in einer Minute den kompletten Artikel und erhalten die Beispieldatenbanken.

E-Mail:

Gedrucktes Heft

Diesen Beitrag finden Sie in Ausgabe 6/2008.

Unser Angebot für Sie!

Lesen Sie diesen Beitrag und 500 andere sofort im Onlinearchiv, und erhalten Sie alle zwei Monate brandheißes Access-Know-how auf 72 gedruckten Seiten! Plus attraktive Präsente, zum Beispiel das bald erscheinende Buch 'Access 2010 - Das Grundlagenbuch für Entwickler'!

Diesen Beitrag twittern

Zusammenfassung

Lernen Sie eine Bibliothek kennen, welche die Fehlerbehandlung von VBA ersetzt und erweitert.

Techniken

VBA

Voraussetzungen

Access 2000 oder höher

Beispieldateien

demo_globalerrorhandler.mdb,
demo_globalerrorhandler.mde

Shortlink

641

VBA-Fehlerbehandlung revolutioniert

Sascha Trowitzsch, Berlin

Es kracht hin und wieder beim Ausführen Ihres VBA-Codes und Sie klicken auf die Debuggen-Schaltfläche der Fehlermeldung? Macht nichts - das kommt vor. Sie verteilen Ihr Werk und der Benutzer berichtet von seltsamen Fenstern und sich öffnendem VBA-Editor? Weniger schön. Sie liefern Ihre Datenbank mit der Access-Runtime aus und der Kunde meldet ungehalten, dass sich die Anwendung allenthalben einfach schließe? Spätestens dann ist Schluss. Es geht aber auch anders ...

Die Fehlerbehandlung ist fester Bestandteil jedes Programmcodes - oder sollte es zumindest sein. Es ist sicher legitim, während der Entwicklung einer Prozedur oder eines Moduls Fehlerbehandlungsmechanismen außen vor zu lassen. Das ist im Gegenteil sogar hilfreich, weil bei auftretenden Fehlern der VBA-Debugger an der richtigen Stelle anhält, diese markiert und Sie nun etwa Variablen auf falsche Werte inspizieren können. Sobald jedoch andere Benutzer oder sogar Kunden mit der Anwendung arbeiten, sollten Fehlerbehandlungen in allen Prozeduren eingebaut sein, damit die Benutzer nicht mit kryptischen Meldungen konfrontiert werden oder gar den VBA-Editor zu Gesicht bekommen.

Besonders wichtig ist das, wenn Ihre Datenbank mit der Runtime-Version von Access gestartet wird, denn diese verzeiht keine Nachlässigkeiten und beendet sich kurzerhand bei jedem unbehandelten Fehler selbst. Das kann auch Datenverlust nach sich ziehen.

Möglichkeiten zur Fehlerbehandlung von VBA-Routinen wurden in Access im Unternehmen bereits vielfach dargestellt. Ob Sie in den Zweig zur Fehlerauswertung einfach eine schnöde Messagebox setzen, die die Fehlerbeschreibung ausgibt, oder die Fehlerbearbeitung an eine separate Fehlerfunktion delegieren, die sich um Ausgabe, Loggen oder gar Versenden per E-Mail kümmert, von einer Arbeit kann Sie niemand befreien: In jede einzelne Prozedur Ihres Projekts müssen entsprechende Anweisungen geschrieben werden, die das Verhalten bei einem auftretenden Fehler regeln.

Zwar erleichtern Ihnen Hilfsmittel, wie die MZ-Tools, die Arbeit beim Anlegen eines Rahmens zur Fehlerbehandlung und optional beim Durchnummerieren der Code-Zeilen. Im Eifer des Gefechts wird es Ihnen versehentlich aber sicher immer wieder passieren, dass Sie mal schnell eine Funktion in ein Modul hineinschreiben, die ohne Fehlerbehandlung bleibt. Lehnen Sie sich zurück! Mit dem brandneuen SimplyVBA Global VBA Error Handler [1] hat Wayne Phillips von everythingaccess.com eine revolutionäre Schnittstelle geschaffen, die Fehlerbehandlung unter VBA auf ein neues Level hebt, ganz neue Konzepte erschließt und Sie in Zukunft ruhig schlafen lässt.

The SimplyVBA Global Error Handler - SVGEH

Der Name Wayne Phillips dürfte den meisten Access-Entwicklern kein Begriff sein. Er ist kaum in Foren präsent, kein MVP und doch möglicherweise der Entwickler mit den tiefsten Kenntnissen zu Interna von Access und VBA weltweit - außerhalb des Microsoft Entwickler-Teams selbstredend.

Seine englische Firma Everythingaccess.com aka iTechMasters dagegen könnte dem einen oder anderen bereits beim Surfen begegnet sein: Dort wird ein Service zum Dekompilieren von Access-MDE-Datenbanken angeboten. Niemand sonst kann seit zwei Jahren einen solchen Dienst anbieten. Karl Donaubauer berichtete in der Ausgabe 4/2006 von Access im Unternehmen darüber. Ich hatte die Ehre, zur Runde der Beta-Tester des Global Error Handlers zu gehören, mit einigen Vorschlägen an der Entwicklung teilhaben zu dürfen und dabei einige Hintergründe über die Wirkungsweise der Schnittstelle zu erfahren. Rein äußerlich handelt es sich um eine ActiveX-DLL, die, zumindest in der Freeware-Version, in die Verweise der eigenen Datenbank, also des VBA-Projekts, aufgenommen wird. Sie klinkt sich außerdem bei Registrierung, wahlweise über ein Setup oder über regsvr32, als COM-Addin in Access ein. Über den Aufruf einer einzigen Methode in der Schnittstellenbibliothek verändert sich der VBA-Debugger komplett und leitet alle Fehlerereignisse an eine wählbare eigene Prozedur weiter - ganz unabhängig davon, wo sich der Fehler ereignet und ob Sie Statements zur Fehlerbehandlung in den Prozeduren Ihres Projekts implementiert haben.

Selbst Fehler, die im VBA-Direktfenster ausgelöst werden, landen dann bei dieser Prozedur, in deren Ablauf beliebige Fehlerauswertungen vorgenommen werden können.

Wie hat er das gemacht?

Bevor ich Ihnen die Verfahrensweisen im Umgang mit dem Global Error Handler beschreibe, soll erwähnt werden, was da intern vor sich geht. Wayne Phillips hat die DLL mit Borland C++ entwickelt und auch vor Assembler-Einsatz nicht Halt gemacht. Der Grund dafür ist, dass das Ausschalten des VBA-internen Debuggers und das Weiterleiten von Fehlerereignissen an eine benutzerdefinierte Funktion sich nur mit einem Patchen der geladenen VBA-System-DLLs erreichen lässt. Das passiert, wohlgemerkt, nur im Access zugewiesenen Arbeitsspeicher und verändert nicht etwa Dateien von Access oder VBA. Um dies zu erreichen, also geschützte Speicherbereiche zu manipulieren, müssen scharfe API-Geschütze aufgefahren werden. Man könnte nun misstrauisch werden, ob solche tief greifenden Manipulationen nicht die Stabilität von VBA gefährden. Tatsächlich kann ich aber seit einigen Versionen der DLL von keinem einzigen Absturz oder irgendwelchen Unzulänglichkeiten oder Fehlfunktionen in allen Testprojekten berichten. Wayne Phillips ist, davon abgesehen, ein zugänglicher Entwickler, der Bugs außerordentlich schnell behebt. Sollten Sie problematisches Verhalten des Error Handlers feststellen, dann zögern Sie nicht, ihm dies in einer kurzen E-Mail mitzuteilen - dann allerdings in Englisch.

Der VBA-Debugger

Ein Ausflug in die Funktionsweise des VBA-Debuggers soll zunächst klären, wie VBA mit Fehlern umgeht.

Dazu legen wir eine einfache Prozedur an, die absichtlich einen Fehler hervorruft:

Sub LetItCrash

    Dim obj As Object

    Set obj = CreateObject("Sascha.Trowitzsch")

End Sub

Hier wird versucht, ein COM-Objekt zu erzeugen, das es (nach meiner Kenntnis) gar nicht gibt. Beim Ausführen der Prozedur werden wir folglich mit dem Fehlerdialog des VBA-Debuggers konfrontiert (Abb. 1). Der Benutzer Ihrer Anwendung wird erst mal ratlos sein, was das zu bedeuten hat, und anschließend möglicherweise die Eingabetaste drücken, weil der Begriff Debuggen so chic aussieht und ohnehin den Fokus hat.

debugmsg.png

Abb. 1: Eine konventionelle VBA-Fehlermeldung

Das jedoch ist der denkbar ungünstigste Fall, weil sich nun ein Fenster öffnet, von dem er noch nicht mal weiß, ob es zu Ihrer Anwendung gehört und ob er hier Daten eingeben soll, weil er bei der Schulung geschlafen hat (s. Abb. 2). Aber verfolgen wir lieber nicht, wie der Benutzer in seiner Verwirrung weiter verfährtÂ… ...

debugline.png

Abb. 2: Eine Fehlermeldung im VBA-Editor

Was hat VBA gemacht?

Wenn VBA auf eine Zeile stößt, die es nicht ausführen kann, weil Syntax oder Werte nicht seinen Regeln entsprechen, dann schaut es zunächst nach, in welchem Modus sich sein Debugger befindet. Dieser Modus kann durch On Error-Direktiven im Code gesteuert werden. In unserem Prozedurbeispiel gibt es keine solche Direktive und der Modus des Debuggers ist damit quasi auf "Interaktiv" geschaltet, was bedeutet, dass VBA nun Entscheidungshilfe benötigt, wie es mit dem Fehler weiter umgehen soll. Da es darüber keine Informationen aus dem VBA-Projekt selbst bekommt, fragt es eben beim Benutzer nach und präsentiert den Fehlerdialog, nachdem es vorsorglich den Code in gelb markierter Zeile angehalten hat (s. Abb. 2).

Wenn Sie die Debuggen-Schaltfläche betätigen, dann gelangen Sie genau zu dieser Zeile und haben nun noch die Möglichkeit, die Zeile syntaktisch oder durch andere Variablenwerte zu korrigieren - etwa die ProgID des zu erzeugenden COM-Objekts auf Forms.Form.1 zu ändern. VBA versucht dann, die korrigierte Zeile nochmals auszuführen. Klicken Sie hingegen die Beenden-Schaltfläche, dann bricht VBA die Ausführung des Codes ab und zerstört nebenbei noch sämtliche lokalen und globalen Variablen, die Sie möglicherweise in Ihrem Projekt untergebracht haben. Der Gedanke dahinter ist der, dass VBA wegen des nicht weiter ausgeführten Codes vorlaut davon ausgeht, dass die Werte der Variablen nun wahrscheinlich eh nicht mehr passen.

Nicht unerwähnt sollte bleiben, dass dies nur das Verhalten unter der Vollversion von Access ist. Die Runtime-Version erlaubt ja keinen Einblick in die VBA-Entwicklungsumgebung und ein Debuggen-Knopf im Fehlerdialog ergibt somit keinen Sinn. Die Runtime stuft jeden VBA-Fehler als kritisch ein und beendet die Datenbank kurzerhand, nachdem sie den Benutzer recht wortkarg über die Ursache informiert (s. Abb. 3). All diese unschönen Auswirkungen unterlassener Anweisungen zur Fehlerbehandlung lassen sich vermeiden, wenn dem VBA-Debugger gesagt wird, was er im Fehlerfall tun soll. Im Prinzip gibt es nur zwei Modi, die Sie einstellen können. Über On Error Resume Next sagen Sie ihm schlicht, dass er nicht ausführbare Zeilen überspringen soll (s. Listing 1).

Listing 1: Fehler übergehen mit On Error Resume Next

Sub LetItCrash2()

    Dim obj As Object

    On Error Resume Next

    Set obj = CreateObject("Sascha.Trowitzsch")

End Sub

missing image file

Abb. 3: Unbehandelter Fehler unter der Access-Runtime - peng!

Mit On Error Goto Label teilen Sie dem Debugger mit, dass er bei nicht ausführbarer Zeile an eine andere Stelle im Code springen soll, die mit einer Zeichenkette, dem Label, gekennzeichnet ist. In diesem Codeabschnitt lassen sich dann weitere Entscheidungen treffen, wie die Ausführung des Codes abschließend aussehen soll (s. Listing 2). Immerhin wird dem Anwender mit dieser Routine eine Meldung angezeigt, die keinen Debuggen-Knopf mehr aufweist, und gesetzte Variablen verlieren auch nicht mehr ihre Werte (s. Abb. 4).

Listing 2: Fehlerbehandlung mit Sprungmarke

Sub LetItCrash3()

    Dim obj As Object

    On Error GoTo Fehler

    Set obj = CreateObject("Sascha.Trowitzsch")

Ende:

    Set obj = Nothing

    Exit Sub

 

Fehler:

    MsgBox Err.Description, vbCritical

    Resume Ende

End Sub

 

Listing 3: Fehlerbehandlung mit Nummerierung und Sprungmarke

Sub LetItCrash4()

    Dim obj As Object

 

    20 On Error GoTo Fehler

    40 Set obj = CreateObject("Sascha.Trowitzsch")

 

Ende:

    60 Set obj = Nothing

    80 Exit Sub

 

Fehler:

    100 MsgBox "Fehler in Zeile " & Erl & _

    " von mdlDemos.LetItCrash4:" & vbCrLf & _

    Err.Description, vbCritical, "Anwendungsfehler"

    120 Resume Ende

End Sub

errormsgbox.png

Abb. 4: Fehlermeldung ohne Debugging-Schaltfläche

Davon abgesehen bringt diese Meldung weder den Benutzer, noch den Entwickler wirklich weiter. Was fangen Sie damit an, wenn der User Ihnen am Telefon die Meldung vorliest? Sie enthält vor allem keine Informationen darüber, wo der Fehler auftrat. Eine aussagekräftigere Meldung enthielte daher zusätzliche Angaben zu Modulnamen, Prozedurnamen und möglichst auch Zeilennummer der nicht ausführbaren Codezeile (s. Abb. 5). Das lässt sich durch eine Erweiterung der Prozedur wie in Listing 3 erreichen. Die Tatsache, dass der Debugger für die Direktive On Error Goto Label immer die Angabe einer Sprungstelle innerhalb (!) der gleichen Prozedur erwartet, führt zu viel Arbeit: In Hunderten von Prozeduren Ihres Projekts müssen Sie die immer gleichen Anweisungen und Fehlerbehandlungsabschnitte einfügen. Und wenn Sie nicht übermäßig pingelig sind, werden Sie dabei immer noch eine Reihe Prozeduren übersehen ...

Listing 4: Die Hauptroutine ruft eine Unterfunktion auf.

Private strTest As String

Public globRet As Boolean

 

Sub LetItCrash5()

    Dim a As Long

    a = 99

    strTest = "Sascha"

    globRet = SubLetItCrash(strTest)

End Sub

 

Function SubLetItCrash(strObj As String) As Boolean

    Dim obj As Object

    Set obj = CurrentDb

    Set obj = CreateObject(strObj & ".Trowitzsch")

    SubLetItCrash = obj.Name

    Set obj = Nothing

    SubLetItCrash = True

End Function

 

Listing 5: Variablenliste

*****************************************************

*** demo_globalerrorhandler.mdlDemos.SubLetItCrash *****************************************************

(PARAM) strObj As String = "Sascha"

(LOCAL) obj As Object = {Object}

(LOCAL) SubLetItCrash As Boolean = False

(MODULE) strTest As String = "Sascha"

(MODULE) globRet As Boolean = False

*****************************************************

*** demo_globalerrorhandler.mdlDemos.LetItCrash5 *****************************************************

(LOCAL) a As Long = 99

(MODULE) strTest As String = "Sascha"

(MODULE) globRet As Boolean = False

*****************************************************

errormsgbox2.png

Abb. 5: Fehlermeldung mit Angabe der VBA-Quellzeile

Und hier setzt der Simply VBA Global Error Handler an. Er ermöglicht, dass bei Fehlern nicht das prozedureigene Label angesprungen wird, sondern eine beliebige öffentliche Fehlerbehandlungsprozedur, die Sie dafür umso reichhaltiger ausstatten und mit allen Schikanen zur Fehlerbeschreibung versehen können. Dabei lässt sich der SimplyVBA Global Error Handler, den ich ab hier abgekürzt nur noch SVGEH nennen werde, durchaus jederzeit über seine Schnittstelle so steuern, dass auch zu einer prozedureigenen Fehlerroutine zurückgesprungen werden kann.

SVGEH einsetzen

Wenn Sie den SVGEH verwenden möchten, dann laden Sie ihn zunächst unter [1] herunter. Es stehen drei Versionen zur Verfügung. Die Freeware-Version kommt erfreulicherweise ohne nervende Popups oder andere Werbemaßnahmen aus und enthält alle wesentlichen Features. Erst, wenn Sie Ihre Anwendung vertreiben wollen, fallen Kosten an, die jedoch relativ bescheiden ausfallen und mit der voraussichtlichen Zeitersparnis schnell wieder hereingeholt sind. Eine Übersicht über Versionsunterschiede finden Sie im Anhang. Die Freeware-Version erfordert die Installation über ein Setup, welches die VBAGlobalErrorHandler.dll als ActiveX-Komponente registriert. Die Installation enthält zusätzlich eine umfangreiche Demo-Datenbank, die alle Features gut demonstriert - allerdings in Englisch. Das gilt auch für die Hilfe, die bislang nur online unter [3] verfügbar ist. In der Freeware-Version benötigen Sie in Ihrem VBA-Projekt einen Verweis auf die SimplyVBA Global Error Handler Library.

Sie haben das Ende des frei verfügbaren Teils des Artikels erreicht. Lesen Sie weiter, um zu erfahren, wie Sie den vollständigen Artikel lesen und auf viele hundert weitere Artikel zugreifen können.

Sind Sie Abonnent?Jetzt einloggen ...
 

Kompletten Artikel lesen?

Einfach für den Newsletter anmelden, dann lesen Sie schon in einer Minute den kompletten Artikel und erhalten die Beispieldatenbanken.

E-Mail:

Verwandte Beiträge:

Debugging im VBA-Editor

Fehlerverwaltung mit Online-Komponente

Fehlersuche und –behandlung mit Access

Tools für den VBA-Editor

Defekte Verweise: Ursachen und Lösungen

Der Objektkatalog

Von Access nach MySQL, Teil 2

Fehlerdokumentation

© 2003-2015 André Minhorst Alle Rechte vorbehalten.