0

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 Answers2

0

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
Gary Evans
  • 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
0

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
Gary Evans
  • 1,850
  • 4
  • 15
  • 30