VBA技術解説
イベント処理について

ExcelマクロVBAの問題点と解決策、VBAの技術的解説
最終更新日:2020-05-12

イベント処理について


VBAのイベントについての概要解説です。


ワークブックのイベント

VBEの操作動画です。

VBA マクロ イベント処理

上図の、「プロジェクト」で、「ThisWorkbook」を選択し、
「表示」→「コード」、または、F7、または「ThisWorkbook」をダブルクリックします。
ワークブックのイベントは、ここに記述します。

「(General)」と表示されているコンボボックスで、「Workbook」を選択すると、
自動で、
Private Sub Workbook_Open()
End Sub
これが作成されます。

その他のイベントは、右のコンボボックスで一覧から選択することが出来ます。
良く使うイベントとしては、「BeforeClose」「BeforSave」これらがあります。
ここでは、この「Workbook_Open」のみ解説します。

ワークブックのイベントは、ブック全体に関するイベントですので、
あまり頻繁には使用しません。
どのようなイベントがあるかは、この一覧を見ればおおよそは理解して頂けると思います。
英語で書いてあるので、概ね直訳すれば、その通りの内容です。

Workbookのイベントの詳細については以下を参照してください。
第124回.Workbookのイベントプロシージャー|VBA入門
Workbookのイベントプロシージャーは、ブックに対し特定の操作(これがイベント)が行われた時に実行されます。イベントは、手動でもVBAでも、どちらで操作が行われても発生します。Workbookのイベントは多数用意されています。

Workbook_Open

ブックが開いた直後に実行されるイベントです。
ワークブックのイベントでは、最も使用頻度の高いイベントです。
このイベントでよくやる処理としては、

1.変数を初期化する
2.指定のシート、フォームを開く
3.キーやアクションにマクロを割り当てる

等々になります。
その他、ピボットの更新等の処理もあります。

ワークシートのイベント

VBEの操作動画です。

VBA マクロ イベント処理

「プロジェクト」で、「Sheet1(Sheet1)」等のシートを選択し、
「表示」→「コード」、または、F7、またはシート名をダブルクリックとます。
ワークシートのイベントは、ここに記述します。

「(General)」と表示されているコンボボックスで、「Worksheet」を選択すると、
自動で、
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
End Sub
これが作成されます。
これは、セルの選択位置が変更された時に発生するイベントです。
なぜ、これが標準で作成されるのか、私は疑問です。
そんなに使わないと思うのですが・・・

Private Sub Worksheet_Activate()

これは、シートがアクティブになったときに発生します。
つまり、他のシートを選択している状態から、そのシートへ移ったときです。
ですから、シートの内容の初期化や、初期表示に使用する事になります。
マクロでシートを切り替える場合は、
必要な処理は同時に処理してしまうので、そんなに頻繁には使用しません。

Private Sub Worksheet_Change(ByVal Target As Range)

これが問題ですね。
少し凝ったプログラムを作成すると、どうしても使うことになります。
どこかのセルに変更が加えられた時に実行されるイベントです。
ここでの問題は、どのセルが変更されたかになります。
それが、Targetに入っているのです。
このTargetに、何が、どのように入ってくるかを理解する必要があります。

Target As Range

引数の型を見て頂ければおわかりになると思いますが、
これは、Rangeオブジェクトです。
従って、通常のRangeと同様に扱えばよいのです。
だだし、問題は普通のRangeなら自分でアドレスを設定する場合が多いかもしれませ。
Range("A1:B10")または、Range(Cells(1, 1), Cells(10, 2))
このように指定しています。

しかし、このTargetにはどこのセルが入っているかが分かりません。
従って、そのセル範囲を判定してから処理するしかなく、これが結構難しいのです。

単独セルしか操作しなければ、大した問題はありません。
Target.Addressには、$B$10のようになっています。

しかし、複数セルを選択した状態で操作した場合は、
$B$2:$C$3
$B$2,$C$10
このように入ってきます。
これが問題です。
そこで、この判定として、

For Each tCell In Target
  If Intersect(tCell, セル範囲) Is Nothing Then
    '対象外
  Else
    '対象
  End If
Next

このように、RangeオブジェクトからFor...Eachで処理するようにします。
もちろん、目的によっては複数セルなら、Exit Subしてしまう場合もあるでしよう。
Intersectは、Targetがセル範囲に無ければNothingが返ります。

ただし、注意として、
イベントの連鎖に気を付ける必要があります。

プログラムでセルの内容を書き換えても、Worksheet_Change、これが再度呼ばれますので、
従って、新たなイベントが発生しないようにイベントの発生を抑止する必要があります。
それが、
Application.EnableEvents = False
です。
必ず、マクロVBAの最後でTrueに戻してください。

Workbookのイベントの詳細については以下を参照してください。
第125回.Worksheetのイベントプロシージャー|VBA入門
Worksheetのイベントプロシージャーは、ワークシートまたはそのセルに対し特定の操作(これがイベント)が行われた時に実行されます。イベントは、手動でもVBAでも、どちらで操作が行われても発生します。Worksheetのイベントプロシージャーの一覧紹介と主要なイベントについて解説します。

