Setting a sheet to be hidden. Code won't work - vba

I have the following code in on a workbook.
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Dim ws As Worksheet
For Each ws In Worksheets
If ws.Name <> "Main Page" Then
ws.Visible = xlSheetHidden
End If
Next ws
ThisWorkbook.Save
End Sub
But when the workbook is next open pages that were left open at the end are still open. I don't have any other macro's or vba script that sets the pages to be unhidden yet, I'm am just doing to manually to test it.
There are no errors that come up, the code complies correctly and runs. I even check the loop with breakpoints and it does go through every worksheet correctly.
Can anyone see what might be the problem? Have I missed one vital key word or something? Its driving me nuts, worse than trying to track down ; in c#
Ask any questions you think would help.
Matt

you should try something like
ws.Visible = xlSheetVeryHidden

Check if the workbook is protected. If it's protected, you have to unprotect the workbook first.

Related

Workbook.Activate method acting strangely

I have an Excel add-in running a procedure that displays an OKOnly MsgBox if a certain criteria is not met, and attempts to close a userform, activate a specific workbook, and terminate code execution. In the UserForm_Terminate() event I have:
Private Sub UserForm_Terminate()
Debug.Print ActiveWorkbook.Name
Application.ScreenUpdating = True
wbk.Activate
sht.Activate
Debug.Print ActiveWorkbook.Name
End
End Sub
If I begin running the procedure with a new blank workbook active, that workbook is still the active workbook when code terminates, but both print statements above indicate that the target wbk is actually active. However if I use a breakpoint and step through wbk.Activate, the target wbk is activated as expected. The workbook and worksheet objects are both available and there is no error. Any ideas why Workbook.Activate is not behaving as expected during execution? I expected turning screenupdating on would solve my issue but no dice.
#barX He's not relying on ActiceWorkbook for code, he's just checking it to see if it's working ....
BTW Welcome to the Excel 2013 SDI bug!
Maybe following the proper way of initializing/using a Userform will help. See Mathieu's RubberDuck article on Userform.Show
On a related note, maybe changing the Parent Window Handle for the form before closing might work as well. See Keeping Userforms On Top Of SDI Windows In Excel 2013 And Up
I'm not sure if the SDI bug is my issue but it did lead me to an answer (thanks #Profex). I was not able to reproduce that bug, and there is also another path in my procedure that ends with the same Userform_Terminate() event and does reactivate the target wbk, though I can't determine what is causing the differing functionality. Nonetheless, one solution to that issue was to hide and then show the active window and that suffices in this case, though probably not ideal in many situations:
Private Sub UserForm_Terminate()
Dim win As Window
wbk.Activate
sht.Activate
Set win = Application.ActiveWindow
win.visible = False
win.visible = True
End
End Sub

Locking Worksheet

I am using Excel 2013, and have a macro that copies a "master" worksheet to the end of the workbook, once filled in by the user. The worksheet that's copied, is renamed, according to the "master" report number. Is there a way that once the sheet is copied to the end, it can be locked so the user can not make any changes to it. I just want them to be able to view it. I've researched some sample code online, but nothing seems to do what I am trying to do. Anyone have any ideas or can help? Much thanks
You can use the .Protect and .Unprotect properties. Below is an example sub that protects all worksheets, charts in a workbook and then protects the workbook itself. Here's a site with more detailed info, and it would also be good to review how items are protected in Excel generally.
Sub protectWk(wk As Workbook)
Dim sh as Worksheet, ch as Chart
For Each sh In wk.Worksheets
sh.Protect ("password")
Next
For Each ch In wk.Charts
ch.Protect ("password")
Next
wk.Protect ("password")
wk.Close SaveChanges:=True
End Sub

How to make vba code to run auto-close only on active workbook?

