Excel VBA - Can't unhide worksheets - excel

I have a log of incoming / outgoing test samples which I've added code to kick users out if no worksheet change is detected for more than 5 minutes (https://excelribbon.tips.net/T008192_Forcing_a_Workbook_to_Close_after_Inactivity.html). In order to make sure users have macros enabled, I have a worksheet called "Splash Screen" which is the only worksheet visible when the workbook is first opened (all other worksheets are set to xlVeryHidden).
The code I have to hide/unhide worksheets looks simple and works perfectly if the workbook is closed manually, but not if forced to close via the timeout. This is called near the end of the Workbook_BeforeClose procedure:
Dim ws As Worksheet
Application.ScreenUpdating = False
For Each ws In ThisWorkbook.Worksheets
Select Case ws.Name
Case Is = "Splash Screen"
ws.Visible = xlSheetVisible
Case Else
ws.Visible = xlSheetVeryHidden
End Select
Next
Application.ScreenUpdating = True
After this code block has run, there is no change to the visibility of the worksheets. Everything which was hidden is still hidden, everything that was visible is still visible, everything that was veryhidden is still veryhidden.
The worksheets are locked, but I've tried unlocking them before hiding them and that doesn't help. I've ensured events are enabled, screenupdating is true, errors are not set to "Resume Next", but none of it seems to help. Any suggestions?
Edited to add more code:
Private Sub Workbook_BeforeClose(Cancel As Boolean)
'Checks for missing data in rows to be locked - if missing, user is prompted to enter
'User can optionally cancel closing the document to enter missing data
Call DataMissing(Cancel) 'If data missing and user wishes to enter, Cancel = True
If Cancel Then Exit Sub 'If Cancel = True, exit without further action
'Locks rows which were changed and Logs changes (if any were made)
Call LockRows
Call EmailPM("Delivered")
Call Internal_LockRows
If Not Not LoggedRows Then
Call LogChanges
Call EmailPM("Edited")
End If
If Not Not Internal_LoggedRows Then
Call Internal_LogChanges
End If
Call EmailPM("Internal")
'If changes have been made to live samples, updates lab manager
If Not Not LiveRows Then Call EmailPM("Live")
If Not Not Internal_LiveRows Then Call EmailPM("Internal_Live")
'Clears all filters on all sheets
Dim ws As Worksheet
On Error Resume Next
For Each ws In ThisWorkbook.Worksheets
ws.AutoFilter.ShowAllData
Next ws
On Error GoTo 0
'Selects MainLab sheet before closing
MainLab.Select
'Ensures TimeStop and RowID will fire on worksheet change
Application.EnableEvents = True
Call TimeStop
'Hides sheets (only unhides if macros are enabled)
Call HideSheets
'Stores who closed the file to log
LogToFile (ThisWorkbook.Name & "; " & OpenState & "; closed by; " & Environ("Username") & "; " & Format(Now, "yyyy-mm-dd hh:mm:ss"))
End Sub
Sub TimeSetting()
'Sets CloseTime to a set time in the future, then runs SavedAndClose
CloseTime = Now + TimeValue("00:00:30") 'Timeout after 5 mins of inactivity
On Error Resume Next
Application.OnTime earliesttime:=CloseTime, procedure:="SavedAndClose", Schedule:=True
On Error GoTo 0
End Sub
Sub TimeStop()
'A sub to stop the timer ticking down
On Error Resume Next
Application.OnTime earliesttime:=CloseTime, procedure:="SavedAndClose", Schedule:=False
On Error GoTo 0
End Sub
Sub SavedAndClose()
'Closes the workbook and saves when called
Application.CutCopyMode = False 'Empties the clipboard to avoid the potential "keep the clipboard" alert
LogToFile (ThisWorkbook.Name & "; " & OpenState & "; auto-closed; " & Environ("Username") & "; " & Format(Now, "yyyy-mm-dd hh:mm:ss"))
ThisWorkbook.Close savechanges:=True
End Sub

The main reason this does not work is ThisWorkbook.saved = True. Essentially this is saying I've already saved so don't bother prompting me to save when I close. Problem is you haven't saved at the time you are calling close.
Here is a basic example of the setup. You want to: 1. Hide the sheets, 2. Save the document, 3. Close.
Sub HideSheets()
' Insert your hide sheet code here
Sheet2.Visible = xlSheetHidden ' Test line to hide one sheet
ThisWorkbook.Save
End Sub
Sub ShutDown()
Call HideSheets
ThisWorkbook.Close
End Sub
Private Sub Workbook_BeforeClose(Cancel As Boolean)
'This doesn't do much on the automated close, because you've saved already.
Call HideSheets
End Sub

