【问题标题】:Why is the workbook protected upon Workbook_Open Event?为什么工作簿在 Workbook_Open 事件中受到保护?
【发布时间】:2013-05-26 18:15:56
【问题描述】:

我改编了一些在这里找到的代码 http://www.vbaexpress.com/kb/getarticle.php?kb_id=379 以获得强制用户启用宏的简洁解决方案。这种方法是解决这个问题的好方法。但是,我的附加要求是:一个特定的用户需要工作簿中更敏感的 2 张工作表版本。根据对 MsgBox 的回答,InputBox 需要密码验证,然后显示这些工作表的敏感版本。 我相信答案在于如何保存工作簿,然后在重新打开工作簿时如何取消隐藏所有工作表(因为其中两张工作表被有效地密码锁定)但是现在当我打开这个工作簿时,用于取消隐藏的密码这两个打开工作簿需要工作表的敏感版本。 所以我更改了验证上述表格所需的密码,但打开工作簿仍然需要原始密码: 诊断此问题的任何帮助都会有所帮助:创建电子表格并在您的系统上测试代码应该不会太难,并且是一个很好的起点!

Option Explicit

Const WelcomePage = "Macros"

Private Sub Workbook_BeforeClose(Cancel As Boolean)
     'Turn off events to prevent unwanted loops
    Application.EnableEvents = False

     'Evaluate if workbook is saved and emulate default propmts
    With ThisWorkbook
        If Not .Saved Then
            Select Case MsgBox("Do you want to save the changes you made to '" & .Name & "'?", _
                vbYesNoCancel + vbExclamation)
            Case Is = vbYes
                 'Call customized save routine
                Call CustomSave
            Case Is = vbNo
                 'Do not save
            Case Is = vbCancel
                 'Set up procedure to cancel close
                Cancel = True
            End Select
        End If

         'If Cancel was clicked, turn events back on and cancel close,
         'otherwise close the workbook without saving further changes
        If Not Cancel = True Then
            .Saved = True
            Application.EnableEvents = True
            .Close savechanges:=False
        Else
            Application.EnableEvents = True
        End If
    End With
End Sub

Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
     'Turn off events to prevent unwanted loops
    Application.EnableEvents = False

     'Call customized save routine and set workbook's saved property to true
     '(To cancel regular saving)
    Call CustomSave(SaveAsUI)
    Cancel = True

     'Turn events back on an set saved property to true
    Application.EnableEvents = True
    ThisWorkbook.Saved = True
End Sub

Private Sub Workbook_Open()
     'Unhide all worksheets


    Application.ScreenUpdating = False
    Call ShowAllSheets
    Application.ScreenUpdating = True

        Dim msg1, msg2, Pwd As String

    Pwd = "5555"

    Do

    msg1 = MsgBox("Are you the Master User?", vbYesNo)

    Loop Until msg1 = vbNo Or msg1 = vbYes

    If msg1 = vbNo Then
    Worksheets("Sensitive Sheet 1").Visible = xlVeryHidden
    Worksheets("Sensitive Sheet 2").Visible = xlVeryHidden

    ThisWorkbook.Unprotect Password:=Pwd
    ElseIf msg1 = vbYes Then

    Do
    msg2 = InputBox("Please Enter the Password", "Password Checker", vbOKOnly)
    Loop Until msg2 = Pwd

    Worksheets("Sensitive Sheet 1").Visible = True
    Worksheets("Sensitive Sheet 2").Visible = True
    Worksheets("Standard Sheet 1").Visible = xlVeryHidden
    Worksheets("Standard Sheet 2").Visible = xlVeryHidden

    End If





End Sub

Private Sub CustomSave(Optional SaveAs As Boolean)
    Dim WS As Worksheet, aWs As Worksheet, newFname As String
     'Turn off screen flashing
    Application.ScreenUpdating = False

     'Record active worksheet
    Set aWs = ActiveSheet

     'Hide all sheets
    Call HideAllSheets

     'Save workbook directly or prompt for saveas filename
    If SaveAs = True Then
        newFname = Application.GetSaveAsFilename( _
        fileFilter:="Macro Enabled Excel Files (*.xlsm), *.xlsm")
        If Not newFname = "False" Then ThisWorkbook.SaveAs newFname
    Else
        ThisWorkbook.Save
    End If

     'Restore file to where user was
    Call ShowAllSheets
    aWs.Activate

     'Restore screen updates
    Application.ScreenUpdating = True
