Excel VBA Protect Sheet without Locking all cells - excel

I am trying to protect the headers in an Excel Spreadsheet. In order to do so, I selected the entire sheet, went to cell properties, and unchecked "locked". Then, I selected the first row only and checked "locked".
My macros run fine once, then on running again I get errors related to the sheets being locked, and when I go back and check my sheets, now ALL the cells are locked again. I do not have any VBA code specifying to lock any cells. I have this macro running to protect the sheets:
Public Sub ProtectSheet(Optional sheetname As String)
Dim thisSheet As Worksheet
'This is to protect sheet from userinterface, but not from macros
If IsMissing(sheetname) Then sheetname = ""
If sheetname = "" Then
Set thisSheet = ActiveWorkbook.ActiveSheet
Else
Set thisSheet = ActiveWorkbook.Worksheets(sheetname)
End If
thisSheet.Protect UserInterfaceOnly:=False, Contents:=True, DrawingObjects:=True, Scenarios:=True, AllowFormattingRows:=True, AllowFormattingColumns:=True, AllowFormattingCells:=True, AllowInsertingHyperlinks:=True, AllowSorting:=True, AllowFiltering:=True
End Sub
I created VBA code as follows to unprotect the sheet, select all and unlock, then lock the first row, then protect. It works when I do this, but I don't understand why I have to.
Public Sub ProtectSheet(Optional sheetname As String)
Dim thisSheet As Worksheet
'This is to protect sheet from userinterface, but not from macros
If IsMissing(sheetname) Then sheetname = ""
If sheetname = "" Then
Set thisSheet = ActiveWorkbook.ActiveSheet
Else
Set thisSheet = ActiveWorkbook.Worksheets(sheetname)
End If
thisSheet.Unprotect
thisSheet.Cells.Locked = False
thisSheet.Rows(1).Locked = True
thisSheet.Protect UserInterfaceOnly:=False, Contents:=True, DrawingObjects:=True, Scenarios:=True, AllowFormattingRows:=True, AllowFormattingColumns:=True, AllowFormattingCells:=True, AllowInsertingHyperlinks:=True, AllowSorting:=True, AllowFiltering:=True
End Sub
I want to understand WHY all my cells are locking and would prefer not to have to add this extra code in when I don't believe I should have to. Is there a bug in Excel causing the locked property to get set, or I am missing something in this code that is locking them automatically?

If the problem is use of Clear then consider creating a separate sub to manage that, and call it instead of Clear.
Sub ClearButUnlocked(rng As Range)
with rng
.clear
.cells.locked=false
end with
end sub
...assuming rng only has one lock state and is not a mix of locked/unlocked cells

Related

How to unlock blank cells in workbook with VBA on open

I have a workbook with multiple sheets that needs all non-blank cells to be locked and protected when opening the workbook.
This will be an employee training record where multiple trainers will be evaluating new staff on skills. I would like to prevent anyone from accidentally deleting training data.
I found a code that will lock all cells, set all blank cells as unlocked, and protect the individual worksheet, but I'm having trouble applying this across my entire workbook.
Private Sub Workbook_Open()
Dim myCell As Range
Set myCell = Selection
Cells.Select
Selection.Locked = True
myCell.Select
Selection.SpecialCells(xlCellTypeBlanks).Select
Selection.Locked = False
ActiveSheet.Protect DrawingObjects:=True, _
Contents:=True, Scenarios:=True
myCell.Select
End Sub
Ideally, I would also like to add password protection to prevent a new employee from unprotecting the workbook. Is this possible within the same code? Can split this to a new question also.
In this case the password for each sheet is secret:
Sub Tony()
Dim s As Worksheet
For Each s In Sheets
s.Unprotect ("secret")
s.Cells.Locked = False
On Error Resume Next
s.Cells.SpecialCells(xlCellTypeConstants).Locked = True
s.Cells.SpecialCells(xlCellTypeFormulas).Locked = True
On Error GoTo 0
s.Protect ("secret")
Next s
End Sub
NOTE:
First make sure this does what you want. Only then have your event macro call it.

