Like many other people, I want to be able to enable grouping and ungrouping with the little +/- buttons on a protected worksheet. Everyone seems to have succeeded with the same sort of code that protects the worksheet, enables outlining and then unprotects it again, which is great and it works except if I save the sheet and then re-open it again EnableOutlining is always set as False, and if the sheet is protected I cannot use the +/- buttons. Is there something else I am supposed to do to save this setting permanently, and not just for the duration of the session?
Here's the code I have been using:
Private Sub Workbook_Open()
MsgBox ActiveSheet.EnableOutlining
End Sub
Sub EnableOutliningWithProtection_AllSheets()
'PURPOSE: Allow Outline functionality during Protection in all Sheets
'SOURCE: www.TheSpreadsheetGuru.com/the-code-vault
'(Except edited by me to include the Errorcatch)
Dim sht As Worksheet
On Error GoTo Errorcatch
'Loop through each Worksheet in ActiveWorkbook
For Each sht In ActiveWorkbook.Worksheets
'Password Protect Current Sheet
sht.Protect Password:="", UserInterfaceOnly:=True
'Enable Group Collapse/Expand Capabilities
sht.EnableOutlining = True
'Unprotect Sheet
sht.Unprotect ""
Next sht
Exit Sub
Errorcatch:
MsgBox Err.Description
End Sub
(I've got the Workbook_Open() bit to check if EnableOutlining was still True)
I've seen the 'protect UserInterfaceOnly and EnableOutlining' question, but I didn't think the results applied as the code was written for C#, and I'm not looking at protecting UserInterfaceOnly.
You can't save it permanently. You have to use the Open event to reset it when the workbook is opened.
Private Sub Workbook_Open()
EnableOutliningWithProtection_AllSheets
End Sub
Related
I know there are lots of questions on this, which I have read - but none seem to give me the code I need to make this work.
I have a number of buttons that I have placed in the Ribbon of my excel sheet. These are attached to macros that copy sheets onto another sheet, as an example
The macro is ran by pressing the button:
Sub btnSheet1_onAction(control As IRibbonControl)
mFunction.CopySheet1toSheet2
End Sub
The macro is contained in my mFunction module as :
Public Sub CopySheet1toSheet2()
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets(1)
ws.Cells.Copy Destination:=ThisWorkbook.Sheets(2).Cells
End Sub
Now.... I need to protect items/cells in sheet 1 and 2. When I protect the sheets the macros make excel crash - no runtime errors or anything.
I have inserted the following code into the 'ThisWorkbook'
Private Sub Workbook_Open()
Sheets(1).Protect Password:="secret", UserInterFaceOnly:=True
Sheets(2).Protect Password:="secret", UserInterFaceOnly:=True
End Sub
But it still doesn't work - I have also tried with the following code in the mFunction module
Public Sub CopySheet1toSheet2()
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets(1)
ws.Unprotect Password = "secret"
ws.Cells.Copy Destination:=ThisWorkbook.Sheets(2).Cells
ws.Protect Password = "secret"
End Sub
But that doesn't seem to work either - I am guessing it might be something to do with the fact that the macro is copying the sheet into another sheet that is locked also?
I should also note that there are other sheets in the workbook that are protected, but that do not have macros attached to them, so they stay protected, could this be causing an issue?
Some help would be greatly appreciated!!
UserInterFaceOnly
When you save a Workbook with sheets that have been protected using UserInterFaceOnly, this property is removed on the file that is saved. So on reopening the file the sheets will remain protected but can not be changed programmatically either.
So, regarding this piece of code, which on first glance appears to do exactly what you need:
Private Sub Workbook_Open()
Sheets(1).Protect Password:="secret", UserInterFaceOnly:=True
Sheets(2).Protect Password:="secret", UserInterFaceOnly:=True
End Sub
.. if you save and reopen your file, when your above Workbook_Open() runs it will fail to set the protection as there is already protection in place.
The workaround is to include lines for each sheet that remove any protection in place first. Then you can set it again correctly - like so:
Private Sub Workbook_Open()
Sheets(1).Unprotect Password:="secret"
Sheets(2).Unprotect Password:="secret"
Sheets(1).Protect Password:="secret", UserInterFaceOnly:=True
Sheets(2).Protect Password:="secret", UserInterFaceOnly:=True
End Sub
This should then allow your copy code to run without issue as I can't see much wrong with that part at all.
Incidentally, if your passwords are the same, you could tidy it up slightly with:
Private Sub Workbook_Open()
Dim sh As Worksheet
For Each sh In Array(Sheets(1), Sheets(2))
sh.Unprotect Password:="secret"
sh.Protect Password:="secret", UserInterFaceOnly:=True
Next
End Sub
Okay - so I have used this as a work around, but if anyone can give a more eloquent solution that would be great:
Dim ws As Worksheet
Set ws1 = ThisWorkbook.Worksheets(1)
Set ws2 = ThisWorkbook.Worksheets(2)
ws1.Unprotect ("2402")
ws2.Unprotect ("2402")
ws1.Cells.Copy Destination:=ws2.Cells
ws1.Protect ("2402")
ws2.Protect ("2402")
I have to protect columns A:O from being edited in a worksheet I'm creating, but it doesn't seem to be working properly.
Set Wb = Workbooks.Add(XlWBATemplate.xlWBATWorksheet)
With Wb
With .Worksheets("Sheet1")
.Cells.Locked = False
.Columns("A:O").Locked = True
End With
Why are those columns able to be edited after I run the macro?
Rest of script underneath (including saving):
.SaveAs strNewPath & strFileName, Password:="password", FileFormat:=51
.Saved = True
.Close
End With
Set Wb = Nothing
End If
Next
I'll just add on with an answer to clarify things. The Locked property simply indicates whether or not the cells is modifiable when the sheet is protected. You can protect a sheet by going to the Review tab in the Excel toolbar, then selecting Protect Sheet.
Alternatively, you can protect and unprotect within your code. For example:
Sub Protect_Sheet()
Sheet1.Protect "Password"
End Sub
Sub Unprotect_Sheet()
Sheet1.Unprotect "Password"
End Sub
You can call these methods within a larger method if you want to perfrom some action on locked sheets, then protect the sheet.
When the code start import:
Sheet1.Unprotect "Password" '<- Unprotect the sheet in order to Unlock sheet and give the opportunity to the code to work.
and when the code finish import:
Sheet1.Protect "Password" '<- Protect the sheet in order to lock the sheet
I have a spreadsheet with several sheets, which is protected except where I want people to make changes, and all is password protected. I am trying to make a command button so others can view the data, but can't make changes to the cells. Here is what I have (not working quite right).
Private Sub mdRead_Click()
Dim ws As Worksheet
For Each ws In ActiveWorkbook.Sheets
'To open wookbook as read only, while proctecting changes.
Worksheet.Unprotect = True
Worksheet.Range("C10:I23,L10:R23,C25:I36,L25:R36,C45:I58,L45:I58,C60:I71,L60:R71").Select
Selection.Locked = True
Next ws
End Sub
Having set the Locked property, you might want to protect the sheet again.
I have this code:
Private Sub Workbook_Open()
Dim wSheet As Worksheet
For Each wSheet In Worksheets
wSheet.Protect Password:="Wordpass", _
UserInterFaceOnly:=True
Next wSheet
End Sub
It protects all worksheet in the workbook but allows macro to run.
However, this code:
wb.RefreshAll 'I've declared and set wb accordingly.
doesn't execute at all even though UserIntergFaceOnly is set to True.
The userinterfaceonly flag certainly doesn't work the way I would expect. Generally speaking, I set it, but I often find that I have to bracket things with unprotect and protect. Whenever I get an error, or failure to do something, its the first thing I try.
I apologise for lack of specifics and I will post back later after surveying my code. To be honest, I'm usually so busy with trial and error due to lack of documentation for VBA that I haven't had time to document this type of behaviour yet. But I will in the near future.
But meanwhile, I also try to make sure object reference are a qualified as possible so, in your case for example, I would try:
Thisworkbook.Refreshall
Or
Application.Thisworkbook.Refreshall
Or maybe even
application.workbooks(application.thisworkbook.name)
Failing that, bracket with unprotect/protect contents:=True, userinterfaceonly:=True
Try this
Private Sub Workbook_Open()
Dim wSheet As Worksheet
Dim pt As PivotTable
For Each wSheet In Worksheets
wSheet.Protect Password:="Wordpass", _
UserInterFaceOnly:=True
Next wSheet
End Sub
'~~> Change "Sheet1" to the relevant sheet which has the pivot
Sub UpdatePivot()
With ThisWorkbook.Sheets("Sheet1")
For Each pt In .PivotTables
pt.RefreshTable
DoEvents
Next pt
End With
End Sub
I have an Excel spreadsheet that needs most of it's cells protected from editing. I can't protect the sheet in the usual way because I work with groups (little + at the top to expand certain columns).
I found a VBA macro to protect my sheet, but noticed in Excel 2010 that I could simply "unprotect sheet" and modify everything, even though the whole workbook is still protected.
This is the macro I use at "ThisWorkbook":
Private Sub Worksheet_Change(ByVal Target As Range)
ActiveSheet.Unprotect Password:="nopassword"
If Range("C3").Value = "protect" Then
Range("C4:C65536").Locked = True
Else
Range("C4:C65536").Locked = False
End If
ActiveSheet.Protect Password:="fakepass"
End Sub
Private Sub Workbook_Open()
Dim x As Long
For x = 1 To ActiveWorkbook.Sheets.Count
With ActiveWorkbook.Sheets(x)
.Protect UserInterfaceOnly:=True
.EnableOutlining = True
End With
Next
End Sub
How can I modify this code to work with Sheet 1?
I'm aware it's not the safest form of protection but it's merely to prevent people modifying cells accidentally.
If you change:
ActiveSheet.Protect Password:="fakepass"
To:
Worksheets("Sheet1").Protect Password:="fakepass"
It will apply to Sheet1 rather than the active sheet only.
Or you could create a macro to protect all sheets, something like:
Sub ProtectAll()
Dim ws As Worksheet
For Each ws In ActiveWorkbook.Worksheets
ws.Protect Password:="fakepass", DrawingObjects:=True, Contents:=True, Scenarios:=True
Next ws
End Sub
And then call it into your main code?
ActiveSheet.Unprotect Password:="nopassword" Will only reference whatever sheet you're on.
Sheets("Sheet1").Activate will set active sheet to sheet1, no matter what sheet is selected.
Is that what you were after?