【初心者でもOK!】マクロで右クリックメニューを追加するVBAコード

VBAに全く触れたことのない人、マクロとは何ぞ?な人向けの記事です。最後まで読めばとりあえずマクロとVBAの雰囲気は掴めます。操作方法含めて紹介するのでまずは触れてみて下さい。もちろん、右クリックメニューを追加するマクロの実装もできます。

本記事はVBAに触れたことが無い人向けの記事になっています。右クリックメニューの追加ができるVBAコードだけが欲しい人は下の記事がおすすめです。

目次

覚える用語は3つだけ

マクロ

エクセルの操作を自動化する機能です。

VBA

Visual Basic for Applicationsの略で、マクロに使われるプログラム言語です。

VBE

Visual Basic Edtorの略で、VBAコードを記述するソフトです。

マクロを作成するには、VBEVBAコードを記述します。

今すぐ覚えなくてもOKです。この記事を読み終えた頃には覚えている筈です。

準備

事前準備としてマクロの実行ができるように開発タブを表示して下さい。

ファイルオプションリボンのユーザー設定開発のチェックボックスをオンにします。(クリックで拡大)

開発タブでVisual BasicアイコンをクリックするとVBE(VisualBasicEditor)が表示されます

ショートカットはAlt+F11です。今後マクロに本気で取り組むのであれば、覚えておいた方が吉です。

表示されたソフトがVisualBasicEditorです。ここにコードを記述してマクロを作成します。

右クリックメニューが追加されたサンプルを動かしてみる

サンプルを入手する

まずはWeb上で適当なサンプルを入手しましょう。適切なワードでググれば、ほとんどの場合目的のサンプルが見つかります。今回は「VBA 右クリックメニュー 追加」で検索します。

検索上位を読むとどうやら、CommandBarsプロパティを使用してCommandBarオブジェクトを参照する事でメニューを追加できるようです。

うん、意味はよく分かりません。ただ参考になりそうなコードがあるのでコピペでいただきましょう。

VBEメニューの挿入から標準モジュールをクリック

挿入されたModule1をダブルクリックし、右側のコードウィンドウへコピペする。

標準モジュールって何?と思うかも知れませんが、とりあえず無視しましょう(乱暴)。今の時点では「ここに書いたコードが実行される」位の理解でOKです。

Module1(標準モジュール)

Sub Sample1() 'マクロ名
    With CommandBars("Cell").Controls.Add(Type:=msoControlButton) '右クリックメニューを追加
        .Caption = "Button" '追加するメニューの名前
        .OnAction = "myMacro" 'メニューを押した時に実行されるマクロ名
    End With
End Sub

Sub myMacro() 'マクロ名
    MsgBox "Hello" 'メッセージボックスに「Hello」と表示される
End Sub

Sub Sample2() 'マクロ名
    CommandBars("Cell").Controls("Button").Delete '追加したメニューを削除する
End Sub

「 ‘ 」の後に続く文字はマクロ実行時には無視されます。コメントとして利用するのが一般的なようです。説明用にコメントを入れていますが、不要なら削除して下さい。

1~6行目、8~10行目、12~14行目がそれぞれSubEnd Subのコードで括(くく)られています。この括りをプロシージャといいます。VBAには単位があり、構成は次の通りです。

  1. 1行ごと…ステートメント
  2. SubEnd Subで括られたステートメントの集まり…プロシージャ
  3. プロシージャの集まり…モジュール
  4. モジュールの集まり…プロジェクト

サンプルで構成を確認してみます。

Module1(標準モジュール)

'///////モジュール///////
'*******プロシージャ始まり*******
Sub Sample1()    'ステートメント
    With CommandBars("Cell").Controls.Add(Type:=msoControlButton)    'ステートメント
        .Caption = "Button"    'ステートメント
        .OnAction = "myMacro"    'ステートメント
    End With    'ステートメント
End Sub    'ステートメント
'*******プロシージャ終わり*******

'*******プロシージャ始まり*******
Sub myMacro()    'ステートメント
    MsgBox "Hello"    'ステートメント
End Sub    'ステートメント
'*******プロシージャ終わり*******

'*******プロシージャ始まり*******
Sub Sample2()    'ステートメント
    CommandBars("Cell").Controls("Button").Delete    'ステートメント
End Sub    'ステートメント
'*******プロシージャ終わり*******

