Most VBA-to-Python converters either quietly produce broken code or hallucinate an idiomatic pandas rewrite and hope you don't notice the behavior change. We don't. This page is the honest reference for exactly what VBAtoPython handles, what it handles with warnings, and what it won't touch.
Our converter is deterministic and rule-based. It translates your VBA line-by-line — the output preserves the structure and control flow of your original code so you can audit it. That's the pitch for finance, payroll, and accounting teams who need to know their macro still does the same thing after the port.
We benchmark against a 374-file corpus of real-world VBA projects scraped from GitHub. Today we pass 76% cleanly (285 of 374 files produce syntactically valid, runnable Python), and the categories below are based on exactly what's in that corpus plus what real customers submit.
✅ Handles cleanly — no review needed
These patterns produce Python that runs without edits. Faithful line-by-line translation, preserved control flow, named variables kept intact.
Procedures and control flow
Sub/Function/Property Get/Let/SetwithDim, type hints, parameters,ByRef/ByValIf/ElseIf/Else/End IfSelect Case→if/elif/elseFor/Next,For Each/Next,Do/While/Loop,Exit Sub/Exit FunctionWithblocks flattened
Standard modules and class modules
.basstandard modules with Sub/Function definitions.clsclass modules with private/public members, Property Get/Let/Set- Multi-module projects — class modules talking to standard modules via method calls
Strings and numbers
Trim,Left,Right,Mid,Len,InStr,Replace,LCase,UCaseFormat(common patterns: currency, dates, numbers)- Arithmetic, comparison,
Likeoperator Val,CStr,CInt,CDbl,CDatetype conversions
Collections and dictionaries
Scripting.Dictionary→ PythondictCollection→ Pythonlistordict(depending on usage)Add,Remove,Count,Exists, iteration
Basic Excel I/O
Range(...),Cells(r, c),.Value- Bulk array reads/writes:
Range(Cells(1,1), Cells(n,m)).Value→ws.iter_rows(...)or per-cell writes Sheets(N)/Worksheets("Name")→workbook.worksheets[N-1]/workbook["Name"]Workbooks.Add,.Open,.Save,.SaveAs,.Close→openpyxl.Workbook(),load_workbook(),.save(),.close()
File I/O
Open/Close/Print #/Input #/Line Input #Dir(pattern)file iteration →glob.glob()with proper next() iterator state- Basic
FileSystemObjectoperations →pathlib.Path
Error handling (basic cases)
On Error GoTo Label→try/exceptwith labeled handlerOn Error GoTo 0→ reset handler- Simple
On Error Resume Nextblocks
⚠️ Translates with warnings — review before running
The converter produces working Python, but the output may behave differently from your VBA. Every conversion comes with a warning report listing these patterns explicitly. Always test before running on production data.
Financial math — the important one
VBA's Currency type is fixed-point (scaled to 4 decimal places). Python's float isn't. For payroll, accounting, or anything involving cents, the translated code may be off by a rounding unit on edge cases. We flag this with a warning. Recommended: wrap money calculations in decimal.Decimal with quantize() before comparing or storing. If your macro processes payroll or reconciles accounts, review these lines by hand.
ByRef parameter mutations
Python primitives are pass-by-value. If your VBA sub modifies a ByRef Long or String and expects the change to persist in the caller, the Python version won't. We warn on every case. Fix: refactor the sub to return the new value and assign it at the call site.
On Error Resume Next + If Err.Number checks
The "silent fail, then check Err.Number" idiom doesn't round-trip cleanly. In VBA, the bad line is silently skipped; in the generated Python, it'll raise unless you've explicitly wrapped it. We emit the try/except shell, but the semantics differ. Review these blocks before running on real data.
Range.Value vs Range.Value2
We treat them identically. If your macro relies on .Value2 returning raw unformatted doubles (common for performance-critical date or currency reads), you'll see type mismatches downstream. We flag the distinction.
Application.WorksheetFunction. (SumIfs, VLookup, Index/Match)*
We emit a # TODO comment with a pandas suggestion, but don't auto-translate. These need a manual rewrite to df.query(), df.merge(), df.lookup(), or the equivalent — the semantics are too context-dependent to translate mechanically.
ListObjects (Excel Tables) and SpecialCells
openpyxl has partial Table support, but methods like DataBodyRange, ListRows.Add, and SpecialCells(xlCellTypeVisible) don't have direct equivalents. We emit guidance in comments; you'll need to adapt.
❌ Not supported — by design
These categories are out of scope. We document them clearly so you don't send them through expecting magic. If your macro is mostly one of these, our converter isn't the right tool.
UI code — UserForms, ActiveX controls. No pandas/openpyxl equivalent exists. Rebuild in Tkinter, PyQt, or a web framework.
Event handlers — Workbook_Open, Worksheet_Change, Application.OnTime. Python has no Excel event model. If you trigger logic on workbook open, convert to a scheduled script or a file-watcher.
PivotTables — pandas pivot_table is the target, but the translation isn't mechanical. The source/pivot-field/aggregation structure needs a human to redesign.
Charts and Conditional Formatting — openpyxl's API exists but differs enough that a literal translation is non-idiomatic. Easier to rebuild the chart in openpyxl or matplotlib from the translated data-prep code.
Win32 Declare PtrSafe statements — kernel32, user32 DLL calls don't translate. Use ctypes manually in Python if you actually need them.
COM automation / late binding — CreateObject("Outlook.Application"), Wscript.Shell, CDO.Message. These need pywin32 and a manual rewrite; the semantics aren't preservable through automatic translation.
Full ADO/ADODB Recordset navigation — .MovePrevious, .Bookmark, multi-resultset navigation. Basic Open / Execute / Fields / MoveNext are partially supported, but complex cursor logic needs a manual port to sqlite3 or SQLAlchemy.
Data Validation rules — Excel-specific constraint system, not in openpyxl's core API.
What this means for you
If your VBA is a typical finance or reporting macro — data prep, aggregation, formatting, report generation — you're in the 80% that translates cleanly. Paste it in and you'll get Python you can read, audit, and adapt.
If your VBA is heavy on UserForms, PivotTables, events, or COM automation, the converter won't save you the rewrite. But the parts of your code that are data-prep and business logic will still translate — and that's usually the part that takes the longest to rewrite by hand.
Every conversion includes a warning report. If you're migrating a critical macro, read the warnings before running the output. We'd rather be accused of being too cautious than of silently breaking someone's payroll run.