TL;DR —
Worksheet_BeforeDoubleClickは、セルをダブルクリックした瞬間に — セルが編集モードに落ちる前に — Excel が発火させるイベントです。手渡されるのは 2 つ、Target(クリックしたセル)とCancelです。Cancel = Trueにすると、 Excel の既定の反応 — 編集モードに入ること — が抑制され、あなたのアクションだけが 起こります。これがダブルクリックを、ひと仕草のボタンに変えます:チェックマークを 切り替える、行を完了にする、明細へ飛ぶ。コードはワークシート自身のモジュールに 置き、そしてほぼ必ずIntersectで 1 つの列にスコープを絞りたくなります。
' シートのモジュールに置く(「Microsoft Excel Objects」の下で "Sheet1" をダブルクリック)。
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
' 列 B の内側でだけ動く。ほかのセルはすべて通常どおり編集可能なまま残す。
If Intersect(Target, Me.Columns("B")) Is Nothing Then Exit Sub
Cancel = True ' <-- 編集モードを抑制する
Target.Value = IIf(Target.Value = "x", "", "x") ' ダブルクリックで印を切り替える
End Sub
ほとんどのマクロはボタンを待ちます。Worksheet_BeforeDoubleClick が待つのは仕草 —
セルへのダブルクリック — で、そして決定的なのは、ダブルクリックがふだん引き起こすこと
(セルを編集モードにすること)を Excel がする前に走る点です。その「前」こそが
すべての要です:あなたは仕草を横取りし、あなたのシートでそれが何を意味すべきかを
決め、既定の動作をキャンセルできます。クリックでチェックするタスクリスト、サマリー
から元の行へのドリルダウン、展開・折りたたみのトグル — その裏にいるイベントであり、
そして人々が「しっくりくる」ための 1 行を欠いたまま配線してしまうイベントでもあります。
この記事で学べること
- 考え方の軸 — ダブルクリックは横取りできる仕草であり、
Cancelがその既定を抑制する - いちばん大事なルール —
Cancel = Trueを忘れると、セルはやはり編集モードに入る - シートの残りを編集可能に保つよう
Intersectでイベントを 1 列にスコープする方法 - 書き戻しの罠 — セルを切り替えると
Worksheet_Changeが発火するので、ガードする - シートレベル対ブックレベル、そしてコードを置かねばならない場所
考え方の軸:観察するクリックではなく、横取りできる仕草
ダブルクリックは、Excel にとってすでに何かを意味しています:「このセルを編集モード
にする」。Worksheet_BeforeDoubleClick を書くと、Excel はまずあなたのコードを呼んで
待ちます — まだ編集モードには入っていません。手に入るのは Target、ダブルクリック
されたまさにそのセルと、参照渡しされる Boolean の Cancel です。Cancel に触れずに
放っておけば、あなたのコードが走ったあと、Excel はそのまま編集モードに入ります。
Cancel = True にすればそうはならず — ダブルクリックの既定の意味は捨てられ、
ハンドラーがした処理に置き換わります。
つまりハンドラーは「セルがダブルクリックされたら教えて」ではありません。「ここで
ダブルクリックがすることを、私に定義し直させて」なのです。この捉え直しこそが、
このイベントを強力にします:ダブルクリックが、ちいさなマウス生まれのコマンドになる
のです — ボタンもリボンもなく、ただ指して、ダブルクリックするだけ。そしてこの一族の
あらゆるイベントと同じく、これも決まった場所に置かれます。これはワークシート自身の
コードモジュールに入ります(プロジェクトエクスプローラーの「Microsoft Excel Objects」
の下でそのシートをダブルクリック) — 標準の Module でも、ThisWorkbook でもありません。
いちばん大事なルール:Cancel = True がなければ、セルはやはり編集される
これは、クリックでトグルするシートを「壊れている」と感じさせるバグです。トグルを 書いたのに、あの 1 行を忘れます:
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
Target.Value = IIf(Target.Value = "x", "", "x") ' 切り替える…そのあと Excel がセルを編集する
End Sub
印は切り替わります — そしてそのあとセルが編集モードに落ち、カーソルが点滅します。
Cancel を何も設定していないからです。ユーザーはタスクを完了にしようとダブルクリック
したのに、結局は編集状態のセルを抱え、そこから抜けるのに Escape を押すはめになります。
あなたのアクションは走りましたが、Excel の既定もそのすぐ上に重ねて走ったのです。
ルールはこうです:ハンドラーがダブルクリックの意味を置き換えるなら、Cancel = True
を設定する — 既定があなたの足元で発火しないように。
Cancel = True ' まず編集モードを抑制する
Target.Value = IIf(Target.Value = "x", "", "x")
このたった 1 つのフラグが、「なめらかなワンクリックのトグル」と「おまけに鬱陶しくも セルを編集用に開いてしまうトグル」との分かれ目です。ダブルクリックが本物の編集では なくあなたのコマンドであるときには、いつでもこれを設定しましょう。
シートを使えるまま保つルール:Intersect でスコープを絞る
スコープを絞らないハンドラーは、ハンドラーがないよりも悪いものです。あなたのコードが
あらゆるダブルクリックで走って Cancel = True を設定すれば、あなたはシート全体で
ダブルクリック編集を無効にしてしまったことになります — ユーザーは二度と、どのセルも
ダブルクリックして編集できません。誰も頼んでいない、意地の悪い副作用です。
直し方は、クリックされるべき範囲の内側でだけ動き、それ以外のどこでも抜けることです:
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
' ガード:クリックが "Done" 列(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")) は、ダブルクリックされたセルがあなたの対象
範囲の外にあるとき Nothing を返すので、Exit Sub がシートの残りを通常どおりに
振る舞わせます — ほかのどこをダブルクリックしても、いつもどおり編集されます。これは、
Worksheet_Change ハンドラーがあらゆる編集で発火しない
ようにするのと同じ Intersect のガードであり、狙いを定めたアフォーダンスと、シート
全体の乗っ取りとを分けるものです。
あとで牙をむく罠:あなたの書き込みが別のイベントを発火させる
ハンドラーがセルに書き込んだ瞬間に — そして印の切り替えはまさにそれをします —
Worksheet_Change が引き起こされます。セルの値を変えたからです。たいていは無害です。
けれど同じシートに、やはり書き込みをする Worksheet_Change ハンドラー(タイム
スタンプ、ログ、再計算した合計)があれば、両者は連鎖しかねず、最悪の場合、その
書き込みがあなた自身のロジックに再突入します。ガードは、このイベント一族の黄金律
です:書き込みを包んで、仕掛けを引き起こせないようにするのです。
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 ' 自分の書き込みが Worksheet_Change を発火させないように
Target.Value = IIf(Target.Value = "x", "", "x")
Application.EnableEvents = True
End Sub
ハンドラーがささいな書き込み以上のことをするなら、EnableEvents = True をエラー
ハンドラーの中にも置きましょう。そうすれば、途中でのクラッシュが、セッション全体に
わたってイベントをオフのまま残すことはありません — Worksheet_Change
で述べたのと同じ規律です。
コードの置き場所を決める区別:シート対ブック
Worksheet_BeforeDoubleClick はシートごとのイベントです — 1 枚のワークシートの
モジュールに置かれ、そのシート上のダブルクリックに対してだけ発火します。すべての
シートで同じ振る舞いがほしいなら、ハンドラーを 12 枚のシートモジュールに貼り付けるのは
やめましょう。ブックレベルの双子、Workbook_SheetBeforeDoubleClick を使います。これは
ThisWorkbook に置かれ、余分な第一引数 Sh を手渡して、どのシートがクリックされたかを
教えてくれます:
' ThisWorkbook に置く — どのシートでのダブルクリックでも発火する。
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
これは、Worksheet_Activate 対 Workbook_SheetActivate
でするのと同じ、シート対ブックの選択です:1 枚のシート → そのシートのモジュール、
どのシートでも → Sh 引数を持つブックモジュール。
ExcelMaster の活用
よくできたダブルクリックのハンドラーは、微妙に間違えやすい 3 つの小さな判断です:
シートの残りを編集可能に保つ Intersect のガード、セルが編集モードに入るのを止める
Cancel = True、そしてどんな書き込みも囲む EnableEvents の門。ひとつでも欠ければ、
この機能は、診断しづらいかたちで壊れて感じられます。
ExcelMaster
なら、代わりに振る舞いを述べられます。「列 B のセルをダブルクリックしたら、チェック
マークを切り替えて、セルを編集用に開かないで」と言えば、正しいシートモジュールに
Worksheet_BeforeDoubleClick を書き、Intersect でスコープを絞り、Cancel を設定し、
書き込みをガードします。ブックもコードもあなたのもの。どの行が何をするかを学ぶ試行
錯誤だけを飛ばせるのです。
よくある質問
Excel でセルがダブルクリックされたときにマクロを走らせるには?
そのシートのコードモジュールに Worksheet_BeforeDoubleClick プロシージャを置きます:
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)。
そのシート上のセルがダブルクリックされるたびに Excel がこれを呼び、Target(そのセル)
を渡します。アクションはそこに足します。すべてのシートを対象にするなら、ThisWorkbook
の Workbook_SheetBeforeDoubleClick を使います。
ダブルクリックでセルが編集モードに入るのを止めるには?
ハンドラーの中で Cancel = True を設定します。Excel はあなたのコードが走ったあとに
Cancel を調べます。True なら既定の反応(編集モードに入ること)を抑制するので、
あなたのアクションだけが起こります。これがないと、セルは切り替わり、かつ編集用に
開きます。
ダブルクリックを 1 つの列だけで効かせるには?
Intersect でガードします:ハンドラーの先頭に
If Intersect(Target, Me.Columns("B")) Is Nothing Then Exit Sub。Intersect は、
ダブルクリックされたセルがあなたの範囲の外にあるとき Nothing を返すので、シートの
残りは、ダブルクリックで通常どおり編集を続けます。
ダブルクリックが自分のコードでなくセルを編集モードにするのはなぜですか?
コードがシート自身のモジュールに入っていないか、マクロが無効になっているか、あるいは
ハンドラーは走るのに Cancel = True を一度も設定していないか、のいずれかです — だから、
あなたのコードのあとに Excel の既定(編集モード)が発火します。プロシージャが正しい
ワークシートモジュールにあることを確かめ、Cancel = True を足しましょう。
BeforeDoubleClick と BeforeRightClick の違いは何ですか?
Worksheet_BeforeDoubleClick はダブルクリックを横取りします(既定の反応は編集モードに
入ること)。Worksheet_BeforeRightClick は
右クリックを横取りします(既定の反応はコンテキストメニューを出すこと)。どちらも
Target と、True にして既定を抑制する Cancel フラグを手渡します。
検証環境
検証環境: Excel 365 (Windows 11), VBA 7.1 — 最終確認 2026-08-06。
関連ガイド: VBA Worksheet_BeforeRightClick · VBA Workbook_BeforePrint · VBA Worksheet_Change · VBA Worksheet_Activate & Deactivate · VBA Range
