Is there a way to crack the password on an Excel VBA Project?


I’ve been asked to update some Excel 2003 macros, but the VBA projects are password protected, and it seems there’s a lack of documentation… no-one knows the passwords.

Is there a way of removing or cracking the password on a VBA project?

You can try this direct VBA approach which doesn’t require HEX editing. It will work for any files (*.xls, *.xlsm, *.xlam …).

Tested and works on

Excel 2007
Excel 2010
Excel 2013 – 32 bit version.
Excel 2016 – 32 bit version.

Looking for 64 bit version? See

how it works

I will try my best to explain how it works – please excuse my english.

  1. The VBE will call a system function to create the password dialog box.
  2. If user enters the right password and click OK, this function returns 1. If user enters the wrong password or click Cancel, this function returns 0.
  3. After the dialog box is closed, the VBE checks the returned value of the system function
  4. if this value is 1, the VBE will “think” that the password is right, hence the locked VBA project will be opened.
  5. The code below swaps the memory of the original function used to display the password dialog with a user defined function that will always return 1 when being called.

using the code

  1. Open the file(s) that contain your locked VBA Projects
  2. Create a new xlsm file and store this code in Module1

    code credited to Siwtom (nick name), a Vietnamese developer
    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 pFunc As Long
    Dim Flag As Boolean
    Private Function GetPtr(ByVal Value As Long) As Long
        GetPtr = Value
    End Function
    Public Sub RecoverBytes()
        If Flag Then MoveMemory ByVal pFunc, ByVal VarPtr(OriginBytes(0)), 6
    End Sub
    Public Function Hook() As Boolean
        Dim TmpBytes(0 To 5) As Byte
        Dim p As Long
        Dim OriginProtect As Long
        Hook = False
        pFunc = GetProcAddress(GetModuleHandleA("user32.dll"), "DialogBoxParamA")
        If VirtualProtect(ByVal pFunc, 6, PAGE_EXECUTE_READWRITE, OriginProtect) <> 0 Then
            MoveMemory ByVal VarPtr(TmpBytes(0)), ByVal pFunc, 6
            If TmpBytes(0) <> &H68 Then
                MoveMemory ByVal VarPtr(OriginBytes(0)), ByVal pFunc, 6
                p = GetPtr(AddressOf MyDialogBoxParam)
                HookBytes(0) = &H68
                MoveMemory ByVal VarPtr(HookBytes(1)), ByVal VarPtr(p), 4
                HookBytes(5) = &HC3
                MoveMemory ByVal pFunc, ByVal VarPtr(HookBytes(0)), 6
                Flag = True
                Hook = True
            End If
        End If
    End Function
    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
            MyDialogBoxParam = DialogBoxParam(hInstance, pTemplateName, _
                               hWndParent, lpDialogFunc, dwInitParam)
        End If
    End Function

  3. Paste this code in Module2 and run it
    Sub unprotected()
        If Hook Then
            MsgBox "VBA Project is unprotected!", vbInformation, "*****"
        End If
    End Sub
  4. Come back to your VBA Projects and enjoy.

Excel VBA Drop Down Lists Using Data Validation

[Originally posted by]:

Excel VBA Drop Down Lists Using Data Validation

JUL 27, 2015

In this article I will explain how you can create drop down lists using data validation.

Jump To:

You can download the file and code related to this article from the link below:

Creating Data Validation (Manually):

Step1 : In the first step you would need to print the data you are going to fill the drop down list with somewhere. Usually I open a new sheet, name it something no one would ever consider using (like “far43fq”) and print the data there.

Excel VBA, Drop Down Lists, Data Validation Data

Step 2: Select the cell you would like to add the drop down list to. Then click on the Data Validation button on the Data Ribbon:

Adding a Data Validation to a specific cell, Excel VBA

Step 3: Select list:

Selecting the list type data validation from the list of available data validation types excel vba