Related

Why does my sub not work when it runs fine in immediate window excel vba

I've been trying to get the typical hide sheets/unhide sheets code to work for encouraging Macro enabling. Since I lock down saving, I needed to do it slightly differently than putting it in the Workbook_BeforeClose Sub as usually is done.
But...my hide sub
Sub HideSheets()
'Error Handling when workbook is unprotected.
On Error GoTo EH
'Unprotect the workbook to allow conditional formatting changes.
ThisWorkbook.Sheets("Field Service Report").Unprotect Password:="x"
ThisWorkbook.Sheets("Prompt").Unprotect Password:="x"
'Main Sub Code
Application.EnableCancelKey = xlDisabled
Sheets("Prompt").Visible = xlSheetVisible
Sheets("Field Service Report").Visible = xlSheetVeryHidden
Application.EnableCancelKey = xlInterrupt
'Reprotect worksheet before ending sub.
ThisWorkbook.Sheets("Field Service Report").Protect Password:="x", UserInterfaceOnly:=True
ThisWorkbook.Sheets("Prompt").Protect Password:="x"
Exit Sub
EH:
Call EH
Resume Next
End Sub
and my unhide sub
Sub UnhideSheets()
'Error Handling
On Error GoTo EH
'Unprotect the workbook to allow conditional formatting changes.
ThisWorkbook.Sheets("Field Service Report").Unprotect Password:="x"
ThisWorkbook.Sheets("Prompt").Unprotect Password:="x"
'Main Sub Code
Application.EnableCancelKey = xlDisabled
Sheets("Field Service Report").Visible = xlSheetVisible
Sheets("Prompt").Visible = xlSheetVeryHidden
Application.EnableCancelKey = xlInterrupt
'Reprotect worksheet before ending sub.
ThisWorkbook.Sheets("Field Service Report").Protect Password:="x", UserInterfaceOnly:=True
ThisWorkbook.Sheets("Prompt").Protect Password:="x"
Exit Sub
EH:
Call EH
Resume Next
End Sub
....works fine when called form the immediate window. Sheets hide and unhide appropriately.
But, when I step through the sub it doesn't actually do anything. The idea is to set the sheets to the "prompt" sheet before saving, save, then revert to usable after saving. But I can't even see if that code is working correctly (it appears to) because stepping through the actual hide/unhide subs doesn't do anything.
Edit: No errors, just doesn't change any settings to hide or unhide sheets.
Thoughts?
Edit: So given the comments below, my subs work when run from the immediate window and when stepped through via debugger. They hide and unhide the worksheets appropriately. So, the only thing that can be wrong is the code that calls these subs. So, here are two more subs. One is the button code for a save button, and the other is the Workbook_BeforeSave Sub.
Sub Save_Form()
'Error Handling ...
On Error GoTo EH
'Unprotect the workbook ...
ThisWorkbook.Sheets("Field Service Report").Unprotect Password:="x"
'Variable to disable any other save but this button.
Module1.SaveChk = 1
'Code to automatically save a copy ...
Module1.UserPath = Environ("USERPROFILE")
Module1.Path = UserPath & "\Desktop\"
If Module1.EditChk = "Y" Then
Module1.SaveName = "FSR Master"
Else
Module1.SaveName = Range("AF6").Value
End If
ThisWorkbook.SaveAs _
Filename:=Path & SaveName & ".xlsm", _
FileFormat:=52
If Module1.SaveError <> 1 Then
'User Display of Save Success
MsgBox "Filename = " & SaveName & vbNewLine _
& "File is saved to your desktop."
Else
Module1.SaveError = 0
End If
'Reset SaveChk variable
Module1.SaveChk = 0
'Reprotect Worksheet
ThisWorkbook.Sheets("Field Service Report").Protect Password:="x", UserInterfaceOnly:=True
Exit Sub
EH:
Call ErHa
Resume Next
End Sub
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
'Error Handling ...
On Error GoTo EH
'Save Initiation Check
If Module1.SaveChk <> 1 Then
Cancel = True
MsgBox "Please Use Form Save Button", vbOKCancel + vbExclamation, "SAVE CANCELLED"
Exit Sub
End If
If Module1.EditChk <> "Y" Then 'Skips the whole block if EditChk = Y
'Create the final range of cells for checking
Set Module1.Required = Application.Union(Module1.Fixed, Module1.Drive, Module1.Stage)
'Check if all required cells are filled in
If WorksheetFunction.CountA(Module1.Required) < Module1.Required.Count Then
Cancel = True
MsgBox "Please Completed Shaded Cells!", vbOK + vbExclamation, "SAVE CANCELLED"
Module1.SaveError = 1
Else
'Set the report date before saving
Application.EnableEvents = False
Range("AE59") = Format(Now(), "mm-dd-yyyy hh:mm:ss AM/PM")
Application.EnableEvents = True
End If
End If
'Renable Macro Splash Screen Before Save
Call HideSheets
Exit Sub
EH:
Call ErHa
Resume Next
End Sub

