Macro to unhide sheets when macros has been enabled.

CV899000

Board Regular
Joined
Feb 11, 2016
Messages
98
Hi,

I have some problems with my workbook.

I have a workbook that I am going to send to employees and it contains macros.
Now, if those employees does not know excel, they might disable macros since it states that it is a security threat. However, then all my work with the workbook is wasted because they cannot use it.

I have therefore created a sheet called "macro disabled" that is showing when they open excel. If they enable macros, I have made a vba code that hides the "macro disabled" sheet and shows three other sheets.

When I close the workbook, I again have a macro that hides the three sheets and unhides the "macro disabled" sheet so that it again is ready if somebody doesn't enable macros.

I then wanted excel to stop asking if the users wanted to save everytime they closed the workbook, and I can do that also, but when I do that, then it doesn't hide the three sheets and shows the "macro disabled" sheet... Please help and see my code beneath.

Private Sub Workbook_BeforeClose(Cancel As Boolean)
Sheets("Macros disabled").Visible = True
Sheets("Information").Visible = xlVeryHidden
Sheets("Prices").Visible = xlVeryHidden
Sheets("Copied Prices").Visible = xlVeryHidden
For Each Worksheet In Worksheets
If Worksheet.Name <> "Macros disabled" Then Worksheet.Visible = xlSheetVeryHidden
Next
Me.Saved = True
End Sub
 

Excel Facts

Waterfall charts in Excel?
Office 365 customers have access to Waterfall charts since late 2016. They were added to Excel 2019.
I would recommend against using BeforeClose to re-hide stuff. Simply put, in every example I have ever read, this methodology comes in two flavors:

  1. Beatable.
  2. Forces a save no matter what (which includes when the user has done some terrible thing and only wants to bail without saving).

I would look for examples using BeforeSave as a pseudo after-save, or maybe AfterSave.

If you don't find a good example, please write back and I'll look thru some old code.

Mark
 
Upvote 0
Okay, if it can be improved I would be happy to.

I do not know what you mean by using BeForeSave as a pseudo after-save, sorry but I am still learning this thing. :D
 
Upvote 0
Okay, no guarantees on this, but here is some old code that appears to be okay. You will no doubt need to customize to suit, by example, the filefilter argument, as I was evidently still using only .xls format. So... for the moment, place in a JUNK COPY of your workbook in .xls format. If it seems to accomplish what you want, we can worry about the different file formats (presumably, .xls and .xlsm) after that.

In ThisWorkbook Module:

Rich (BB code):
Option Explicit
  
Private bolClosing As Boolean
Private bolInProcess As Boolean
  
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Dim lResponse As Long
     
  Application.DisplayAlerts = False
  
  '// bolClosing will be false by default, so we will initially pass this test.       //
  If Not bolClosing Then
    
    '// IF the workbook is saved, it will close without further ado.  ELSE, we will //
    '// see what the user wants to do and control the results.                      //
    If Not ThisWorkbook.Saved Then
      
      lResponse = MsgBox("Do you want to save the changes you made to '" & _
                         Left(ThisWorkbook.Name, InStrRev(ThisWorkbook.Name, ".") - 1) & "'?", _
                         vbExclamation Or vbYesNoCancel Or vbDefaultButton1, _
                         "My Custom Project")
      
      Select Case lResponse
      Case vbYes
        '// bolClosing is used in BeforeSave                                //
        bolClosing = True
        '// See function.  We don't need to execute the save here, and in   //
        '// fact, due to a weird glitch in Excel (least 2000), this is      //
        '// better.                                                         //
        Call Workbook_BeforeSave(False, False)
        
        '//This is required, as even though the file saved while in         //
        '// BeforeSave, changes occurred post save.                         //
        ThisWorkbook.Saved = True
      Case vbNo
        bolClosing = True
        
        '// User doesn't want to save changes, so just mark file saved.     //
        ThisWorkbook.Saved = True
      Case vbCancel
        '// User cancelled closing, and least in Excel 2000, I found it     //
        '// necessary to reactivate stuff if I wanted the focus returned.   //
        ThisWorkbook.Activate
        bolClosing = False
        Cancel = True
        Application.DisplayAlerts = True
        ActiveCell.Activate
        Exit Sub
      End Select
    
    End If
  End If
  
  Application.DisplayAlerts = True
