TL;DR —
Range.Lockedis a label, not a lock. SettingLocked = Truechanges nothing you can see or feel; the cell only becomes uneditable once the sheet is protected, at which point Excel reads every cell label and freezes the ones markedLocked. That is why the classic complaint — "I setLocked = Truebut users can still edit the cell" — is not a bug: the sheet was never protected. And because every cell startsLocked = True, the real workflow is inverted: you unlock the input cells (Locked = False) and then protect, letting everything else inherit the default lock.
Sub MarkEditableCells()
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Form")
ws.Cells.Locked = True ' every cell already is - being explicit
ws.Range("C4:C12").Locked = False ' the inputs are the exceptions
ws.Range("C4:C12").FormulaHidden = False
ws.Protect Password:="ac" ' NOW the labels start to mean something
End Sub
Locked is the checkbox in Format Cells ▸ Protection, and it is the single most misunderstood
property in Excel automation — because setting it appears to do nothing. You run cell.Locked = True,
you click the cell, and you can still type in it. Everything is working exactly as designed; you have
just discovered that Locked is inert on its own. Once you internalize that Locked is a note to the
protection system rather than an act of locking, the whole feature becomes predictable.
What you'll learn
- The mental model —
Lockedis a label the protection switch reads, not a lock in itself - The one rule that explains the number-one bug —
Lockeddoes nothing until you protect the sheet - Why every cell starts locked, and the inverted "unlock the inputs" workflow that follows
- Why
Lockedreads backNullon a mixed selection, and how to test for it FormulaHidden— the companion label that hides a formula from the formula bar- Why you must set
Lockedwhile the sheet is unprotected
The mental model: a label, not a lock
Picture Locked as a sticky note on each cell that reads "freeze me when protection is on." Writing the
note does not freeze anything; it just records an intention. The actual freezing happens later, and by
someone else — Worksheet.Protect — which walks the sheet, reads each note, and enforces it. Two cells
can carry identical Locked labels and behave completely differently, purely depending on whether their
sheet is protected.
This is why Locked and Protect are a pair that must be understood together.
Locked is the map of who-may-edit-what; Protect is the switch that starts honoring the map.
Neither does the job alone: a map nobody enforces changes nothing, and a switch with no map just locks
everything (because the default map marks every cell locked).
The rule that explains the number-one bug: Locked is inert until you protect
The most-searched frustration behind this topic is "I set the cell to Locked = True but the user can
still edit it." It is never a bug in Locked. It means the sheet is not protected, so nothing is
enforcing the label. The Locked property has no effect whatsoever on an unprotected sheet — you can
set it on every cell in the workbook and change nothing about what anyone can type.
ws.Range("A1").Locked = True ' A1 is now labeled locked...
' (sheet is not protected) ' ...and still fully editable
ws.Protect ' NOW A1 is frozen
So Locked is always half of a two-step, and the second step is the one people forget. If a cell must
resist editing, setting Locked = True is necessary but not sufficient — the sheet has to be protected
for the label to bite. Any time locking "does not work," the first thing to check is whether
ws.ProtectContents is even True.
Every cell starts locked — so unlock the exceptions
Here is the fact that flips the whole workflow: every cell in a new sheet is already Locked = True.
That means "locking the cells I want to protect" is almost never the right move — they are locked
already. The correct pattern is the inverse: leave the default in place and unlock the handful of
cells you want people to edit.
ws.Cells.Locked = True ' the default; state it for the next reader
ws.Range("C4:C12").Locked = False ' unlock the inputs - the exceptions
ws.Protect Password:="ac" ' everything else inherits the lock
Think in terms of "which cells are the inputs?" and unlock those; everything else — labels, formulas, headings — keeps the default lock and is frozen the moment you protect. This scales far better than trying to enumerate every cell that should be read-only, and it is why well-built templates unlock a small, obvious input region and lock the rest by omission.
The Null trap: reading Locked on a mixed selection
Locked reads back cleanly only when a range is uniform. If a range contains both locked and unlocked
cells, reading .Locked returns Null, not True or False. So a naive test blows up:
If ws.Range("A1:A10").Locked Then ' run-time error if the range is mixed (Null)
When A1:A10 has some locked and some unlocked cells, .Locked is Null, and If Null Then raises
"Invalid use of Null." Guard it with IsNull when a range might be mixed:
Dim state As Variant
state = ws.Range("A1:A10").Locked
If IsNull(state) Then
' mixed - decide per cell
ElseIf state Then
' all locked
Else
' all unlocked
End If
This is the same three-state behavior you see with WrapText and other cell
properties: uniform ranges give a Boolean, mixed ranges give Null. Read one cell at a time when you
need certainty.
FormulaHidden: lock the cell, hide the recipe
Locked has a companion label, FormulaHidden, and together they cover the two things you usually want
from a delivered model: the user cannot change the formula, and cannot even see it. Like Locked,
FormulaHidden does nothing until the sheet is protected; once it is, a cell with
FormulaHidden = True shows its result in the grid but a blank formula bar when selected.
ws.Range("D4:D100").Locked = True
ws.Range("D4:D100").FormulaHidden = True ' hide the calculation from the formula bar
ws.Protect Password:="ac"
Use it when you are shipping a calculation as a black box — a pricing model, a scoring formula — and you want people to trust the number without lifting the hood. As always, it is a convenience and IP gesture, not security: like protection passwords, it is easily defeated. But for keeping a formula out of casual sight it is exactly the right label.
Why you must set Locked while the sheet is unprotected
The Locked map has to be drawn while the sheet is open. Attempting cell.Locked = False on a
protected sheet raises run-time error 1004 — you cannot rewrite the map while the switch that enforces
it is on. So the order is fixed and non-negotiable: Unprotect (if needed), set
every Locked and FormulaHidden label, then Protect. If a macro needs to change which cells are
editable at run time, it must unprotect first, adjust the labels, and re-protect — you can never edit the
labels through an active lock.
How ExcelMaster helps
Locked fails silently in the most confusing way possible: it does exactly nothing, with no error,
until the sheet is protected — so people set it, watch users edit "locked" cells anyway, and assume the
property is broken. Then the inverse workflow trips them up, or a mixed-range read throws "Invalid use
of Null," or they try to relabel cells through an active protection and hit 1004.
ExcelMaster lets you say the goal —
"let people edit only the yellow input cells and hide the formulas" — and it sets Locked and
FormulaHidden in the right order, unlocks the inputs rather than trying to lock everything else, pairs
the labels with the Protect call that actually enforces them, and guards mixed-range reads against
Null. You keep the workbook and the code.
Frequently asked questions
Why can users still edit a cell after I set Locked to True in VBA?
Because Locked does nothing until the sheet is protected. It is only a label the protection system
reads — an unprotected sheet ignores it entirely. Set the cells Locked = True (or leave the default),
then call ws.Protect. If editing is still possible after that, confirm the sheet is actually protected
with ws.ProtectContents.
How do I lock only some cells and leave the rest editable?
Use the inverted workflow. Every cell starts Locked = True, so unlock the exceptions rather than
locking the targets: ws.Cells.Locked = True then ws.Range("C4:C12").Locked = False for the input
cells, then ws.Protect. Everything you did not unlock inherits the default lock and is frozen once the
sheet is protected.
Why does reading the Locked property give an error?
Because the range is mixed. Locked returns Null when a range contains both locked and unlocked
cells, and If Range.Locked Then on a Null raises "Invalid use of Null." Test with IsNull first, or
read one cell at a time: a uniform range returns a Boolean, a mixed one returns Null.
What is the difference between Locked and FormulaHidden?
Locked stops a cell being edited once the sheet is protected; FormulaHidden stops its formula being
seen in the formula bar once the sheet is protected. Both are labels that only take effect under
protection. Use them together to ship a calculation the user cannot change or inspect — lock the cell and
hide the formula, then protect.
Can I change a cell's Locked state while the sheet is protected?
No. Setting Locked (or FormulaHidden) on a protected sheet raises run-time error 1004. You must draw
the map while enforcement is off: Unprotect if needed, set the Locked labels, then Protect. A macro
that changes editability at run time has to unprotect, adjust, and re-protect.
Tested in
Tested in: Excel 365 (Windows 11), VBA 7.1 — last verified 2026-09-11.
Related guides: VBA Protect Sheet · VBA Unprotect · VBA Wrap Text · VBA Range · VBA Formula