Macro that spellchecks worksheet and then locks it without erasing rules

I have a macro that unlocks my excel document, spellchecks, then locks the worksheet. However, upon locking the worksheet, it removes the rules regarding what a user can do in the locked spreadsheet (ex: add/delete rows, change box height/width, etc)
I've tried listing out the rules after .Protect Password but it doesn't work.
Sub ProtectSheetCheckSpellCheck()
'Update by Extendoffice 2018/11/2
Dim xRg As Range
On Error Resume Next
Application.ScreenUpdating = False
With ActiveSheet
.Unprotect ("Password123")
Set xRg = .UsedRange
xRg.CheckSpelling
.Protect Password:="Password123", AllowInsertingRows:=True, AllowInsertingColumns:=True
End With
Application.ScreenUpdating = True
End Sub
What you are looking for is being able to modify your worksheet without actually unprotecting it.
You can protect a sheet but allow VBA to make changes, whilst the user cannot:
ActiveSheet.Protect UserInterfaceOnly:=True
https://learn.microsoft.com/en-us/office/vba/api/excel.worksheet.protect
Name: UserInterfaceOnly
Description: True to protect the user interface, but not macros. If this argument is omitted, protection applies both to macros and to the user interface.
This assumes the option was set to True when the sheet was protected in the first place.
Alternatively, you can store the status of the current protection settings in a Protection object:
Dim myProtection as Protection
Set myProtection = ActiveSheet.Protection
Which would look like this:
Note that for some reasons .AllowEditRanges return an error when read so I did not include it in the list.
Sub test()
'Pick your Worksheet
Dim mySheet As Worksheet
Set mySheet = ActiveSheet
'Unprotect it
Dim myProtection As Protection
Set myProtection = mySheet.Protection
mySheet.Unprotect
'Do your VBA things
'Re Protect it
With myProtection
mySheet.Protect AllowFormattingCells:=.AllowFormattingCells, _
AllowFormattingColumns:=.AllowFormattingColumns, _
AllowFormattingRows:=.AllowFormattingRows, _
AllowInsertingColumns:=.AllowInsertingColumns, _
AllowInsertingRows:=.AllowInsertingRows, _
AllowInsertingHyperlinks:=.AllowInsertingHyperlinks, _
AllowDeletingColumns:=.AllowDeletingColumns, _
AllowDeletingRows:=.AllowDeletingRows, _
AllowSorting:=.AllowSorting, _
AllowFiltering:=.AllowFiltering, _
AllowUsingPivotTables:=.AllowUsingPivotTables
End With
End Sub
Note: .Protect includes [DrawingObjects], [Scenarios], and [USerInterfaceOnly], whilst these settings are not provided by the Protection object. I understand the [Contents] parameter should relate to the .AllowEditRanges, but since it cannot be acessed I guess it will be skipped too,

Protect worksheet not workbook

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?

Just-recorded macro fails to execute - AdvancedFilter method of Range class failed

