VBA-在打开工作簿之前检查工作簿是否受到保护

Dor*_*ian 6 excel vba password-protection

有没有办法尝试打开工作簿之前检查工作簿是否受到保护。

这是我的代码,但我不知道方法(如果可能)

Sub MySub()
Dim Wb As Workbook
For i = 14 To Cells(Rows.Count, 1).End(xlUp).Row
'I Would like to check if the workbook is Protected here

Set Wb = GetObject(Cells(i, 4).Value)



Wb.Open

End Sub
Run Code Online (Sandbox Code Playgroud)

注意:此代码中的代码Cells(i,4).Value将等于工作簿路径。

Tom*_*Tom 8

Had a bit more of a think about this and came up with the following - although will need a lot more testing and probably a bit of modification. I don't like that the default result is that it is protected but in my quick test I could only get a non-protected file to list its items.

This works by converting the file to a zip file, trying to navigate its contents and then converting back to the original type. I've only tested it with xlsx files but principle should be the same for xlsm as well. Once converted I use a shell to explore the zip contents. An unprotected file will return a list of its contents, where as a protected one won't.

Public Function IsWorkbookProtected(WorkbookPath As String) As Boolean
    Dim fileExtension As String
    Dim tmpPath As Variant
    Dim sh As Object
    Dim n

    fileExtension = Right(WorkbookPath, Len(WorkbookPath) - InStrRev(WorkbookPath, "."))
    tmpPath = Left(WorkbookPath, InStrRev(WorkbookPath, ".")) & "zip"

    Name WorkbookPath As tmpPath

    Set sh = CreateObject("shell.application")
    Set n = sh.Namespace(tmpPath)

    IsWorkbookProtected = Not n.Items.Count > 0

    Name tmpPath As WorkbookPath

End Function
Run Code Online (Sandbox Code Playgroud)

Called using

Sub test()
    Dim FolderPath As String
    Dim fPath1 As String, fPath2 As String

    FolderPath = "ParentFolder"

    ' protected
    fPath1 = FolderPath & "\testProtection.xlsx"
    ' unprotected
    fPath2 = FolderPath & "\testProtection - Copy.xlsx"

    Debug.Print fPath1, IsWorkbookProtected(fPath1)
    Debug.Print fPath2, IsWorkbookProtected(fPath2)
End Sub
Run Code Online (Sandbox Code Playgroud)

Output to immediate window:

ParentFolder\testProtection.xlsx     True
ParentFolder\testProtection - Copy.xlsx   False
Run Code Online (Sandbox Code Playgroud)

This was a brief test into exploring the issue and I will state that this is most likely not a conclusive nor fool-proof answer. Ideally I'd want to traverse the zip folder contents and test for the 'EncryptedPackage' but NameSpace wasn't returning any items. There may be another way of being able to do it but I haven't investigated further.

Protected Excel file zip contents: 在此处输入图片说明

Non-Protected Excel file zip contents: 在此处输入图片说明

Update with timer tests

Using a timer code from TheSpreadSheetGuru

Sub CalculateRunTime_Seconds()
    'PURPOSE: Determine how many seconds it took for code to completely run
    'SOURCE: www.TheSpreadsheetGuru.com/the-code-vault

    Dim StartTime As Double
    Dim SecondsElapsed As Double

    'Remember time when macro starts
      StartTime = Timer

'    Debug.Print "IsWorkbookProtected"
    Debug.Print "testOpen"

    '*****************************
    'Insert Your Code Here...
    '*****************************
'    Call testZip
    Call testOpen

    'Determine how many seconds code took to run
      SecondsElapsed = Round(Timer - StartTime, 2)

    'Notify user in seconds
      Debug.Print "This code ran successfully in " & SecondsElapsed & " seconds"

End Sub
Run Code Online (Sandbox Code Playgroud)

and using the following code to test by opening the files, testing for protection and closing

Sub testOpen()
    Dim wb As Workbook
    Dim FolderPath As String
    Dim fPath1 As String, fPath2 As String
    Dim j As Long

    FolderPath = "FolderPath"

    Application.ScreenUpdating = False
    ' protected
    fPath1 = FolderPath & "\testProtection.xlsx"
    ' unprotected
    fPath2 = FolderPath & "\testProtection - Copy.xlsx"
    For j = 1 To 2

        On Error Resume Next
        Set wb = Workbooks.Open(Choose(j, fPath1, fPath2), , , , "")

        Debug.Print Choose(j, fPath1, fPath2), wb Is Nothing

        wb.Close
        On Error GoTo 0
    Next j

    Application.ScreenUpdating = True

