ワークシートの内容が変更されるとChangeイベントが発生します。このときに自動実行させるマクロはWorksheet_Change
イベントプロシージャとして作成します。発動の時点で値は変更済みなので通常は変更前の値は確認できません。しかし、Worksheet_SelectionChange
イベントプロシージャと組み合わせることで、それを実現できます。
Changeイベントは、セルを編集状態にしてそのまま確定した場合も発生します。このため、値が変更された場合だけ処理を実行するには、変更前の値との比較が必要になります。
Worksheet_SelectionChange と Worksheet_Change の連携
Option Explicit
'============================
'宣言セクション
Dim VAL As Variant
'============================
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
On Error GoTo ENDUP
If Intersect(Target, Range("変更管理")) Is Nothing Then Exit Sub
If Target.Cells.Count <> 1 Then Exit Sub
VAL = Target.Value
ENDUP:
End Sub
'============================
Private Sub Worksheet_Change(ByVal Target As Range)
On Error Resume Next
If Intersect(Target, Range("変更管理")) Is Nothing Then Exit Sub
If Target.Cells.Count <> 1 Then Exit Sub
If Target.Value <> VAL Then
MsgBox Target.Address & " の値が変更されました" & vbCrLf & _
"元の値 : " & VAL
End If
End Sub
ポイント解説
宣言セクションの変数で値の受け渡し
Worksheet_SelectionChange
は、ワークシートで選択操作をしたときに発動するプロシージャです。ここで変更前の値を取得し、宣言セクションのVAL
変数に入れています。値の変更で発動したWorksheet_Change
では、VAL変数の値と現在の値を比較できるようになります。
宣言セクションは、
Option Explicit
の次行からプロシージャ(Sub
)の前までの記述を指します。ここで宣言した変数は、各プロシージャで共通の変数になります。プロシージャの終了時に値がリセットされないので、次のプロシージャへの引継ぎが可能になります。発動頻度とエラーの対策
SelectionChangeイベント、Changeイベントともに、ワークシートの操作中に高頻度で発生します。ユーザー操作のストレスにならないように対策しましょう。
複雑な処理を避ける
複雑な処理を組み込むと、操作のたびに引っかかるような動きになって使いにくくなります。処理の内容はシンプルかつ最小限にしましょう。
処理の実行条件を絞り込む
SelectionChangeイベントはシートのどこかを選択するたびに発生し、Change イベントは値の変更以外にも行・列の追加や削除などでも発生します。不要な場面で処理が実行されないよう、条件を絞り込みます。
実行開始は避けられないので、条件に外れる場合はすぐに Exit Sub
で抜けるようにします。上記サンプルでは、名前を付けた範囲内の1セルが操作された場合を条件としています。
エラーの対策
目的の操作以外でも発動するのでTargetの中身は意図しない状態になったりします。On Error GoTo
や On Error Resume Next
でエラーの発生に備えておきます。
例えば、シートで全選択するとSelectionChangeイベントが発生しますが、その状態では Target.Cells.Count
はエラーになります。エラーにならないように制御するのではなく、エラーになったら処理を抜けるようにしています。
イベント発動の一時停止スイッチ : Application.EnableEvents
上記コードでは使っていませんが、イベントプロシージャの処理でセル入力などを行う場合は注意が必要です。その場合もChangeイベントが発生し、Worksheet_Change
プロシージャが実行されるためです。
無限入れ子のループになるような場合は、EnableEvents
プロパティを使います。このプロパティで、イベントに対する反応を一時的に停止できるようになります。
Application.EnableEvents = False
' ----------------------
' イベント発動停止中の処理
' ----------------------
Application.EnableEvents = True
このマクロを応用したものを以下で紹介しています。