Ich benutze MZ Tools für Excel VBA bei der Arbeit, und ich benutze ihre automatische Fehlerhandler-Funktion für die meisten meiner Verfahren, weil es mir ermöglicht, leicht meinen Kontakt Informationen in der Fehlermeldung und automatisch Display-Warnungen und Bildschirmaktualisierung wieder einschalten. Wenn jedoch ein Fehlerhandler in VBA verwendet wird, wird es schwierig, die genaue Codezeile zu finden, die den Fehler ausgelöst hat, insbesondere in einer längeren Prozedur. Der Standardwert war die einzige Möglichkeit, einen benutzerdefinierten Error-Handler zu verwenden und die Codezeile zu erhalten, die den Fehler ausgelöst hat, indem diese beiden Zeilen am Ende des Error-Handlers hinzugefügt wurden (damit die Problem-Zeile erneut ausgeführt wird) die Standard-Fehlerbehandlung nach dem Handler benutzerdefinierten Fehlers hatte seine Arbeit) getan:Wie zu vermeiden, Kaskadierung bei der Verwendung von Standard-Fehlerhandler zusätzlich zu benutzerdefinierten Fehlerhandler
On Error GoTo 0
Resume
das funktioniert gut, wenn es nur eine Fehler-Handler ist; Der Benutzer muss durch ein zusätzliches Dialogfeld klicken, aber ich kann normal debuggen, während die in meinen benutzerdefinierten Fehlerhandlern integrierte Funktionalität beibehalten wird. Wenn sowohl die aufrufende als auch die untergeordnete Routine unterschiedliche Fehlerbehandlungsroutinen haben, beginnt der Benutzer eine lange Kaskade ähnlich aussehender Dialogfelder zu erhalten. Genau, ich bekomme 1 + n! Dialogfelder, wobei n die Anzahl der Ebenen von Unterprogrammen mit Fehlerbehandlern ist.
Der einfachste Weg, um das Problem zu veranschaulichen, wenn ich die erste Routine laufen, bekomme ich 4 Fehlermeldungen statt nur 2:
Sub TstErrHndlr()
On Error GoTo TstErrHndlr_Error1
Call TstErrHndlrA
On Error GoTo 0
Exit Sub
TstErrHndlr_Error1:
Application.ScreenUpdating = True
Application.DisplayAlerts = True
Call MsgBox("Error " & Err.Number & " (" & Err.Description _
& ") in procedure TstErrHndlr " _
& "of Module Create_Package." _
& " Contact [My Name] for assistance " _
& "([email protected], (123)456-7890)")
On Error GoTo 0
Resume
End Sub
Sub TstErrHndlrA()
On Error GoTo TstErrHndlrA_Error1
Dim X As Double
X = 1/0
On Error GoTo 0
Exit Sub
TstErrHndlrA_Error1:
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
Application.DisplayAlerts = True
Call MsgBox("Error " & Err.Number & " (" & Err.Description _
& ") in procedure TstErrHndlrA " _
& "of Module Create_Package." _
& " Contact [My Name] for assistance " _
& "([email protected], (123)456-7890")
On Error GoTo 0
Resume
End Sub
Nachdem im Debug-Modus durch den Code gehen, scheint es wie wann immer Eine Prozedur wird von einer anderen Prozedur aufgerufen. Je nachdem, welcher Fehlerhandler in der aufrufenden Funktion aktiviert wurde, wird der Fehlerhandler, der von der Zeile On Error GoTo 0
aktiviert wird, unabhängig davon, wie oft er wiederholt wird. Ich würde gerne wissen, warum sich VBA so verhält, wie man es so verhält und/oder ob es besser ist, mein Ziel zu erreichen, die Codezeile zu bekommen, die einen Fehler ausgelöst hat, während man einen Fehlerhandler benutzt. Ich weiß, dass ich zum Standard-Fehlerhandler zurückkehren könnte, bevor eine Funktion mit einem neuen Fehlerhandler aufgerufen wird (z. B. On Error GoTo 0: Call TstErrHndlrA
), aber das führt zu hässlichem, verwirrendem Code und behandelt keine Fehler beim Funktionsaufruf.
'OEG0' deaktiviert den Fehlerhandler für die aufgerufene Routine. Bei einem zweiten Fehler wird daher die Steuerung an die aufrufende Routine und ihren Fehlerbehandler zurückgegeben. Ich schlage vor, dass Sie bedingte Kompilierung für Ihre On Error-Anweisungen verwenden, oder Zeilennummern hinzufügen und 'Erl' verwenden. – Rory
@Rory Ich bin mir nicht sicher, ob ich den Vorschlag zur bedingten Kompilierung verstehe - Meinst du, dass ich bedingte Kompilierung verwenden würde, um meine Fehlerbehandlungsroutinen zu deaktivieren, wenn ich der Benutzer bin, und sie für andere Benutzer zu aktivieren? Oder gibt es eine andere Möglichkeit, wie eine bedingte Kompilierung dieses Problem lösen könnte? – nateAtwork