{"id":55000509,"date":"2026-06-01T00:00:00","date_gmt":"2026-07-28T14:35:34","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=509"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"Fehlerbehandlung_in_VBA_Patterns_fuer_die_Praxis","status":"publish","type":"post","link":"https:\/\/vbentwickler.de\/Fehlerbehandlung_in_VBA_Patterns_fuer_die_Praxis\/","title":{"rendered":"Fehlerbehandlung in VBA: Patterns f&uuml;r die Praxis"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/vg08.met.vgwort.de\/na\/c236c65793804408857b50de3485e0f2\" width=\"1\" height=\"1\" alt=\"\"><b>Eine Prozedur, die monatelang unauff&auml;llig ihren Dienst getan hat, bricht pl&ouml;tzlich mit einer kryptischen Meldung ab &#8211; und der Anwender steht vor einem Dialog, mit dem er nichts anfangen kann. Der Grund ist fast immer derselbe: Es gibt keine oder nur eine halbherzige Fehlerbehandlung. Dabei ist &#8220;<b>On Error&#8221;<\/b> eines der m&auml;chtigsten Werkzeuge in VBA, wenn man wei&szlig;, wie man es einsetzt. Wir schauen uns die Muster an, die aus einer fragilen L&ouml;sung eine robuste machen: wie wir Fehler nicht nur abfangen, sondern strukturiert behandeln, Ressourcen zuverl&auml;ssig freigeben, Fehler zwischen den Schichten einer Anwendung weiterreichen und sie in einer Tabelle protokollieren. Die Beispiele findest Du im Modul &#8220;<b>mdlFehlerbehandlung&#8221;<\/b> der Beispieldatenbank. Wie das im Einzelnen gelingt, zeigt der vorliegende Beitrag.<\/b><\/p>\n<h2>Was passiert ohne Fehlerbehandlung?<\/h2>\n<p>Schauen wir uns zuerst an, was VBA von sich aus tut, wenn ein Laufzeitfehler auftritt.<\/p>\n<p>Die Prozedur <b>DateiOhneSchutz<\/b> aus folgendem Listing 1 &ouml;ffnet eine Textdatei, die es gar nicht gibt:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>DateiOhneSchutz()\r\n    <span style=\"color:blue;\">Dim <\/span>intFile<span style=\"color:blue;\"> As Integer<\/span>\r\n    intFile = FreeFile\r\n    Open \"C:\\NichtVorhanden.txt\" _\r\n        For Input<span style=\"color:blue;\"> As <\/span>#intFile\r\n    Close #intFile\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Existiert die Datei nicht, bricht VBA mit dem Laufzeitfehler <b>53<\/b> ab und zeigt den Dialog aus Bild 1 &#8211; mit einer Meldung, die dem Anwender nichts sagt, und mit den Schaltfl&auml;chen <b>Beenden<\/b> und <b>Debuggen<\/b>, die in einer ausgelieferten Anwendung beide nichts zu suchen haben.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2026_03\/pic_509_001.png\" alt=\"Der Standarddialog von VBA beim Laufzeitfehler 53 - so etwas darf der Anwender nie zu sehen bekommen\" width=\"499,6267\" height=\"283,6019\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Der Standarddialog von VBA beim Laufzeitfehler 53 &#8211; so etwas darf der Anwender nie zu sehen bekommen<\/span><\/b><\/p>\n<p>Klicken wir auf <b>Debuggen<\/b>, sehen wir die farbig hinterlegte fehlerhafte Anweisung (siehe Bild 2).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2026_03\/pic_509_002.png\" alt=\"Anschlie&szlig;end wird die fehlerhafte Zeile farbig hinterlegt.\" width=\"499,6267\" height=\"203,4809\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 2: Anschlie&szlig;end wird die fehlerhafte Zeile farbig hinterlegt.<\/span><\/b><\/p>\n<p>Zwei Dinge sind hier schiefgelaufen: Der Anwender bekommt keine verst&auml;ndliche Meldung, und die Prozedur bricht mitten im Ablauf ab. In anderen Prozeduren k&ouml;nnen dadurch bereits ge&ouml;ffnete Dateien, Recordsets oder andere Ressourcen unaufger&auml;umt zur&uuml;ckbleiben.<\/p>\n<h2>Die drei Formen von On Error<\/h2>\n<p>VBA kennt genau drei Varianten der <b>On Error<\/b>-Anweisung, und sie bestimmen, was bei einem Laufzeitfehler geschieht:<\/p>\n<ul>\n<li><b>On Error GoTo Marke<\/b> springt zur angegebenen Sprungmarke. Das ist die Standardform f&uuml;r eine strukturierte Fehlerbehandlung.<\/li>\n<li><b>On Error Resume Next<\/b> ignoriert den Fehler und macht mit der n&auml;chsten Anweisung weiter. Das ist n&uuml;tzlich, wenn wir den Fehler unmittelbar danach selbst pr&uuml;fen wollen.<\/li>\n<li><b>On Error GoTo 0<\/b> schaltet jede aktive Fehlerbehandlung in der aktuellen Prozedur ab. Ein Fehler f&uuml;hrt danach wieder zum Standarddialog.<\/li>\n<\/ul>\n<p>Ein Punkt, der sp&auml;ter noch wichtig wird: <b>On Error<\/b> gilt immer nur innerhalb der Prozedur, in der es steht. Eine globale Fehlerbehandlung gibt es in VBA nicht &#8211; jede Prozedur muss sich selbst sch&uuml;tzen.<\/p>\n<h2>Das Standard-Pattern: On Error GoTo<\/h2>\n<p>Das bew&auml;hrteste Muster sieht so aus: Am Anfang der Prozedur leiten wir auftretende Fehler auf eine Sprungmarke um, am Ende springen wir &uuml;ber den Fehlerblock hinweg. Bauen wir unser Beispiel entsprechend um &#8211; das Ergebnis hei&szlig;t <b>DateiMitSchutz<\/b> und steht in folgendem Listing:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>DateiMitSchutz()\r\n    <span style=\"color:blue;\">On Error GoTo<\/span> ErrHandler\r\n    <span style=\"color:blue;\">Dim <\/span>intFile<span style=\"color:blue;\"> As Integer<\/span>\r\n    intFile = FreeFile\r\n    Open \"C:\\NichtVorhanden.txt\" For Input<span style=\"color:blue;\"> As <\/span>#intFile\r\n    ' ... Datei verarbeiten ...\r\n    Close #intFile\r\nExitHere:\r\n    <span style=\"color:blue;\">Exit Sub<\/span>\r\nErrHandler:\r\n    <span style=\"color:blue;\">MsgBox<\/span> \"Fehler \" & Err.Number & \": \" _\r\n        & Err.Description, <span style=\"color:blue;\">vbCr<\/span>itical, \"DateiMitSchutz\"\r\n    Resume ExitHere\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Der Ablauf im Einzelnen: <b>On Error GoTo ErrHandler<\/b> aktiviert die Fehlerbehandlung &#8211; ab hier springt VBA bei einem Laufzeitfehler zur Marke <b>ErrHandler<\/b>.<\/p>\n<p>L&auml;uft alles glatt, erreichen wir <b>ExitHere<\/b> und verlassen die Prozedur mit <b>Exit Sub<\/b>. Tritt dagegen ein Fehler auf, landen wir im <b>ErrHandler<\/b>, zeigen eine Meldung an und springen mit <b>Resume ExitHere<\/b> zur Austrittsmarke.<\/p>\n<p>Warum eigentlich <b>Resume ExitHere<\/b> und nicht einfach <b>GoTo ExitHere<\/b>? Der Unterschied sieht nach Geschmackssache aus, ist aber entscheidend: <b>Resume<\/b> meldet VBA, dass der Fehler behandelt wurde. Erst danach kann &uuml;berhaupt wieder ein Fehler abgefangen werden. Mit <b>GoTo<\/b> bleibt die Prozedur dagegen im Fehlerzustand.<\/p>\n<h2>Den Fehlerzustand sichtbar machen<\/h2>\n<p>Das ist eine Behauptung &#8211; schauen wir sie uns an, statt sie zu glauben. Die Prozedur <b>GoToStattResume<\/b> in macht den Unterschied im Direktbereich sichtbar:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>GoToStattResume()\r\n    <span style=\"color:blue;\">On Error GoTo<\/span> ErrHandler\r\n    Err.Raise 53\r\nExitHere:\r\n    <span style=\"color:blue;\">Debug.Print<\/span> \"In ExitHere: Err.Number = \" & Err.Number\r\n    <span style=\"color:blue;\">Exit Sub<\/span>\r\nErrHandler:\r\n    <span style=\"color:blue;\">Debug.Print<\/span> \"Im Handler:  Err.Number = \" & Err.Number\r\n    GoTo ExitHere\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Rufe die Prozedur im Direktbereich mit <b>GoToStattResume<\/b> auf. Die Ausgabe zeigt in beiden Zeilen die <b>53<\/b> &#8211; der Fehler ist in <b>ExitHere<\/b> also immer noch aktiv (siehe Bild 3).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2026_03\/pic_509_003.png\" alt=\"Der Direktbereich zeigt es schwarz auf wei&szlig;: Nach GoTo steht Err.Number immer noch auf 53\" width=\"499,6267\" height=\"306,1712\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 3: Der Direktbereich zeigt es schwarz auf wei&szlig;: Nach GoTo steht Err.Number immer noch auf 53<\/span><\/b><\/p>\n<p>Tauschst Du das <b>GoTo ExitHere<\/b> gegen <b>Resume ExitHere<\/b>, steht in der zweiten Zeile eine <b>0<\/b>: Der Fehler gilt als erledigt.<\/p>\n<p>Und genau daran h&auml;ngt die Praxisfolge &#8211; ein weiterer Fehler in der Aufr&auml;umlogik w&uuml;rde in der <b>GoTo<\/b>-Variante nicht mehr abgefangen, sondern f&uuml;hrte direkt zum Standarddialog.<\/p>\n<h2>Das Err-Objekt im Detail<\/h2>\n<p>Das <b>Err<\/b>-Objekt ist immer verf&uuml;gbar und beschreibt den zuletzt aufgetretenen Fehler. Wichtig sind drei Eigenschaften:<\/p>\n<ul>\n<li><b>Number<\/b> ist die Fehlernummer, wobei <b>0<\/b> f&uuml;r &#8220;kein Fehler&#8221; steht. F&uuml;r eigene Fehler nutzen wir Nummern ab <b>vbObjectError + 512<\/b> &#8211; dazu kommen wir gleich.<\/li>\n<li><b>Description<\/b> liefert die Fehlerbeschreibung im Klartext.<\/li>\n<li><b>Source<\/b> nennt die Quelle: standardm&auml;&szlig;ig den Namen des VBA-Projekts, bei externen Bibliotheken deren Namen, etwa <b>DAO.Database<\/b> oder <b>ADODB.Connection<\/b>.<\/li>\n<\/ul>\n<p>Dazu kommen zwei Methoden. <b>Clear<\/b> setzt <b>Number <\/b>auf <b>0 <\/b>und leert die &uuml;brigen Eigenschaften des <b>Err<\/b>-Objekts. Beim Verlassen einer Prozedur und durch eine <b>Resume<\/b>-Anweisung wird der Fehlerzustand ebenfalls zur&uuml;ckgesetzt. Wenn wir mehrere Operationen unter <b>On Error Resume Next <\/b>pr&uuml;fen, sollten wir <b>Err.Clear <\/b>dagegen ausdr&uuml;cklich zwischen den Operationen aufrufen.<\/p>\n<p>Und <b>Raise<\/b> l&ouml;st einen Laufzeitfehler aus &#8211; damit erzeugen wir gleich gezielt eigene Fehler.<\/p>\n<h2>Resume &#8211; drei Varianten<\/h2>\n<p>Aus dem Fehlerblock heraus haben wir drei M&ouml;glichkeiten, den Programmfluss fortzusetzen. <b>Resume<\/b> f&uuml;hrt die fehlerausl&ouml;sende Zeile erneut aus &#8211; sinnvoll nur dann, wenn wir die Ursache im Fehlerblock tats&auml;chlich beseitigt haben.<\/p>\n<p><b>Resume Next<\/b> macht mit der Zeile danach weiter, wenn der Fehler tolerierbar ist. Und <b>Resume Marke<\/b> springt zu einer bestimmten Marke, was die h&auml;ufigste Variante ist: Genau so kommen wir geordnet zur Austrittsmarke.<\/p>\n<p>Wie Resume gezielt eingesetzt werden kann, zeigt das folgende Listing. Die Prozedur <b>OrdnerAnlegen<\/b> legt einen Ordner an, dessen &uuml;bergeordneter Ordner wom&ouml;glich noch fehlt &#8211; in dem Fall legen wir diesen an und versuchen es erneut:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>OrdnerAnlegen(strPfad<span style=\"color:blue;\"> As String<\/span>)\r\n    <span style=\"color:blue;\">On Error GoTo<\/span> ErrHandler\r\n    MkDir strPfad\r\nExitHere:\r\n    <span style=\"color:blue;\">Exit Sub<\/span>\r\nErrHandler:\r\n    <span style=\"color:blue;\">If <\/span>Err.Number = 76<span style=\"color:blue;\"> Then<\/span>\r\n        'Pfad nicht gefunden: \r\n        '&uuml;bergeordneten Ordner anlegen\r\n        MkDir <span style=\"color:blue;\">Left<\/span>(strPfad, <span style=\"color:blue;\">InStrRev<\/span>(strPfad, \"\\\") - 1)\r\n        Resume\r\n    <span style=\"color:blue;\">Else<\/span>\r\n        <span style=\"color:blue;\">MsgBox<\/span> \"Fehler \" & Err.Number & \": \" _\r\n            & Err.Description\r\n        Resume ExitHere\r\n    <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Aufgerufen wird das etwa so:<\/p>\n<pre>OrdnerAnlegen \"C:\\Temp\\Export\\Kunden\"<\/pre>\n<p>Zwei Stolpersteine stecken hier drin: Erstens legt die Korrektur nur eine Ebene an &#8211; fehlen zwei, scheitert schon das <b>MkDir<\/b> im Fehlerblock. Ein weiterer Fehler innerhalb eines bereits aktiven Fehlerhandlers kann von demselben Handler nicht erneut behandelt werden. Gibt es keinen &uuml;bergeordneten aktiven Handler, erscheint der VBA-Standarddialog. Zweitens droht eine Endlosschleife, wenn die Korrektur das Problem gar nicht l&ouml;st: <b>Resume<\/b> wiederholt dann immer wieder dieselbe Zeile. Wie wir das mit einem Z&auml;hler entsch&auml;rfen, sehen wir weiter unten.<\/p>\n<h2>On Error Resume Next &#8211; gezielt und sparsam<\/h2>\n<p><b>On Error Resume Next<\/b> hat einen schlechten Ruf, und der ist meistens verdient: Wer es als Allzweckwaffe einsetzt, verschluckt Fehler stillschweigend und macht die Anwendung unberechenbar. Es gibt aber Situationen, in denen es genau das richtige Werkzeug ist &#8211; n&auml;mlich dann, wenn wir den Fehlerstatus einer einzelnen Operation bewusst abfragen wollen.<\/p>\n<p>Ein typischer Fall: Wir wollen wissen, ob ein Eintrag in einer <b>Collection<\/b> existiert. Eine <b>Exists<\/b>-Methode gibt es dort nicht, also nutzen wir den Zugriffsfehler als Pr&uuml;fmittel. Das erledigt die Funktion <b>ExistiertInCollection<\/b>. Sie erwartet die zu pr&uuml;fende <b>Collection<\/b> und den Schl&uuml;ssel und liefert <b>True<\/b> oder <b>False<\/b> zur&uuml;ck:<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>ExistiertInCollection(col<span style=\"color:blue;\"> As <\/span>Collection, _\r\n        strKey<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As Boolean<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>varDummy<span style=\"color:blue;\"> As Variant<\/span>\r\n    On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n    varDummy = col(strKey)\r\n    ExistiertInCollection = (Err.Number = 0)\r\n    <span style=\"color:blue;\">On Error GoTo<\/span> 0\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p>Das Muster dahinter ist immer dasselbe: <b>On Error Resume Next<\/b> einschalten, die kritische Anweisung ausf&uuml;hren, <b>Err.Number<\/b> pr&uuml;fen und sofort danach mit <b>On Error GoTo 0<\/b> zur&uuml;cksetzen &#8211; oder, wenn die Prozedur eine eigene Fehlerbehandlung hat, mit <b>On Error GoTo ErrHandler<\/b> wieder auf die regul&auml;re Marke umleiten. Ausprobieren l&auml;sst sich das wie folgt:<\/p>\n<pre><span style=\"color:blue;\">Dim <\/span>col<span style=\"color:blue;\"> As <\/span><span style=\"color:blue;\">New<\/span> Collection\r\ncol.Add \"Wert\", \"Schluessel\"\r\n<span style=\"color:blue;\">Debug.Print<\/span> ExistiertInCollection(col, \"Schluessel\")\r\n'Liefert <span style=\"color:blue;\">True<\/span>\r\n<span style=\"color:blue;\">Debug.Print<\/span> ExistiertInCollection(col, \"Fehlt\")    \r\n'Liefert <span style=\"color:blue;\">False<\/span><\/pre>\n<p>Entscheidend ist die Disziplin: <b>On Error Resume Next<\/b> sollte nie l&auml;nger als zwei oder drei Zeilen aktiv sein. Alles andere ist ein Wartungsrisiko.<\/p>\n<h2>Aufr&auml;umen bei Fehlern: das Exit-Pattern<\/h2>\n<p>In vielen Prozeduren m&uuml;ssen wir am Ende Ressourcen freigeben &#8211; Recordsets schlie&szlig;en, Objektvariablen auf <b>Nothing<\/b> setzen, Dateien schlie&szlig;en. Diese Arbeit darf der Fehlerblock nicht &uuml;berspringen.<\/p>\n<p>Deshalb bekommt die Prozedur eine gemeinsame Austrittsmarke, die sowohl der regul&auml;re Ablauf als auch der Fehlerblock anspringt. Wie das aussieht, zeigt die Prozedur <b>DatenExportieren<\/b> (siehe Listing 1). Sie liest die Tabelle <b>tblKunden<\/b> aus und schreibt die Namen in eine Textdatei.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>DatenExportieren(strPfad<span style=\"color:blue;\"> As String<\/span>)\r\n    <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n    <span style=\"color:blue;\">Dim <\/span>rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n    <span style=\"color:blue;\">Dim <\/span>intFile<span style=\"color:blue;\"> As Integer<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>bolDateiOffen<span style=\"color:blue;\"> As Boolean<\/span>\r\n    <span style=\"color:blue;\">On Error GoTo<\/span> ErrHandler\r\n    <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n    <span style=\"color:blue;\">Set<\/span> rst = db.OpenRecordset(\"SELECT KundenName FROM tblKunden\", dbOpenSnapshot)\r\n    intFile = FreeFile\r\n    Open strPfad For Output<span style=\"color:blue;\"> As <\/span>#intFile\r\n    bolDateiOffen = <span style=\"color:blue;\">True<\/span>\r\n    Do Until rst.EOF\r\n        Print #intFile, rst!KundenName\r\n        rst.Move<span style=\"color:blue;\">Next<\/span>\r\n    <span style=\"color:blue;\">Loop<\/span>\r\nExitHere:\r\n    <span style=\"color:blue;\">If <\/span>bolDateiOffen<span style=\"color:blue;\"> Then<\/span>\r\n        Close #intFile\r\n        bolDateiOffen = <span style=\"color:blue;\">False<\/span>\r\n    <span style=\"color:blue;\">End If<\/span>\r\n    <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> rst Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n        rst.Close\r\n        <span style=\"color:blue;\">Set<\/span> rst = Nothing\r\n    <span style=\"color:blue;\">End If<\/span>\r\n    <span style=\"color:blue;\">Set<\/span> db = Nothing\r\n    <span style=\"color:blue;\">Exit Sub<\/span>\r\nErrHandler:\r\n    <span style=\"color:blue;\">MsgBox<\/span> \"Fehler in DatenExportieren:\" & <span style=\"color:blue;\">vbCrLf<\/span> _\r\n        & Err.Number & \" - \" & Err.Description, _\r\n        <span style=\"color:blue;\">vbCr<\/span>itical\r\n    Resume ExitHere\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 1: Beispiel f&uuml;r das Exit-Pattern<\/span><\/b><\/p>\n<p>Der Aufruf sieht so aus:<\/p>\n<pre>DatenExportieren \"C:\\Temp\\Kunden.txt\"<\/pre>\n<p>Beachte die Pr&uuml;fung <b>If Not rst Is Nothing<\/b>: Der Fehler kann auch schon vor dem <b>OpenRecordset<\/b> auftreten &#8211; dann w&auml;re <b>rst<\/b> noch <b>Nothing<\/b>, und ausgerechnet das Aufr&auml;umen w&uuml;rde einen neuen Fehler ausl&ouml;sen. Ob die Datei tats&auml;chlich ge&ouml;ffnet wurde, halten wir in der Variablen <b>bolDateiOffen <\/b>fest. Eine von <b>FreeFile <\/b>gelieferte Dateinummer allein beweist noch nicht, dass die anschlie&szlig;ende <b>Open<\/b>-Anweisung erfolgreich war.<\/p>\n<h2>Fehler weiterreichen mit Err.Raise<\/h2>\n<p>Nicht jeder Fehler geh&ouml;rt dort behandelt, wo er auftritt. In einer sauber aufgebauten Anwendung gibt es Schichten: Datenzugriff, Gesch&auml;ftslogik und Benutzeroberfl&auml;che. Eine Datenzugriffsfunktion soll dem Aufrufer melden, dass etwas schiefgelaufen ist &#8211; aber keine <b>MsgBox<\/b> anzeigen. Daf&uuml;r ist <b>Err.Raise<\/b> da.<\/p>\n<p>Die Funktion <b>KundeNachID<\/b> liest zu einer Kundennummer den Namen aus <b>tblKunden<\/b>. Findet sie keinen Datensatz, l&ouml;st sie selbst einen Fehler aus; tritt ein anderer Fehler auf, r&auml;umt sie auf und reicht ihn nach oben weiter (siehe Listing 2).<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>KundeNachID(lngID<span style=\"color:blue;\"> As Long<\/span>)<span style=\"color:blue;\"> As String<\/span>\r\n    <span style=\"color:blue;\">On Error GoTo<\/span> ErrHandler\r\n    <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n    <span style=\"color:blue;\">Dim <\/span>rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n    <span style=\"color:blue;\">Dim <\/span>lngNummer<span style=\"color:blue;\"> As Long<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>strQuelle<span style=\"color:blue;\"> As String<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>strText<span style=\"color:blue;\"> As String<\/span>\r\n    <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n    <span style=\"color:blue;\">Set<\/span> rst = db.OpenRecordset(\"SELECT Firma FROM tblKunden WHERE KundeID = \" & lngID, dbOpenSnapshot)\r\n    <span style=\"color:blue;\">If <\/span>rst.EOF<span style=\"color:blue;\"> Then<\/span>\r\n        Err.Raise vbObjectError + 1001, \"KundeNachID\", \"Kein Kunde mit der ID \" & lngID & \" gefunden.\"\r\n    <span style=\"color:blue;\">End If<\/span>\r\n    KundeNachID = rst!Firma\r\nExitHere:\r\n    <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> rst Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n        rst.Close\r\n        <span style=\"color:blue;\">Set<\/span> rst = Nothing\r\n    <span style=\"color:blue;\">End If<\/span>\r\n    <span style=\"color:blue;\">Set<\/span> db = Nothing\r\n    <span style=\"color:blue;\">Exit Function<\/span>\r\nErrHandler:\r\n    ' Fehlerdaten sichern, bevor wir aufr&auml;umen\r\n    lngNummer = Err.Number\r\n    strQuelle = Err.Source\r\n    strText = Err.Description\r\n    <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> rst Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n        rst.Close\r\n        <span style=\"color:blue;\">Set<\/span> rst = Nothing\r\n    <span style=\"color:blue;\">End If<\/span>\r\n    <span style=\"color:blue;\">Set<\/span> db = Nothing\r\n    Err.Raise lngNummer, strQuelle, strText\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 2: Fehler weiterreichen mit Err.Raise<\/span><\/b><\/p>\n<p>Hier geschehen zwei verschiedene Dinge. Findet die Abfrage keinen Kunden, erzeugen wir mit <b>Err.Raise<\/b> einen eigenen Fehler.<\/p>\n<p>Seine Nummer berechnen wir als <b>vbObjectError + 1001<\/b> &#8211; die Konstante <b>vbObjectError<\/b> ist der daf&uuml;r vorgesehene Offset, und der Bereich von <b>vbObjectError + 512<\/b> bis <b>vbObjectError + 65535<\/b> steht uns f&uuml;r eigene Zwecke zur Verf&uuml;gung. Tritt dagegen irgendein anderer Fehler auf, r&auml;umen wir im <b>ErrHandler<\/b> auf und l&ouml;sen ihn danach mit den Originaldaten erneut aus. F&uuml;r den Aufrufer verh&auml;lt sich der weitergereichte Fehler wie ein gew&ouml;hnlicher Laufzeitfehler. Da wir Nummer, Quelle und Beschreibung &uuml;bernehmen, bleiben die urspr&uuml;nglichen Fehlerinformationen erhalten.<\/p>\n<p>Der Umweg &uuml;ber die drei Variablen <b>lngNummer<\/b>, <b>strQuelle<\/b> und <b>strText<\/b> ist kein Zierrat. Wir w&uuml;rden die Werte gern direkt aus dem <b>Err<\/b>-Objekt an <b>Err.Raise<\/b> &uuml;bergeben &#8211; aber zwischen Fehlerblock und Weiterreichen liegt das Aufr&auml;umen, und das kann das <b>Err<\/b>-Objekt ver&auml;ndern. Deshalb sichern wir die drei Werte, bevor wir irgendetwas anderes tun. Auf der anderen Seite steht das Formular <b>frmKundensuche<\/b>. Seine Ereignisprozedur <b>btnSuchen_Click<\/b> aus unterscheidet, ob der Kunde schlicht nicht existiert oder ob etwas Unerwartetes passiert ist:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>Test_KundeNachID()\r\n    <span style=\"color:blue;\">On Error GoTo<\/span> ErrHandler\r\n    <span style=\"color:blue;\">Dim <\/span>strFirma<span style=\"color:blue;\"> As String<\/span>\r\n    strFirma = KundeNachID(1)\r\n    <span style=\"color:blue;\">MsgBox<\/span> \"Firma: \" & strFirma\r\nExitHere:\r\n    <span style=\"color:blue;\">Exit Sub<\/span>\r\nErrHandler:\r\n    <span style=\"color:blue;\">If <\/span>Err.Number = vbObjectError + 1001<span style=\"color:blue;\"> Then<\/span>\r\n        <span style=\"color:blue;\">MsgBox<\/span> \"Nicht gefunden.\"\r\n        Resume ExitHere\r\n    <span style=\"color:blue;\">Else<\/span>\r\n        <span style=\"color:blue;\">MsgBox<\/span> \"Unerwarteter Fehler: \" & Err.Description, <span style=\"color:blue;\">vbCr<\/span>itical\r\n        Resume ExitHere\r\n    <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Damit haben wir eine saubere Trennung: Die Datenzugriffsfunktion meldet, was schiefgelaufen ist &#8211; das Formular entscheidet, was der Anwender davon zu sehen bekommt.<\/p>\n<h2>Die fehlerhafte Zeile finden: Erl<\/h2>\n<p>Das <b>Err<\/b>-Objekt sagt uns, was schiefgelaufen ist &#8211; aber nicht, wo. Bei einer Prozedur mit zwanzig Zeilen kommen wir noch durch Nachdenken darauf; bei einer mit zweihundert wird daraus eine Suchaktion. Dabei gibt es daf&uuml;r l&auml;ngst eine Funktion, die kaum jemand kennt, weil sie in IntelliSense nicht angeboten wird und in der t&auml;glichen VBA-Programmierung nur selten auftaucht: <b>Erl<\/b>.<\/p>\n<p><b>Erl<\/b> liefert die Nummer der Zeile, in der der Fehler aufgetreten ist. Der Haken daran ist ein Erbst&uuml;ck aus den BASIC-Zeiten: Das funktioniert nur, wenn der Code tats&auml;chlich Zeilennummern tr&auml;gt. Ohne Nummerierung liefert <b>Erl<\/b> schlicht <b>0<\/b> &#8211; und deshalb halten viele die Funktion f&uuml;r nutzlos, obwohl sie das Gegenteil ist.<\/p>\n<p>Schauen wir es uns an. Die Prozedur <b>ZeileErmitteln<\/b> ist unser Dateibeispiel von weiter oben, diesmal mit nummerierten Zeilen:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>ZeileErmitteln()\r\n    <span style=\"color:blue;\">On Error GoTo<\/span> ErrHandler\r\n10  Dim intFile<span style=\"color:blue;\"> As Integer<\/span>\r\n20  intFile = FreeFile\r\n30  Open \"C:\\NichtVorhanden.txt\" For Input<span style=\"color:blue;\"> As <\/span>#intFile\r\n40  Close #intFile\r\nExitHere:\r\n    <span style=\"color:blue;\">Exit Sub<\/span>\r\nErrHandler:\r\n    <span style=\"color:blue;\">Debug.Print<\/span> \"Fehler \" & Err.Number & \" in Zeile \" & Erl\r\n    Resume ExitHere\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Der Aufruf von <b>ZeileErmitteln<\/b> im Direktbereich meldet <b>Fehler 53 in Zeile 30<\/b> &#8211; und damit genau die Zeile mit dem <b>Open<\/b>. Die Nummern schreiben wir an den Zeilenanfang, gefolgt von mindestens einem Leerzeichen. Sie m&uuml;ssen nur innerhalb einer Prozedur eindeutig sein, jede weitere Prozedur darf also wieder bei <b>10<\/b> beginnen.<\/p>\n<p>Und Zehnerschritte haben sich eingeb&uuml;rgert, damit sp&auml;ter noch Zeilen dazwischenpassen. Die <b>On Error<\/b>-Zeile und die Sprungmarken bleiben &uuml;blicherweise ohne Nummer &#8211; dort kann ohnehin kein Laufzeitfehler auftreten.<\/p>\n<p>Jetzt der Stolperstein, und der ist heimt&uuml;ckisch: Nummerieren wir nur einen Teil der Anweisungen, bekommen wir trotzdem eine Zahl &#8211; nur die falsche. Das folgende Listing f&uuml;hrt das vor:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>TeilweiseNummeriert()\r\n    <span style=\"color:blue;\">On Error GoTo<\/span> ErrHandler\r\n10  Dim intFile<span style=\"color:blue;\"> As Integer<\/span>\r\n    intFile = FreeFile\r\n    Open \"C:\\NichtVorhanden.txt\" For Input<span style=\"color:blue;\"> As <\/span>#intFile\r\nExitHere:\r\n    <span style=\"color:blue;\">Exit Sub<\/span>\r\nErrHandler:\r\n    <span style=\"color:blue;\">Debug.Print<\/span> \"Fehler \" & Err.Number & \" in Zeile \" & Erl\r\n    Resume ExitHere\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Diese Prozedur meldet <b>Fehler 53 in Zeile 10<\/b> &#8211; obwohl der Fehler zwei Anweisungen sp&auml;ter passiert ist. Der Grund ist einfach: <b>Erl<\/b> kennt nur nummerierte Zeilen und meldet deshalb die letzte, die vor dem Fehler ausgef&uuml;hrt wurde.<\/p>\n<p>Halbe Nummerierung ist damit schlechter als gar keine: Eine <b>0<\/b> erkennen wir als &#8220;keine Information&#8221;, eine falsche Zeilennummer schickt uns dagegen an die falsche Stelle.<\/p>\n<p>Ein zweiter Punkt geh&ouml;rt dazu: <b>Erl <\/b>steht nur w&auml;hrend der Behandlung des aktuellen Fehlers zuverl&auml;ssig zur Verf&uuml;gung. Insbesondere nach einer <b>Resume<\/b>-Anweisung oder nach dem Verlassen der Prozedur ist der Wert nicht mehr nutzbar.<\/p>\n<p>Wir lesen den Wert deshalb gleich in der ersten Zeile des Fehlerblocks aus &#8211; wer erst aufr&auml;umt und dann <b>Erl<\/b> abfragt, bekommt eine <b>0<\/b> zur&uuml;ck. Bleibt die Frage, wer all diese Nummern tippen soll. Von Hand ist das bei f&uuml;nf Prozeduren noch machbar, bei f&uuml;nfzig jedoch kaum noch praktikabel &#8211; und genau deshalb f&uuml;hrt der Weg zu <b>Erl<\/b> in der Praxis &uuml;ber ein Werkzeug, das die Nummerierung automatisch einf&uuml;gt und vor der Weitergabe wieder entfernt. Dazu mehr im Ausblick.<\/p>\n<h2>Fehler in eine Tabelle protokollieren<\/h2>\n<p>In einer produktiven Anwendung reicht eine <b>MsgBox<\/b> nicht aus. Fehler geh&ouml;ren protokolliert, mit Zeitstempel, Benutzer, Prozedurname, Modulname, Fehlerdaten &#8211; und jetzt auch mit der Zeilennummer aus <b>Erl<\/b>. Daf&uuml;r legen wir die Tabelle <b>tblFehlerLog<\/b> mit den folgenden Feldern an:<\/p>\n<ul>\n<li><b>FehlerLogID<\/b>: Prim&auml;rschl&uuml;ssel (AutoWert)<\/li>\n<li><b>Zeitpunkt<\/b>: Wann der Fehler aufgetreten ist (Datum\/Uhrzeit)<\/li>\n<li><b>Benutzer<\/b>: Windows-Anmeldename (Text, 50 Zeichen)<\/li>\n<li><b>Prozedur<\/b>: Name der Prozedur, in der der Fehler auftrat (Text, 100 Zeichen)<\/li>\n<li><b>Modul<\/b>: Name des Moduls, in dem der Fehler auftrat (Text, 100 Zeichen)<\/li>\n<li><b>Fehlernummer<\/b>: Wert von <b>Err.Number<\/b> (Zahl, Long Integer)<\/li>\n<li><b>Beschreibung<\/b>: Wert von <b>Err.Description<\/b> (Langer Text)<\/li>\n<li><b>Zeilennummer<\/b>: Wert von <b>Erl<\/b>, also die fehlerhafte Zeilennummer (Zahl, Long Integer)<\/li>\n<\/ul>\n<p>Den Entwurf der Tabelle sehen wir in Bild 4.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2026_03\/pic_509_004.png\" alt=\"Entwurf der Protokolltabelle\" width=\"599,6265\" height=\"457,8293\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 4: Entwurf der Protokolltabelle<\/span><\/b><\/p>\n<p>Die zugeh&ouml;rige Prozedur hei&szlig;t <b>FehlerProtokollieren<\/b> und ist bewusst schlank gehalten. Sie erwartet den Prozedur- und den Modulnamen, die Fehlernummer, die Beschreibung und die Zeilennummer und schreibt daraus einen Datensatz (siehe Listing 3).<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>FehlerProtokollieren(strProzedur<span style=\"color:blue;\"> As String<\/span>, strModul<span style=\"color:blue;\"> As String<\/span>, lngNummer<span style=\"color:blue;\"> As Long<\/span>, _\r\n        strBeschreibung<span style=\"color:blue;\"> As String<\/span>, <span style=\"color:blue;\">Optional<\/span> lngZeile<span style=\"color:blue;\"> As Long<\/span> = 0)\r\n    On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n    <span style=\"color:blue;\">Dim <\/span>strSQL<span style=\"color:blue;\"> As String<\/span>\r\n    <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n    strSQL = \"INSERT INTO tblFehlerLog (Zeitpunkt, Benutzer, Prozedur, Modul, Fehlernummer, \" _\r\n           & \"Beschreibung, Zeilennummer) VALUES (#\" & Format(Now, \"yyyy-mm-dd hh:nn:ss\") & \"#, \" _\r\n           & \"'\" & <span style=\"color:blue;\">Replace<\/span>(Environ(\"USERNAME\"), \"'\", \"''\") & \"', \" & \"'\" & <span style=\"color:blue;\">Replace<\/span>(strProzedur, \"'\", \"''\") _\r\n           & \"', '\" & <span style=\"color:blue;\">Replace<\/span>(strModul, \"'\", \"''\") & \"', \" & lngNummer & \", '\" & <span style=\"color:blue;\">Replace<\/span>(strBeschreibung, \"'\", \"''\") _\r\n           & \"', \" & lngZeile & \")\"\r\n    db.Execute strSQL, dbFailOnError\r\n    <span style=\"color:blue;\">Set<\/span> db = Nothing\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 3: Die zentrale Prozedur FehlerProtokollieren mit Zeilennummer<\/span><\/b><\/p>\n<p>Der letzte Parameter ist bewusst als <b>Optional<\/b> deklariert und mit <b>0<\/b> vorbelegt. So funktioniert die Prozedur auch dort weiter, wo der Code (noch) keine Zeilennummern tr&auml;gt &#8211; im Protokoll steht dann eben eine <b>0<\/b>, und wir wissen sofort, woran es liegt.<\/p>\n<p>Warum ausgerechnet hier <b>On Error Resume Next<\/b>? Ganz einfach: Die Protokollprozedur darf selbst niemals einen Fehler ausl&ouml;sen, sonst verlieren wir den Originalfehler. Schl&auml;gt das Protokollieren fehl &#8211; etwa weil die Tabelle fehlt -, geht der Eintrag still verloren. Das ist immer noch besser als ein zweiter, verwirrender Fehler.<\/p>\n<p>Eingebunden wird sie im Fehlerblock der aufrufenden Prozedur &#8211; hier siehst Du die wenigen Zeilen, die daf&uuml;r n&ouml;tig sind:<\/p>\n<pre>ErrHandler:\r\n    FehlerProtokollieren \"DatenExportieren\", _\r\n        \"mdlFehlerbehandlung_Beispiele\", _\r\n        Err.Number, Err.Description, Erl\r\n    <span style=\"color:blue;\">MsgBox<\/span> \"Ein unerwarteter Fehler ist aufgetreten.\" _\r\n         & <span style=\"color:blue;\">vbCrLf<\/span> & \"Die Details wurden protokolliert.\", _\r\n           <span style=\"color:blue;\">vbCr<\/span>itical\r\n    Resume ExitHere<\/pre>\n<p>Wichtig ist die Reihenfolge: Der Aufruf steht als erste Anweisung im Fehlerblock, damit <b>Erl<\/b> und die Eigenschaften des <b>Err<\/b>-Objekts noch gef&uuml;llt sind.<\/p>\n<p>Der Anwender sieht daraufhin nur eine neutrale Meldung, w&auml;hrend die technischen Details in <b>tblFehlerLog<\/b> landen &#8211; inklusive der Zeile, in der es geknallt hat (Bild 5).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2026_03\/pic_509_005.png\" alt=\"Protokolltabelle mit Beispieldatens&auml;tzen\" width=\"700\" height=\"151,6549\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 5: Protokolltabelle mit Beispieldatens&auml;tzen<\/span><\/b><\/p>\n<h2>Endlosschleifen mit Resume vermeiden<\/h2>\n<p>Weiter oben haben wir gesehen, dass <b>Resume<\/b> die fehlerausl&ouml;sende Zeile wiederholt &#8211; und dass daraus eine Endlosschleife wird, wenn die Ursache nicht verschwindet. Ein Z&auml;hler schafft Abhilfe.<\/p>\n<p>Die Prozedur <b>MitWiederholung<\/b> in Listing 4 versucht bis zu dreimal, eine Datei zu &ouml;ffnen, die auf einem Netzlaufwerk liegen k&ouml;nnte.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>MitWiederholung(strPfad<span style=\"color:blue;\"> As String<\/span>)\r\n    <span style=\"color:blue;\">On Error GoTo<\/span> ErrHandler\r\n    <span style=\"color:blue;\">Dim <\/span>intRetry<span style=\"color:blue;\"> As Integer<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>intFile<span style=\"color:blue;\"> As Integer<\/span>\r\n    intFile = FreeFile\r\n    Open strPfad For Input<span style=\"color:blue;\"> As <\/span>#intFile\r\n    <span style=\"color:blue;\">Debug.Print<\/span> \"Datei ge&ouml;ffnet nach \" & intRetry & \" Wiederholungen.\"\r\nExitHere:\r\n    <span style=\"color:blue;\">If <\/span>intFile &gt; 0<span style=\"color:blue;\"> Then<\/span> Close #intFile\r\n    <span style=\"color:blue;\">Exit Sub<\/span>\r\nErrHandler:\r\n    intRetry = intRetry + 1\r\n    <span style=\"color:blue;\">If <\/span>intRetry &lt; 3<span style=\"color:blue;\"> Then<\/span>\r\n        <span style=\"color:blue;\">Debug.Print<\/span> \"Versuch \" & intRetry & \" fehlgeschlagen, neuer Versuch ...\"\r\n        Resume\r\n    <span style=\"color:blue;\">Else<\/span>\r\n        <span style=\"color:blue;\">MsgBox<\/span> \"Fehler nach \" & intRetry & \" Versuchen: \" _\r\n             & Err.Description, <span style=\"color:blue;\">vbCr<\/span>itical\r\n        Resume ExitHere\r\n    <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 4: Wiederholungsversuch mit Z&auml;hler<\/span><\/b><\/p>\n<p>Der Z&auml;hler <b>intRetry<\/b> wird beim Eintritt in die Prozedur auf <b>0<\/b> gesetzt und &uuml;berlebt die Spr&uuml;nge in den Fehlerblock &#8211; jeder Durchlauf erh&ouml;ht ihn um eins, nach dem dritten vergeblichen Versuch geben wir auf. F&uuml;r Netzwerkzugriffe oder Datenbankverbindungen, die kurzzeitig gest&ouml;rt sein k&ouml;nnen, kann dieses Muster sinnvoll sein. F&uuml;r einen Fehler, der sich nicht von selbst erledigt, bringt es dagegen nichts au&szlig;er Verz&ouml;gerung.<\/p>\n<h2>H&auml;ufige Fallen<\/h2>\n<p>Zum Schluss noch f&uuml;nf Fehler, die uns in der Praxis immer wieder begegnen:<\/p>\n<p>Falle 1: <b>On Error Resume Next<\/b> ohne Pr&uuml;fung. Wer <b>On Error Resume Next<\/b> setzt und <b>Err.Number<\/b> danach nie abfragt, verschluckt jeden Fehler. Die Folgeprobleme tauchen an ganz anderer Stelle auf und sind schwer zu diagnostizieren.<\/p>\n<p>Falle 2: <b>GoTo<\/b> statt <b>Resume<\/b> im Fehlerblock. Prozeduren bleiben nach <b>GoTo<\/b> im Fehlerzustand. Ein weiterer Fehler in der Aufr&auml;umlogik l&auml;sst sich dann nicht mehr abfangen.<\/p>\n<p>Falle 3: Fehlerbehandlung in aufgerufenen Prozeduren vergessen. Hat Prozedur <b>A<\/b> eine Fehlerbehandlung und ruft Prozedur <b>B<\/b> auf, die keine hat, f&auml;ngt <b>A<\/b> den Fehler aus <b>B<\/b> zwar ab.<\/p>\n<p>Nur meldet <b>Erl<\/b> dann die Aufrufzeile in <b>A<\/b> und nicht die tats&auml;chliche Fehlerzeile in <b>B<\/b> &#8211; das Protokoll f&uuml;hrt uns also mit einer scheinbar pr&auml;zisen Zahl in die Irre. Deshalb bekommt auch die kleinste Hilfsprozedur ihren eigenen Fehlerblock.<\/p>\n<p>Falle 4: <b>Err.Clear<\/b> zwischen mehreren Pr&uuml;fungen vergessen. Pr&uuml;fen wir mehrere Operationen nacheinander mit <b>On Error Resume Next<\/b>, m&uuml;ssen wir zwischendurch <b>Err.Clear<\/b> aufrufen &#8211; sonst ordnen wir einen Fehler aus der ersten Operation f&auml;lschlich der zweiten zu:<\/p>\n<pre>On Error Resume <span style=\"color:blue;\">Next<\/span>\r\nKill \"C:\\Datei1.txt\"\r\n<span style=\"color:blue;\">If <\/span>Err.Number &lt;&gt; 0<span style=\"color:blue;\"> Then<\/span> <span style=\"color:blue;\">Debug.Print<\/span> \"Datei1: \" & Err.Description\r\nErr.Clear\r\nKill \"C:\\Datei2.txt\"\r\n<span style=\"color:blue;\">If <\/span>Err.Number &lt;&gt; 0<span style=\"color:blue;\"> Then<\/span> <span style=\"color:blue;\">Debug.Print<\/span> \"Datei2: \" & Err.Description\r\n<span style=\"color:blue;\">On Error GoTo<\/span> 0<\/pre>\n<p>Falle 5: <b>MsgBox<\/b> im Fehlerblock einer Prozedur, die im Hintergrund l&auml;uft. Timer-Prozeduren wie <b>Form_Timer<\/b>, Ereignisprozeduren oder automatisch gestartete Abl&auml;ufe sollten im Fehlerblock keine <b>MsgBox<\/b> anzeigen &#8211; sie blockiert den gesamten Ablauf und wartet wom&ouml;glich stundenlang auf einen Klick, den niemand tut. Hier ist das Protokollieren in <b>tblFehlerLog<\/b> die richtige Wahl.<\/p>\n<h2>Zusammenfassung und Ausblick<\/h2>\n<p>Fehlerbehandlung in VBA folgt wenigen, aber wichtigen Regeln. Jede nicht-triviale Prozedur braucht ein <b>On Error GoTo<\/b> mit Fehlerblock und Austrittsmarke. Ressourcen werden in der Austrittsmarke freigegeben, nicht im Fehlerblock allein.<\/p>\n<p><b>On Error Resume Next<\/b> ist ein Pr&auml;zisionswerkzeug f&uuml;r einzelne Zeilen und kein Rundumschutz. <b>Err.Raise<\/b> macht den Fehler zum Kommunikationsmittel zwischen den Schichten einer Anwendung. Und mit nummerierten Zeilen und <b>Erl<\/b> protokollieren wir in <b>tblFehlerLog<\/b> nicht nur, was schiefgelaufen ist, sondern auch wo.<\/p>\n<p>Drei Richtungen bieten sich zum Weiterlesen an. Wer <b>Erl<\/b> ernsthaft einsetzen will, braucht die Zeilennummern automatisch &#8211; wie sich der VBA-Code per Add-In umschreiben l&auml;sst, zeigt der Beitrag <b> VBA-Editor: Quellcode-Bearbeitung automatisieren<\/b> (<b>www.vbentwickler.de\/426<\/b>), und ein Werkzeug zum Nummerieren und Entnummerieren ist damit nur noch eine Finger&uuml;bung.<\/p>\n<p>Der Beitrag <b> SQL Server: Fehlerbehandlung in DAO und ADODB<\/b> (<b>www.vbentwickler.de\/451<\/b>) vertieft, was beim Zugriff auf SQL-Server-Daten hinzukommt &#8211; dort spielen die <b>Errors<\/b>-Auflistungen beider Bibliotheken die Hauptrolle, weil ein einziger Vorgang mehrere Fehler gleichzeitig melden kann.<\/p>\n<p>Und wer Fehler in eigenen Klassen einsetzen m&ouml;chte, findet in den Beitr&auml;gen  <b>Klassen programmieren unter VBA <\/b>(<b>www.vbentwickler.de\/423<\/b>),  <b>Wozu mit Klassen programmieren? <\/b>(<b>www.vbentwickler.de\/424<\/b>) und  <b>Ereignisse in Klassen programmieren <\/b>(<b>www.vbentwickler.de\/425<\/b>) die Grundlagen zu <b>WithEvents<\/b> und <b>RaiseEvent<\/b>, die sich hervorragend mit <b>Err.Raise<\/b> kombinieren lassen.<\/p>\n<h2>Downloads zu diesem Beitrag<\/h2>\n<p>Enthaltene Beispieldateien:<\/p>\n<p>VBA_Fehlerbehandlung.accdb<\/p>\n<p><a href=\"..\/fileadmin\/beispiele\/78F04EE3-DCAA-4646-BCBC-7E5D35A58FF7\/vbe_509.zip\">Download<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Eine Prozedur, die monatelang unauff&auml;llig ihren Dienst getan hat, bricht pl&ouml;tzlich mit einer kryptischen Meldung ab &#8211; und der Anwender steht vor einem Dialog, mit dem er nichts anfangen kann. Der Grund ist fast immer derselbe: Es gibt keine oder nur eine halbherzige Fehlerbehandlung. Dabei ist &#8220;On Error&#8221; eines der m&auml;chtigsten Werkzeuge in VBA, wenn man wei&szlig;, wie man es einsetzt. Wir schauen uns die Muster an, die aus einer fragilen L&ouml;sung eine robuste machen: wie wir Fehler nicht nur abfangen, sondern strukturiert behandeln, Ressourcen zuverl&auml;ssig freigeben, Fehler zwischen den Schichten einer Anwendung weiterreichen und sie in einer Tabelle protokollieren. Die Beispiele findest Du im Modul &#8220;mdlFehlerbehandlung&#8221; der Beispieldatenbank. Wie das im Einzelnen gelingt, zeigt der vorliegende Beitrag.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[662026,66032026,44000025],"tags":[],"yst_prominent_words":[],"class_list":["post-55000509","post","type-post","status-publish","format-standard","hentry","category-662026","category-66032026","category-VBAProgrammierung"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 4.9.10 - aioseo.com -->\n\t<meta name=\"description\" content=\"Eine Prozedur, die monatelang unauff\u00e4llig ihren Dienst getan hat, bricht pl\u00f6tzlich mit einer kryptischen Meldung ab - und der Anwender steht vor einem Dialog, mit dem er nichts anfangen kann. Der Grund ist fast immer derselbe: Es gibt keine oder nur eine halbherzige Fehlerbehandlung. Dabei ist &quot;On Error&quot; eines der m\u00e4chtigsten Werkzeuge in VBA, wenn man wei\u00df, wie man es einsetzt. Wir schauen uns die Muster an, die aus einer fragilen L\u00f6sung eine robuste machen: wie wir Fehler nicht nur abfangen, sondern strukturiert behandeln, Ressourcen zuverl\u00e4ssig freigeben, Fehler zwischen den Schichten einer Anwendung weiterreichen und sie in einer Tabelle protokollieren. Die Beispiele findest Du im Modul &quot;mdlFehlerbehandlung&quot; der Beispieldatenbank. Wie das im Einzelnen gelingt, zeigt der vorliegende Beitrag.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Andr\u00e9 Minhorst\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/vbentwickler.de\/Fehlerbehandlung_in_VBA_Patterns_fuer_die_Praxis\/\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 4.9.10\" \/>\n\t\t<meta property=\"og:locale\" content=\"de_DE\" \/>\n\t\t<meta property=\"og:site_name\" content=\"Visual Basic Entwickler - Das Magazin f\u00fcr Datenbankentwickler auf Basis von Visual Studio und Co.\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"Fehlerbehandlung in VBA: Patterns f\u00fcr die Praxis - Visual Basic Entwickler\" \/>\n\t\t<meta property=\"og:description\" content=\"Eine Prozedur, die monatelang unauff\u00e4llig ihren Dienst getan hat, bricht pl\u00f6tzlich mit einer kryptischen Meldung ab - und der Anwender steht vor einem Dialog, mit dem er nichts anfangen kann. Der Grund ist fast immer derselbe: Es gibt keine oder nur eine halbherzige Fehlerbehandlung. Dabei ist &quot;On Error&quot; eines der m\u00e4chtigsten Werkzeuge in VBA, wenn man wei\u00df, wie man es einsetzt. Wir schauen uns die Muster an, die aus einer fragilen L\u00f6sung eine robuste machen: wie wir Fehler nicht nur abfangen, sondern strukturiert behandeln, Ressourcen zuverl\u00e4ssig freigeben, Fehler zwischen den Schichten einer Anwendung weiterreichen und sie in einer Tabelle protokollieren. Die Beispiele findest Du im Modul &quot;mdlFehlerbehandlung&quot; der Beispieldatenbank. Wie das im Einzelnen gelingt, zeigt der vorliegende Beitrag.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/vbentwickler.de\/Fehlerbehandlung_in_VBA_Patterns_fuer_die_Praxis\/\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/datenbankentwickler.net\/wp-content\/uploads\/2022\/08\/cropped-header_vbe-1.png\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/datenbankentwickler.net\/wp-content\/uploads\/2022\/08\/cropped-header_vbe-1.png\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2026-07-28T14:35:34+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"-001-11-30T00:00:00+00:00\" \/>\n\t\t<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n\t\t<meta name=\"twitter:title\" content=\"Fehlerbehandlung in VBA: Patterns f\u00fcr die Praxis - Visual Basic Entwickler\" \/>\n\t\t<meta name=\"twitter:description\" content=\"Eine Prozedur, die monatelang unauff\u00e4llig ihren Dienst getan hat, bricht pl\u00f6tzlich mit einer kryptischen Meldung ab - und der Anwender steht vor einem Dialog, mit dem er nichts anfangen kann. Der Grund ist fast immer derselbe: Es gibt keine oder nur eine halbherzige Fehlerbehandlung. Dabei ist &quot;On Error&quot; eines der m\u00e4chtigsten Werkzeuge in VBA, wenn man wei\u00df, wie man es einsetzt. Wir schauen uns die Muster an, die aus einer fragilen L\u00f6sung eine robuste machen: wie wir Fehler nicht nur abfangen, sondern strukturiert behandeln, Ressourcen zuverl\u00e4ssig freigeben, Fehler zwischen den Schichten einer Anwendung weiterreichen und sie in einer Tabelle protokollieren. Die Beispiele findest Du im Modul &quot;mdlFehlerbehandlung&quot; der Beispieldatenbank. Wie das im Einzelnen gelingt, zeigt der vorliegende Beitrag.\" \/>\n\t\t<meta name=\"twitter:image\" content=\"https:\/\/datenbankentwickler.net\/wp-content\/uploads\/2022\/08\/cropped-header_vbe-1.png\" \/>\n\t\t<script type=\"application\/ld+json\" class=\"aioseo-schema\">\n\t\t\t{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"BlogPosting\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/Fehlerbehandlung_in_VBA_Patterns_fuer_die_Praxis\\\/#blogposting\",\"name\":\"Fehlerbehandlung in VBA: Patterns f\\u00fcr die Praxis - Visual Basic Entwickler\",\"headline\":\"Fehlerbehandlung in VBA: Patterns f&uuml;r die Praxis\",\"author\":{\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/author\\\/andreminhorst-com\\\/#author\"},\"publisher\":{\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/#organization\"},\"image\":{\"@type\":\"ImageObject\",\"url\":\"http:\\\/\\\/vg08.met.vgwort.de\\\/na\\\/c236c65793804408857b50de3485e0f2\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/Fehlerbehandlung_in_VBA_Patterns_fuer_die_Praxis\\\/#articleImage\"},\"datePublished\":\"2026-06-01T00:00:00+00:00\",\"dateModified\":\"-0001-11-30T00:00:00+00:00\",\"inLanguage\":\"de-DE\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/Fehlerbehandlung_in_VBA_Patterns_fuer_die_Praxis\\\/#webpage\"},\"isPartOf\":{\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/Fehlerbehandlung_in_VBA_Patterns_fuer_die_Praxis\\\/#webpage\"},\"articleSection\":\"2026, 3\\\/2026, VBA-Programmierung\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/Fehlerbehandlung_in_VBA_Patterns_fuer_die_Praxis\\\/#breadcrumblist\",\"itemListElement\":[{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/vbentwickler.de#listItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/vbentwickler.de\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/category\\\/2026\\\/#listItem\",\"name\":\"2026\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/category\\\/2026\\\/#listItem\",\"position\":2,\"name\":\"2026\",\"item\":\"https:\\\/\\\/vbentwickler.de\\\/category\\\/2026\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/category\\\/2026\\\/3\\\/2026\\\/#listItem\",\"name\":\"3\\\/2026\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/vbentwickler.de#listItem\",\"name\":\"Home\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/category\\\/2026\\\/3\\\/2026\\\/#listItem\",\"position\":3,\"name\":\"3\\\/2026\",\"item\":\"https:\\\/\\\/vbentwickler.de\\\/category\\\/2026\\\/3\\\/2026\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/Fehlerbehandlung_in_VBA_Patterns_fuer_die_Praxis\\\/#listItem\",\"name\":\"Fehlerbehandlung in VBA: Patterns f&uuml;r die Praxis\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/category\\\/2026\\\/#listItem\",\"name\":\"2026\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/Fehlerbehandlung_in_VBA_Patterns_fuer_die_Praxis\\\/#listItem\",\"position\":4,\"name\":\"Fehlerbehandlung in VBA: Patterns f&uuml;r die Praxis\",\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/category\\\/2026\\\/3\\\/2026\\\/#listItem\",\"name\":\"3\\\/2026\"}}]},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/#organization\",\"name\":\"Datenbankentwickler\",\"description\":\"Das Magazin f\\u00fcr Datenbankentwickler auf Basis von Visual Studio und Co.\",\"url\":\"https:\\\/\\\/vbentwickler.de\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https:\\\/\\\/vbentwickler.de\\\/wp-content\\\/uploads\\\/2022\\\/08\\\/cropped-header_vbe-1.png\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/Fehlerbehandlung_in_VBA_Patterns_fuer_die_Praxis\\\/#organizationLogo\",\"width\":664,\"height\":225},\"image\":{\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/Fehlerbehandlung_in_VBA_Patterns_fuer_die_Praxis\\\/#organizationLogo\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/author\\\/andreminhorst-com\\\/#author\",\"url\":\"https:\\\/\\\/vbentwickler.de\\\/author\\\/andreminhorst-com\\\/\",\"name\":\"Andr\\u00e9 Minhorst\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/Fehlerbehandlung_in_VBA_Patterns_fuer_die_Praxis\\\/#authorImage\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"width\":96,\"height\":96,\"caption\":\"Andr\\u00e9 Minhorst\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/Fehlerbehandlung_in_VBA_Patterns_fuer_die_Praxis\\\/#webpage\",\"url\":\"https:\\\/\\\/vbentwickler.de\\\/Fehlerbehandlung_in_VBA_Patterns_fuer_die_Praxis\\\/\",\"name\":\"Fehlerbehandlung in VBA: Patterns f\\u00fcr die Praxis - Visual Basic Entwickler\",\"description\":\"Eine Prozedur, die monatelang unauff\\u00e4llig ihren Dienst getan hat, bricht pl\\u00f6tzlich mit einer kryptischen Meldung ab - und der Anwender steht vor einem Dialog, mit dem er nichts anfangen kann. Der Grund ist fast immer derselbe: Es gibt keine oder nur eine halbherzige Fehlerbehandlung. Dabei ist \\\"On Error\\\" eines der m\\u00e4chtigsten Werkzeuge in VBA, wenn man wei\\u00df, wie man es einsetzt. Wir schauen uns die Muster an, die aus einer fragilen L\\u00f6sung eine robuste machen: wie wir Fehler nicht nur abfangen, sondern strukturiert behandeln, Ressourcen zuverl\\u00e4ssig freigeben, Fehler zwischen den Schichten einer Anwendung weiterreichen und sie in einer Tabelle protokollieren. Die Beispiele findest Du im Modul \\\"mdlFehlerbehandlung\\\" der Beispieldatenbank. Wie das im Einzelnen gelingt, zeigt der vorliegende Beitrag.\",\"inLanguage\":\"de-DE\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/#website\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/Fehlerbehandlung_in_VBA_Patterns_fuer_die_Praxis\\\/#breadcrumblist\"},\"author\":{\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/author\\\/andreminhorst-com\\\/#author\"},\"creator\":{\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/author\\\/andreminhorst-com\\\/#author\"},\"datePublished\":\"2026-06-01T00:00:00+00:00\",\"dateModified\":\"-0001-11-30T00:00:00+00:00\"},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/#website\",\"url\":\"https:\\\/\\\/vbentwickler.de\\\/\",\"name\":\"Datenbankentwickler\",\"description\":\"Das Magazin f\\u00fcr Datenbankentwickler auf Basis von Visual Studio und Co.\",\"inLanguage\":\"de-DE\",\"publisher\":{\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/#organization\"}}]}\n\t\t<\/script>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"Fehlerbehandlung in VBA: Patterns f\u00fcr die Praxis - Visual Basic Entwickler","description":"Eine Prozedur, die monatelang unauff\u00e4llig ihren Dienst getan hat, bricht pl\u00f6tzlich mit einer kryptischen Meldung ab - und der Anwender steht vor einem Dialog, mit dem er nichts anfangen kann. Der Grund ist fast immer derselbe: Es gibt keine oder nur eine halbherzige Fehlerbehandlung. Dabei ist \"On Error\" eines der m\u00e4chtigsten Werkzeuge in VBA, wenn man wei\u00df, wie man es einsetzt. Wir schauen uns die Muster an, die aus einer fragilen L\u00f6sung eine robuste machen: wie wir Fehler nicht nur abfangen, sondern strukturiert behandeln, Ressourcen zuverl\u00e4ssig freigeben, Fehler zwischen den Schichten einer Anwendung weiterreichen und sie in einer Tabelle protokollieren. Die Beispiele findest Du im Modul \"mdlFehlerbehandlung\" der Beispieldatenbank. Wie das im Einzelnen gelingt, zeigt der vorliegende Beitrag.","canonical_url":"https:\/\/vbentwickler.de\/Fehlerbehandlung_in_VBA_Patterns_fuer_die_Praxis\/","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"BlogPosting","@id":"https:\/\/vbentwickler.de\/Fehlerbehandlung_in_VBA_Patterns_fuer_die_Praxis\/#blogposting","name":"Fehlerbehandlung in VBA: Patterns f\u00fcr die Praxis - Visual Basic Entwickler","headline":"Fehlerbehandlung in VBA: Patterns f&uuml;r die Praxis","author":{"@id":"https:\/\/vbentwickler.de\/author\/andreminhorst-com\/#author"},"publisher":{"@id":"https:\/\/vbentwickler.de\/#organization"},"image":{"@type":"ImageObject","url":"http:\/\/vg08.met.vgwort.de\/na\/c236c65793804408857b50de3485e0f2","@id":"https:\/\/vbentwickler.de\/Fehlerbehandlung_in_VBA_Patterns_fuer_die_Praxis\/#articleImage"},"datePublished":"2026-06-01T00:00:00+00:00","dateModified":"-0001-11-30T00:00:00+00:00","inLanguage":"de-DE","mainEntityOfPage":{"@id":"https:\/\/vbentwickler.de\/Fehlerbehandlung_in_VBA_Patterns_fuer_die_Praxis\/#webpage"},"isPartOf":{"@id":"https:\/\/vbentwickler.de\/Fehlerbehandlung_in_VBA_Patterns_fuer_die_Praxis\/#webpage"},"articleSection":"2026, 3\/2026, VBA-Programmierung"},{"@type":"BreadcrumbList","@id":"https:\/\/vbentwickler.de\/Fehlerbehandlung_in_VBA_Patterns_fuer_die_Praxis\/#breadcrumblist","itemListElement":[{"@type":"ListItem","@id":"https:\/\/vbentwickler.de#listItem","position":1,"name":"Home","item":"https:\/\/vbentwickler.de","nextItem":{"@type":"ListItem","@id":"https:\/\/vbentwickler.de\/category\/2026\/#listItem","name":"2026"}},{"@type":"ListItem","@id":"https:\/\/vbentwickler.de\/category\/2026\/#listItem","position":2,"name":"2026","item":"https:\/\/vbentwickler.de\/category\/2026\/","nextItem":{"@type":"ListItem","@id":"https:\/\/vbentwickler.de\/category\/2026\/3\/2026\/#listItem","name":"3\/2026"},"previousItem":{"@type":"ListItem","@id":"https:\/\/vbentwickler.de#listItem","name":"Home"}},{"@type":"ListItem","@id":"https:\/\/vbentwickler.de\/category\/2026\/3\/2026\/#listItem","position":3,"name":"3\/2026","item":"https:\/\/vbentwickler.de\/category\/2026\/3\/2026\/","nextItem":{"@type":"ListItem","@id":"https:\/\/vbentwickler.de\/Fehlerbehandlung_in_VBA_Patterns_fuer_die_Praxis\/#listItem","name":"Fehlerbehandlung in VBA: Patterns f&uuml;r die Praxis"},"previousItem":{"@type":"ListItem","@id":"https:\/\/vbentwickler.de\/category\/2026\/#listItem","name":"2026"}},{"@type":"ListItem","@id":"https:\/\/vbentwickler.de\/Fehlerbehandlung_in_VBA_Patterns_fuer_die_Praxis\/#listItem","position":4,"name":"Fehlerbehandlung in VBA: Patterns f&uuml;r die Praxis","previousItem":{"@type":"ListItem","@id":"https:\/\/vbentwickler.de\/category\/2026\/3\/2026\/#listItem","name":"3\/2026"}}]},{"@type":"Organization","@id":"https:\/\/vbentwickler.de\/#organization","name":"Datenbankentwickler","description":"Das Magazin f\u00fcr Datenbankentwickler auf Basis von Visual Studio und Co.","url":"https:\/\/vbentwickler.de\/","logo":{"@type":"ImageObject","url":"https:\/\/vbentwickler.de\/wp-content\/uploads\/2022\/08\/cropped-header_vbe-1.png","@id":"https:\/\/vbentwickler.de\/Fehlerbehandlung_in_VBA_Patterns_fuer_die_Praxis\/#organizationLogo","width":664,"height":225},"image":{"@id":"https:\/\/vbentwickler.de\/Fehlerbehandlung_in_VBA_Patterns_fuer_die_Praxis\/#organizationLogo"}},{"@type":"Person","@id":"https:\/\/vbentwickler.de\/author\/andreminhorst-com\/#author","url":"https:\/\/vbentwickler.de\/author\/andreminhorst-com\/","name":"Andr\u00e9 Minhorst","image":{"@type":"ImageObject","@id":"https:\/\/vbentwickler.de\/Fehlerbehandlung_in_VBA_Patterns_fuer_die_Praxis\/#authorImage","url":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","width":96,"height":96,"caption":"Andr\u00e9 Minhorst"}},{"@type":"WebPage","@id":"https:\/\/vbentwickler.de\/Fehlerbehandlung_in_VBA_Patterns_fuer_die_Praxis\/#webpage","url":"https:\/\/vbentwickler.de\/Fehlerbehandlung_in_VBA_Patterns_fuer_die_Praxis\/","name":"Fehlerbehandlung in VBA: Patterns f\u00fcr die Praxis - Visual Basic Entwickler","description":"Eine Prozedur, die monatelang unauff\u00e4llig ihren Dienst getan hat, bricht pl\u00f6tzlich mit einer kryptischen Meldung ab - und der Anwender steht vor einem Dialog, mit dem er nichts anfangen kann. Der Grund ist fast immer derselbe: Es gibt keine oder nur eine halbherzige Fehlerbehandlung. Dabei ist \"On Error\" eines der m\u00e4chtigsten Werkzeuge in VBA, wenn man wei\u00df, wie man es einsetzt. Wir schauen uns die Muster an, die aus einer fragilen L\u00f6sung eine robuste machen: wie wir Fehler nicht nur abfangen, sondern strukturiert behandeln, Ressourcen zuverl\u00e4ssig freigeben, Fehler zwischen den Schichten einer Anwendung weiterreichen und sie in einer Tabelle protokollieren. Die Beispiele findest Du im Modul \"mdlFehlerbehandlung\" der Beispieldatenbank. Wie das im Einzelnen gelingt, zeigt der vorliegende Beitrag.","inLanguage":"de-DE","isPartOf":{"@id":"https:\/\/vbentwickler.de\/#website"},"breadcrumb":{"@id":"https:\/\/vbentwickler.de\/Fehlerbehandlung_in_VBA_Patterns_fuer_die_Praxis\/#breadcrumblist"},"author":{"@id":"https:\/\/vbentwickler.de\/author\/andreminhorst-com\/#author"},"creator":{"@id":"https:\/\/vbentwickler.de\/author\/andreminhorst-com\/#author"},"datePublished":"2026-06-01T00:00:00+00:00","dateModified":"-0001-11-30T00:00:00+00:00"},{"@type":"WebSite","@id":"https:\/\/vbentwickler.de\/#website","url":"https:\/\/vbentwickler.de\/","name":"Datenbankentwickler","description":"Das Magazin f\u00fcr Datenbankentwickler auf Basis von Visual Studio und Co.","inLanguage":"de-DE","publisher":{"@id":"https:\/\/vbentwickler.de\/#organization"}}]},"og:locale":"de_DE","og:site_name":"Visual Basic Entwickler - Das Magazin f\u00fcr Datenbankentwickler auf Basis von Visual Studio und Co.","og:type":"article","og:title":"Fehlerbehandlung in VBA: Patterns f\u00fcr die Praxis - Visual Basic Entwickler","og:description":"Eine Prozedur, die monatelang unauff\u00e4llig ihren Dienst getan hat, bricht pl\u00f6tzlich mit einer kryptischen Meldung ab - und der Anwender steht vor einem Dialog, mit dem er nichts anfangen kann. Der Grund ist fast immer derselbe: Es gibt keine oder nur eine halbherzige Fehlerbehandlung. Dabei ist &quot;On Error&quot; eines der m\u00e4chtigsten Werkzeuge in VBA, wenn man wei\u00df, wie man es einsetzt. Wir schauen uns die Muster an, die aus einer fragilen L\u00f6sung eine robuste machen: wie wir Fehler nicht nur abfangen, sondern strukturiert behandeln, Ressourcen zuverl\u00e4ssig freigeben, Fehler zwischen den Schichten einer Anwendung weiterreichen und sie in einer Tabelle protokollieren. Die Beispiele findest Du im Modul &quot;mdlFehlerbehandlung&quot; der Beispieldatenbank. Wie das im Einzelnen gelingt, zeigt der vorliegende Beitrag.","og:url":"https:\/\/vbentwickler.de\/Fehlerbehandlung_in_VBA_Patterns_fuer_die_Praxis\/","og:image":"https:\/\/datenbankentwickler.net\/wp-content\/uploads\/2022\/08\/cropped-header_vbe-1.png","og:image:secure_url":"https:\/\/datenbankentwickler.net\/wp-content\/uploads\/2022\/08\/cropped-header_vbe-1.png","article:published_time":"2026-07-28T14:35:34+00:00","article:modified_time":"-001-11-30T00:00:00+00:00","twitter:card":"summary_large_image","twitter:title":"Fehlerbehandlung in VBA: Patterns f\u00fcr die Praxis - Visual Basic Entwickler","twitter:description":"Eine Prozedur, die monatelang unauff\u00e4llig ihren Dienst getan hat, bricht pl\u00f6tzlich mit einer kryptischen Meldung ab - und der Anwender steht vor einem Dialog, mit dem er nichts anfangen kann. Der Grund ist fast immer derselbe: Es gibt keine oder nur eine halbherzige Fehlerbehandlung. Dabei ist &quot;On Error&quot; eines der m\u00e4chtigsten Werkzeuge in VBA, wenn man wei\u00df, wie man es einsetzt. Wir schauen uns die Muster an, die aus einer fragilen L\u00f6sung eine robuste machen: wie wir Fehler nicht nur abfangen, sondern strukturiert behandeln, Ressourcen zuverl\u00e4ssig freigeben, Fehler zwischen den Schichten einer Anwendung weiterreichen und sie in einer Tabelle protokollieren. Die Beispiele findest Du im Modul &quot;mdlFehlerbehandlung&quot; der Beispieldatenbank. Wie das im Einzelnen gelingt, zeigt der vorliegende Beitrag.","twitter:image":"https:\/\/datenbankentwickler.net\/wp-content\/uploads\/2022\/08\/cropped-header_vbe-1.png"},"aioseo_meta_data":{"post_id":"55000509","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":"default","schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"limit_modified_date":false,"created":"2026-07-28 12:58:34","updated":"2026-07-28 12:58:34","ai":null,"breadcrumb_settings":null,"seo_analyzer_scan_date":null},"aioseo_breadcrumb":"<div class=\"aioseo-breadcrumbs\"><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/vbentwickler.de\" title=\"Home\">Home<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/vbentwickler.de\/category\/2026\/\" title=\"2026\">2026<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/vbentwickler.de\/category\/2026\/3\/2026\/\" title=\"3\/2026\">3\/2026<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\tFehlerbehandlung in VBA: Patterns f\u00fcr die Praxis\n\t\t<\/span><\/div>","aioseo_breadcrumb_json":[{"label":"Home","link":"https:\/\/vbentwickler.de"},{"label":"2026","link":"https:\/\/vbentwickler.de\/category\/2026\/"},{"label":"3\/2026","link":"https:\/\/vbentwickler.de\/category\/2026\/3\/2026\/"},{"label":"Fehlerbehandlung in VBA: Patterns f&uuml;r die Praxis","link":"https:\/\/vbentwickler.de\/Fehlerbehandlung_in_VBA_Patterns_fuer_die_Praxis\/"}],"_links":{"self":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000509","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/comments?post=55000509"}],"version-history":[{"count":0,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000509\/revisions"}],"wp:attachment":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/media?parent=55000509"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/categories?post=55000509"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/tags?post=55000509"},{"taxonomy":"yst_prominent_words","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/yst_prominent_words?post=55000509"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}