Here's the scenario. I have multiple excel workbooks that copy and paste data among each other. So the macro works to open.copy.close from one workbook then open.paste.close to another. I am working on creating a function to auto run macro when file is closed.
Here's the issue, when I click macro button in workbook 1, it is supposed to open.copy.close from workbook 2. However, because of the auto run when file is closed function in workbook 2, an error will occur (2 macros cannot run at the same time)Any solution for this? I am looking for a solution to only auto run macro when file is closed IF IT IS AN ACTIVE WORKBOOK. Here is what I have now:
Workbook 1
Sub workbook_beforeclose(cancel As Boolean)
Application.Run "Sheet1.UpdateYellowTabs_Click"
End Sub
Workbook 2
Sub Workbook_BeforeClose(Cancel As Boolean)
Workbook.BeforeClose
Application.Run "Sheet12.UpdateGreen_Click"
End Sub
How do I code it in the workbook code to only make this run only when it's active/closed by a human user and not when open/close by macro?
Thanks!
Well I am not sure to understand your final goal from this, but I can answer the "technical" question. Technically, if you want to check if a given workbook is active: If Application.ActiveWorkbook Is Me,
Private Sub Workbook_BeforeClose(Cancel As Boolean)
If Not Application.ActiveWorkbook Is Me Then Exit Sub ' <-- add this test
''''''''''''''''''''''''''
' Whatever code goes here
''''''''''''''''''''''''''
End Sub
EDIT
But problem is that invoking wb2.close will make the workbook wb2 the "active" one during the execution of the macro. So this method won't work. Another method is to disable events before closing the workbook; so that the event Workbook_BeforeClose will not fire. After that, you can enable events back if needed. The code looks like this:
' ... open wb2 and do the work with it
Application.EnableEvents = False
wb2.Close False
Application.EnableEvents = True
notice, if you had already disabled events at the beginning of the current macro, which is usually recommended, then this additional code wouldn't be needed.

Using VBA range commands with ActiveX buttons in other sheets

while building up a user Interface I made use of ActiveX buttons in VBA2010. I wrote the Macros first, checked them, then copied them into the ActiceX button code.
The macro then crashes at a range command of another sheet. To test it I separated the commands:
Sheets("Data").Visible = xlSheetVisible
Sheets("Data").Select
Columns("O:O").Select ' The code crashes here
As a result I get a 1004 runtime error.
I found a similar topic which seems to be unsolved aswell.
Unable to Execute Macro With ActiveX Controls (Excel VBA)
Help is well appreciated.
Thanks in advance!
Select is not recommended.Modify your code to
Dim ws As Worksheet
Set ws = Sheets("Data")
ws.Visible = xlSheetVisible
ws.Select
With ws
.Columns("O:O").Select
End With

How do you run macros upon opening Excel workbook, then re-protect after finished running?

Is there a way to first, unprotect a workbook at the beginning of opening, run all the workbook_open() macros and then re-protect the workbook so that a common user can not change anything on any worksheets? I'd like to prevent the common user from changing anything but allow the macros to do its auto-update and computations.
Any suggestions? Is this even feasible?
What I think you're looking for is the Worksheet.Protect method.
At the beginning of your Workbook_Open event, place this code:
ThisWorkbook.Sheets("SheetYouWantToUnprotect").Unprotect _ Password:="TheSheetPassword"
Then at the end of your Workbook_Open event code, you want to protect the sheet again, so place this code:
ThisWorkbook.Sheets("SheetYouWantToProtect").Protect _
Password:="SheetPassword"
Of course, you can do this with more than one sheet if multiple sheets need to be unprotected. If each sheet has the same password, place a simple loop at the beginning of your Open event:
Dim sht as Worksheet
For Each sht in Thisworkbook.Sheets
sht.Unprotect Password:="YourPassword"
Next sht
At the end of your code you can use the same loop to protect the sheets, just change .Unprotect to .Protect.
Or, if there are many different passwords (aside from recommending you change them all to one password), you can place as many instances of the first line of code I mentioned as it takes to unprotect the necessary sheets.
Note: There are many more optional arguments to the .Protect method which I did not cover, but you can find an exhaustive list here.
EDIT: Here's more info on the Unprotect method.
Yes, it can be done
Private Sub Workbook_Open()
Dim WS As Worksheet
For Each WS In ThisWorkbook.Sheets
WS.Unprotect Password:="YourPassword"
WS.Protect Password:="YourPassword", UserInterfaceOnly:=True
Next WS
End Sub
The UserInterfaceOnly:=True allows VBA to act on any part of your worksheets while the common user can only interact with "unlocked" cells.