TL;DR —
Worksheet_BeforeDoubleClickis an event Excel fires the instant you double-click a cell — before the cell drops into edit mode. It hands you two things:Target(the cell you clicked) andCancel. SetCancel = Trueand Excel's default reaction — entering edit mode — is suppressed, so your action is the only thing that happens. That turns a double-click into a one-gesture button: toggle a checkmark, mark a row done, jump to detail. The code lives in the worksheet's own module, and you almost always want to scope it to one column withIntersect.
' Lives in the sheet's module (double-click "Sheet1" under Microsoft Excel Objects).
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
' Only act inside column B; leave every other cell editable as normal.
If Intersect(Target, Me.Columns("B")) Is Nothing Then Exit Sub
Cancel = True ' <-- suppress edit mode
Target.Value = IIf(Target.Value = "x", "", "x") ' double-click toggles a mark
End Sub
Most macros wait for a button. Worksheet_BeforeDoubleClick waits for a gesture — a
double-click on a cell — and, crucially, it runs before Excel does the thing a
double-click normally does (put the cell in edit mode). That "before" is the whole point:
you get to intercept the gesture, decide what it should mean on your sheet, and cancel
the default. It's the event behind click-to-check task lists, drill-downs from a summary
to its source rows, and expand/collapse toggles — and it's the event people wire up
without the one line that makes it feel right.
What you'll learn
- The mental model — a double-click is a gesture you can hijack,
Cancelsuppresses its default - The rule that matters most — forget
Cancel = Trueand the cell still enters edit mode - How to scope the event to one column with
Intersectso the rest of the sheet stays editable - The write-back trap — toggling a cell fires
Worksheet_Change, so guard it - Sheet-level vs workbook-level, and where the code has to live
The mental model: a gesture you can hijack, not a click you observe
A double-click already means something to Excel: "put this cell in edit mode." When you
write Worksheet_BeforeDoubleClick, Excel calls your code first and waits — it hasn't
entered edit mode yet. You get Target, the exact cell double-clicked, and Cancel, a
Boolean passed by reference. Leave Cancel alone and, after your code runs, Excel goes
ahead and enters edit mode. Set Cancel = True and it doesn't — the double-click's
default meaning is thrown away and replaced by whatever your handler did.
So the handler is not "tell me when a cell is double-clicked." It's "let me redefine what
a double-click does here." That reframing is what makes the event powerful: a
double-click becomes a tiny, mouse-native command — no button, no ribbon, just point and
double-click. And like every event in this family, it lives in a specific place. This one
goes in the worksheet's own code module (double-click the sheet under "Microsoft Excel
Objects" in the Project Explorer) — not a standard Module, and not ThisWorkbook.
The rule that matters most: without Cancel = True, the cell still edits
Here is the bug that makes a click-to-toggle sheet feel broken. You write the toggle but forget the one line:
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
Target.Value = IIf(Target.Value = "x", "", "x") ' toggles... then Excel edits the cell
End Sub
The mark toggles — and then the cell drops into edit mode, blinking cursor and all,
because nothing set Cancel. The user double-clicked to mark a task done and ended up with
an editing cell they now have to press Escape to leave. Your action ran, but Excel's default
ran too, right on top of it. The rule: when your handler replaces the meaning of the
double-click, set Cancel = True so the default doesn't fire underneath you.
Cancel = True ' suppress edit mode first
Target.Value = IIf(Target.Value = "x", "", "x")
That single flag is the difference between "a slick one-click toggle" and "a toggle that also annoyingly opens the cell for editing." Set it whenever the double-click is your command, not a genuine edit.
The rule that keeps the sheet usable: scope it with Intersect
An unscoped handler is worse than no handler. If your code runs on every double-click
and sets Cancel = True, you have just disabled edit-by-double-click for the entire
sheet — the user can never double-click any cell to edit it again. That's a hostile side
effect nobody asked for.
The fix is to act only inside the range that's meant to be clickable, and bail out everywhere else:
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
' Guard: do nothing unless the click is in the "Done" column (B2:B100).
If Intersect(Target, Me.Range("B2:B100")) Is Nothing Then Exit Sub
Cancel = True
Target.Value = IIf(Target.Value = "x", "", "x")
End Sub
Intersect(Target, Me.Range("B2:B100")) returns Nothing when the double-clicked cell is
outside your target range, so Exit Sub leaves the rest of the sheet behaving normally —
double-click anywhere else and it edits as usual. This is the same Intersect guard that
keeps a Worksheet_Change handler from firing on every edit,
and it's what separates a targeted affordance from a sheet-wide takeover.
The trap that comes back to bite: your write fires another event
The moment your handler writes to a cell — and toggling a mark does exactly that — it triggers
Worksheet_Change, because you changed a cell's value. Most of the time that's harmless.
But if the same sheet has a Worksheet_Change handler that also writes (a timestamp, a
log, a recalculated total), the two can chain, and in the worst case the write re-enters
your own logic. The guard is the event family's golden rule: wrap the write so it can't
trigger the machinery.
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
If Intersect(Target, Me.Range("B2:B100")) Is Nothing Then Exit Sub
Cancel = True
Application.EnableEvents = False ' my write won't fire Worksheet_Change
Target.Value = IIf(Target.Value = "x", "", "x")
Application.EnableEvents = True
End Sub
If your handler does more than a trivial write, put the EnableEvents = True in an error
handler too, so a mid-way crash can't leave events switched off for the whole
session — the same discipline described in Worksheet_Change.
The distinction that decides where the code goes: sheet vs workbook
Worksheet_BeforeDoubleClick is a per-sheet event — it lives in one worksheet's module
and only fires for double-clicks on that sheet. If you want the same behaviour on every
sheet, don't paste the handler into twelve sheet modules. Use the workbook-level twin,
Workbook_SheetBeforeDoubleClick, which lives in ThisWorkbook and hands you an extra
first argument, Sh, telling you which sheet was clicked:
' In ThisWorkbook - fires for a double-click on ANY sheet.
Private Sub Workbook_SheetBeforeDoubleClick(ByVal Sh As Object, ByVal Target As Range, Cancel As Boolean)
If Sh.Name <> "Tasks" Then Exit Sub
If Intersect(Target, Sh.Range("B2:B100")) Is Nothing Then Exit Sub
Cancel = True
Target.Value = IIf(Target.Value = "x", "", "x")
End Sub
That's the same sheet-vs-workbook choice you make with
Worksheet_Activate vs Workbook_SheetActivate: one sheet →
the sheet's module; any sheet → the workbook module with the Sh argument.
How ExcelMaster helps
A good double-click handler is three small decisions that are easy to get subtly wrong: the
Intersect guard that keeps the rest of the sheet editable, the Cancel = True that stops
the cell entering edit mode, and the EnableEvents gate around any write. Miss one and the
feature feels broken in a way that's hard to diagnose.
ExcelMaster
lets you describe the behaviour instead. Say "double-clicking a cell in column B should
toggle a checkmark and not open the cell for editing," and it writes a
Worksheet_BeforeDoubleClick in the right sheet module, scopes it with Intersect, sets
Cancel, and guards the write. You keep the workbook and the code; you skip the
trial-and-error of learning which line does what.
Frequently asked questions
How do I run a macro when a cell is double-clicked in Excel?
Put a Worksheet_BeforeDoubleClick procedure in the sheet's code module:
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean). Excel
calls it whenever a cell on that sheet is double-clicked and passes Target (the cell).
Add your action there. For all sheets, use Workbook_SheetBeforeDoubleClick in
ThisWorkbook.
How do I stop the cell from entering edit mode on double-click?
Set Cancel = True inside the handler. Excel checks Cancel after your code runs; True
suppresses the default reaction (entering edit mode), so only your action happens. Without
it, the cell toggles and opens for editing.
How do I make double-click only work in one column?
Guard with Intersect: If Intersect(Target, Me.Columns("B")) Is Nothing Then Exit Sub at
the top of the handler. Intersect returns Nothing when the double-clicked cell is
outside your range, so the rest of the sheet keeps editing normally on double-click.
Why does double-clicking a cell put it in edit mode instead of running my code?
Either the code isn't in the sheet's own module, macros are disabled, or your handler runs
but never sets Cancel = True — so Excel's default (edit mode) fires after your code.
Confirm the procedure is in the correct worksheet module and add Cancel = True.
What is the difference between BeforeDoubleClick and BeforeRightClick?
Worksheet_BeforeDoubleClick intercepts a double-click (default reaction: enter edit mode);
Worksheet_BeforeRightClick intercepts a right-click
(default reaction: show the context menu). Both hand you Target and a Cancel flag you
set to True to suppress the default.
Tested in
Tested in: Excel 365 (Windows 11), VBA 7.1 — last verified 2026-08-06.
Related guides: VBA Worksheet_BeforeRightClick · VBA Workbook_BeforePrint · VBA Worksheet_Change · VBA Worksheet_Activate & Deactivate · VBA Range
