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

アイキャッチ

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

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

目次

覚える用語は3つだけ

マクロ

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

VBA

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

VBE

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

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

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

準備

STEP
開発タブの表示
開発タブの表示を設定するダイアログ画像。詳細は以下。

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

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

STEP
VBEの起動
Visual Basicの起動方法を説明する画像。詳細は以下。

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

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

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

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

サンプルを入手する

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

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

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

STEP
標準モジュールの挿入
標準モジュールを挿入する画像。詳細は以下。

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

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

STEP
コードをコピペする
標準モジュールへコードをコピペする画像。詳細は以下。

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

STEP
コードにコメントを付与する
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

の後に続く文字はマクロ実行時には無視されます。コメントとして利用するのが一般的です。説明、備忘と用途は多岐に渡ります。不要なら付与する必要はありません。

STEP
VBAの構成単位

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

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

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

'///////モジュール///////
'*******プロシージャ始まり*******
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画面にも保存アイコンがあるのでそこを押して保存して下さい。

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

STEP
マクロの実行
Sample1マクロを実行する画像。詳細は以下。

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

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

STEP
右クリックメニューにメニュー追加
マクロの実行結果画像。詳細は以下。

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

STEP
メッセージボックスの表示
追加メニューの実行結果画像。詳細は以下。

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

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

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

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

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

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

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

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

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

STEP
サンプルを参考にしてコードを改造する

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

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

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

STEP
サブメニューの追加
サブメニュー追加後のマクロ実行結果画像。詳細は以下。

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

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

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

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

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

STEP
シートを追加する

シートを一つ追加して下さい(Sheet2を用意する)。

STEP
Worksheet_BeforeRightClickイベントプロシージャの作成

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

STEP
コードをコピペする

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

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
Sub 台詞1()
    MsgBox "柱として不甲斐なし"
End Sub

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

Sub メニュー削除()
    CommandBars("Cell").Controls("無限列車編").Delete
End Sub
STEP
マクロを実行する

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

右クリックメニュー追加マクロの実行結果画像。同じメニューが並んでいる。詳細は以下。

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

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

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

STEP
増殖防止のためメニュー追加前にメニューを削除する

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

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
Sub 台詞1()
    MsgBox "柱として不甲斐なし"
End Sub

Sub 台詞2()
    MsgBox "穴があったら入りたい"
End Sub
マクロ実行結果の画像。エラーダイアログが表示される。詳細は以下。

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

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

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

STEP
別の命令文を試してみる

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

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

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と書けば、ある処理がエラーになってもその次の処理へスキップしてくれるようです。

STEP
エラーを無視して処理を継続する
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はおそらく「アクティブではなくなった時」って意味っぽいじゃないですか。早速プロシージャを作成してみましょう。

STEP
シート遷移で追加メニューを削除する

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_Close2通りの方法があるようです。それぞれ微妙に違うようですが、アドバイスがありました。

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

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

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

STEP
Bookモジュールを選択
Bookモジュールへの記述方法説明画像。詳細は以下。

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

STEP
オブジェクトの選択
オブジェクト選択画像。詳細は以下。

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

STEP
イベントプロシージャの選択
プロシージャ選択画像。詳細は以下。

右側のプロシージャから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入門」でググると、オブジェクトプロパティメソッド変数といった用語がたくさん出てきます。基礎知識からスタートするのは至極当然のアプローチだと思いますが、この記事は別のアプローチ(とりあえず動くマクロを作成する)で構成されています。頭でっかちになるより、まずはマクロを作成して動かすことが脱初心者の近道だと思います。

よかったらシェアしてね!
  • URLをコピーしました!
目次