何かの操作が行われたときに、その操作を「キッカケ」にして処理を実行する仕組みのことを、プログラミング用語で「イベント処理」と言います。
例えば、「ボタンをクリックしたら、画面を切り替える」とか、「キーボードのキーを押したら、ある処理を始める」といったような感じです。
ExcelのVBAでは、イベントの発生時に実行される処理を、「イベントプロシージャ」といいます。
VBAで扱えるイベントは数多くありますので、ここでは代表的なものを4つ、ご紹介いたします。
イベントプロシージャの記述方法
イベントプロシージャの説明の前に、Visual Basic Editorでのイベントの記述方法をご説明いたします。
① まず、Visual Basic Editor左上の「プロジェクト」の部分で、イベントを記述したいシートまたはブックをダブルクリックします。

② 次に、表示されたコードウインドウで、(General)の部分をWorksheet(ブックの場合はWorkbook)に変更して下さい。

③ デフォルトで「Worksheet_SelectionChange」というイベントプロシージャ(ブックの場合はWorkbook_Open)が表示されます。
この状態で、コードウインドウ右上のプルダウンメニューを選択すると、記述可能なイベントが選択できるようになります。ここから、使いたいイベントを選択して下さい。
デフォルトで表示された「Worksheet_SelectionChange」プロシージャは、使わなければ消しても良いですし、そのまま放置しても良いですし、どちらでも構いません。

ここから、具体的なイベントの説明に入ります。
Workbook_Open(ブックを開いた直後)
ブックを開いた直後に実行されるイベントプロシージャです。
例
ブックを開いた直後に、ファイル選択ダイアログボックスを開きたい場合、こんな感じになります。
Private Sub Workbook_Open()
'ブックを開いた直後に実行したい処理をここに記述する
Sheets("Sheet1").Range("A1") = Application.GetOpenFilename
End Sub
Workbook_Openプロシージャを実行させない方法(マクロを無効にする)
当プロシージャは、ブックを開いた直後に実行されるため、ブックを開くと有無を言わさず実行されます。
しかし、デバッグを行いたい場合など、プロシージャを実行したくない場合は、以下の方法でブックを開くと、プロシージャを実行せずにブックを開くことが出来ます。
※Workbook_Openプロシージャに限らず、ブック内の全てのマクロが無効になります。
- Excelを起動する。
- メニューの「開く」を選択。
- 「参照」を選択して、「ファイルを開く」ダイアログで、開きたいファイルを選択する。この時点ではまだファイルを開かないこと。
- Shiftを押しながら「開く」をクリックする。
これで、マクロを無効にしてブックを開くことができます。
Worksheet_Change(どこかのセルの値が変更されたとき)
セルの値が変更された時に実行されるイベントプロシージャです。
当プロシージャでは、変更されたセル(Target)が、Rangeオブジェクトとして引数で渡されます。
例1:変更されたセルの値(Target.Value)をメッセージボックスで表示する。
※変更前の値を取得することは出来ません。
Private Sub Worksheet_Change(ByVal Target As Range)
MsgBox "変更後のセルの値は " & Target.Value
End Sub



例2:変更されたセルのアドレス(Target.Address)をメッセージボックスで表示する。
Private Sub Worksheet_Change(ByVal Target As Range)
MsgBox "変更されたセルは " & Target.Address
End Sub



※「$」が邪魔な場合は、Replace関数で除去して下さい。
注意点:イベントを一時的に無効にする必要がある場合(Application.EnableEventsの使用)
当イベントプロシージャ内で、シート内のセルの値を更新する場合は、以下の命令により、イベントの発生を止める必要があります。
Application.EnableEvents = False
これが無いと、セルの更新時に再びWorksheet_Changeイベントが発生してしまい、無限ループに陥ります。
但し、この命令は全てのイベントを止めるのと、マクロ終了後もイベントが発生しないままになります。
そのため、必ず以下の命令を実行して、イベントが発生する状態に戻す必要があります。
Application.EnableEvents = True
Application.EnableEventsの使用例
Private Sub Worksheet_Change(ByVal Target As Range)
'イベントの発生を止める
Application.EnableEvents = False
'変更されたセルの値が数値の場合は、入力値を2倍にする
If IsNumeric(Target.Value) = True Then
Target.Value = Target.Value * 2
End If
'イベントが発生する状態に戻す
Application.EnableEvents = True
End Sub
応用例1:イベントプロシージャを発生させるセルを限定したい場合
Worksheet_Changeイベントは、イベントプロシージャを記述したシート全体が対象となります。
「それでは困る。対象のセルを限定したい。」という場合は、以下のようにTarget.Addressでの判定文を記述すれば、イベントプロシージャを発生させるセルを限定できます。
以下のようにすれば、セル「B2」が変更された場合のみ、メッセージボックスが表示されます。
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$B$2" Then
MsgBox "変更後のセルの値は " & Target.Value
End If
End Sub
セルを範囲指定する場合(例えばセル「B1」~「D3」を指定したい場合)は、以下のようにTarget.Row(行番号)やTarget.Column(列番号)で判定すると良いです。
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Row >= 1 And Target.Row <= 3 And _
Target.Column >= 2 And Target.Column <= 4 Then
MsgBox "変更後のセルの値は " & Target.Value
End If
End Sub
応用例2:複数のセルをまとめて処理対象にしたい場合(コピー&ペーストした場合など)
Worksheet_Changeイベントを記述したシートにてコピー&ペーストした場合など、複数のセルがまとめて変更された場合は、以下のようにFor Each文を使って、それぞれのセルを処理する必要があります。
Private Sub Worksheet_Change(ByVal Target As Range)
Dim objRange As Range
For Each objRange In Target
MsgBox "変更されたセルは " & objRange.Address & vbCrLf & _
"変更後のセルの値は " & objRange.Value
Next
End Sub





For Each文を使わずに、引数のTargetをそのまま処理すると、以下のような結果になります。
- Target.Address ➡ 「$C$1:$C$2」のようにセル範囲がまとめて返され、プログラムで扱いづらい形式になる。
- Target.Value ➡ 「型が一致しません。」という実行時エラーになる。
Worksheet_SelectionChange(セルの選択範囲を変更したとき)
セルの選択範囲が変更された時に実行されるイベントプロシージャです。
矢印キーでセルの選択位置を動かした時など、セルの値を変更しなくても当イベントが発生します。
Worksheet_Changeと使い方が似ており、変更後に選択されたセル(Target)が、Rangeオブジェクトとして引数で渡されます。
例:変更後に選択されたセルのアドレス(Target.Address)をメッセージボックスで表示する。
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
MsgBox "選択されたセルは " & Target.Address
End Sub
Worksheet_BeforeDoubleClick(セルがダブルクリックされたとき)
セルがダブルクリックされた時に実行されるイベントプロシージャです。
当プロシージャでは、変更されたセル(Target)が、Rangeオブジェクトとして引数で渡されます。
また、第2引数のCancelにTrueを設定すると、ダブルクリック時の挙動(セルが編集中の状態)をキャンセルできます。
通常は、イベントプロシージャ終了時に、第2引数のCancelにTrueを設定することを推奨します。
理由は、セルが編集中のままだと、下図のようにカーソルが点滅中のままになり、思わぬ誤操作を起こすリスクがあるためです。

例:ダブルクリックされたセルのアドレス(Target.Address)をメッセージボックスで表示する。
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
MsgBox "ダブルクリックされたセルは " & Target.Address
Cancel = True 'セルを編集中の状態にしたくない場合
End Sub
コメント