Auto save and close workbook (in a share) if Screen/Workstation is Locked

Something which we encounter on a daily basis at work is when a member of the team opens Excel Workbook from a network share to update the workbook and forget to save and close the file after he is finished.
The issue arise when the user locks his workstation and walks away from his desk leaving his co-workers unable to modify the shared excel workbook (read only).
P.S Locking your workstation before each time you leave your desk is something crucial for security reasons and I encourage the reader to adopt this good cyber hygiene habit.
How can I solve this issue once and for all?
One might argue that opening such documents in the cloud might solve the problem but this depends on the nature of the contents being stored in the document.
I had some initial parameters defined wrong and it's always better to do stuff like this at the Modules level.
For your ThisWorkbook section, only have this code:
Private Sub Workbook_Open()
Call TheTimerMac
End Sub
Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
Call RestApplicationTimer
End Sub
Then in a standard Module insert the below code. The settings can be adjusted with the constants, which it looks like you understand (btw thanks for CDATE function -- shorter than TimeValeu)
I also inserted a couple audio warnings, partially just for my own entertainment. You look sharp enough that you can just nuke them if you don't like them.
'STANDARD MODULE CODE
'Constants
'Time settings
Const idleTimeLIMIT As String = "00:35:00" '<---- Edit this to whatever timer you want (hour:min:sec)
Const checkIntervalTime As String = "00:01:00" '<---- this can be executed frequently as it has low overhead
'Set this variable TRUE to confirm the macro is working with popup messages
Const conFirmRunning As Boolean = False
Dim LastCalculate As Date 'Make sure this is outside and above the other macros
Option Private Module
Public Sub TheTimerMac()
'message you can have displayed to make sure it's running
If conFirmRunning Then MsgBox "TheTimerMac is running."
'Schedules application to execute below macro at set time.
Application.OnTime Now + CDate(checkIntervalTime), "AnyBodyWorking"
End Sub
Private Sub AnyBodyWorking()
'OPTIONAL Warning messages to be spoken
Const TenMinuteWarning As String = "Your file will save and close in approximately 10 minutes"
Const FiveMinuteWarning As String = "Your file will save and close in approximately 5 minutes"
Const OneMinuteWarning As String = "This is the last warning. Your file will save and close in a little over a minute."
'message you can have displayed to make sure it's running
If conFirmRunning Then MsgBox "AnyBodyWorking Macro is running."
If LastCalculate = 0 Then
'Won't close application if lastCalc hasn't been set
Call RestApplicationTimer
ElseIf Now > LastCalculate Then
'if nothing has happened in the last idleTime interval... then it closes.
'close and lock it up!!
ThisWorkbook.Save
ThisWorkbook.Close
Exit Sub 'not even sure if this is needed, but probably good to be sure
''Optional spoken warnings
ElseIf DateDiff("S", Now, LastCalculate) < 60 Then
Application.Speech.Speak OneMinuteWarning
ElseIf DateDiff("S", Now, LastCalculate) < 300 Then
Application.Speech.Speak FiveMinuteWarning
ElseIf DateDiff("S", Now, LastCalculate) < 600 Then
Application.Speech.Speak TenMinuteWarnin
End If
Call TheTimerMac
End Sub
Sub RestApplicationTimer()
LastCalculate = Now + CDate(idleTimeLIMIT)
End Sub
Lastly, I think you could slightly improve the the locked function to be as follows and you could inculde it in your if statements.
Function IsLocked() As Boolean
IsLocked = _
GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & _
Environ$("computername") & "\root\cimv2"). _
ExecQuery("select * from Win32_Process where Name='logonui.exe'").Count > 0
End Function
Save the excel file as .xlsm to enable the storing of macros in the workbook itself.
Go to: Developer Tab -> Visual Basic
Double click: 'This Workbook', on the left hand pane
Paste the following VBA code:
Private Sub Workbook_Open()
Application.OnTime Now + TimeValue("00:01:00"), "Save1"
End Sub
Right Click VBAProject -> Insert -> Module
Paste the following VBA Code:
Sub Save1()
Application.DisplayAlerts = False
ThisWorkbook.Save
Application.DisplayAlerts = True
If IsLocked(Environ$("computername")) > 0 Then
Workbooks("book1test.xlsm").Close SaveChanges:=True
End If
Application.OnTime Now + TimeValue("00:01:00"), "Save1"
End Sub
Function IsLocked(strComputer)
With GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
IsLocked = .ExecQuery("select * from Win32_Process where Name='logonui.exe'").Count '
End With
End Function
Save the Macro: Ctrl+s
This macro will be triggered every time you open the workbook, save your work every minute and only close the workbook if your screen/workstation is logged. You can remove the auto-save feature if you want.
Credits:
Check if computer is locked using VBscript
How to save Excel file every say minute?
#PGSystemTester this was the only way I could get it to work:
In ThisWorkbook:
Public idleTIME As Date '<---- Edit this to whatever timer you want (hour:min:sec)
Private Sub Workbook_Open()
idleTIME = CDate("00:10:00")
LastCalculate = Now + idleTIME
Check
End Sub
Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
LastCalculate = Now + idleTIME
End Sub
In module Option 1:
Public LastCalculate As Date
Const checkIntervalTime As String = "00:01:00"
Sub Check()
Call TheTimerMac
End Sub
Private Sub TheTimerMac()
Dim nextRunTime As Date
nextRunTime = Now + CDate(checkIntervalTime)
'Schedules application to execute below macro at set time.
Application.OnTime nextRunTime, "AnyBodyWorking"
End Sub
Private Sub AnyBodyWorking()
If Now > LastCalculate Then
'if nothing has happened in the last idleTime interval... then it closes.
'close and lock it up!!
ThisWorkbook.Save
ThisWorkbook.Close
Else
'executes the timerMacagain
Call TheTimerMac
End If
End Sub
module Option 2 (for locked screen):
Public LastCalculate As Date 'Make sure this is outside and above the other macros
Const checkIntervalTime As String = "00:00:30" '<---- this can be frequent as it has low overhead
Sub Check()
Call TheTimerMac
End Sub
Private Sub TheTimerMac()
Dim nextRunTime As Date
nextRunTime = Now + CDate(checkIntervalTime)
'Schedules application to execute below macro at set time.
Application.OnTime nextRunTime, "AnyBodyWorking"
End Sub
Private Sub AnyBodyWorking()
If Now > LastCalculate Or (IsLocked("FIBRE-X") > 0) Then
'if nothing has happened in the last interval idleTime OR Screen is Locked... then it closes.
'close and lock it up!!
ThisWorkbook.Save
ThisWorkbook.Close
Else
'executes the timerMacagain
Call TheTimerMac
End If
End Sub
Function IsLocked(strComputer)
With GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
IsLocked = .ExecQuery("select * from Win32_Process where Name='logonui.exe'").Count '
End With
End Function
Anything I can improve on this please?