Step 4: Input the range of the data. If the drop down list (data validation) and the data are in the same sheet you would reference them using a statement like “=A1:A6”. If they are in separate sheets you would use a statement like “=SheetName!A1:A6”, where “SheetName” is replaced with the name of the sheet.

Excel VBA, Drop Down Lists, Data Validation Input Data

Note: I this example the input data is in another sheet. The name of the sheet is Sheet1″.

After pressing Ok your drop down list is ready:

A drop down list created using data validation

Creating Data Validation (Using VBA):

Using the code below a drop down list (data validation) will be created in the cell “J2” . The data for the drop down list will come from the range “=A1:A6” in the sheet “Sheet1”. Note you must change the highlighted parts based on the location of your source and the location for your drop down list:

Private Sub main()
	'replace "J2" with the cell you want to insert the drop down list 
	With Range("J2").Validation
		'replace "=A1:A6" with the range the data is in. 
		.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, _
		Operator:= xlBetween, Formula1:="=Sheet1!A1:A6" 
		.IgnoreBlank = True 
		.InCellDropdown = True 
		.InputTitle = "" 
		.ErrorTitle = "" 
		.InputMessage = "" 
		.ErrorMessage = "" 
		.ShowInput = True 
		.ShowError = True 
	End With 
End Sub


Selection Change:

The data validation itself doesn’t have a built in function for determining when the user hasselected a new value. Though you could use the worksheet_change event handler to determine when the user has selected a new value from the drop down list.  Theworksheet_change event triggers every time changes are made to a worksheet. You could use the worksheet_change event handler to catch this event and check if the changes made were to the value selected in the drop down list.

The code below is a worksheet_change event handler. It checks if the changes in the worksheet have occurred in the cell with the drop down list or not:

Private Sub Worksheet_Change(ByVal Target As Range)
    If Target.Address = Range("J2").Address Then 
        'your code 
    End If 
End Sub 

Modifying, Adding, Inserting and Removing Items (Usin VBA):

In order to modify, add, insert and remove items from a drop down list created using data validation, you would have to follow 2 steps.

Step 1: The first thing you would have to do is change the source data. For example lets say we want to modify the second item to “New Item 2”,  we would need to change thedata validation’s source to the values below:

Excel VBA, Drop Down Lists, Data Validation Data, Modified Data
Or for example lets say we want to add an item to the list of items. Again the first thing would be to modify the source data:

Excel VBA, Drop Down Lists, Data Validation Data, Modified Data 2
Or for example lets say we want to remove “item 4”. Again the first step would be tomodify the source data:

Excel VBA, Drop Down Lists, Data Validation Data, Modified Data 3
Step 2: In the next step we need to update the drop down list to accommodate for the changes made in its source. This can be done using the code below. The code below must be copied to the sheet with the source data. The highlighted parts must be changed based on the location of your source data and the location you would like the drop down list to appear:

Option Explicit
Dim flagProgram As Boolean 

Private Sub Worksheet_Change(ByVal Target As Range)
    Dim intRowCount As Integer 
    If flagProgram = False Then 
	flagProgram = True 
	'get the total rows of data 
	intRowCount = Get_Count 
	'update the drop down list(data validation) 
	Call Update_DataValidation(intRowCount) 
	flagProgram = False 
    End If 
End Sub

'This function will return the total count of rows in the 
'drop down list(data validation) source 
Private Function Get_Count() As Integer 
    Dim i As Integer 
    'determines if the we have reached the end 
    Dim flag As Boolean 

    i = 1
    flag = True
    While flag = True
	If Cells(i, 1) <> "" Then 
  	    'if there is still data go on 
	    i = i + 1 
	    'if there is no more data left stop the loop 
	    flag = False 
	End If 

    'return the total row count 
    Get_Count = i - 1
End Function 