用語を今覚える必要はありません。SubEnd Subが一括りである事が理解できればOKです

VBEの画面を閉じ(右上の×を押せば閉じます)、早速コピペしたコードを実行してみましょう。

VBEに記述したコードは、エクセルのファイルと一緒に保存されるのでここで保存しなくても消える事はありません。が、マクロ作成中は不測の事態が起きやすいのでまめに保存しておいた方がいいかも知れません。気になる人はVBE画面にも保存アイコンがあるのでそこを押して保存して下さい。

サンプルを実行して動きを確認する

開発タブのマクロアイコンを押し、Sample1を選択、実行する。

ショートカットはAlt+F8です。今後マクロに本気で取り組むのであれば、覚えておいた方が吉です。

右クリックすると、最下段にButtonメニューが追加されています。

Buttonを押すと、メッセージボックスが表示される。

これで右クリックメニューが追加されました。しかしこの追加メニュー、やっかいな事に削除してやらないとずっと残ったままです(このファイルを閉じても他のファイルにも反映されます)。

削除しないでSample1を実行するとさらに同じものが追加されます。現段階ではSample1を実行したら、Sample2を実行して削除するようにしてください。もちろん、最終的には自動で削除するようにします。

右クリックメニュー追加のサンプルコードを改造する

次に、実際にやりたい事を挙げてみます。今回はこんな仕様にしてみました。

  1. 追加したメニューを一番上に表示したい
  2. メニューを2段階のリストにしたい
  3. 右クリックメニューを表示するのは特定のシートのみにしたい

あとは検索ワードをひねり出して、ひたすらググるのみです。

メニューの表示位置とサブメニューの追加

「VBA 右クリックメニュー 追加 一番上」で検索してみました。この記事にやりたい事リスト1番目と2番目の答えがありました。

コードを参考にして先ほどのコードを改造します。プロシージャ名(マクロ名)とメニュー名も読みやすいように日本語に変えました。

Module1(標準モジュール)

Sub 右クリックメニュー追加() 
'Before:= で表示位置(行)、Type:= でコントロールの種類を設定
    With CommandBars("Cell").Controls.Add(Before:=1, Type:=msoControlPopup)
        .Caption = "無限列車編"
            With .Controls.Add 'サブメニューを追加
                 .Caption = "セリフ1" 'サブメニュー(1段目)の名前
                 .OnAction = "台詞1"
            End With
            With .Controls.Add
                 .Caption = "セリフ2" 'サブメニュー(2段目)の名前
                 .OnAction = "台詞2"
            End With
    End With
End Sub

Sub 台詞1()
    MsgBox "柱として不甲斐なし"
End Sub

Sub 台詞2()
    MsgBox "穴があったら入りたい"
End Sub

Sub メニュー削除()
    CommandBars("Cell").Controls("無限列車編").Delete
End Sub

右クリックメニュー追加を実行すると1番上にサブメニューが追加されました。

Before:=1数字の部分で表示位置(上から何行目か)を決めているようです(0にするとエラーになりました)。Type:=msoControlPopupで目的の2段階リスト(サブメニュー)にできました。

WithEnd Withのくだりは「動けばいい」の精神で潔く無視しましょう(次の記事で詳しく説明します)。

特定のシートでのみ、右クリックメニューを表示する

「特定のシート 右クリックメニュー」で検索しました。

検索上位を読むと、「ワークシートがアクティブになった(選択された)時」にマクロを実行する方法と「特定のワークシートで右クリックした時」にマクロを実行する方法があるようです。

今回は「特定のワークシートで右クリックした時」に実行するようにします。

Worksheetのイベントプロシージャを記述します。準備としてシートを一つ追加して下さい(Sheet2を用意する)。

また、上の記事内のWorksheet_BeforeRightClickイベント1項から4項の手順を実施してSheet1Worksheet_BeforeRightClickイベントプロシージャを作成して下さい。ここに記述したコードは「ワークシートを右クリックした時」に実行されます。

準備ができたら右クリックメニュー追加WithEnd Withまで切り取って、準備したWorksheet_BeforeRightClickプロシージャ内に貼り付けます。切り取った後、残ったSub Sample1()End Subは削除して下さい。