標準モジュールとの使い分け

特段の決まりがある訳ではないですが、覚えておかなければならないことがあります。

他のモジュールからCallする場合は、
モジュール.Subモジュール
となります、このモジュールとは、
「プロジェクト」の「Sheet1(Sheet1)」の括弧内の「Sheet1」です。
()内は、シートのオブジェクト名です。
このシートモジュールの名称は、「プロパティ」で変更ができます。
ただし、プロパティを変更しても、Callしている箇所は自動では直りませんのでご注意を。

VBA マクロ イベント処理

また、当然のことではありますが、
このシートモジュールは、シートと対なので、
シートを他のブックに移動・複写した時も、一緒にくっついていきます。
そして、これが最も考慮すべきことです。

つまり、作成したシートだけを誰かに渡す可能性があるなら、
全て、シートモジュールに記述しないと、動作しなくなります。
もちろん、標準モジュールも一緒に渡せればよいのですが、
そこには、膨大なコードが入っている場合は、ちょっと困ることもあります。

では、通常の使い分けはどうするべきか。
基本的には、イベントのみ記述するところから始めてください。
ただ、イベントのプロシージャーからCallする、SubやFunctionで、
他からCallする可能性が無いものは、入れても構わないと思います。
ただし、他のシートを操作するようなコードは、標準モジュールに入れた方が良いでしょう。

また、標準モジュールでは、シートの指定は必ずするようにしてください。
たとえ、そのシートがActiveになっていることが確実であったとしても、
シート指定は省略すべきではないと思います。
つまり、コードの「流用性」を考慮すべきでしょう。
もちろん、そのSubモジュールの先頭でActiveにしているのなら動作的には問題はないですが、
Activeを期待したVBAは書かない方が良いでしょう。

しかし、シートモジュールではどうでしょうか。
そのシートでしか使用しないのですから、指定する必要がありません。
他のシートモジュールにコピペしたとしても、結果は同じになります。

以下でより詳しく解説しています。
標準モジュールとシートモジュールの違い
エクセルVBAを始めたばかりの人に教えるとき、まずは標準モジュールを挿入して、そこに書きましょう、と教えます。しかし後で見ると、時に間違ってシートモジュールに書いている場合が結構あります。そういう時に、必ず聞かれるのが、「何が違うんですか?」「どこが違うんですか?」そういう時は、「今はその違いについて説明しても混乱するだけですから、

イベント処理は使うのも難しいですが、説明も難しいです。
少しはイベントに対する理解の助けになっていれば良いのですが。




同じテーマ「マクロVBA技術解説」の記事

イベント処理について
ブックが開いた時に自動実行(Workbook_OpenとAuto_Open)
ブックが閉じる時に自動実行(Workbook_BeforeCloseとAuo_Close)
オートフィルタを退避回復するVBAクラス


新着記事NEW ・・・新着記事一覧を見る

VBA100本ノック 18本目:名前定義の削除|VBA練習問題100(11月6日)
VBA100本ノック 17本目:重複削除(ユニーク化)|VBA練習問題100(11月6日)
VBA100本ノック 16本目:無駄な改行を削除|VBA練習問題100(11月5日)
VBA100本ノック 15本目:シートの並べ替え|VBA練習問題100(11月4日)
VBA100本ノック 14本目:社外秘シート削除|VBA練習問題100(11月3日)
VBA100本ノック 13本目:文字列の部分フォント|VBA練習問題100(11月1日)
VBA100本ノック 12本目:セル結合を解除|VBA練習問題100(10月31日)
VBA100本ノック 11本目:セル結合の警告|VBA練習問題100(10月30日)
VBA100本ノック 10本目:行の削除|VBA練習問題100(10月29日)
VBA100本ノック 9本目:フィルターコピー|VBA練習問題100(10月28日)


アクセスランキング ・・・ ランキング一覧を見る

1.最終行の取得(End,Rows.Count)|VBA入門
2.RangeとCellsの使い方|VBA入門
3.変数宣言のDimとデータ型|VBA入門
4.セルのコピー&値の貼り付け(PasteSpecial)|VBA入門
5.マクロって何?VBAって何?|VBA入門
6.Range以外の指定方法(Cells,Rows,Columns)|VBA入門
7.繰り返し処理(For Next)|VBA入門
8.セルに文字を入れるとは(Range,Value)|VBA入門
9.とにかく書いてみよう(Sub,End Sub)|VBA入門
10.マクロはどこに書くの(VBEの起動)|VBA入門




このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。


記述には細心の注意をしたつもりですが、
間違いやご指摘がありましたら、「お問い合わせ」からお知らせいただけると幸いです。
掲載のVBAコードは動作を保証するものではなく、あくまでVBA学習のサンプルとして掲載しています。
掲載のVBAコードは自己責任でご使用ください。万一データ破損等の損害が発生しても責任は負いません。



このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。
本文下部へ