Restrict viewing access to an Excel worksheet

I thought this would be a readily used function in Excel but it's surprisingly difficult to implement a simple process of restricting access to specific worksheets within a larger workbook.
There's a few methods that prompt an initial password to open various versions of the same workbook. But I want to keep the workbook identical for all users but restrict access to certain sheets. Surely there's a password protect function that requires the user to enter a password to view a sheet. Rather than create multiple versions of the same workbook based on different users.
I have tried the following but it doesnt prompt a password to access the sheet
Private Sub Workbook_SheetActivate(ByVal Sh As Object)
Dim MySheets As String, Response As String
Dim MySheet As Worksheet
MySheet = "COMMUNICATION"
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
Am I doing this right?
It sounds like according to the comments that this isn't as much as a security issue as it is a convenience issue. So please bear in mind when considering implementing this into your project that this is easily breakable if there is any malicious intent to gain unauthorized access.
First, I would recommend a common landing zone. A main worksheet that is displayed immediately after opening a workbook. To do this, we would use the Workbook_Open() event and activate a sheet from there.
This can be a hidden sheet if desired, that will be up to you.
Option Explicit
Private lastUsedSheet As Worksheet
Private Sub Workbook_Open()
Set lastUsedSheet = Me.Worksheets("MainSheet")
Application.EnableEvents = False
lastUsedSheet.Activate
Application.EnableEvents = True
End Sub
Next, we should decide on what should occur when there's an attempt to access a new sheet. In the below method, once a sheet is activated it will automatically redirect the user back to the last used sheet until a successful password attempt has been made.
We can track the last used sheet in a module-scoped variable, which in this example will be named lastUsedSheet. Any time a worksheet is successfully changed, this variable will be set to that worksheet automatically - this way when when someone attempts to access another sheet, it will redirect them back to the prior sheet until the password is successfully entered.
Private Sub Workbook_SheetActivate(ByVal Sh As Object)
On Error GoTo SafeExit
Application.EnableEvents = False
' Error protection in case lastUsedSheet is nothing
If lastUsedSheet Is Nothing Then
Set lastUsedSheet = Me.Worksheets("MainSheet")
End If
' Allow common sheets to be activated without PW
If Sh.Name = "MainSheet" Then
Set lastUsedSheet = Sh
Sh.Activate
GoTo SafeExit
Else
' Temporarily send the user back to last sheet until
' Password has been successfully entered
lastUsedSheet.Activate
End If
' Set each sheet's password
Dim sInputPW As String, sSheetPW As String
Select Case Sh.Name
Case "Sheet1"
sSheetPW = "123456"
Case "Sheet2"
sSheetPW = "987654"
End Select
' Create a loop that will keep prompting password
' until successful pw or empty string entered
Do
sInputPW = InputBox("Please enter password for the " & _
"worksheet: " & Sh.Name & ".")
If sInputPW = "" Then GoTo SafeExit
Loop While sInputPW <> sSheetPW
Set lastUsedSheet = Sh
Sh.Activate
SafeExit:
Application.EnableEvents = True
If Err.Number <> 0 Then
Debug.Print Time; Err.Description
MsgBox Err.Description, Title:="Error # " & Err.Number
End If
End Sub
Side note, disabling events is necessary due to the fact that your Workbook_SheetActivate event will continue to fire after a successful sheet change.
Preventing file type changes during SaveAs1
You can further protect the accidental removal of VBA code by restricting the file save type. This can be accomplished using the Workbook_BeforeSave() event. The reason this is a potential problem is that saving as a non-macro enabled workbook will erase the code, which will prevent the password protection features you just implemented above.
First, we need to check if this is a Save or SaveAs. You can accomplish this using the Boolean property SaveAsUI that is included with the event itself. If this value is True, then it's a SaveAs event - which means we need to perform additional checks to ensure that the file type isn't accidentally changed from the save dialog box. If the value is False, then this is a normal save, and we can bypass these checks because we know the workbook will be saved as type .xlsm.
After this initial check, we will display the dialog box using Application.FileDialog().Show.
Afterwards, we will check if the user canceled the operation .SelectedItems.Count = 0 or clicked Save. IF user clicked cancel, then we simply set Cancel = True and the workbook will not save.
We proceed to check the type of extension selected by the user using this line:
If Split(fileName, ".")(UBound(Split(fileName, "."))) <> "xlsm" Then
This will split the file path by a period ., and will grab the last instance of the period (UBound(Split(fileName, "."))) in the event a file name may contain additional periods. If the extension does not match xlsm, then we abort the save operation.
Finally, after all checks passed, you can save the document:
Me.SaveAs .SelectedItems(1), 52
Since we already saved it with the above line, we can go ahead and set Cancel = True and exit the routine.
The full code (to be placed in the Worksheet obj module):
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
On Error GoTo SafeExit
If SaveAsUI Then
With Application.FileDialog(msoFileDialogSaveAs)
.Show
If .SelectedItems.Count = 0 Then
Cancel = True
Else
Dim fileName$
fileName = .SelectedItems(1)
If Split(fileName, ".")(UBound(Split(fileName, "."))) <> "xlsm" Then
MsgBox "You must save this as an .xlsm document. Document has " & _
"NOT been saved", vbCritical
Cancel = True
Else
Application.EnableEvents = False
Application.DisplayAlerts = False
Me.SaveAs .SelectedItems(1), 52
Cancel = True
End If
End If
End With
Else
Exit Sub
End If
SafeExit:
Application.EnableEvents = True
Application.DisplayAlerts = True
If Err.Number <> 0 Then
Debug.Print Time; Err.Description
MsgBox Err.Description, Title:="Error # " & Err.Number
End If
End Sub
1 Shoutout to PatricK for the suggestion
If you want to restrict access to a worksheet, you can just hide it:
ActiveWorkbook.Sheets("YourWorkSheet").Visible = xlSheetVeryHidden
I concur with Mathieu Guindon that any VBA attempt to "Restrict viewing access to an Excel worksheet" will be flimsy as explained by Mathieu Guindon. Moreover, If the file is opened with Excel option Macro security level other than the lowest, any VBA code including this is bound to fail.
However just for shake of simplicity I prefer to use workbook open event and Sheet Activate of the restricted sheet. Using Workbook Sheet Activate event will trigger password prompt even during switching between sheets by user with viewing access.
Private Sub Workbook_Open()
Sheets("COMMUNICATION").Visible = xlSheetHidden
End Sub
Public ViewAccess As Boolean 'In restricted sheet's activate event
Private Sub Worksheet_Activate()
If ViewAccess = False Then
Me.Visible = xlSheetHidden
response = Application.InputBox("Password", xTitleId, "", Type:=2)
If response = "123" Then
Me.Visible = xlSheetVisible
ViewAccess = True
End If
End If
End Sub