Sheet1(Sheetモジュール)

Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean)'右クリック(の直前)でイベント開始
'右クリックメニュー追加をここに貼り付け
    With CommandBars("Cell").Controls.Add(Before:=1, Type:=msoControlPopup)
        .Caption = "無限列車編"
            With .Controls.Add 'サブメニューを追加
                 .Caption = "セリフ1" 'サブメニュー(1段目)の名前
                 .OnAction = "台詞1"
            End With
            With .Controls.Add
                 .Caption = "セリフ2" 'サブメニュー(2段目)の名前
                 .OnAction = "台詞2"
            End With
    End With
End Sub

Module1(標準モジュール)

Sub 台詞1()
    MsgBox "柱として不甲斐なし"
End Sub

Sub 台詞2()
    MsgBox "穴があったら入りたい"
End Sub

Sub メニュー削除()
    CommandBars("Cell").Controls("無限列車編").Delete
End Sub

エクセル画面に戻って右クリックしてみましょう。

右クリックでイベントが発生し、無事メニューが追加される、のですが…

この状態だとSheet1を右クリックするたびにメニューが増えていきます。「特定のシートで右クリック」をする度に発生する訳ですね。

とりあえず増えたメニューをメニュー削除実行で消します(マクロアイコンから実行して下さい)。全て消し終わったらメニュー削除右クリックメニュー追加同様に切り取って貼り付けます。貼り付け場所はWith~の前です。

メニューを追加する前に削除する事で差し引きゼロにする訳です。

Sheet1(Sheetモジュール)

Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean)
    CommandBars("Cell").Controls("Button").Delete '[メニュー削除]をここに貼り付け
    With CommandBars("Cell").Controls.Add(Before:=1, Type:=msoControlPopup)
        .Caption = "無限列車編"
        With .Controls.Add
            .Caption = "セリフ1"
            .OnAction = "台詞1"
        End With
        With .Controls.Add
            .Caption = "セリフ2"
            .OnAction = "台詞2"
        End With
    End With
End Sub

Module1(標準モジュール)

Sub 台詞1()
    MsgBox "柱として不甲斐なし"
End Sub

Sub 台詞2()
    MsgBox "穴があったら入りたい"
End Sub

右クリックすると、エラーが出ました

すると今度はエラーになります。どうも追加メニューがない状態でメニューを削除しようとするとエラーになるようです。

エラーダイアログでデバッグを選択するとVBE画面に戻り、エラー箇所が黄色でハイライトされます。[終了]を押すと実行中のマクロを終了し、エクセル画面に留まります。

先ほどの記事内でメニューを削除するコードとしてApplication.CommandBars(“Cell”).Resetが書かれていました。これを試してみましょう。

CommandBars(“Cell”).Controls(“Button”).DeleteApplication.CommandBars(“Cell”).Resetを置き換えてみます。

Sheet1(Sheetモジュール)

Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean)
    Application.CommandBars("Cell").Reset '追加したメニューをリセットする
    With CommandBars("Cell").Controls.Add(Before:=1, Type:=msoControlPopup)
        .Caption = "無限列車編"
        With .Controls.Add
            .Caption = "セリフ1"
            .OnAction = "台詞1"
        End With
        With .Controls.Add
            .Caption = "セリフ2"
            .OnAction = "台詞2"
        End With
    End With
End Sub

エラーになりませんでした。

これでいいじゃんと思ったものの、違いが気になるので「Commandbars Reset Delete 違い」でググりました。

自分で追加したメニューを削除するときにはDelete、全ての追加メニュー(他人が追加したものも含む)を初期化するときにはResetを使うようです。

Resetでエラー吐かないならそれでいいかと思った矢先、他サイトにお叱りの言葉が書かれていました。以下引用です。

自分が追加したメニューやコマンドを削除するとき、メニューを初期化するためのResetメソッドは、できるだけ使わないようにしてください。Resetメソッドを実行すると、他のマクロやアドインが追加したメニューやコマンドもすべて削除されてしまうからです。メニューは、あなただけのものではありません。他のマクロやアドインなどがメニューを操作する可能性も十分に考慮して、メニューの追加や削除は慎重に行うようにしてください。

https://www.moug.net/tech/exvba/0080026.html

海より深く反省しました。という事で元々使用していたCommandBars(“Cell”).Controls(“Button”).Deleteでどうにかする事にします。

