I have a workbook which processes a series of input workbooks, some of which have VBA password set but are not locked for viewing – i.e. no password is required to navigate the vb code but a password is required to view project properties (e.g. Tools/References). In this situation VBProject.Protection is set to vbext_pp_none even though a password is set. What can I check to detect that ‘Password to view project properties’ is present?
2 Answers
When you protect the project you must both tick the box and supply a password.
- If you supply a password without ticking the box the protection is not applied
- If you tick the box with supplying a password your are prompted to add a password to continue
In other words, your logic of one but the other makes sense but doesn't happen (that I'm aware of (I tested on Excel 2010)), it is either vbext_pp_none
(0) or vbext_pp_locked
(1).
EDIT/ADDITIONAL: -
After reading your comments, I could not reproduce the situation but amongst all the versions/platforms I can't imagine it's not possible. Below is a example whereby a property is attempted to be changed while in an error trapping procedure, if its successful then it wasn't locked at all.
Public Sub Sample()
Dim WkBk As Workbook
Set WkBk = Application.Workbooks.Open(Environ("UserProfile") & "\Desktop\Book1.xlsm")
If WkBk.VBProject.Protection = 1 Then 'vbext_pp_locked then
MsgBox "It is locked"
Else
If LockedForEdits(WkBk) Then
MsgBox "It is locked for edits"
Else
MsgBox "It is not locked"
End If
End If
WkBk.Close 0
Set WkBk = Nothing
End Sub
Private Function LockedForEdits(ByRef WkBk As Workbook) As Boolean
Dim StrDescription As String
On Error GoTo ErrorHandle
StrDescription= WkBk.VBProject.Description
WkBk.VBProject.Description = WkBk.VBProject.Description & "TEST"
WkBk.VBProject.Description = StrDescription
Exit Function
ErrorHandle:
Err.Clear
LockedForEdits = True
End Function