End Sub
  
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Dim lCalculationSetting As Long
Dim wksWorksheet        As Worksheet
Dim wksLastActive       As Worksheet
Dim strSaveAs_Filename  As String
     
  If Not (bolInProcess And Not Cancel) Then
    
    '// Set bolProcess to True, which will later prevent a recurse to this IF.      //
    bolInProcess = True
    
    '// Let's see what the user's choices were, as to a few settings that we wish   //
    '// to temporarily control.                                                     //
    lCalculationSetting = Application.Calculation
    
    '// We'll stop screen updates and uneccessary calculations, which will give a   //
    '// better appearance and increase run speed.                                   //
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual
    DoEvents
    
    '// Find the ActiveSheet, so we can redisplay it later.                         //
    Set wksLastActive = ThisWorkbook.ActiveSheet
    
    '// Display the prompt (the warning) sheet BEFORE hidng remaining sheets.       //
    shtForceEnable.Visible = xlSheetVisible
    
    For Each wksWorksheet In ThisWorkbook.Worksheets
      If Not wksWorksheet.CodeName = "shtForceEnable" Then
        wksWorksheet.Visible = xlSheetVeryHidden
      End If
    Next
    
    '// Set Cancel to True!  If the user executed a "normal" save (clicking Save    //
    '// button or Ctrl+s...), then only the user's called Save is cancelled.  A     //
    '// couple of lines down, we'll execute a Save that will not be cancelled.      //
    '//                                                                             //
    '// If on the other hand, BeforeSave is called programatically, the Cancel does //
    '// nothing, and the .Save (or SaveAs) executes under our control.              //
    '// I would also note that excluding the Cancel results in Saving the file      //
    '// twice.                                                                      //
    Cancel = True
    DoEvents
    
    '// Now, Save workbook.  If you step-thru this, you'll see that it immedietely  //
    '// recurses to Workbook_BeforeSave, but as bolInProcess is currently True,     //
    '// there is no true recurse.  Thus - the statements below the .Save execute,   //
    '// and the user sheets are redisplayed.                                        //
    If SaveAsUI Then
      ChDir ThisWorkbook.Path
      strSaveAs_Filename = Application.GetSaveAsFilename(InitialFileName:=ThisWorkbook.FullName, _
                                                         FileFilter:="Excel Files (*.xls), *.xls", _
                                                         Title:="Are you sure you want to SaveAs?" _
                                                         )
      '// Check to see if user cancelled; in which case reset bolInProcess and    //
      '// allow sheets to be redisplayed.  Nothing is saved, so no harm, no foul. //
      If strSaveAs_Filename = "False" Then
        bolInProcess = False
      Else
        '// If user chose a filename and committed to the saveas, I strip the   //
        '// proposed name from the proposed fullname, so that we can saveas to  //
        '// the same folder we opened this workbook in.                         //
        strSaveAs_Filename = "\" & Right(strSaveAs_Filename, Len(strSaveAs_Filename) - InStrRev(strSaveAs_Filename, "\", -1, vbTextCompare))
        
        '// One last check.  If user selects same name as current, then cancels //
        '// the app alert msg (are your sure?  there's already a workbook with  //
        '// this name...), an error ensues.                                     //
        On Error Resume Next
        ThisWorkbook.SaveAs ThisWorkbook.Path & strSaveAs_Filename
        Err.Clear
        On Error GoTo 0
      End If
    Else
      ThisWorkbook.Save
    End If
    
    '// IF we were closing the workbook when we decided to save, we'll leave        //
    '// everything hidden, reset settings, turn screen updating back on,            //
    '// and let the workbook close.                                                 //
    If bolClosing = True Then
      Application.Calculation = lCalculationSetting
      Application.ScreenUpdating = True
      Exit Sub
    End If
    
    '// Redisplay whichever sheets you want the user to be able to see.             //
    For Each wksWorksheet In ThisWorkbook.Worksheets
      wksWorksheet.Visible = xlSheetVisible
    Next
    
    '// THEN hide Prompt sheet AFTER redisplaying desired Worksheets.               //
    shtForceEnable.Visible = xlSheetVeryHidden
    
    If Not ActiveSheet.Name = wksLastActive.Name Then
      On Error Resume Next
      wksLastActive.Select
      On Error GoTo 0
    End If
    
    '// You can also scroll  to the last sheet you had active before the save.      //
    '// This does not effect which sheet is actually selected; it just puts which   //
    '// tabs you want in view.                                                      //
    ActiveWindow.ScrollWorkbookTabs Position:=xlFirst
    Application.Calculation = lCalculationSetting
    Application.ScreenUpdating = True
    ThisWorkbook.Saved = True
    
    '// Reset bolInProcess for the next time that user saves file.                  //
    bolInProcess = False
  End If
  
