VBA support
VBA support is experimental. Only pure worksheet UDFs run in production; workbooks that rely on macros, events, or worksheet mutation are refused rather than partially run. The supported subset and its behavior may change between releases, so treat a compile refusal — not a saved value — as the authoritative support decision.
xplo runs a deliberately narrow, production-safe slice of VBA: pure worksheet user-defined functions (UDFs). Covered Functions are compiled into every runtime artifact and recompute from live worksheet inputs, exactly like a built-in formula function.
What xplo runs
Support is decided for the whole VBA project, not one formula at a time. A macro-enabled .xlsm file is simply how the Function source reaches xplo — it is not permission to automate Excel.
| Capability | Production workbooks |
|---|---|
| Run covered worksheet UDFs from cell formulas | Yes |
| Return scalars, worksheet errors, or arrays / spills | Yes |
| Read cells and ranges passed in as Function arguments | Yes |
| Run Sub procedures or button / form callbacks | No — workbook refused |
| Run Workbook_Open, Auto_Open, or worksheet events | No — workbook refused |
| Mutate cells, formulas, names, formatting, or app state | No — workbook refused |
| Use files, the shell, COM, DLLs, or the network | No — workbook refused |
The whole-project acceptance rule
A workbook's VBA is accepted only when every one of these is true:
- The embedded VBA source extracted completely and every module parses.
- The project contains at least one Function.
- Every procedure is an analyzer-proven pure Function.
- Every Function lowers completely to the portable UDF runtime.
- No procedure is a
Sub, event handler, property procedure, workbook read, workbook mutation, or external / world effect. - The native Rust, WASM, and XVM artifacts all carry the same UDF programs.
If any part of the project falls outside this boundary, code generation fails with unsupported_vba and specific blocking reasons. xplo does not silently skip the unsupported procedure, and it never substitutes the values Excel last saved.
Sub ExportReport() is still refused. Removing the Sub, or shipping a deployment copy whose VBA project contains only the pure Functions, makes the supported boundary explicit.How to use supported VBA
Put pure Functions in a standard VBA module, save the workbook as .xlsm, and call them from ordinary worksheet formulas. Upload or build the .xlsm through the same workflow you use for .xlsx— there is no separate “enable macros” switch in xplo. The ingest pipeline extracts and analyzes the project, and the compiler embeds accepted Functions into every runtime artifact.
Option Explicit
Public Function WeightedAmount( _
ByVal amount As Double, _
Optional ByVal factor As Double = 1# _
) As Double
WeightedAmount = amount * factor
End Function
Public Function NumericTotal(ByVal source As Range) As Double
Dim cell As Range
For Each cell In source.Cells
If IsNumeric(cell.Value2) Then
NumericTotal = NumericTotal + CDbl(cell.Value2)
End If
Next cell
End FunctionThese worksheet formulas are supported:
=WeightedAmount(A2, B2) =WeightedAmount(A2) =NumericTotal(C2:C20) =Module1.NumericTotal(C2:C20)
For the smoothest path:
- Use a standard module and
ByValparameters. - Pass every worksheet value or Range the Function reads as an explicit formula argument, so the dependency graph knows every cell it touches.
- Keep the project free of
Subprocedures, events, module state, and external capabilities. - Prefer small Functions and private pure helper Functions.
Workbook_Open or from a button will not run in production.What is not supported
Anything that automates or mutates Excel puts the whole project outside the supported boundary:
- An
.xlsmfile does not mean xplo runs its macros.Subprocedures, form / ActiveX and Ribbon callbacks,Workbook_Open,Auto_Open, and worksheet events all make the project unsupported. - The embedded project, not the filename, is authoritative. xplo checks for an actual
xl/vbaProject.bin. Renaming an.xlsxto.xlsm, or dropping.basfiles beside the workbook, does not add production VBA. - Files, the shell, COM, DLLs, and the network are never available to a production UDF.
The supported UDF subset
The portable runtime covers a focused subset. This describes the production runtime — not everything the parser or engineering tools understand.
Values, parameters, and results
- Scalar
Variant,Double,String,Boolean,Single,Currency,Date,Byte,Integer,Long, andLongLongvalues, with VBA coercion (including banker's rounding and four-decimalCurrency) at typed boundaries. ByValparameters, optional parameters with literal defaults, omitted arguments, andParamArray. A worksheet cell is never mutated by passing itByRef.- Local fixed-size and dynamic arrays (including non-one-based bounds and
Option Base), and one- and two-dimensional array results with mixed values, blanks, and worksheet errors. - Worksheet errors via
CVErr, error propagation,Empty/Nullbehavior, and returning an explicit Range parameter withSet FunctionName = source.
Statements and control flow
- Local declarations and assignments;
If/ElseIf/Else(including single-line forms). Forloops with an omitted or positive-literalStep;For Eachover local arrays, Range cells, and Range areas.ReDimwithoutPreserve,Exit Function, self-recursion with a depth guard, and calls to other covered pure Functions (mutual recursion is refused).On Error GoTo label,On Error GoTo 0, theErrorstatement, and the error-number portion ofErr.Raise.
Operators and built-ins
- Arithmetic
+ - * /andMod, concatenation&, comparisons= < <= >, andOr/Notwith unary+/-. String comparison is VBA's default binary, case-sensitive ordering. - A focused built-in set:
CVErr,CStr,CDbl,CCur,CSng,CLng,DateSerial,Year,Month,Day,Sqr,LBound,UBound,Len,LCase,ChrW,IsNumeric,IsMissing,IsObject,IsError,IsEmpty,TypeName, andVarType, plus the worksheet error constants. - Range operations rooted in an explicit Range parameter:
.Value/.Value2,.Cells(row, column),.Rows.Count,.Columns.Count,.Cells.Count,.Areas.Count, iteration over.Cellsand.Areas,.Worksheet.Name,.HasFormula, andApplication.WorksheetFunction.Sum(...).