TL;DR —
Worksheet_BeforeRightClickは、セルを右クリックした瞬間に — コンテキストメニューが現れる前に — Excel が発火させるイベントです。手渡される のはTarget(そのセル)とCancelです。Cancel = Trueにすると、Excel の 組み込みの右クリックメニューが抑制されるので、その場所にあなたのメニュー — あるいは直接のアクション — を置けます。ほぼ誰もがはまる罠はスコープです:無条件のCancel = Trueはシート全体で Copy・Paste・Insert を無効にしてしまうので、Intersectでガードします。そして最初に知っておいてください — 右クリックの無効化は UX の選択で あって、セキュリティの選択ではありません。
' シートのモジュールに置く(「Microsoft Excel Objects」の下で "Sheet1" をダブルクリック)。
Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean)
' Status 列の内側の右クリックだけを横取りする。シートの残りはそのままにしておく。
If Intersect(Target, Me.Range("C2:C100")) Is Nothing Then Exit Sub
Cancel = True ' <-- 組み込みのコンテキストメニューを抑制する
Target.Value = Date ' 代わりに右クリックで今日の日付を刻む
End Sub
ほとんどのマクロはボタンを待ちます。Worksheet_BeforeRightClick が待つのは仕草 —
セルへの右クリック — で、そして右クリックがふだん引き起こすこと、つまりコンテキスト
メニューを出すことを Excel がする前に走ります。その「前」こそが、あなたに必要な
糸口です。既定のメニューを抑制して自分のものに差し替えることも、右クリックをひと仕草の
コマンドに変えることも、Excel がすでに用意しているものに独自の項目をいくつか足すことも
できます。これはまた、シートを「ロックダウン」しようと人々が手を伸ばすイベントでも
あります — そして、いちばん大事な教訓はそこにあります。
この記事で学べること
- 考え方の軸 — 右クリックはメニューの要求であり、あなたがそれに答える
- いちばん大事なルール — 組み込みメニューを実際に抑制するのは
Cancel = True Intersectでのスコープ絞りが任意ではない理由 — 絞らない版はシートを不自由にする- 判断のしどころ — 右クリックの無効化は UX であって、決して保護ではない
- シートレベル対ブックレベル、そしてコードを置かねばならない場所
考え方の軸:あなたが答えることになる、メニューの要求
右クリックは、Excel にとってすでに何かを意味しています:「このセルのコンテキスト
メニューを見せて」。Worksheet_BeforeRightClick を書くと、Excel はまずあなたのコードを
呼んで待ちます — メニューはまだ現れていません。手に入るのは Target、右クリックされた
セルと、参照渡しされる Boolean の Cancel です。Cancel に触れずに放っておけば、
あなたのコードが走ったあと Excel は通常のメニューを出します。Cancel = True に
すればそうはならず — あなたが自分で要求に答えたのであり、いまや右クリックは、ハンドラー
がそう意味づけたとおりのものになります。
これがイベントを捉え直させます。「右クリックしたら教えて」ではありません。「ここで
右クリックが差し出すものを、私に決めさせて」なのです。アクションを直接走らせることも
(日付を刻む、行に印を付ける、明細フォームを開く)、CommandBars で組んだ自分の
メニューを出すこともできます。いずれにせよ、組み込みメニューが消えるのは、あなたが
Cancel = True でそう告げたときだけです。そしてこの一族のあらゆるイベントと同じく、
これもワークシート自身のコードモジュールに置かれます — 標準の Module でも、
ThisWorkbook でもありません。
いちばん大事なルール:Cancel = True が組み込みメニューを抑制する
これが間違いです。右クリックに自分のコマンドを走らせたいので、アクションを書いて、 そこで止めます:
Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean)
Target.Value = Date ' 日付を刻む…それでも Excel のメニューはやはり出てくる
End Sub
日付は収まります — そしてそのあと、結局フルのコンテキストメニューが現れます。
Cancel を何も設定していないからです。ユーザーはいま、あなたのアクションと、その上に
重なった Excel の Cut/Copy/Paste メニューの両方を抱えています。ルールはこうです:
メニューを置き換える行は Cancel = True です。 ハンドラーが右クリックの応答その
ものであるべきときには、いつでもこれを設定しましょう:
Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean)
Cancel = True ' 組み込みメニューは決して出ない
Target.Value = Date ' あなたのコマンドがやり取りのすべて
End Sub
もし置き換えるのではなく項目を足したいなら、Cancel には触れずに、
Application.CommandBars("Cell") にあなたのコントロールを足します — Excel は、あなたの
追加項目を載せたメニューを出します。置き換えるときは(Cancel = True で)抑制し、
足すときは Cell の CommandBar を拡張します。
シートを使えるまま保つルール:Intersect でスコープを絞る
このイベントは、スコープを絞らないハンドラーを、ほかのどれよりも厳しく罰します。あなた
のコードがあらゆる右クリックで走って Cancel = True を設定すれば、あなたはシート
全体から右クリックメニューを丸ごと取り除いてしまったのです — Copy も Paste も Insert も
Filter も Format Cells も、どこにもありません。あなたはシートをカスタマイズしたのでは
なく、壊したのです。
独自の振る舞いを持つべきセルにスコープを絞り、ほかのすべてのセルには通常のメニューを 保たせましょう:
Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean)
' 独自の振る舞いは Status 列だけ。ほかのどこでも通常のメニュー。
If Intersect(Target, Me.Range("C2:C100")) Is Nothing Then Exit Sub
Cancel = True
Target.Value = Date
End Sub
Intersect(Target, Me.Range("C2:C100")) は、対象範囲の外では Nothing を返すので、
Exit Sub が制御を Excel に返し、組み込みメニューはいつもどおり現れます。これは、
Worksheet_Change ハンドラーの狙いを絞り込むのと同じ
Intersect のガードです — ここではそれが、役に立つシートと、使いものにならないシート
との分かれ目になります。
判断のしどころ:右クリックの無効化は UX であって、セキュリティではない
人々はこのイベントを、「シートを守るために右クリックを無効にするには」と検索して
見つけます。だからはっきり言いましょう:Cancel = True の右クリックブロックは、何も
守りません。 それが止めるのは入力経路をひとつ — マウスメニュー — だけです。ほかの
すべては依然として効きます:Ctrl+C と Ctrl+V、リボン、名前ボックス、別のマクロ、
そして — 議論に決着をつけるもの — マクロを無効にしてファイルを開くこと。これはあなたの
イベントを丸ごとオフにします。腹を決めたユーザーや悪意ある者があなたの脅威モデルなら、
BeforeRightClick はそれに手が届きません。
このイベントが本当に得意なのは、やり取りを形づくることです:データ入力エリアで 無関係なメニューを隠す、タスクに実際に合う 2 つのコマンドに差し替える、あるいは仕草で 値を刻む。正しいことをしやすくするために使い、間違ったことを不可能にするために使っては いけません。本物の保護が必要なら、それはシートの保護、ブック構造の保護であり、 クライアント側のイベントを信用しないことです — まったく別の道具です。
コードの置き場所を決める区別:シート対ブック
Worksheet_BeforeRightClick はシートごとのイベントです — 1 枚のワークシートの
モジュールに置かれ、そのシートでだけ発火します。同じ振る舞いをどこにでも適用するには、
ThisWorkbook にブックレベルの双子 Workbook_SheetBeforeRightClick を使います。これは、
関わっているシートのための第一引数 Sh を足します:
' ThisWorkbook に置く — どのシートでの右クリックでも発火する。
Private Sub Workbook_SheetBeforeRightClick(ByVal Sh As Object, ByVal Target As Range, Cancel As Boolean)
If Sh.Name <> "Log" Then Exit Sub
If Intersect(Target, Sh.Range("C2:C100")) Is Nothing Then Exit Sub
Cancel = True
Target.Value = Date
End Sub
Worksheet_Activate 対 Workbook_SheetActivate でするのと
同じ選択です:1 枚のシート → そのシートのモジュール、どのシートでも → Sh 引数を持つ
ブックモジュール。そしてこれは、仕草の兄弟である
Worksheet_BeforeDoubleClick と自然に組みます。
あちらは、同じ Target プラス Cancel のかたちでダブルクリックを横取りします。
ExcelMaster の活用
右クリックのハンドラーは、間違えやすい 3 つの判断です:対象範囲の外で Copy と Paste を
生かしておく Intersect のガード、メニューを実際に抑制する Cancel = True、そして、
ブロックが何を守り何を守らないかについての正直な判断。
ExcelMaster
なら、代わりに振る舞いを述べられます。「Status 列のセルを右クリックしたら、今日の日付を
刻んで、通常のメニューは出さないで。でもシートの残りはそのままにして」と言えば、正しい
モジュールに Worksheet_BeforeRightClick を書き、Intersect でスコープを絞り、Cancel
を設定します。ブックもコードもあなたのもの。試行錯誤を飛ばせて — そして、それが何を
守るかを、売り込まれるのではなく、正直に伝えられます。
よくある質問
Excel で右クリック時にマクロを走らせるには?
そのシートのコードモジュールに Worksheet_BeforeRightClick プロシージャを置きます:
Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean)。その
シート上のセルが右クリックされたときに Excel がこれを呼び、Target を渡します。
アクションを足し、組み込みメニューを置き換えたいなら Cancel = True を設定します。
VBA で右クリックメニューを無効にするには?
Worksheet_BeforeRightClick の中で Cancel = True を設定します。それがコンテキスト
メニューを抑制します。シート全体で本当に消したいのでないかぎり、Intersect でスコープを
絞りましょう — 無条件のブロックは、どこでも Copy・Paste・Insert を取り除きます。これは
マウスメニューをブロックするだけであり、セキュリティの制御ではないことに注意してください。
右クリックの無効化はデータを守りますか?
いいえ。入力経路をひとつ取り除くだけです。Ctrl+C/Ctrl+V、リボン、別のマクロ、そして
マクロを無効にしてファイルを開くこと — すべてがこれを迂回します。BeforeRightClick は
やり取りを整えるために使い、本物の保護にはシート/ブックの保護を使いましょう。
メニューを置き換えるのではなく、右クリックメニューに独自の項目を足すには?
Cancel は設定せずに、Application.CommandBars("Cell") にコントロールを足します — Excel
は、あなたの追加項目を載せた通常のメニューを出します。Cancel = True を設定するのは、
拡張するのではなくメニューを置き換えたいときだけにしましょう。
Worksheet_BeforeRightClick のコードはどこに書きますか?
特定のワークシートのコードモジュールの中です — プロジェクトエクスプローラーの
「Microsoft Excel Objects」の下でそのシートをダブルクリックします。どのシートでの
右クリックにも効かせるには、代わりに ThisWorkbook の Workbook_SheetBeforeRightClick
を使います。標準の Module からは発火せず、マクロが有効である必要があります。
検証環境
検証環境: Excel 365 (Windows 11), VBA 7.1 — 最終確認 2026-08-06。
関連ガイド: VBA Worksheet_BeforeDoubleClick · VBA Workbook_BeforePrint · VBA Worksheet_Change · VBA Worksheet_Activate & Deactivate · VBA Range
