'VBA macro code not executing on workbook opening
I have VBA macro code that is supposed to execute on opening a workbook but the vbaproject password prevents the code executing. My understanding is than a macro protection password prevents viewing and editing the code, and should not prevent execution.
I suspect the problem is that the code makes use of 'Extensibility 5.3' to list all the procedures in the code base, as turning off password protection allows execution on workbook open
I would be grateful for any advice on how to password protect the code and still ensure that code using extensibility features still executes
I think i need a way to unprotect the vbaproject by supplying the password programmatically
Code ends with VBA Excel - Run-time Error 50289
Function genHashesAndStore(ByVal nameCol As Integer, ByVal hashCol As Integer) As Integer
Dim VBAProj As VBIDE.VBProject
Dim VBAComp As VBIDE.VBComponent
Dim VBAProc As VBIDE.CodeModule
Dim procKind As VBIDE.vbext_ProcKind
Dim modName As String
Dim ProcName, procHash As String
Dim concatLines As String
Dim index As Long
Dim wsModuleHashRow, count, noOfLines As Integer
Dim noOfProcNames, noOfProcHashes As Integer
Dim process As Boolean
wsModuleHashRow = firstDataRow
genHashesAndStore = 0
'On openning and closing, calculate each module procedures hash
Set VBAProj = ActiveWorkbook.VBProject
With Worksheets("Module Hashes")
For Each VBAComp In VBAProj.VBComponents
Set VBAProc = VBAComp.CodeModule
'Process decision
Select Case VBAComp.Type
Case vbext_ct_StdModule
'Subroutines and Functions
modName = VBAComp.Name
process = True
Case vbext_ct_Document
'Exceptions list
process = False
If VBAComp.Name = "ThisWorkbook" Then 'Object: "ThisWorkbook"
modName = VBAComp.Name
process = True
End If
If VBAComp.Name = "Sheet8" Then 'Worksheet: "Setup & User Guide"
modName = ThisWorkbook.Worksheets(3).Name 'Worksheet position: DO NOT CHANGE
process = True
End If
'add exception, If...
Case Else
'Excluded: userforms and class modules, not used
process = False
End Select
If process Then
'Module or Object declaration lines (module/object or project scope declarations)
concatLines = vbNullString
noOfLines = 0
index = VBAProc.CountOfDeclarationLines + 1
'Start count at 1: No procedure declaration line for an Object/document type
'End count at (index-1) because index points to the start of the first procedure
For count = 1 To index - 1
'Do not include empty/spaceing lines or commnet lines in the hash
If Not (VBAProc.Lines(count, 1) = vbNullString Or _
Left(LTrim(VBAProc.Lines(count, 1)), 1) = "'") Then
concatLines = concatLines & VBAProc.Lines(count, 1)
noOfLines = noOfLines + 1
End If
Next count
If Len(concatLines) > 0 Then
procHash = stringToMD5Hex(concatLines)
Else
procHash = "No declaration section"
End If
'Write the declaration name and hash
'Debug.Print concatLines
.Cells(wsModuleHashRow, nameCol).Value = modName & ".Dec"
'procKindIs(procKind)
'"(" & noOfLines & ")"
.Cells(wsModuleHashRow, hashCol).Value = procHash
wsModuleHashRow = wsModuleHashRow + 1
'Procedure lines, combine declaration and code lines
Do While index < VBAComp.CodeModule.CountOfLines
ProcName = VBAProc.ProcOfLine(index, procKind)
'Debug.Print modName & "." & procName
index = VBAProc.ProcStartLine(ProcName, procKind) + VBAProc.ProcCountLines(ProcName, procKind)
concatLines = vbNullString
noOfLines = 0
'Start count at (...+1), don't include the procedure decalarion line in the hash:
' allows for procedure renaming to be identified
'End count at (index-1) because index points to the start of the next procedure
'End count at (index-1)
For count = VBAProc.ProcStartLine(ProcName, procKind) + 1 To index - 1
'
If Not (VBAProc.Lines(count, 1) = vbNullString Or _
Left(LTrim(VBAProc.Lines(count, 1)), 1) = "'") Then
concatLines = concatLines & VBAProc.Lines(count, 1)
noOfLines = noOfLines + 1
End If
Next count
If noOfLines > 1 Then
'Procedure has at least one line of code and "End Sub/Function"
'Don't hash procedure declaration line Sub/Function name(...) [As ...]
'Greater than one (>1) ensures at least 2 or more lines
procHash = stringToMD5Hex(concatLines)
Else
'Set warning: Nothing to hash, empty procedure (maybe a place holder?)
genHashesAndStore = 1
procHash = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
End If
'Write the procedure name and hash
'Debug.Print concatLines
.Cells(wsModuleHashRow, nameCol).Value = modName & "." & ProcName
'procKindIs(procKind)
'"(" & noOfLines & ")"
.Cells(wsModuleHashRow, hashCol).Value = procHash
wsModuleHashRow = wsModuleHashRow + 1
Loop
Else
'Not processed, skip to next VBAComp
End If
Next VBAComp
'Verify procedure names and hashes have been generated and written
noOfProcNames = getLastUsedRow(.Name, nameCol)
noOfProcHashes = getLastUsedRow(.Name, hashCol)
If noOfProcNames <> noOfProcHashes Then GoTo errorHandlerLabel
If noOfProcNames < firstDataRow Then GoTo errorHandlerLabel
If noOfProcHashes < firstDataRow Then GoTo errorHandlerLabel
End With
'Skip error handling
Set VBAProj = Nothing
Set VBAProc = Nothing
Exit Function
'Error handlig errorHandlerLabel: 'Set error: Nothing generated or written. Automated Version Control will not proces code-base changes genHashesAndStore = 2 Set VBAProj = Nothing Set VBAProc = Nothing Exit Function
End Function
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