- 1,850
- 4
- 15
- 30
-
Hi Gary - Sorry but this is not correct. Using Excel 2010 supplying a password without ticking the box allows access to the vb code but requests the password when examining properties - I have encountered 10 workbooks where this is the case - easy to demonstrate. – allan brayshaw May 30 '16 at 06:40
-
Thanks Gary - I will study your code but the point is that the vb code can be edited but any attempt to examine properties results in a password input box. It is odd that you cannot replicate the problem as I have encountered it in 10 of the 300+ workbooks I have examined. My home and office versions of Excel can both create the situation where the checkbox is not ticked but a password is present. I could send you an example workbook if it helps. – allan brayshaw May 30 '16 at 14:28
-
tried code - says not locked but right click on VBA Project properties asks for a password. – allan brayshaw May 30 '16 at 14:42
-
@allanbrayshaw I was able to create a workbook with a password and 'lock for viewing' unticked, I think I was failing because I didn't close Excel before trying again. I now see your issue, via VBA I can not supply the password for locking/unlocking. But I was still able to read/write the properties even though I had not given then password. I.e. `WkBk.VBProject.Description = "TEST"` worked even though the properties were behind a password when access via the UI. Meaning I can not detect/clear the password, nor does it stop me. Code edited above as I was targeting the wrong properties. – Gary Evans May 30 '16 at 21:58
-
great that you can see the issue. Have you any idea how this condition can be detected? I have a crude solution which involves sendkeys and asking the user whether the password box appears but there must be an indicator other than .Protection in the VBProject model which I could test. – allan brayshaw May 31 '16 at 04:58
-
@allanbrayshaw It would look like not via the exposed VBA :( I really missed the point on this question. I'll delete my answer in a while. – Gary Evans Jun 01 '16 at 15:15
-
@allanbrayshaw what about this http://stackoverflow.com/questions/16174469/unprotect-vbproject-from-vb-code – Gary Evans Jun 01 '16 at 15:20
-
Gary - your efforts much appreciated. yes seen and tried handle approach but having 2003 and virtual 2010 installed created new instance of 2003, uninstalled 2003 and all ok but on reinstalling 2003 cannot recreate same condition so had to revert to sendkeys for users to run. But latest sendkeys Wait not working. Have a workaround for most conditions and only found one other developer report so far but expecting more. see http://www.mrexcel.com/forum/excel-questions/912585-sendkeys-wont-work-if-followed-any-other-code-why.html – allan brayshaw Jun 03 '16 at 16:57
The below code relies on information not present in the question but, if working exclusively on a PC using Excel 2010 (tested) or 2007 (not tested) it should detect the presence of a password and along with code you already have and code in the previous answer, it should answer the question of a way of detecting the presence of a password.
The latest office file format is a zip package, to that end you can rename it from .xlsm
to .zip
and view its content. Within the zip package there may be a bin
file (not present if there is no VBA in the file) in the xl
folder. In the bin
file there is a string value called 'DPB' the value is encrypted but if there is a password, the value is long, thus the presence of a password can be detected by the length of the 'DPB' value.
The below code will benefit from significant error handling as there is a lot of file manipulation happening, and as mentioned, this used in conjunction with an altered version of the code in the previous answer, should provide with the answer to the question.
The code below will need the 'Windows Scripting Runtime' reference added (Tools > References > tick 'Windows Scripting Runtime'), I didn't late-bind to make writing it quicker and potentially clearer. I've also commented throughout the code to describe what is happening
Public Sub Sample()
Dim FSO As New FileSystemObject
Dim Shl As Object
Dim Fl As Scripting.File
Dim Fldr As Scripting.Folder
Dim LngCounter As Long
Dim Ts As Scripting.TextStream
Dim StrTmpFldr As String
Dim StrWkBk As String
Dim StrWkBkName As String
Dim StrContainer As String
Dim WkBk As Excel.Workbook
'A place to work with temp files, for my own ease I done it on the desktop
'but this is not good practice
StrTmpFldr = Environ("UserProfile") & "\Desktop\"
'A path to a workbook (may be passed in)
StrWkBk = Environ("UserProfile") & "\Desktop\Book4.xlsm"
'We need the file name seperate from the path
StrWkBkName = Right(StrWkBk, Len(StrWkBk) - InStrRev(StrWkBk, "\"))
'Copy the workbook and change it to a .zip (xlsx, and other new forms are zip packages)
FSO.CopyFile StrWkBk, StrTmpFldr & Left(StrWkBkName, InStrRev(StrWkBkName, ".")) & "zip", True
'Create a folder to extract the zip to
FSO.CreateFolder StrTmpFldr & Left(StrWkBkName, InStrRev(StrWkBkName, ".") - 1)
'Unzip it into the folder we created
Set Shl = CreateObject("Shell.Application")
Shl.Namespace(StrTmpFldr & Left(StrWkBkName, InStrRev(StrWkBkName, ".") - 1) & "\").CopyHere Shl.Namespace(StrTmpFldr & Left(StrWkBkName, InStrRev(StrWkBkName, ".")) & "zip").Items
Set Shl = Nothing
'Delete the zip
FSO.DeleteFile StrTmpFldr & Left(StrWkBkName, InStrRev(StrWkBkName, ".")) & "zip", True
Set Fldr = FSO.GetFolder(StrTmpFldr & Left(StrWkBkName, InStrRev(StrWkBkName, ".") - 1) & "\xl\")
'Is there a project file? (there won't be if there is no code in it)
For Each Fl In Fldr.Files
If Right(Fl.Name, 4) = ".bin" Then Exit For
Next
If Fl Is Nothing Then
MsgBox "It is not protected"
Else
'Parse the file looking for the line starting "DPB="" if the value in here is over 25 long,
'then it is storing a password
Set Ts = Fl.OpenAsTextStream(ForReading)
Do Until Ts.AtEndOfStream
StrContainer = Ts.ReadLine
If Left(StrContainer, 5) = "DPB=" & """" Then
StrContainer = Replace(Replace(StrContainer, "DPB=", ""), """", "")
If Len(StrContainer) > 25 Then
MsgBox "It is protected"
Else
MsgBox "It is not protected"
End If
Exit Do
End If
Loop
Ts.Close
Set Ts = Nothing
Set Fl = Nothing
End If
Set Fldr = Nothing
'Delete the folder
FSO.DeleteFolder StrTmpFldr & Left(StrWkBkName, InStrRev(StrWkBkName, ".") - 1), True
End Sub

- 1,850
- 4
- 15
- 30