End Sub

Private Sub HideAllSheets()
     'Hide all worksheets except the macro welcome page
    Dim WS As Worksheet

    Worksheets(WelcomePage).Visible = xlSheetVisible

    For Each WS In ThisWorkbook.Worksheets
        If Not WS.Name = WelcomePage Then WS.Visible = xlSheetVeryHidden
    Next WS

    Worksheets(WelcomePage).Activate
End Sub

Private Sub ShowAllSheets()
     'Show all worksheets except the macro welcome page

    Dim WS As Worksheet


    For Each WS In ThisWorkbook.Worksheets

        If WS.Name <> "Sensitive Sheet 1" And WS.Name <> "Sensitive Sheet 2" Then

            If Not WS.Name = WelcomePage Then WS.Visible = xlSheetVisible

        End If

    Next WS

    Worksheets(WelcomePage).Visible = xlSheetVeryHidden

End Sub

【问题讨论】:

  • 我认为您不必费心锁定工作簿,只需对两张工作表使用 xlVeryHidden。取消保护工作簿,保存它,然后在 VBA 中删除取消保护它的代码行。
  • 嗨,蒂姆,感谢您回复我....我不知道工作簿为何/如何被锁定。我不希望它被锁定,这就是我用来隐藏工作表的方法。如果主用户输入正确的密码,他会看到工作表的完整版本,如果不是主用户,则使用您描述的方法显示更改后的版本。问题是这个过程一定以某种方式锁定了工作簿——问题是如何解锁它并防止它再次发生?
  • 我正在尝试一些方法,如果可行,我会尽快为您提供答案 - 或者至少是一个建议。
  • 给了你一个建议...我会稍微修改一下并提出进一步的建议,但这应该会让你继续前进。

标签: vba excel password-protection


【解决方案1】:

您无需保护整个工作簿即可隐藏工作表。 xlVeryHidden 将隐藏工作表并阻止它显示在隐藏/取消隐藏列表中。

首先,取消保护工作簿。您可以通过 Review 选项卡执行此操作,然后单击 Protect Workbook 并清除您已检查的任何保护。我还会单击每个工作表的“保护工作表”按钮并清除那里的所有保护设置。

然后,修改您的 Workbook_Open 子例程以执行以下操作:

Private Sub Workbook_Open()

    Dim msg1, msg2, Pwd As String

    Pwd = "5555"

    Do
        msg1 = MsgBox("Are you the Master User?", vbYesNo)
    Loop Until msg1 = vbNo Or msg1 = vbYes

    If msg1 = vbNo Then
        Worksheets("Sensitive Sheet 1").Visible = xlVeryHidden
        Worksheets("Sensitive Sheet 2").Visible = xlVeryHidden
    ElseIf msg1 = vbYes Then
        Do
            msg2 = InputBox("Please Enter the Password", "Password Checker", vbOKOnly)
        Loop Until msg2 = Pwd

        Worksheets("Sensitive Sheet 1").Visible = True
        Worksheets("Sensitive Sheet 2").Visible = True
        Worksheets("Standard Sheet 1").Visible = xlVeryHidden
        Worksheets("Standard Sheet 2").Visible = xlVeryHidden
    End If
End Sub

基本上,工作簿在打开时是不受保护的。如果用户不是特殊用户,则隐藏两个特殊工作表。如果他们是特殊用户,则隐藏两个特殊工作表,并且无法取消隐藏。

补充建议

当用户保存时,您会遇到工作表可见性问题 - 如果是特殊用户,一旦保存完成,他们将无法看到敏感工作表,因为您的 ShowAllSheets 子例程将隐藏他们。

为了解决这个问题,设置一个全局变量来记录用户是否是特殊用户,并使用它来确定在ShowAllSheets 中显示哪些工作表,如下所示:

Option Explicit

Public IsMasterUser As String