Deleteが使えなかったのはそもそもエラーのせいです。「VBA エラー」で検索してみます。

エラーが発生した際、処理をスキップする方法がありました。On Error Resume Nextと書けば、ある処理がエラーになってもその次の処理へスキップしてくれるようです。

Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean)
'エラーが出たら次の処理へスキップ
    On Error Resume Next
'ここがエラーになったら
    CommandBars("Cell").Controls("無限列車編").Delete
'ここまでスキップしてくれる
    With CommandBars("Cell").Controls.Add(Before:=1, Type:=msoControlPopup)
        .Caption = "無限列車編"
        With .Controls.Add
            .Caption = "セリフ1"
            .OnAction = "台詞1"
        End With
        With .Controls.Add
            .Caption = "セリフ2"
            .OnAction = "台詞2"
        End With
    End With
End Sub

無事動いたので、エラーはちゃんとスキップされたようです。が、Sheet2でもメニューが表示されます。

(クリックで拡大)

無事動きました。が、Sheet2でも追加メニューは表示されたままです。

CommandBars(“Cell”).Controls(“Button”).Deleteが実行されるのはSheet1で右クリックされた時のみです。Sheet1Worksheetイベントに書いてあるので当たり前ですね。

Sheet2でメニューを無効にするためにどのイベントを利用すればいいか考えました。Worksheet_BeforeRightClickイベントプロシージャを作成する際にちらっと見えたWorksheet_Deactivateが使えそうです。

Deactivateはおそらく「アクティブではなくなった時」って意味っぽいじゃないですか。早速プロシージャを作成してみましょう。

Worksheet_BeforeRightClickイベントプロシージャを作成した時と同じ方法です。イベントでDeactivateを選択して下さい。

Private Sub Worksheet_Deactivate() 'ワークシートがアクティブでなくなった時にイベント発生
    On Error Resume Next
    CommandBars("Cell").Controls("無限列車編").Delete
End Sub

Sheet2で右クリックをしても追加メニューは現れません。

シートについての処理はこれで完了です。あと一息で完成です。

ブックの処理

色々テストを重ねた結果、

  1. 他のファイルがアクティブになった時
  2. ファイルを閉じた時

にメニュー削除の処理をしないとメニューが残ったままになります。シート同様、ファイルについての処理が必要という事ですね。「VBA ファイルを閉じたとき」で検索します。

エクセルでしか操作できないファイルの事をブックと呼ぶそうです(*.xlsx,*.xlsm等の形式で保存されたファイル)。乱暴ですが、今回の記事内ではファイル=ブックと捉えて問題ありません。

エクセルで新規ファイルを作成、保存し、拡張子を.xlsxから.zipに変更すれば、ブックの正体が判ります。

Workbook_BeforeCloseAuto_Closeの2通りの方法があるようです。それぞれ微妙に違うようですが、アドバイスがありました。

Auto_Closeは以前のバージョンとの互換性を保持するために残されているものですので、特段の理由がなければ、Workbook_BeforeCloseのみを使用した方が良いでしょう。

https://excel-ubara.com/excelvba4/EXCEL240.html

はい、特段の理由はないのでWorkbook_BeforeCloseを使用します。Microsoft Excel Objects内のThisWorkbookに記述しろと書いてあるので、

VBE画面のプロジェクトウィンドウ内のThisWorkbookをダブルクックします。

オブジェクトWorkbookを選択します。この時勝手にイベントが選択され、プロシージャが生成されますが無視して下さい。

右側のプロシージャからBeforeCloseを選択します。先ほど勝手に生成されたプロシージャは削除します。

Workbook_BeforeCloseイベントプロシージャを作成する際、ちらっとDeactivateの文字が見えたので「他のファイルがアクティブになったとき」の処理もまとめて書きました。

Private Sub Workbook_BeforeClose(Cancel As Boolean) 'ブックが閉じる時にイベントが発生
    On Error Resume Next
    Application.CommandBars("Cell").Controls("無限列車編").Delete
End Sub

Private Sub Workbook_Deactivate() 'ブックがアクティブでなくなった時にイベント発生
    On Error Resume Next
    Application.CommandBars("Cell").Controls("無限列車編").Delete
End Sub

いきなりApplication.CommandBars(“Cell”).Controls(“Button”).Deleteになっていますね。Application.を追加しています。以下、理由です。

