VBA GoTo & Error Handling to Python
GoTo and On Error are the most challenging VBA patterns to convert. This guide shows how to refactor unstructured jumps into clean Python with try/except, while loops, and functions.
Why GoTo Exists in VBA
VBA inherited GoTo from BASIC. It serves three common purposes in legacy code:
- Error handling:
On Error GoTo ErrHandleris VBA's only structured error mechanism. - Retry loops: Jumping back to a label after a failed operation.
- Cleanup blocks: Jumping to a cleanup label before exiting a Sub.
Python has structured alternatives for all three — try/except, while loops, and try/finally.
Why the Converter Flags GoTo
The VBAtoPython converter does not attempt to automatically convert GoTo or On Error statements. Instead, it flags them with TODO comments and warnings. This is intentional:
- GoTo can jump to arbitrary labels, creating control flow that has no direct Python equivalent.
- Guessing the intent of a GoTo jump risks introducing subtle bugs that are harder to find than doing the refactor manually.
- The right Python pattern depends on what the GoTo is doing (error handling, retry, cleanup), which requires human judgment.
Pattern 1: On Error GoTo → try/except
This is the most common GoTo pattern. VBA uses labels for error handlers; Python uses structured exception blocks.
VBA
Sub ProcessFile()
On Error GoTo ErrHandler
Open "data.txt" For Input As #1
' ... process file ...
Close #1
Exit Sub
ErrHandler:
MsgBox "Error: " & Err.Description
Close #1
End SubPython
def process_file():
try:
with open("data.txt") as f:
# ... process file ...
pass
except Exception as e:
print(f"Error: {e}")Python's with statement also replaces the need for explicit Closecalls — the file is closed automatically when the block exits, even if an exception occurs.
Pattern 2: On Error Resume Next → explicit try/except
On Error Resume Next silently ignores all errors and continues execution. This is dangerous because it hides bugs. In Python, handle specific expected errors explicitly.
VBA
Sub SafeRead()
On Error Resume Next
val = Cells(1, 1).Value
x = CDbl(val)
If Err.Number <> 0 Then
x = 0
Err.Clear
End If
On Error GoTo 0
End SubPython
def safe_read(ws):
val = ws.cell(row=1, column=1).value
try:
x = float(val)
except (ValueError, TypeError):
x = 0Instead of suppressing all errors, Python catches only the specific exceptions you expect (ValueError, TypeError). Unexpected errors still propagate and surface immediately.
Pattern 3: GoTo Retry → while loop
VBA
Sub GetInput()
Retry:
answer = InputBox("Enter a number:")
If Not IsNumeric(answer) Then
MsgBox "Invalid input"
GoTo Retry
End If
End SubPython
def get_input():
while True:
answer = input("Enter a number:")
try:
float(answer)
break
except ValueError:
print("Invalid input")Any GoTo that jumps backward to a label is effectively a loop. Replace with while True and break when the condition is met.
Pattern 4: GoTo Cleanup → try/finally
VBA
Sub DoWork()
Dim conn As Object
Set conn = CreateObject("...")
On Error GoTo Cleanup
' ... work with conn ...
Cleanup:
conn.Close
Set conn = Nothing
End SubPython
def do_work():
conn = create_connection()
try:
# ... work with conn ...
pass
finally:
conn.close()finally guarantees the cleanup code runs whether an exception occurred or not — exactly the same guarantee as VBA's GoTo Cleanup pattern.
VBA Labels → Comments
Labels that are only used as GoTo targets (not for error handling) are converted to comments by the converter, since Python has no label concept.
VBA
StartProcess:
' code here
Done:
Exit SubPython (converter output)
# label: StartProcess
# code here
# label: Done
returnRelated Guides
- Complete Syntax Mapping Reference — All operators, control flow, and error handling patterns.
- Complete Migration Guide — End-to-end process for migrating a VBA project.
- VBA Loops to Python — GoTo retry patterns are really loops in disguise.
See what the converter flags
Paste a macro with GoTo or On Error and see exactly which lines need manual refactoring.