'the function below updates the source range for the data validation 
'based on the number of rows provided by the input 
Private Sub Update_DataValidation(ByVal intRow As Integer)
    'the reference string to the source range 
    Dim strSourceRange As String 

    strSourceRange = "=Sheet1!A1:A" + Strings.Trim(Str(intRow))
    With Sheet2.Range("J2").Validation
	.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, _ 
	Operator:= xlBetween, Formula1:=strSourceRange 
	.IgnoreBlank = True 
	.InCellDropdown = True 
	.InputTitle = "" 
	.ErrorTitle = "" 
	.InputMessage = "" 
	.ErrorMessage = "" 
	.ShowInput = True 
	.ShowError = True 
    End With 
End Sub

The code above has 3 different function. The main function is Worksheet_Change event handler. The event handler executes when the user makes changes to the sheet with the source data:

Private Sub Worksheet_Change(ByVal Target As Range)
End Sub 

flagProgram determines if the current changes made to the sheet have been done by the program or the user. This is to prevent an endless recursion of the Worksheet_Changeevent handler:

If flagProgram = False Then 
    flagProgram = True 
    flagProgram = False 
End If

The line below gets the number of rows in the source for the data validation. This value must be checked each time to account for added and removed items:

intRowCount = Get_Count

The function Update_DataValidation updates the data validation based on the input parameter intRow. The input parameter intRow determines how many rows of data thedrop down list must use. The first line of this function creates a string which is a reference to the range with the source data:

strSourceRange = "=Sheet1!A1:A" + Strings.Trim(Str(intRow))

Note the highlighted section must changed if your source data is not in Sheet1 starting from cell A1. The resulting string will be something like this:




For more information about string processing and manipulation please see the link below:

The rest of the lines in the function Update_DataValidation creates a drop down list in the cell “J2” in sheet2.

You can download the file and code related to this article from the link below:

See also:

If you need assistance with your code, or you are looking to hire a VBA programmer feel free tocontact me. Also please visit my website

Exit / disable edit mode after double click handled event

[Originally posted by]:

You have to cancel the action with the variable given in argument:

Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
     MsgBox "a cell was clicked!", vbOKOnly, "a click"
     'Disable standard behavior     
     Cancel = True
End Sub

Here is a dummy example:

Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
    Dim response As Variant
    response = MsgBox("Are you sure you want to edit the cell?", vbYesNo, "Check")
    If response = vbYes Then
        Cancel = False
        Cancel = True
    End If
End Sub

Note that you wouldn’t have to set Cancel to False because it the default value (this is for the example purpose).


Wait until ActiveWorkbook.RefreshAll finishes – VBA

[Originally Posted By]:

As commented:

‘~~> your code here before refresh


‘~~> rest of your code here after refresh

What DoEvents does is like momentarily allowing Windows to take a break from Macro to process all pending events before returning to the macro.
So when you refresh your workbook and put DoEvents after, it will not resume the macro until the refresh is finished.


I had the same issue, however DoEvents didn’t help me as my data connections had background-refresh enabled. Instead, using Wayne G. Dunn‘s answer as a jumping-off point, I created the following solution, which works just fine for me;

Sub Refresh_All_Data_Connections()

For Each objConnection In ThisWorkbook.Connections
‘Get current background-refresh value
bBackground = objConnection.OLEDBConnection.BackgroundQuery

‘Temporarily disable background-refresh
objConnection.OLEDBConnection.BackgroundQuery = False

‘Refresh this connection

‘Set background-refresh value back to original value
objConnection.OLEDBConnection.BackgroundQuery = bBackground

MsgBox "Finished refreshing all data connections"

End Sub

The MsgBox is for testing only and can be removed once you’re happy the code waits.

Also, I prefer ThisWorkbook to ActiveWorkbook as I know it will target the workbook where the code resides, just in case focus changes. Nine times out of ten this won’t matter, but I like to err on the side of caution.

EDIT: Just saw your edit about using an xlConnectionTypeXMLMAP connection which does not have a BackgroundQuery option, sorry. I’ll leave the above for anyone (like me) looking for a way to refresh OLEDBConnection types.