Getestet in: Excel 365 v2509 · Excel 2021 · Excel 2019 · zuletzt geprüft am 08.06.2026
Kurz gesagt — Wenn ein Laufzeitfehler auftritt, füllt VBA ein einziges globales Objekt — Err — mit allem, was es über den Absturz weiß. Du liest es in einer Fehlerbehandlungsroutine, um zu entscheiden, was zu tun ist; du kannst es mit Err.Raise aber auch beschreiben, um einen eigenen Fehler auszulösen:
Sub PreisLesen()
On Error Resume Next
Dim preis As Double
preis = CDbl(Range("A1").Value) ' scheitert, wenn A1 nicht numerisch ist
If Err.Number <> 0 Then
MsgBox "Fehler " & Err.Number & ": " & Err.Description
Err.Clear ' zurücksetzen, damit die nächste Prüfung sauber ist
End If
On Error GoTo 0
End Sub
Das ganze Objekt an einem Ort:
Err.Number ' der Fehlercode — 0 bedeutet "kein Fehler"
Err.Description ' die für Menschen lesbare Meldung
Err.Source ' wer ihn ausgelöst hat (Projekt-/Objektname)
Err.Raise 513 ' selbst einen Fehler AUSLÖSEN
Err.Clear ' Err wieder in einen sauberen Zustand zurücksetzen
Das Denkmodell: Err ist die Blackbox des letzten Absturzes
Err ist ein einziges, immer vorhandenes, globales Objekt. Stell es dir als Flugschreiber deines Makros vor: In dem Moment, in dem ein Laufzeitfehler auftritt, schreibt VBA drei Fakten hinein, bevor die Steuerung zu deiner Routine springt —
Err.Number— der numerische Code (1004,13,9…).0heißt „nichts ist schiefgegangen".Err.Description— derselbe Text, den du im roten Dialog sähst („Typen unverträglich", „Index außerhalb des gültigen Bereichs").Err.Source— welches Projekt oder Objekt ihn ausgelöst hat.
Es gibt nur ein Err-Objekt für die ganze Sitzung, und es hält den jüngsten Fehler. Deshalb zählt das Wann du es liest genauso viel wie das Was du liest — und deshalb wird es automatisch gelöscht (mehr dazu gleich).
Die eine Regel: Err.Number ist das einzig verlässliche „ist es wirklich gescheitert?"
Nach On Error Resume Next läuft dein Code weiter, egal ob die Zeile funktioniert hat oder nicht. Der einzige Weg zu wissen, was von beidem passierte, ist, Err.Number zu lesen:
On Error Resume Next
Set wb = Workbooks("Budget.xlsx") ' ist diese Mappe schon offen?
If Err.Number = 0 Then
MsgBox "Bereits geöffnet."
Else
Err.Clear
Set wb = Workbooks.Open("C:\Daten\Budget.xlsx")
End If
On Error GoTo 0
Resume Next ohne Err.Number-Prüfung ist vergeudet: Du hast VBA gesagt, es solle Fehlschläge ignorieren, erfährst aber nie, dass einer passiert ist. Die Prüfung ist die Behandlung. Das ist die Begleitregel zu On Error Resume Next — die beiden funktionieren nur als Paar.
Du kannst auch nach dem konkreten Code verzweigen, denn verschiedene Nummern bedeuten verschiedene Probleme:
Select Case Err.Number
Case 0: ' kein Fehler
Case 9: MsgBox "Dieses Blatt oder dieser Index existiert nicht." ' Index außerhalb des Bereichs
Case 13: MsgBox "Dieser Wert hat nicht den richtigen Typ." ' Typen unverträglich
Case 1004: MsgBox "Excel hat diesen Vorgang verweigert." ' allgemeiner Automatisierungsfehler
Case Else: MsgBox "Unerwarteter Fehler " & Err.Number & ": " & Err.Description
End Select
Die Falle: Err löscht sich, wenn du es am wenigsten erwartest
Err bleibt nicht gefüllt, bis du damit fertig bist. VBA setzt es bei jedem dieser Ereignisse automatisch auf Number = 0 zurück:
- eine
On Error-Anweisung jeder Art (einschließlichOn Error GoTo 0) - ein
ResumeoderResume Next Exit Sub/Exit Function- der nächste Laufzeitfehler (er wird überschrieben, nicht angehängt)
Wenn du also Nummer oder Beschreibung nach einem dieser Ereignisse brauchst — um sie zu protokollieren, später zu zeigen, nach oben weiterzureichen —, sichere sie in eigene Variablen, sobald deine Routine startet:
Fehlerbehandlung:
Dim fehlerNum As Long, fehlerMsg As String
fehlerNum = Err.Number ' JETZT greifen
fehlerMsg = Err.Description
On Error Resume Next ' ← diese Zeile würde Err löschen ...
Application.ScreenUpdating = True ' ... das Aufräumen kann Err danach nicht mehr lesen
InsBlattProtokollieren fehlerNum, fehlerMsg ' die gesicherten Kopien nutzen, nicht Err.*
Dieser eine Stolperstein steckt hinter den meisten Bug-Meldungen „mein Fehlerprotokoll zeigt Fehler 0".
Eigene Fehler mit Err.Raise auslösen
Err zu lesen ist die halbe Miete. Die andere Hälfte ist, es zu beschreiben — gezielt einen Fehler auszulösen, wenn deine Regeln verletzt werden, nicht nur die von VBA:
Function NettoPreis(brutto As Double, steuerSatz As Double) As Double
If steuerSatz < 0 Or steuerSatz > 1 Then
Err.Raise vbObjectError + 513, "NettoPreis", _
"steuerSatz muss zwischen 0 und 1 liegen, war aber " & steuerSatz
End If
NettoPreis = brutto / (1 + steuerSatz)
End Function
Err.Raise Number, Source, Description erzeugt einen echten Laufzeitfehler — die On Error-Routine des Aufrufers fängt ihn genauso ab wie einen eingebauten. Nimm vbObjectError + n (mit n von 513 bis 65535) für eigene Fehler; diese Konstante versetzt dich sauber jenseits des Bereichs 0–512, den VBA für Systemcodes reserviert, sodass du nie mit einem echten kollidierst.
Die Meinung: einen Fehlercode zurückzugeben ist Hoffnung; einen auszulösen ist Durchsetzung
Viel VBA „validiert", indem es einen Platzhalter zurückgibt — -1, False, eine leere Zeichenfolge — und darauf vertraut, dass jeder Aufrufer daran denkt, ihn zu prüfen. Werden sie nicht. Sechs Monate später ruft jemand deine Funktion auf, ignoriert die -1 und dividiert durch sie.
Err.Raise nimmt die Wahl weg. Ein ausgelöster Fehler kann nicht stillschweigend ignoriert werden — er trifft entweder eine Routine oder stoppt das Makro. Genau das ist der Sinn. Err.Number zu lesen macht dich kompetent in der Fehlerbehandlung; eigene Fehler für falsche Eingaben und Geschäftsregeln auszulösen ist das, was deinen Code defensiv statt nur höflich macht. Wenn ein Wert das Ergebnis weiter unten zerstören würde, gib kein Flag zurück und hoffe — löse einen Fehler aus.
Häufige Err-Fehler (und die Lösung)
| Symptom | Ursache | Lösung |
|---|---|---|
| Protokoll zeigt immer „Fehler 0" | Err gelesen, nachdem Resume/On Error/Aufräumen es löschte |
Err.Number/Err.Description zuerst in Variablen sichern |
Resume Next „fängt" nichts |
Err.Number nach der riskanten Zeile nie geprüft |
If Err.Number <> 0 Then … ergänzen |
| eigener Fehler kollidiert mit einem System-Fehler | rohe kleine Nummer wie Err.Raise 5 verwendet |
Err.Raise vbObjectError + 513 aufwärts nehmen |
| zweite Prüfung feuert auf einem alten Fehler | Err.Clear nach der ersten Behandlung vergessen |
Err.Clear aufrufen, sobald er erledigt ist |
Err.Description ist leer |
nach Err.Clear oder einem Reset gelesen |
Beschreibung vor dem Löschen lesen |
Schluss mit handgeschriebener Fehler-Leitungsverlegung — beschreib die Regel einfach
Die Hälfte von robustem VBA ist genau das: Err.Number lesen, die Beschreibung sichern, eigene Fehler für falsche Daten auslösen, löschen, wiederholen. Es ist nötig und es ist mühsam. ExcelMaster Agent lässt dich „prüfe, dass der Steuersatz zwischen 0 und 1 liegt, und stopp mit einer klaren Meldung, falls nicht" in Klartext-Deutsch sagen — und das erzeugte Python löst den Fehler aus und meldet ihn für dich, mit zuvor gesicherter Datei. Kostenlos testen →
Verwandte Anleitungen
- VBA On Error — Resume Next vs. GoTo & warum Makros Bugs verstecken
- VBA Fehlerbehandlung — Das eine Muster, das jedes verlässliche Makro nutzt
- VBA Function in Excel — Rückgabewerte & eigene Arbeitsblattfunktionen
- VBA For-Schleife in Excel — 8 Praxisbeispiele
FAQ
Was ist das Err-Objekt in VBA?
Err ist ein globales Objekt, das Informationen über den jüngsten Laufzeitfehler hält. Seine wichtigsten Eigenschaften sind Err.Number (der Fehlercode, 0 = kein Fehler), Err.Description (die Meldung) und Err.Source (wer ihn auslöste). Du liest es in einer Fehlerbehandlungsroutine, um zu entscheiden, was zu tun ist.
Wie prüfe ich die Fehlernummer in VBA?
Lies Err.Number. Nach On Error Resume Next testest du mit If Err.Number <> 0 Then, ob die vorige Zeile gescheitert ist. Der Wert 0 bedeutet, dass kein Fehler auftrat. Mit Select Case Err.Number kannst du auf bestimmte Codes wie 9 (Index außerhalb des Bereichs) oder 13 (Typen unverträglich) unterschiedlich reagieren.
Wann wird das Err-Objekt zurückgesetzt?
Automatisch bei jeder On Error-Anweisung, bei Resume/Resume Next, bei Exit Sub/Exit Function und wenn der nächste Fehler es überschreibt. Brauchst du die Werte danach noch, kopiere Err.Number und Err.Description sofort in eigene Variablen. Manuell zurücksetzen kannst du es mit Err.Clear.
Wie löse ich einen eigenen Fehler in VBA aus?
Mit Err.Raise Number, Source, Description. Für eigene Fehler nimm vbObjectError + n, wobei n zwischen 513 und 65535 liegt, z. B. Err.Raise vbObjectError + 513, "MeineFunktion", "Ungültige Eingabe". Das vermeidet den für Systemfehler reservierten Bereich 0–512 und lässt die Routine des Aufrufers ihn wie jeden eingebauten Fehler abfangen.
Was ist der Unterschied zwischen Err.Clear und On Error GoTo 0?
Err.Clear setzt die Eigenschaften des Err-Objekts in einen sauberen Zustand zurück, lässt deinen Fehlerüberwachungs-Modus aber unverändert. On Error GoTo 0 setzt den Überwachungs-Modus auf den Standard (bei Fehler anhalten) zurück — und löscht als Nebeneffekt auch Err. Nimm Err.Clear, um Err innerhalb derselben Routine wiederzuverwenden; nimm On Error GoTo 0, um das Ignorieren von Fehlern zu beenden.
