简体   繁体   English

为什么Workbook_Open事件会保护工作簿?

[英]Why is the workbook protected upon Workbook_Open Event?

I adapted some code found here http://www.vbaexpress.com/kb/getarticle.php?kb_id=379 for a neat solution that forces users to enable macros. 我修改了一些http://www.vbaexpress.com/kb/getarticle.php?kb_id=379上的代码,以提供一种简洁的解决方案,迫使用户启用宏。 This method is a really good way of getting around this problem. 此方法是解决此问题的一种非常好的方法。 However, my additional requirements are: one particular user needs a more sensitive version of 2 sheets within the workbook. 但是,我的其他要求是:一个特定用户需要工作簿中2张纸的更敏感版本。 Depending on the answer to a MsgBox an InputBox requires password verification and then shows the sensitive versions of these sheets. 根据MsgBox的答案,InputBox需要密码验证,然后显示这些表的敏感版本。 I believe the answer lies in how the workbook is saved and then how all sheets are unhidden upon re-opening the workbook (since two of the sheets are effectively password locked) but somehow now when I open this workbook the password used for unhiding the two sensitive versions of the sheets is required to open the workbook. 我相信答案在于如何保存工作簿,然后在重新打开工作簿时如何取消隐藏所有工作表(因为其中两个工作表已有效地密码锁定),但是现在我打开此工作簿时以某种方式使用的密码隐藏了两个工作表必须打开工作表的敏感版本才能打开工作簿。 So I changed the password required for verification of the said sheets but the Original password is still required to open the workbook: Any assistance in diagnosing this problem would be a help: Creating a spread-sheet and testing the code on your system shouldn't be too difficult and a good place to start! 因此,我更改了验证上述工作表所需的密码,但是打开工作簿仍需要原始密码:诊断此问题的任何帮助都将有所帮助:创建电子表格并测试系统上的代码不应该太难了,是一个很好的起点!

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

You don't need to protect the whole workbook to hide the sheets. 您无需保护整个工作簿即可隐藏工作表。 xlVeryHidden will hide the sheet and prevent it from being shown on the Hide/Unhide list. xlVeryHidden将隐藏工作表并阻止其在“隐藏/取消隐藏”列表中显示。

First, unprotect the workbook. 首先,取消保护工作簿。 You can do this by the Review tab, and then clicking on the Protect Workbook and clear any protection you have checked. 您可以通过“审阅”选项卡,然后单击“保护工作簿”并清除所有已检查的保护来执行此操作。 I'd also click on the Protect Sheet button for each sheet and clear any protection set there. 我还要单击每个工作表的“保护工作表”按钮,然后清除那里的所有保护设置。

Then, modify your Workbook_Open subroutine to do something like this: 然后,修改您的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

Basically, the workbook is unprotected when opened. 基本上,工作簿在打开时不受保护。 If the user is not the special user, then it hides the two special sheets. 如果用户不是特殊用户,则它将隐藏两个特殊工作表。 If they are the special user, then it hides the two special sheets and they can't be unhidden. 如果他们是特殊用户,则它将隐藏这两个特殊工作表,并且不能将其隐藏。

Additional Suggestion 附加建议

You'll run into a problem with the sheet visibility when the user saves - if it's the special user, once the save is complete they won't be able to see the sensitive sheets, because your ShowAllSheets subroutine will hide them. 用户保存时,工作表可见性会出现问题-如果是特殊用户,保存完成后,他们将无法看到敏感工作表,因为ShowAllSheets子例程会将其隐藏。

To get around this, set a global variable to record whether the user is the special user or not, and use that to determine what sheets to show in ShowAllSheets , like this: 要解决此问题,请设置一个全局变量以记录该用户是否为特殊用户,并使用该变量来确定在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

This code will set a flag ( IsMasterUser ) depending on the selection in Workbook_Open . 此代码将根据Workbook_Open的选择设置一个标志( IsMasterUser )。 Then when ShowAllSheets is called, it will determine whether to show the standard sheets or the special sheets based on IsMasterUser . 然后,当ShowAllSheets时,它将基于IsMasterUser确定是显示标准图纸还是特殊图纸。 Note that IsMasterUser is defaulted to "N" when its declared. 请注意, IsMasterUser在声明时默认为“ N”。

EDIT 编辑

A couple of minor problems with the code above. 上面的代码有几个小问题。 First, the global variable needs to be declared as Public IsMasterUser As String , and secondly it needs to be set to a value inside a function, so I set it to "N" at the start of the Workbook_Open subroutine. 首先,需要将全局变量声明为Public IsMasterUser As String ,其次需要将其设置为函数内部的值,因此我在Workbook_Open子例程的开头将其设置为“ N”。

I tested the posted code (the second set), along with the unaltered code from the original post in a Excel 2010 workbook with 6 sheets - Macros, User, Standard Sheet 1, Standard Sheet 2, Sensitive Sheet 1 and Sensitive Sheet 2, and it worked just fine. 我测试了已发布的代码(第二组),以及Excel 2010工作簿中原始帖子的未更改代码,其中包含6个工作表-宏,用户,标准工作表1,标准工作表2,敏感工作表1和敏感工作表2,以及它工作得很好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM