VBA Error Handling to Python
VBA uses On Error statements and the Err object to handle runtime errors. Python replaces this entirely with structured try/except blocks, giving you clearer control flow and more readable error handling.
On Error Resume Next
On Error Resume Next tells VBA to silently ignore errors and continue execution on the next line. In Python, wrap the risky operation in a try/except block with pass to achieve the same effect.
VBA
Sub SafeDivide()
On Error Resume Next
Dim result As Double
result = 10 / 0 ' No crash
result = 10 / 2 ' Continues here
MsgBox result
End SubPython
def safe_divide():
try:
result = 10 / 0
except ZeroDivisionError:
pass # Silently ignore
result = 10 / 2 # Continues here
print(result)Unlike VBA, Python encourages you to catch specific exceptions rather than silencing all errors globally.
On Error GoTo Label
VBA's On Error GoTo jumps to a labeled section when an error occurs. Python's try/except block is the direct equivalent, with the except clause acting as the error handler.
VBA
Sub OpenFile()
On Error GoTo ErrorHandler
Open "C:\data.txt" For Input As #1
' ... process file ...
Close #1
Exit Sub
ErrorHandler:
MsgBox "Error " & Err.Number & _
": " & Err.Description
End SubPython
def open_file():
try:
with open("data.txt") as f:
# ... process file ...
pass
except FileNotFoundError as e:
print(f"Error: {e}")
except PermissionError as e:
print(f"Error: {e}")On Error GoTo 0
On Error GoTo 0 resets the error handler, so subsequent errors crash normally. In Python, this concept is unnecessary because try/except blocks are scoped: code outside the block is not protected.
VBA
Sub PartialProtection()
On Error Resume Next
' Protected section
val = CLng("abc") ' Error ignored
On Error GoTo 0
' Unprotected section
val = CLng("xyz") ' This WILL crash
End SubPython
def partial_protection():
# Protected section
try:
val = int("abc") # Error caught
except ValueError:
pass
# Unprotected section
val = int("xyz") # This WILL crashPython's block scoping makes it obvious which lines are protected and which are not, unlike VBA's global On Error state.
Err.Number and Err.Description
VBA's Err object exposes Number and Description properties. In Python, the caught exception object carries all relevant information, and you can access the exception type and message directly.
VBA
Sub CheckError()
On Error Resume Next
Dim x As Double
x = 1 / 0
If Err.Number <> 0 Then
Debug.Print "Error #" & Err.Number
Debug.Print Err.Description
Debug.Print Err.Source
Err.Clear
End If
End SubPython
def check_error():
try:
x = 1 / 0
except Exception as e:
print(f"Type: {type(e).__name__}")
print(f"Message: {e}")
# e.args contains all arguments
# No need to "clear" - scoped| VBA Err Object | Python Exception |
|---|---|
| Err.Number | type(e).__name__ |
| Err.Description | str(e) |
| Err.Clear | Not needed (scoped) |
| Err.Raise n, src, desc | raise ValueError(desc) |
Resume and Resume Next
VBA's Resume retries the failed line, while Resume Next skips to the line after the failure. Python handles these patterns differently using loops and control flow.
VBA (Resume - retry)
Sub RetryExample()
On Error GoTo RetryHandler
Dim filePath As String
filePath = InputBox("Enter path:")
Open filePath For Input As #1
Exit Sub
RetryHandler:
filePath = "C:\default.txt"
Resume ' Retry with new path
End SubPython (retry with loop)
def retry_example():
file_path = input("Enter path: ")
while True:
try:
f = open(file_path)
break # Success, exit loop
except FileNotFoundError:
file_path = "default.txt"
# Loop retries with new pathNested Error Handlers
VBA supports nested error handlers but they can be confusing because only one On Error handler is active at a time per procedure. Python's nested try/except blocks are explicit and easier to follow.
VBA
Sub NestedHandlers()
On Error GoTo OuterHandler
' Outer protected code
Dim ws As Worksheet
Set ws = Sheets("Data")
On Error GoTo InnerHandler
' Inner protected code
ws.Range("A1").Value = 1 / 0
Exit Sub
InnerHandler:
Debug.Print "Cell error ignored"
Resume Next
OuterHandler:
Debug.Print "Sheet not found"
End SubPython
def nested_handlers():
try:
# Outer protected code
ws = workbook["Data"]
try:
# Inner protected code
ws["A1"] = 1 / 0
except ZeroDivisionError:
print("Cell error ignored")
except KeyError:
print("Sheet not found")Cleanup Code (Finally)
VBA has no Finally equivalent. Developers typically duplicate cleanup code in both the normal path and the error handler. Python's try/except/finally solves this cleanly.
VBA
Sub WithCleanup()
On Error GoTo ErrHandler
Application.ScreenUpdating = False
' ... do work ...
CleanUp:
Application.ScreenUpdating = True
Exit Sub
ErrHandler:
MsgBox Err.Description
GoTo CleanUp
End SubPython
def with_cleanup():
try:
app.screen_updating = False
# ... do work ...
except Exception as e:
print(str(e))
finally:
# Always runs, error or not
app.screen_updating = TrueBest Practices for Migrating Error Handling
- Avoid blanket exception catching. Replace
On Error Resume Nextwith targetedtry/exceptblocks that catch specific exception types likeValueError,KeyError, orFileNotFoundError. - Narrow the scope. VBA's
On Errorapplies to an entire procedure. In Python, wrap only the lines that might fail in thetryblock, keeping the rest outside. - Use
finallyfor cleanup. Any code that must run regardless of errors (closing files, resetting state) belongs in afinallyblock or awithstatement. - Replace
Err.Raisewith custom exceptions. Instead of raising error numbers, define meaningful exception classes:class InvalidInputError(ValueError): pass. - Use
logginginstead ofDebug.Print. Python'sloggingmodule supports levels (debug, info, warning, error) and can write to files, consoles, or external services. - Leverage context managers. Python's
withstatement automatically handles resource cleanup. Usewith open(path) as f:instead of manualOpen/Closepatterns.
Have VBA code with error handling?
Paste your VBA macro into the converter and get clean Python with proper try/except blocks instantly.