I am working with Microsoft Office 2010.
I want to create a button that refreshes an 'AdvancedFilter' upon click.
What I did is to record a macro in order to replay my actions.
But the macro fails already at its first execution.
Sub Test()
'
' Test Macro
'
Workbooks("requirement_spec.xls") _
.Sheets("Requirements").Range("A4:BU279").AdvancedFilter _
Action:=xlFilterCopy, _
CriteriaRange:=Range("A1:F5"), _
CopyToRange:=Range("A11:BU11"), _
Unique:=False
End Sub
Starting the macro via Excel's macro menu or via a button results in this error:
Run-time error '1004':
AdvancedFilter method of Range class failed
I didn't change a character of the automatically recorded macro when producing the error message.
(I just did some line-breaking changes for SO)
I ran into something similar today with Excel 2013. Coming here, I noticed the old question with no real solution.
What I found out, is that the error does not appear when a range in the sheet with the filter is being selected. Therefore, the following worked for me:
Sub Test()
'
' Test Macro
'
Dim wb As Workbook, wbSave As Workbook, _
ws As Worksheet, wsSave As Worksheet, rSel As Range
'don't annoy users with changing the selection
Application.ScreenUpdating = False
'save old selection values to be sure
Set wbSave = ActiveWorkbook
Set wsSave = ActiveSheet
Set rSel = Selection
'activate target workbook + select something
'in my case it's a sheet in the same test workbook
Set wb = Workbooks("requirement_spec.xls")
wb.Activate
Sheets("Filter").Select
Range("A11").Select
'apply filter now
Sheets("Requirements").Range("A4:BU279").AdvancedFilter Action:=xlFilterCopy, _
CriteriaRange:=Range("A1:F5"), CopyToRange:=Range("A11"), Unique:=False
'restore old selection to be sure
wbSave.Activate
wsSave.Activate
rSel.Select
'allow screen updating again
Application.ScreenUpdating = True
End Sub
maybe try:
Workbooks("requirement_spec.xls") _
.Sheets("Requirements").Range("A4:BU279").AdvancedFilter _
Action:=xlFilterCopy, _
CriteriaRange:=Range("A1:F5"), _
CopyToRange:=Range("A11"), _
Unique:=False
End Sub
so you're hoping that from 275 rows with about 50 columns (A4 to BU 279) will be copied to the same worksheet Range("A11") ?

how to have unlocked cells on a protected VBA created worksheet

An input file of data is processed using VBA to create an Excel(2003) protected spreadsheet(Invoice).
The spreadsheet is then to be distributed to other offices where some designated cells are to be amended.
How can I create the worksheet to allow these cells to be amended when the whole sheet is protected?
I have tried using the code below, and other similar variations, but it does not seem to work.
Can you help?
Private Sub CellLock1()
Cells.Select
' unlock all the cells
Selection.Locked = False
' lock only these cells
Range("J49:K49").Select
Selection.Locked = True
ActiveSheet.Protect DrawingObjects:=True, _
Contents:=True, _
Scenarios:=True, _
UserInterfaceOnly:=True, _
AllowFormattingCells:=True, _
AllowFormattingColumns:=True, _
AllowFormattingRows:=True, _
AllowInsertingColumns:=True, _
AllowInsertingRows:=True, _
AllowInsertingHyperlinks:=True, _
AllowDeletingColumns:=True, _
AllowDeletingRows:=True, _
AllowSorting:=True, _
AllowFiltering:=True, _
AllowUsingPivotTables:=True
End Sub
Every cell on excel is Locked by default and after protecting a workbook, you won't be able to edit the cells unless you unlock them beforehand.
You aren't able to unlock the cells, even using VBA code, if the sheet is protected.
So if you want to use code to unlock some cells, you have to unprotect the workbook/worksheet first.
Please try my code:
Sub UnlockCells()
Sheet1.Unprotect
Sheet1.Range("A1", "B6").Locked = False 'Unlock the range A1 to B6
Sheet1.Cells(6, 6).Locked = False 'Unlock the cell F6
Sheet1.Protect
End Sub
This may be a bit late ...but I hope it helps
here are the steps to do:
Lock the sheet under consideration
View Code to create a private Subroutine(Right Click Sheet --> View Code --> Select the 'Microsoft Excel Objects' corresponding to this Sheet)
Paste this code :
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim ws As Worksheet
Dim inputRange As Range
Set ws = Worksheets("WorkSheetName")
'tell this sub to unprotect only these cells
Set inputRange = Range("I5,I7,I11")
' If the selected cell is not in the range keep the sheet locked
If Intersect(Target, inputRange) Is Nothing Then
'else unprotect the sheet by providing password
'(same as the one that was used to protect this sheet)
Else
ws.Unprotect Password:="password"
Target.Locked = False
ws.Protect Password:="password"
End If
End Sub

Resources