I've found the following code in this Stackoverflow answer and copied (and slightly modified) it because it was very helpful to me.
Intstructions:
Open the document (Excel workbook etc) with the locked VBA project
Add a new workbook
Add a module in the new workbook
Paste this code in the (empty) module
Call bypassVBApasswordCheck in immediate window (opens MsgBox in case of error)
Open protected VBA code
option explicit
private const PAGE_EXECUTE_READWRITE = &h40
private declare sub MoveMemory Lib "kernel32" Alias "RtlMoveMemory" ( _
destination as long, _
source as long, _
byVal length as long)
private declare function VirtualProtect Lib "kernel32" ( _
lpAddress as long, _
byVal dwSize as long, _
byVal flNewProtect as long, _
lpflOldProtect as long _
) as long
private declare function GetModuleHandleA Lib "kernel32" ( _
byVal lpModuleName as string _
) as long
private declare function GetProcAddress Lib "kernel32" (byVal hModule as long, _
byVal lpProcName as string _
) as long
private declare function DialogBoxParam Lib "user32" Alias "DialogBoxParamA" ( _
byVal hInstance as long, _
byVal pTemplateName as long, _
byVal hWndParent as long, _
byVal lpDialogFunc as long, _
byVal dwInitParam as long _
) as integer
dim HookBytes (0 To 5) as byte
dim OriginBytes(0 To 5) as byte
dim ptrDialogBoxParam as long
dim hooked as boolean
private function getPtr(byVal value as long) as long
getPtr = value
end function
public sub recoverBytes()
if hooked then
MoveMemory byVal ptrDialogBoxParam, byVal varPtr(OriginBytes(0)), 6
end if
end sub
public sub bypassVBApasswordCheck()
dim tmpBytes(0 To 5) as byte
dim ptrMyDialogBoxParam as long
dim oldProtect as long
ptrDialogBoxParam = GetProcAddress(GetModuleHandleA("user32.dll"), "DialogBoxParamA")
if VirtualProtect(byVal ptrDialogBoxParam, 6, PAGE_EXECUTE_READWRITE, oldProtect) = 0 then
msgBox "VirtualProtect returned 0"
exit sub
end if
MoveMemory byVal varPtr(tmpBytes(0)), byVal ptrDialogBoxParam, 6
if tmpBytes(0) = &h68 then
msgBox "tmpBytes(0) = &h68
exit sub
end if
MoveMemory byVal varPtr(OriginBytes(0)), byVal ptrDialogBoxParam, 6
ptrMyDialogBoxParam = getPtr(addressOf MyDialogBoxParam)
HookBytes(0) = &h68
MoveMemory byVal varPtr(HookBytes(1)), byVal varPtr(ptrMyDialogBoxParam), 4
HookBytes(5) = &hc3
MoveMemory byVal ptrDialogBoxParam, byVal varPtr(HookBytes(0)), 6
hooked = True
end sub
private function MyDialogBoxParam( _
byVal hInstance as long, _
byVal pTemplateName as long, _
byVal hWndParent as long, _
byVal lpDialogFunc as long, _
byVal dwInitParam as long _
) as integer
if pTemplateName = 4070 then
MyDialogBoxParam = 1
else
recoverBytes
MyDialogBoxParam = DialogBoxParam(hInstance, pTemplateName, hWndParent, lpDialogFunc, dwInitParam)
bypassVBApasswordCheck
end if
end function