End Sub
Run Code Online (Sandbox Code Playgroud)

I got the following times:

在此处输入图片说明

Run this multiple times and got similar results

  • 我不明白,但是粗略的测试表明它是有效的。非常聪明。 (2认同)

Jvd*_*vdV 5

任何文档都完全不支持这一点,但我想我发现了一些有趣的东西。我很好奇关于这个的其他意见。


假设

因此,每次我查看所有文件属性时,都有一个属性在文件受密码保护时似乎发生了变化,这是属性 42(即“程序名称”),它是扩展文件属性的一部分。请参阅下面的屏幕截图(@Tom),其中左侧是未受保护的文件,右侧是受保护的文件。

在此处输入图片说明

每次我取消保护工作簿时,都会显示一个值,例如“Microsoft Excel”,有时甚至是“Microsoft Excel Online”。但是,在我保护工作簿的所有情况下,该值为空。因此,这让我认为查看此特定属性会以某种方式告诉我们,当该属性为空时,该文件受到保护。这可能是因为由于保护而无法读取该属性吗?

在@Tom 的帮助下,我们发现此属性的索引可能有所不同。虽然在我的系统上,这个属性的索引为 42,但在 Tom 的系统中,它似乎低于 8。因此,他好心地实现了一个智能循环,以便在循环文件之前返回正确的索引。值得注意的是:该属性的名称取决于语言!例如,对于荷兰语,我会寻找“Programmanaam”。


代码

使用以下代码,我们可以遍历特定文件夹和循环文件以返回此特定属性的值:

Sub MySub()

Dim sFile As Variant
Dim oShell: Set oShell = CreateObject("Shell.Application")
Dim oDir:   Set oDir = oShell.Namespace("C:\Users\...\")
Dim i as long, x as long

For i = 0 To 288
    If oDir.GetDetailsOf(oDir.Items, i) = "Program name" Then
        x = i
        Exit For
    End If
Next i

For Each sFile In oDir.Items
    If oDir.GetDetailsOf(sFile, x) = "" Then
        Debug.Print sFile.Name & " is protected"
    Else
        Debug.Print sFile.Name & " is unprotected and can be openened"
    End If
Next

End Sub
Run Code Online (Sandbox Code Playgroud)

再调整一下以循环一个范围并检查一堆可能如下所示的工作簿名称:

在此处输入图片说明

工作代码如下所示:

Sub MySub()

Dim MainPath As String: MainPath = "C:\Users\...\"
Dim i As Long, x As Long
Dim oDir As Object: Set oDir = CreateObject("Shell.Application").Namespace(CStr(MainPath))

'Get the right index for property "Program Name"
For i = 0 To 288
    If oDir.GetDetailsOf(oDir.Items, i) = "Program Name" Then
        x = i
        Exit For
    End If
Next i

'Loop the range of workbooks and check whether or not they are protected
With ThisWorkbook.Sheets("Sheet1") 'Change accordingly
    For i = 1 To .Cells(.Rows.Count, 1).End(xlUp).Row
        If oDir.GetDetailsOf(oDir.Items.Item(CStr(.Cells(i, 1))), x) = "" Then
            Debug.Print .Cells(i, 1) & " is protected"
        Else
            Debug.Print .Cells(i, 1) & " is unprotected and can be openened"
            'Open your workbook here?
        End If
    Next i
End With

End Sub
Run Code Online (Sandbox Code Playgroud)

注意:请注意Cstr()MainPath 和单元格值上的使用。据我所知不是很清楚为什么,但没有它,代码将返回“错误 445:对象不支持此操作”更新:检查 问题以了解有关此特定问题的更多信息。


例子

例如,我有以下工作簿,其中 Map2 和 Map5 受到保护:

在此处输入图片说明

运行第一个宏后的立即窗口:

在此处输入图片说明

接下来我只保护了 map1 和 map3,结果如下:

在此处输入图片说明


结论

假设得到证实?我不知道,但在我看来,这个假设从来没有被证明是错误的。同样,没有关于此的文档。但这可能只是您快速了解工作簿是否受保护的方式。

顺便说一句,我在这里借用了一些代码表格