Private Sub Workbook_Open()

    Dim msg1, msg2, Pwd As String

    Pwd = "5555"

    IsMasterUser = "N"

    Application.ScreenUpdating = False
    Call ShowAllSheets
    Application.ScreenUpdating = True

    Do
        msg1 = MsgBox("Are you the Master User?", vbYesNo)
    Loop Until msg1 = vbNo Or msg1 = vbYes

    If msg1 = vbNo Then
        IsMasterUser = "N"

        Worksheets("Sensitive Sheet 1").Visible = xlVeryHidden
        Worksheets("Sensitive Sheet 2").Visible = xlVeryHidden
    ElseIf msg1 = vbYes Then
        Do
            msg2 = InputBox("Please Enter the Password", "Password Checker", vbOKOnly)
        Loop Until msg2 = Pwd

        IsMasterUser = "Y"

        Worksheets("Sensitive Sheet 1").Visible = True
        Worksheets("Sensitive Sheet 2").Visible = True
        Worksheets("Standard Sheet 1").Visible = xlVeryHidden
        Worksheets("Standard Sheet 2").Visible = xlVeryHidden
    End If
End Sub

Private Sub ShowAllSheets()
'Show all worksheets except the macro welcome page

    Dim WS As Worksheet

    For Each WS In ThisWorkbook.Worksheets
        If Not WS.Name = WelcomePage Then
            If IsMasterUser = "N" _
               And WS.Name <> "Sensitive Sheet 1" _
               And WS.Name <> "Sensitive Sheet 2" Then
                WS.Visible = xlSheetVisible
            ElseIf IsMasterUser = "Y" _
               And WS.Name <> "Standard Sheet 1" _
               And WS.Name <> "Standard Sheet 2" Then
                WS.Visible = True
            End If
        End If
    Next WS

    Worksheets(WelcomePage).Visible = xlSheetVeryHidden
End Sub

此代码将根据Workbook_Open 中的选择设置一个标志(IsMasterUser)。那么当ShowAllSheets被调用时,它会根据IsMasterUser来决定是显示标准图纸还是特殊图纸。请注意,IsMasterUser 在声明时默认为“N”。

编辑

上面的代码有几个小问题。首先,全局变量需要声明为Public IsMasterUser As String,其次需要在函数内部设置一个值,所以我在Workbook_Open子程序的开头将它设置为“N”。

我在 Excel 2010 工作簿中测试了发布的代码(第二组)以及原始帖子中未更改的代码,其中包含 6 张工作表 - 宏、用户、标准工作表 1、标准工作表 2、敏感工作表 1 和敏感工作表2,效果很好。

【讨论】:

  • 每当我听到“不能”时,我都会感到很痒……“他们不能被隐藏”?假设有人进入 VBA 编辑器——他们可以自己编写一个宏来取消隐藏敏感表吗?我想是的...For each sh in Workbook("some name").Worksheets, sh.Visible=True, next sh 可能有用吗?您可以从隐藏代码开始(人们可能不知道有非常隐藏的工作表)。有没有办法防止“其他”代码(来自另一个工作簿)在工作簿上运行?
  • 另外我认为您不想为主用户将标准表设置为xlVeryHidden。我怀疑应该允许主用户查看所有内容...
  • @Floris - 您可以对给定工作簿的 VBA 进行密码保护,这将阻止用户这样做。虽然您可能可以使用其他工作簿中的 VBA,但普通用户会这样做吗?我对此表示怀疑。如果信息如此敏感/重要,那么 Excel 就不是该工作的错误工具——即使是受保护的工作簿也可能被破解。我不知道是否有办法阻止一个工作簿中的代码在另一个工作簿上运行(除非工作簿受到保护)。
  • @Floris - 基于 OP 的问题和他们发布的代码,标准工作表被设置为隐藏,因为主用户需要特殊工作表而不是标准工作表。
  • @tripkane - 我在我的代码中修复了这些问题,并在一个包含 6 张工作表的工作簿中对其进行了测试(如我的编辑中所述)。至于您的替代解决方案,这可能有效 - 您可以将宏绑定到 Excel 中的几乎任何类型的控件。仍然不确定为什么您的工作簿认为它已被锁定....如果它不是很多工作表并且它们非常简单,您可以尝试从头开始,看看是否有东西损坏。
猜你喜欢
  • 2020-10-05
  • 2022-12-19
  • 2015-05-16
  • 2019-06-04
  • 1970-01-01
  • 2011-10-02
  • 1970-01-01
  • 2018-09-21
  • 1970-01-01
相关资源
最近更新 更多