Is there a built-in way in Excel to protect just one spreadsheet in a Workbook with a Password?
Something like when user ticks or selects a Control , a password is prompted before a Worksheet become visible.
If its not built into Excel, can it be implemented with VBA?
You could try this approach which:
Makes the sheet VeryHidden and Protected so that it can't be unprotected - or detected - from the standard xl menus
Adds back in this protection on the Workbook_BeforeClose and Workbook_Open events
I haved used a sheet called YourSheet for this example
You should protect the VBA in this project as well to add further security.
Insert an Active X checkbox and use code to check if:
The checkbox is True
The user knows the password to UnHide the sheet. (Fred is used in this example)
CheckBox code
Private Sub CheckBox1_Click()
Dim StrPass As String
If CheckBox1.Value Then
StrPass = Application.InputBox("Please enter the password", "Admin check")
If StrPass = "fred" Then
With ThisWorkbook.Sheets("YourSheet")
.Unprotect "fred"
.Visible = xlSheetVisible
MsgBox "Sheet unhidden!", vbInformation
End With
Else
MsgBox "wrong password", vbCritical
End If
End If
End Sub
the ThisWorkbook module
Private Sub Workbook_BeforeClose(Cancel As Boolean)
With ThisWorkbook.Sheets("YourSheet")
.Protect "fred"
.Visible = xlVeryHidden
End With
End Sub
Private Sub Workbook_Open()
With ThisWorkbook.Sheets("YourSheet")
.Protect "fred"
.Visible = xlVeryHidden
End With
End Sub
Related
At the time of opening a document, it indicates to view it I must enable editing of the protected view.
I want at the time it is detected, to close the document until deleting that configuration of Excel.
Is there any small VBA function that does this procedure?
error 91 occurred at variable object runtime with block not set
If Application.ProtectedViewWindows.Count > 0 Then
ActiveWorkbook.Close savechanges:=False
Application.Quit
Else
End If
The entire ActiveWorbook code
Private Sub Workbook_Open()
Dim hoja As Worksheet
For Each hoja In ThisWorkbook.Worksheets
hoja.Visible = xlSheetVisible
Next hoja
If Application.ProtectedViewWindows.Count > 0 Then
ActiveWorkbook.Close savechanges:=False
Application.Quit
Else
End If
If Not VBATrusted() Then
Application.Visible = False
MsgBox "Aviso. Ya no puedes usar este archivo. Comunícate con el desarrollador Arq. Luis Eduardo Ramírez Aguayo entremuros.masterplan#hotmail.com Cel. +(52) 415.151.102"
ActiveWorkbook.Close savechanges:=False
Application.Quit
End If
Sheets("Hoja1").Visible = xlVeryHidden
'----------------------------------------------------------------'
Application.Visible = False
UserForm1.Show
End Sub
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Dim hoja As Worksheet
Sheets("Hoja1").Visible = xlSheetVisible
For Each hoja In ThisWorkbook.Worksheets
If hoja.Name <> "Hoja1" Then
hoja.Visible = xlSheetVeryHidden
End If
Next hoja
'----------------------------------------------------------------'
Sheets("HojaEscondida").Range("A4") = "admin"
Sheets("HojaEscondida").Range("A4") = "admin"
Application.DisplayAlerts = False
End Sub
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
If SaveAsUI Then
MsgBox "NO SE PUEDE GUARDAR COMO." & Chr(10) _
& "Guarde el original, usando el icono guardar," & Chr(10) _
& "o simplemente use la x de cerrar, y se guardará" & Chr(10) _
& "automáticamente en el lugar correcto", vbCritical
Cancel = True
End If
End Sub
Function VBATrusted() As Boolean
On Error Resume Next
VBATrusted = (Application.VBE.VBProjects.Count) > 0
End Function
Try this one.
Click File > Options.
Click Trust Center > Trust Center Settings > Protected View.
Uncheck Enable Protected View for files originating from the internet.
Hope it helps
Protected View is a security feature that disables macros and editing of the file. If you could run VBA code in the protected view this would be a securtity hole. Therefore you cannot run any code in protected view.
As a workaround you can add a worksheet ProtectionInfo and write some warning message on in like "This workbook needs to be opened with macros enabled and without protected view!"
Then you write a code in your Workbook_Open which hides the worksheet ProtectionInfo if the workbook opens. That means if macros are enabled and the user is not in protected view he will not see the warning worksheet. But if macros are disabled or in protected view, the user will see the warning.
Make sure to make the worksheet ProtectionInfo visible on Workbook_BeforeClose so it is shown again next time anyone opens it with macros disabled. Additionally you might want to hide all other worksheet so ProtectionInfo is the only worksheet that is shown when macros are disabled.
As #Pᴇʜ said, you can only do a workaround by hiding all Worksheets except one where it says you have to disable protected view and unhide the worksheets when macros are enabled. But you should do that at Workbook_BeforeSave because some people save it in between but don't save it in the end and then the worksheets wouldn't be hidden then next time it's opened.
Since I already made that for myself for when macros are disabled with notification, I can share it here.
The following code will hide all worksheets except "No Macros" where I have a message shown how to enable macros.
Notice that I added a Variable LastSheet so when someone saves the file that it knows where to jump back to after it has unhidden all worksheets again
Dim LastSheet As String
Private Sub Workbook_AfterSave(ByVal Success As Boolean)
Unhide_Worksheets
ThisWorkbook.Saved = True
End Sub
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
LastSheet = ThisWorkbook.ActiveSheet.Name
Hide_Worksheets
End Sub
Private Sub Workbook_Open()
Unhide_Worksheets
End Sub
Private Sub Hide_Worksheets()
'Application.ScreenUpdating = False
ThisWorkbook.Worksheets("No Macros").Visible = xlSheetVisible
ThisWorkbook.Worksheets("No Macros").Activate
On Error Resume Next
For Each Worksheet In ThisWorkbook.Worksheets
If Worksheet.Name <> "No Macros" Then
Worksheet.Visible = xlSheetVeryHidden
End If
Next Worksheet
On Error GoTo 0
'Application.ScreenUpdating = True
End Sub
Private Sub Unhide_Worksheets()
'Application.ScreenUpdating = False
On Error Resume Next
For Each Worksheet In ThisWorkbook.Worksheets
Worksheet.Visible = xlSheetVisible
Next Worksheet
On Error GoTo 0
If LastSheet <> vbNullString Then
ThisWorkbook.Worksheets(LastSheet).Activate
End If
ThisWorkbook.Worksheets("No Macros").Visible = xlSheetHidden
'Application.ScreenUpdating = True
End Sub
I have an excel workbook containing several worksheets.
What I want to do is have a mechanism like a user form or something where the user would authenticate to one of several possible users.
Based on the username supplied I want to display certain worksheets and hide other sheets, and block the user from accessing worksheets they should not be able to view.
Has anyone done something like this in Excel?
Any thoughts are appreciated
Sean
I actually enjoyed the task of typing this one up. Keep in mind, VBE is not protected in this code so you may want to add some protection, but this should do what you need.
You should also create a generic Login worksheet. This would be the only sheet open before a password is entered. This is essential as you are unable to hide every sheet without throwing an error. (You need to have 1 visible sheet).
WARNING: This code is mildly tested. You are responsible for any loss of data for using the below code, such as (but not limited to) forgetting a password. You have been warned!!!!
1. Open the Workbook, then make a Call to GetLogin
Option Explicit
Private Sub Workbook_Open()
GetLogin 1
End Sub
2. The Login Code
Private Sub GetLogin(ByVal AttemptNumber As Integer)
Dim Sheet As Worksheet
With ThisWorkbook.Worksheets("Login")
.Visible = xlSheetVisible
.Activate
End With
For Each Sheet In ThisWorkbook.Sheets
If Not Sheet.Name = "Login" Then
Sheet.Visible = xlSheetVeryHidden
End If
Next Sheet
Dim Password As String
Password = Application.InputBox("Please enter your password")
Select Case Password
Case "Ma$terPas$"
For Each Sheet In ThisWorkbook.Sheets
Sheet.Visible = xlSheetVisible
Next Sheet
ThisWorkbook.Worksheets(1).Activate 'For when you hide login sheet
Case "Oth3Rpa$$"
With ThisWorkbook
.Worksheets(1).Visible = xlSheetVisible
End With
ThisWorkbook.Worksheets(1).Activate 'For when you hide login sheet
Case Else
If AttemptNumber <= 3 Then
If MsgBox("You entered an incorrect password", vbRetryCancel, "Attempt # " & AttemptNumber) = vbRetry Then
AttemptNumber = AttemptNumber + 1
GetLogin AttemptNumber
Else
ThisWorkbook.Saved = True
ThisWorkbook.Close
End If
Else
ThisWorkbook.Saved = True
ThisWorkbook.Close
End If
End Select
ThisWorkbook.Worksheets("Login").Visible = xlSheetHidden
End Sub
3. Close the Workbook
Private Sub Workbook_BeforeClose(Cancel As Boolean)
If ThisWorkbook.Saved = False Then
If MsgBox("Would you like to save?", vbYesNo) = vbYes Then
ThisWorkbook.Save
End If
End If
Dim Sheet As Worksheet
With ThisWorkbook.Worksheets("Login")
.Visible = xlSheetVisible
.Activate
End With
For Each Sheet In ThisWorkbook.Sheets
If Not Sheet.Name = "Login" Then
Sheet.Visible = xlSheetVeryHidden
End If
Next Sheet
'Prevent from being asked to save the fact you just hid the sheets
ThisWorkbook.Saved = True
End Sub
Ensure that the Workbook_Open and Workbook_Close are in your Workbook's Module.
You could probably achieve this by using the Auto_Open event
Function Auto_Open()
Select Case True
Case InStr(Application.UserName, "Dan Smith") > 0
ActiveWorkbook.Sheets(1).Visible = xlSheetVeryHidden
Case InStr(Application.UserName, "Jon Doe") > 0
ActiveWorkbook.Sheets(1).Visible = True
End Select
End Function
Of course this would take a lot of work considering you'd have to find out everyone's usernames and then the sheets that you want to hide from them, but that's what I thought of
Trying to work out how only I can see the work book and everyone else can see the userform, based on network username.
Here's what I've got so far:
Private Sub Workbook_Open()
Application.Visible = False
UtilitiesReportingTool.Show
End Sub
You'll need a couple of things to stop your users looking at your worksheets - and these can easily be broken with a little knowledge.
Create a sheet with big text saying "Please enable macros"
Very hide all sheets except the macro enable sheet.
Create these two procedures in a normal module
Sub StartUp()
Dim wrkSht As Worksheet
If Environ("username") <> "CAES_MATT" Then
Application.Visible = False
UtitlitiesReportingTool.Show
Else
For Each wrkSht In ThisWorkbook.Worksheets
wrkSht.Visible = xlSheetVisible
Next wrkSht
End If
End Sub
Sub ShutDown()
Dim wrkSht As Worksheet
For Each wrkSht In ThisWorkbook.Worksheets
Select Case wrkSht.CodeName
Case "Sheet1" 'This should really be shtMacroEnable or something.
wrkSht.Visible = xlSheetVisible
Case Else
wrkSht.Visible = xlSheetVeryHidden
End Select
Next wrkSht
End Sub
In your Workbook_Open event add this code:
Private Sub Workbook_Open()
StartUp
End Sub
In your UserForm_Terminate event add this:
Private Sub UserForm_Terminate()
Application.Visible = True
ShutDown
End Sub
When you open the workbook only the 'Enable Macros' sheet will be visible if macros aren't enabled.
When macros are enabled the form is displayed, unless it's you in which case all the sheets are unhidden.
When the form is closed everything except the sheet with codename Sheet1 is hidden.
I may have missed something ... heading home.
I have an excel workbook with multiple sheets. Is there any way to password protect users from even opening a sheet within the workbook? The sheet has a large graph on it that I don't want everyone to be able to see, let alone edit.
Thanks in advance for your help
EDIT
I used the following code to allow users to click a formcontrol button to access the sheet in question.
Sub ShowHeatMap()
Dim S As String
S = InputBox("Enter Password")
If S = vbNullString Then
Exit Sub
ElseIf S <> "wiretransfer" Then
Exit Sub
Else
Worksheets("Training Heat Map").Visible = xlSheetVisible
End If
End Sub
This is associated with my button on a kind of "homepage" sheet that I added to the workbook.
But I can't get the sheet to remain hidden when you open the workbook again. I tried this code:
Private Sub Workbook_BeforeClose(Cancel As Boolean)
ThisWorkbook.Worksheets("Training Heat Map").Visible = xlSheetVeryHidden
End Sub
Any ideas? This code is inputted on the module for the sheet under general declarations
Via this answer, I think this might do the trick for you. Within VBA, put this within ThisWorkbook:
Private Sub Workbook_SheetActivate(ByVal Sh As Object)
Dim MySheets As String, Response As String
MySheet = "Sheet1"
If ActiveSheet.Name = MySheet Then
ActiveSheet.Visible = False
Response = InputBox("Enter password to view sheet")
If Response = "MyPass" Then
Sheets(MySheet).Visible = True
Application.EnableEvents = False
Sheets(MySheet).Select
Application.EnableEvents = True
End If
End If
Sheets(MySheet).Visible = True
End Sub
Obviously will require a bit of tailoring to your needs. Remember that you will also need to password protect your VBA code, otherwise anyone will be able to view it and find out the password.
How can the following conditions be met with VBA code?
A particular worksheet is always displayed on open, even if the worbook is opened without enabling macros.
A workbook user may save the workbook while working on any worksheet.
The save must not interfere with the user - no navigating away to a different sheet, no messageboxes, etc.
The regular save functions (Ctrl-S, clicking Save) must remain available and when used must obey the criteria above.
I'd like to avoid the attempted solutions I've listed at the bottom of this question.
Details:
The workbook is created using Office 2007 on a Windows 7 machine. It is an .xlsm workbook with 2 worksheets, "Scheduler" and "Info." Sheet tabs are not visible. Not all users will enabled macros when the workbook is opened.
Upon opening the workbook, a user will only be exposed to one sheet as follows:
"Info" shows up if macros are disabled, and basically tells anyone who opens the workbook that macros need to be enabled for full workbook functionality. If macros are enabled at this point, "Scheduler" is activated.
"Scheduler" is where data is stored and edited, and is automatically shown if macros are enabled. It is not presented to the user when the workbook is opened without macros enabled.
"Info" must show up first thing if the workbook is opened and macros are disabled.
Attempted Solutions (I'm looking for better solutions!):
Placing code in the Workbook.BeforeSave event. This saves with "Info" activated so it shows up when the workbook is opened. However, if the user is in "Scheduler" and not done, I cannot find a way in this event to re-activate "Scheduler" after the save.
Using Application.OnKey to remap the Ctrl-s and Ctrl-S keystrokes. Unfortunately this leaves out the user who saves using the mouse (clicking File...Save or Office Button...Save).
Checking during every action and if needed activating "Scheduler". In other words, inserting code in something like the Workbook.SheetActivate or .SheetChange events to put "Scheduler" back into focus after a save with "Info" activated. This runs VBA code constantly and strikes me as a good way to get the other code in the workbook into trouble.
Placing code in the Worksheet("Info").Activate event, to change focus back to "Scheduler". This leads to the result of "Scheduler", not "Info", showing when the workbook is opened, even with macros disabled.
Will this not work? Updated to handle Saving gracefully
Private Sub Workbook_Open()
ThisWorkbook.Worksheets("Scheduler").Activate
End Sub
Private Sub Workbook_BeforeClose(Cancel As Boolean)
ThisWorkbook.Worksheets("Info").Activate
If (ShouldSaveBeforeClose()) Then
Me.Save
Else
Me.Saved = True ' Prevents Excel Save prompt.
End If
End Sub
Private Function ShouldSaveBeforeClose() As Boolean
Dim workbookDirty As Boolean
workbookDirty = (Not Me.Saved)
If (Not workbookDirty) Then
ShouldSaveBeforeClose= False
Exit Function
End If
Dim response As Integer
response = MsgBox("Save changes to WorkBook?", vbYesNo, "Attention")
ShouldSaveBeforeClose= (response = VbMsgBoxResult.vbYes)
End Function
I don't have time to test this out, but you might be able to do this using Application.OnTime in your BeforeSave event handler. Something like:
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Dim objActiveSheet
Set objActiveSheet = Me.ActiveSheet
If objActiveSheet Is InfoSheet Then Exit Sub
If Module1.PreviousSheet Is Nothing Then
Set Module1.PreviousSheet = objActiveSheet
InfoSheet.Activate
Application.OnTime Now, "ActivatePreviousSheet"
End If
End Sub
Then in Module1:
Public PreviousSheet As Worksheet
Public Sub ActivatePreviousSheet()
If Not PreviousSheet Is Nothing Then
PreviousSheet.Activate
Set PreviousSheet = Nothing
End If
End Sub
Edit 2: Here is a re-write that does not utilize AfterSave. You may need to tweak the dialog created from GetSaveAsFilename according to your needs.
This relies on overriding default save behavior and handling the save yourself.
Private actSheet As Worksheet
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Cancel = True
PrepareForSave
manualSave SaveAsUI
AfterSave ThisWorkbook.Saved
End Sub
Private Sub PrepareForSave()
Set actSheet = ThisWorkbook.ActiveSheet
ThisWorkbook.Sheets("Info").Activate
hidesheets
End Sub
Private Sub manualSave(ByVal SaveAsUI As Boolean)
On Error GoTo SaveError 'To catch failed save as
Application.EnableEvents = False
If SaveAsUI Then
If Val(Application.Version) >= 12 Then
sPathname = Application.GetSaveAsFilename(FileFilter:="Excel Files (*.xlsm), *.xlsm")
If sPathname = False Then 'User hit Cancel
GoTo CleanUp
End If
ThisWorkbook.SaveAs Filename:=sPathname, FileFormat:=52
Else
sPathname = Application.GetSaveAsFilename(FileFilter:="Excel Files (*.xls), *.xls")
If sPathname = False Then
GoTo CleanUp
End If
ThisWorkbook.SaveAs Filename:=sPathname, FileFormat:=xlNormal
End If
Else
ThisWorkbook.Save
End If
SaveError:
If Err.Number = 1004 Then
'Cannot access save location
'User clicked no to overwrite
'Or hit cancel
End If
CleanUp:
Application.EnableEvents = True
End Sub
Private Sub AfterSave(ByVal bSaved As Boolean)
showsheets
If actSheet Is Nothing Then
ThisWorkbook.Sheets("Scheduler").Activate
Else
actSheet.Activate
Set actSheet = Nothing
End If
If bSaved Then
ThisWorkbook.Saved = True
End If
End Sub
Private Sub hidesheets()
For Each ws In ThisWorkbook.Worksheets
If ws.Name <> "Info" Then
ws.Visible = xlVeryHidden
End If
Next
End Sub
Private Sub showsheets()
For Each ws In ThisWorkbook.Worksheets
ws.Visible = True
Next
End Sub
Private Sub Workbook_Open()
AfterSave True
End Sub
The only way to make Info display first without macros enabled is if that is how the workbook was saved. This is most reasonably handled when saving.
Unless I misunderstood your issue, not using BeforeSave seems misguided. Just make sure to use AfterSave as well. Here's an example:
Private actSheet As Worksheet
Private Sub Workbook_AfterSave(ByVal Success As Boolean)
showsheets
actSheet.Activate
Set actSheet = Nothing
Thisworkbook.Saved = true 'To prevent save prompt from appearing
End Sub
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Set actSheet = ThisWorkbook.activeSheet
ThisWorkbook.Sheets("Info").Activate
hidesheets
End Sub
Private Sub Workbook_Open()
showsheets
ThisWorkbook.Sheets("Scheduler").Activate
End Sub
Private Sub hidesheets()
For Each ws In ThisWorkbook.Worksheets
If ws.Name <> "Info" Then
ws.Visible = xlVeryHidden
End If
Next
End Sub
Private Sub showsheets()
For Each ws In ThisWorkbook.Worksheets
ws.Visible = True
Next
End Sub
The use of the private object actSheet allows the "ActiveSheet" to be reselected after save.
Edit: I noticed you had more requirements in the comments. The code has been updated so that now upon saving, only the Info sheet will be visible, but when opened or after saving, every sheet will reappear.
This makes it so that any user opening the file without macros will not be able to save with a different sheet activated, or even view the other sheets. That would certainly help motivate them to enable macros!
This problem has been flogged to death in the past, its just hard to find a solution that actually works. Take a look at this code which should do what you need. Basically it shows a splash screen, with all other sheets hidden if the user does not enable macros. It will still save normally if the user clicks save and wont interfere with their work. If they save with there worksheet open it will still show only the splash screen when next opened. Download the sample file below and you can test for yourself, make sure you download the file posted by Reafidy it has over 400 views. If you need it modified further let me know.
Private Sub Workbook_BeforeClose(Cancel As Boolean)
bIsClosing = True
End Sub
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Dim wsArray() As Variant
Dim iCnt As Integer
Application.ScreenUpdating = 0
Splash.Visible = True
For Each wsSht In ThisWorkbook.Worksheets
If Not wsSht.CodeName = "Splash" Then
If wsSht.Visible = True Then
iCnt = iCnt + 1: Redim Preserve wsArray(1 To iCnt)
wsArray(iCnt) = wsSht.Name
End If
wsSht.Visible = xlSheetVeryHidden
End If
Next
Application.EnableEvents = 0
ThisWorkbook.Save
Application.EnableEvents = 1
If Not bIsClosing Then
For iCnt = 1 To UBound(wsArray)
Worksheets(wsArray(iCnt)).Visible = True
Next iCnt
Splash.Visible = False
Cancel = True
End If
Application.ScreenUpdating = 1
End Sub
Private Sub Workbook_Open()
Dim wsSht As Worksheet
For Each wsSht In ThisWorkbook.Worksheets
wsSht.Visible = xlSheetVisible
Next wsSht
Splash.Visible = xlSheetVeryHidden
bIsClosing = False
End Sub
A sample file can be found here.
How about using a 'proxy workbook'.
The 'proxy workbook'
is the only workbook which is directly opened by the users
contains the info sheet
contains VBA to open your 'real workbook' using Workbooks.Open (As I've checked with Workbooks.Open documentation by default it will not add the file name to your recent files history unless you set the AddToMru argument to true)
if required the VBA code could even make sure that your 'target workbook' is trusted (I found some sample code here)
The 'target workbook'
contains your Schedule and any other sheets
is only opened if the VBA code in 'proxy workbook' was executed
can be saved by the user at any time as usual
I've got no Office 2007 at hand to test this but think it should do.