標準モジュールではアクティブブックがデフォルトのブックになり、ThisWorkbookのモジュールではそのブックがデフォルトのブックになります。ThisWorkbookモジュールでは…

CommandBars(“Cell”).ShowPopup…×誤り。ThisWorkbook.CommandBarsの意味になる

Application.CommandBars(“Cell”).ShowPopup…○正しい。セルのショートカットメニューを表示する

https://vbae.odyssey-com.co.jp/column4/s41502.html

何と、コードを書く場所によって参照するオブジェクトが変わるとのこと。要は今まで省略しててもたまたま問題なかったって事ですね。これは難しいので理解は後回しです。

ググって拾ってきたサンプルを適当に使いまわすとこういう目に合います。が、助けてくれるのも「ググる」なのです。

これで無事完成です。適当に複数のファイルを開いた状態で、右クリックをしてみて下さい。狙った通りの動きになっているはずです。

完成

以下、今回の出来高です。

Sheet1(Sheetモジュール)

'右クリックでメニュー追加
Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean)
    On Error Resume Next
    CommandBars("Cell").Controls("無限列車編").Delete
    With CommandBars("Cell").Controls.Add(Before:=1, Type:=msoControlPopup)
        .Caption = "無限列車編"
        With .Controls.Add
            .Caption = "セリフ1"
            .OnAction = "台詞1"
        End With
        With .Controls.Add
            .Caption = "セリフ2"
            .OnAction = "台詞2"
        End With
    End With
End Sub

'シートがアクティブでなくなった時、メニューを削除する
Private Sub Worksheet_Deactivate()
    On Error Resume Next
    CommandBars("Cell").Controls("無限列車編").Delete
End Sub

ThisWorkBook(Bookモジュール)

'ブックが閉じた時、メニューを削除する
Private Sub Workbook_BeforeClose(Cancel As Boolean)
    On Error Resume Next
    Application.CommandBars("Cell").Controls("無限列車編").Delete
End Sub

'ブックがアクティブでなくなった時、メニューを削除する
Private Sub Workbook_Deactivate()
    On Error Resume Next
    Application.CommandBars("Cell").Controls("無限列車編").Delete
End Sub

Module1(標準モジュール)

Sub 台詞1()
    MsgBox "柱として不甲斐なし"
End Sub

Sub 台詞2()
    MsgBox "穴があったら入りたい"
End Sub

ブックモジュールシートモジュールはイベントが用意されているので、それをトリガーとしてマクロが実行できました。

標準モジュール内に書いたSubプロシージャは2通りの実行方法がありました。一つはマクロボタンを使って手動で実行する方法、もう一つはブックやシートのイベントプロシージャから呼び出して実行する方法です。

これで右クリックメニューの完成です。機能としてはまだメッセージボックスが表示されるだけですが、右クリックメニューのひな型として今後も使えそうです。サブメニューを増やすのもコピペで簡単にできそうです。

おさらい

POINT
覚える用語
マクロ

エクセルの操作を自動化する機能です。

VBA

Visual Basic for Applicationsの略で、マクロに使われるプログラム言語です。

VBE

Visual Basic Edtorの略で、VBAコードを記述するソフトです。

POINT
マクロの作成方法

マクロの作成方法はVBEVBAコードを記述します。

POINT
プログラムの括り

プログラムはSubEnd Subで括られ、それが一つの実行単位になります(プロシージャ)。

いかがだったでしょうか?とりあえずググってコピペしただけですが一つのマクロが完成しました。このマクロ、実際に私が初めて作成したマクロとほぼ同じものです。作り方もおおよそこの記事の通りです(かかった時間は言わずもがなですが…)。

初めてVBAに触れた人は、何となく雰囲気を掴めればOKです。今回の成果は「マクロが作成できた事」です。

VBA入門」でググると、オブジェクトプロパティメソッド変数といった用語がたくさん出てきます。基礎知識からスタートするのは至極当然のアプローチだと思いますが、このサイトは別のアプローチで初心者のお手伝いができればと考えています。

次回は、書式設定を変更するマクロでWithステートメントを詳しく紹介します。

よかったらブックマークとシェアをお願いします。最後までご高覧いただきありがとうございました。

よかったらシェアしてください
URLをコピーする
URLをコピーしました!
目次へ
トップへ
目次
閉じる