Excel - Limit view of worksheets to certian users

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

How to Freeze sheets in Excel

I am facing a problem in my excel workbook. I have 25+ sheets in my workbook
and I want to look to sheet1 time to time. Is their any way that I can freeze first
two sheets of my workbook?
Currently I am navigating through sheets by pressing ctrl+page up button.
FYI I am Using MS-Office 2007
If I have understood well: you want the users stay only on Sheet1 & 2:
In the Main event:
Private Sub Workbook_Open()
ActiveWindow.DisplayWorkbookTabs = False
End Sub
and in the Event:
Private Sub Workbook_SheetActivate(ByVal Sh As Object)
If ActiveWindow.DisplayWorkbookTabs Then ActiveWindow.DisplayWorkbookTabs = False
If ((Sh.Name) <> "Sheet1") And ((Sh.Name) <> "Sheet2") Then Sheets("Sheet1").Select
End Sub
When open disable Tabs. If people show if you try to change the code return to Sheet1.
Ad Password to VBA macro ...If is only for quick change remove the code of Tabs...
This code (in the ThisWorkbook module) will keep Sheet1 just to the left of whatever sheet you're on.
Private Sub Workbook_SheetActivate(ByVal Sh As Object)
Application.EnableEvents = False
If Sh.Name <> Sheet1.Name Then
Sheet1.Move Sh
Sh.Activate
End If
Application.EnableEvents = True
End Sub
It's a little weird pressing Ctrl+PgUp to navigate a bunch of sheets because it now takes two Ctrl+PgUps to move one sheet - one moves you onto Sheet1 (because it's always to the left) and the second moves you to the next sheet (which then moves Sheet1 to the left of it).
Maybe you could build in a timer so it only moves sheet1 if you've been on a sheet for a couple of seconds.
Update Using a timer
In a standard module:
Public gshToMove As Object
Public gdtTimeToMove As Date
Sub MoveSheet()
Application.EnableEvents = False
Sheet1.Move gshToMove
gshToMove.Activate
Set gshToMove = Nothing
gdtTimeToMove = 0
Application.EnableEvents = True
End Sub
In the ThisWorkbook module
Private Sub Workbook_SheetActivate(ByVal Sh As Object)
If Sh.Name <> Sheet1.Name Then
'if something's schedule, unschedule it
If gdtTimeToMove <> 0 Then
Application.OnTime gdtTimeToMove, "MoveSheet", , False
End If
'schedule the sheet move for three seconds from now
gdtTimeToMove = Now + TimeSerial(0, 0, 3)
Set gshToMove = Sh
Application.OnTime gdtTimeToMove, "MoveSheet", , True
End If
Application.EnableEvents = True
End Sub
You still get a little flash when the code actually runs.
In each sheet
Private Sub Worksheet_Activate ( )
Call Funciona
End Sub
In Module
Sub Funciona()
With ActiveSheet
If .Index > 1 Then
If .Previous.Name <> "Principal" Then
Sheets("Principal").Move Before:=ActiveSheet
End If
End If
End With
End Sub

Resources