Skip to content

VBA Compatibility

VBA Padlock compiles VBA (Visual Basic for Applications) into protected bytecode executed inside your secured DLL.

Use this page as your practical compatibility guide: what compiles into the DLL, what stays in the host document (and why), and what to adapt when needed.

VBA Padlock code editor with VBA script modules

AreaStatusNotes
Core VBA language (Dim, loops, procedures, arrays, Enum, Type)✅ Fully supportedIncludes dynamic and multi-dimensional arrays, recursion
Class modules (.cls)✅ SupportedNew, Me, Property Get/Let/Set, Implements, Class_Initialize; see below
Collection✅ SupportedNew Collection, Add/Item/Remove/Count, string keys, For Each
Built-in VBA functions✅ Broad coverage80+ builtins; see Script Functions Reference
Office object model (Application)✅ Fully supportedUnqualified host globals are auto-qualified during conversion
COM automation (CreateObject, GetObject)✅ SupportedScripting.Dictionary, ADODB.*, indexed property writes, etc.
Conditional compilation (#If / #Const)✅ SupportedEvaluated at compile time, line numbers preserved
Windows API Declare / Declare PtrSafe⚠️ Opt-inDisabled by default; enabled on request. See DLL Calls
UserForms🏠 Stay in the hostForms and their code-behind remain in the Office file
Event handlers, document modules🏠 Stay in the hostOffice fires events only on host code; see What stays in the host
FeatureSupportedNotes
Variables (Dim, Private, Public)YesAll standard data types; Static procedure locals too
Constants (Const)Yes
Arrays (fixed, dynamic, multi-dimensional)YesDim a(i, j, k), ReDim (lo To hi), ReDim Preserve, Erase, Option Base 0/1
User-defined types (Type)YesFlat scalar fields with true value-copy semantics; fixed-bounds array fields
Enumerations (Enum)YesExplicit values, auto-increment, hex, negative
Class modulesYesSee Class Modules below
Option ExplicitYesRecommended; also helps more procedures move to the DLL
Option CompareYesBinary, Text, and Database; honored per module by comparisons, Select Case, Like, and string builtins
Option BaseYes0 or 1
Conditional compilationYesNested #If/#ElseIf/#Else/#End If and #Const
Comments (' and Rem)Yes
Hex literals (&H)Yes&HFF, &H8000000F, &HFF& (Long suffix); 5& Long-suffix literals
$ suffix functionsYesChr$, Left$, Mid$, Format$, etc.; equivalent to non-$ version
Mid statementYesMid(s, i, n) = v
Unicode identifiersYesVariable and routine names in any script (e.g. CJK)
Bracket identifiersYes.[Name], statement-leading [_Enum]
Debug.PrintYesOutputs via OutputDebugString, visible in DebugView

Class modules compile into the DLL, and are removed from the protected document, making them ideal for your most sensitive logic:

FeatureSupportedNotes
Set x = New C / Dim x As New CYesEager auto-instantiation at declaration
MeYesIncluding dotted Me.<member> read and write
Public/Private fields and methods, FriendYes
Class_InitializeYesDispatched on New
Property Get/Let/SetYesScalar and parameterized/indexed, strict Let-vs-Set separation
Default memberYesAttribute <name>.VB_UserMemId = 0 honored on calls and indexed access
ImplementsYesDuck-typed conformance; multiple interfaces; TypeOf x Is IFoo
TypeOf x Is <Class>YesBy class or interface name
Typed declarationsYesDim x As <Class> with runtime member resolution

The bundled 05_ClassModuleDemo example shows a class compiled into the DLL while the workbook keeps working against it.

TypeSupportedNotes
BooleanYes
ByteYes
IntegerYes
LongYes
LongLongYes64-bit integer
LongPtrYesPointer-sized at runtime: 4 bytes on Win32, 8 on Win64
SingleYes
DoubleYes
CurrencyYes
StringYesVariable-length strings
DateYesStored as Double internally
VariantYesFull support
ObjectYesCOM objects via Application and CreateObject(); script classes
FeatureSupported
If...Then...Else...End IfYes
Select Case (incl. Case X To Y ranges)Yes
For...NextYes
For Each...Next (arrays, collections, COM)Yes
Do...Loop (While/Until)Yes
While...WendYes
GoToYes
GoSub...ReturnYes
On Error GoTo / Resume / Resume NextYes
On Error Resume NextYes
Exit Sub/Function/For/DoYes
EndYes
FeatureSupportedNotes
SubYes
FunctionYes
Property Get/Let/SetYesIn standard modules and classes; accessor groups move to the DLL together
Optional parametersYesIncluding Optional x = True/False keyword defaults
ParamArrayYesTrailing arguments collapse into a zero-based Variant array
ByRef / ByValYesByRef is default
Recursive callsYes
Declare / Declare PtrSafe (DLL calls)Opt-inDisabled by default; see DLL Calls
Module-level codeYesExecuted on module initialization

All standard VBA operators are supported:

  • Arithmetic: +, -, *, /, \ (integer division), Mod, ^
  • Comparison: =, <>, <, >, <=, >=
  • Logical: And, Or, Not, Xor, Eqv, Imp
  • String: & (concatenation), Like (pattern matching, incl. character-list ranges)
  • Other: Is, TypeOf...Is, chained indexing x(a)(b) (read access)

VBA Padlock includes a comprehensive set of built-in functions that mirror standard VBA functions. See the Script Functions Reference for the complete list, including:

  • String functions (Mid, Left, Right, InStr, InStrRev, Replace, Split, Join, Trim, LTrim, RTrim, UCase, LCase, StrComp, StrReverse, Chr, ChrW, Asc, AscW, Hex, Space, String, Format, FormatNumber, FormatCurrency, FormatPercent, FormatDateTime)
  • Math functions (Abs, Sqr, Sin, Cos, Tan, Atn, Log, Exp, Round, Int, Fix, Sgn, Rnd, Val)
  • Date functions (Now, Date, Time, Timer, DateAdd, DateDiff, DatePart, DateSerial, DateValue, TimeSerial, TimeValue, Weekday, WeekdayName, MonthName, Year, Month, Day, Hour, Minute, Second)
  • Type functions (TypeName, VarType, IsObject, IsMissing, IsArray, IsDate, IsEmpty, IsNull, IsNumeric, IsError)
  • Conversion functions (CInt, CLng, CLngLng, CDbl, CSng, CStr, CBool, CByte, CDate, CCur, CDec, CVErr)
  • Flow functions (IIf, Choose, Switch, CallByName)
  • Utility functions (Array, DoEvents, RGB, Nz, LBound, UBound, Randomize, InputBox, MsgBox)

VBA Padlock ships with ready-to-use constant libraries: thousands of Office constants (xl*, wd*, pp*, ac*, mso*, fm*) plus Financial and ErrorHandler helper modules. Select them in the References dialog; the right host constants are pre-selected automatically.

See the Script Libraries & Constants reference for the full catalog, usage instructions, and code examples.


The automatic analysis (the compile gate) keeps some code in the Office file, not because it doesn’t compile, but because it must run there. The Protection Review shows each decision with its reason:

Kept in the hostWhyWhat you can do
UserForm modulesForms and their code-behind cannot run inside a DLLKeep UI thin; move logic into standard-module procedures
Document modules (ThisWorkbook, Sheet1, ThisDocument, …)Document code belongs to the documentSame: delegate to standard modules
Event handlersOffice fires events only on host-module codeOne-line handler calls a protected Sub
Procedures sharing module-level variablesMoving part of the group would split state between host and DLLRestructure the shared state, or accept the verdict
Dependency closures (depends on <proc>)A procedure calling kept code is demoted with itFix the root cause; the closure follows
Unqualified host globals in modules without Option ExplicitThe DLL cannot resolve the bare nameAdd Option Explicit or qualify with Application.

These verdicts are behavior, not errors: a partially-protected module still works perfectly; the kept procedures simply remain readable VBA.


Compiled scripts have full access to the host Office application through the Application object. You can manipulate worksheets, documents, presentations, and databases exactly as you would in regular VBA.

Protected code in VBA Padlock using the Office object model

' PROTECTED CODE (compiled into the DLL)
Sub WriteToCell(CellAddress, Value)
Application.ActiveSheet.Range(CellAddress).Value = Value
End Sub
Function ReadFromCell(CellAddress)
ReadFromCell = Application.ActiveSheet.Range(CellAddress).Value
End Function

Symbolic constants (wdStatisticPages, ppLayoutTitle, xlUp, …) resolve when the matching constants library is ticked in References, which is the default for your host.

The wrappers generated by Produce call your compiled procedures for you: same names, same signatures. If you write callers by hand (advanced scenarios), the generic entry point is VBAPL_Execute:

' CALLER CODE (inside the Office document)
Sub RunMyProtectedCode()
Call VBAPL_Execute("WriteToCell", "A1", "Hello!")
End Sub

Office VBA caller code invoking VBAPL_Execute

CreateObject() and GetObject() are supported in compiled scripts. You can create and use COM objects such as Scripting.Dictionary, ADODB.Connection, ADODB.Stream, etc., including indexed property writes (obj("key") = value).

Function RemoveDuplicates(ColumnIndex)
Dim Dict
Set Dict = CreateObject("Scripting.Dictionary")
Dim WS, LastRow, Row, Key
Set WS = Application.ActiveSheet
LastRow = WS.Cells(WS.Rows.Count, ColumnIndex).End(xlUp).Row
For Row = 2 To LastRow
Key = CStr(WS.Cells(Row, ColumnIndex).Value)
If Not Dict.Exists(Key) Then
Dict.Add Key, Row
End If
Next Row
RemoveDuplicates = Dict.Count
End Function

VBA Padlock supports standard VBA Declare statements, including the modern Declare PtrSafe form with LongLong and LongPtr, to call functions in external DLLs (Windows APIs and third-party DLLs). The syntax is identical to regular VBA:

Declare PtrSafe Function GetTickCount Lib "kernel32" () As Long
Declare PtrSafe Function GetComputerNameW Lib "kernel32" (ByVal lpBuffer As String, ByRef nSize As Long) As Long
Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

LongPtr is pointer-sized at runtime (4 bytes on 32-bit Office, 8 bytes on 64-bit), and As Any is accepted as a fallback parameter type.

VBA UserForms are not compiled; they stay in the Office file with their code-behind (shown as VBA (form) in the review). For the built-in dialogs your protected app needs (activation, trial nag, EULA), VBA Padlock provides its own, configured through the Licensing Features tab.

ParamArray is currently resolved at same-module call sites; a ParamArray procedure called from a different module may be kept in VBA by the gate.

x(a)(b) chains (nested default-member/array indexing) are read-only; writing through a chained index is not supported.

VBAPL_Execute supports any number of parameters. Calls with 0 to 4 arguments use optimized dedicated DLL exports, while calls with 5 or more arguments are automatically packed into an array and routed through ExecuteVBAFunctionN. This is handled transparently.

' Call with few parameters
result = VBAPL_Execute("Main|CalculatePrice", quantity, unitPrice)
' Call with many parameters (no limit)
result = VBAPL_Execute("Reports|Generate", title, startDate, endDate, format, outputPath, includeCharts)

When omitting the module name (e.g., VBAPL_Execute("MyFunction", arg1)), the function is searched in the default Main script. To call a function in another module, use the "ModuleName|FunctionName" syntax.


Compiled scripts use Unicode (UTF-16) strings internally, consistent with modern VBA. String comparisons default to binary comparison unless the module specifies Option Compare Text (or Database in Access).

On Error GoTo, On Error Resume Next, Resume, and Resume Next work as expected. The Err object provides Number and Description properties. However, Err.Raise with custom error numbers should use values above 512 to avoid conflicts with built-in errors.

Module-level code (code outside any Sub or Function) is executed when the module is first loaded. This happens on the first call to any function in that module.

  • Integer is 16-bit signed (−32,768 to 32,767)
  • Long is 32-bit signed (−2,147,483,648 to 2,147,483,647)
  • LongLong is 64-bit signed; LongPtr is pointer-sized
  • Double follows IEEE 754 double-precision
  • Arithmetic rounding uses the Round function (arithmetic rounding, not banker’s rounding)
  • Hexadecimal literals use the &H prefix: &HFF (255), &H8000000F (−2,147,483,633 as Long). An optional & suffix forces Long type: &HFF&

VBA Padlock can protect projects for these Office applications:

ApplicationFile TypesNotes
Excel.xlsm, .xlsb, .xla, .xlamMost common use case
Word.docm, .dotmDocuments and templates
Access.accdb, .accdeDatabases (analyzed copy-first)
PowerPoint.pptm, .ppamPresentations and add-ins

All Office versions from Office 2016 through Office 2024 and Microsoft 365 desktop apps are supported and tested, in both 32-bit and 64-bit editions. The automatic workflow (analyze → review → produce) works end to end with all four hosts.

Protected VBA result in Excel


  1. Let the analysis guide you. Open your file, read the Protection Review, and fix the reasons for kept procedures rather than restructuring blindly.

  2. Keep event handlers thin. A one-line handler calling a standard-module Sub protects the logic while keeping the event wiring in the host.

  3. Use Option Explicit. It catches typos at compile time and removes the unresolved-host-global reason for keeping procedures in VBA.

  4. Use symbolic Office constants. Tick the right libraries in References and write xlUp, not -4162.

  5. Test with Test Run. Ctrl+F5 produces the protected file and opens it in Office, the closest thing to what your users will run. For unit-style checks of individual routines, use Run DLL Function.

  6. Validate frequently with Syntax Check. It reports move/keep verdicts in seconds, without building.