End Sub
  
Private Sub Workbook_Open()
Dim wksWorksheet As Worksheet
     
  '// Redisplay whichever sheets you want the user to be able to see.                 //
  For Each wksWorksheet In ThisWorkbook.Worksheets
    wksWorksheet.Visible = xlSheetVisible
  Next
  
  '// Then hide Prompt sheet AFTER redisplaying desired Worksheets.                   //
  shtForceEnable.Visible = xlSheetVeryHidden
  
  '// Mark workbook as saved, in case the user decides to close w/o making any        //
  '// changes.  This way, if the user opens and closes the workbook w/o making any    //
  '// changes, he isn't uneccessarily asked about saving changes.                     //
  ThisWorkbook.Saved = True
End Sub

PLEASE NOTE:

As you already have code in your workbook, you may well have ThisWorkbook.Save peppered about. I have always noted a weird glitch, at least in Excel: 9.0 (2000), Excel 2003, and Excel 2010 (so probably all recent versions). In short, the 'force enable' workaround functions correctly when the workbook is saved 'normally' by the user; that is - the user presses the save button or keys in the CTRL + s shortcut key combination.

However, if running code initiates the save (let us say it runs into a ThisWorkbook.Save), then if you follow (step-through) the code, you will see that rather than immediately jumping back to line the beginning of 'Workbook_BeforeSave' as it should, it just continues and doesn't actually save. I have no explanation for this...

Here's examples to show this:

Standard Module:

Rich (BB code):
Option Explicit
  
Sub example01()
  Stop
  ThisWorkbook.Save
End Sub
  
Sub example02()
  Stop
  Application.Run "ThisWorkbook.Workbook_BeforeSave", False, False
End Sub
 
Upvote 0
Thank you, I will try and see if I can figure it out.

However, I do not want the users to be able to save the document.
I have macros that delete everything they have previously typed in when they open the workbook, so I do not a prompt asking if they want to safe or not. They just should not get the opportunity at all.

Basically all I want is 1 sheet to be shown if they have not enabled macros, and if they have I want to have three other sheets shown.
Then when they close the workbook, I just want the workbook to close regardless of what they have done.
 
Last edited:
Upvote 0
Firstly, my apologies as I forgot to point out that where 'shtForceEnable' is referred to, this is the CodeName of the 'Macro Warning' sheet.

As to not allowing any saving, what format is the workbook in, .xlsm?
 
Upvote 0
Yes, it is .xlsm, and I can get to close without asking to save or not.

If I then want to test it, I save the workbook manually in another name and when I open it I am asked to enable macros and if I don't enable them I should see the "macros disabled" sheet, but I don't. It goes to the three sheets that should be very hidden.
 
Last edited:
Upvote 0
I might be incorrect, but I believe we are down to just this.

Rich (BB code):
Option Explicit
  
Private Sub Workbook_BeforeClose(Cancel As Boolean)
  ThisWorkbook.Saved = True
End Sub
  
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
  
  Cancel = True
  ThisWorkbook.Saved = True
  
End Sub
  
Private Sub Workbook_Open()
Dim wksWorksheet As Worksheet
     
  For Each wksWorksheet In ThisWorkbook.Worksheets
    wksWorksheet.Visible = xlSheetVisible
  Next
  
  shtForceEnable.Visible = xlSheetVeryHidden
  
  ThisWorkbook.Saved = True


End Sub

You would need to manually set all sheets (excepting shtForceEnable) to very hidden, make shtForceEnable visible, then place a breakpoint at the top of BeforeSave. When you click Save, drag down to the End Sub and press F5 so we actually save the first time.

Does that get it done?

Mark
 
Upvote 0
If I understand correctly, you are not allowing (via code) users to save any of the changes they make to the workbook -Right ?

If that's the case then the only code that you would need (to prevent saving users changes) is probably this:

Code:
Private Sub Workbook_BeforeClose(Cancel As Boolean)
  Saved = True
End Sub
  
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
  Cancel = True
End Sub

Then whenever the workbook is reopened it will default to its initial saved state ie : All sheets hidden except the sheet called "macro disabled" will be showing.
 
Last edited:
Upvote 0

Forum statistics

Threads
1,224,823
Messages
6,181,175
Members
453,021
Latest member
Justyna P

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top