【VBA基礎④】イベント
皆さんはVBAでイベントを利用していますか?イベントを利用すればユーザーが操作を行った瞬間に処理が実行されるので、マクロ実行の手間を省き、スムーズな操作が可能になります。今回はVBAのイベントの使い方についてまとめているので、この記事を読めば、イベントの基礎について理解することができます!
この記事はVBAの基礎シリーズです。他の記事は以下のリンクからご覧いただけます!
第4回の今回はイベントについて解説します。
目次
イベントとは?
イベントとはExcelである特定の操作が行われた時にマクロを自動実行する仕組みです。例えば「ブックを開いた時」や「クリックした時」、「セルの値を変更した時」などにプロシージャ内に記述した処理が実行されるのです。
イベントを作成するには?
イベントを発生させるには、決められたモジュール内の決められたプロシージャ内に記述しなければなりません。「ブックを開いた時」にマクロを自動実行したいなら、「ブックを開いた時」用のモジュールとプロシージャを用意します。
VBAの画面を開き、「ThisWorkbook」をダブルクリックしてブックモジュールを開きます。モジュール上部のプルダウンで左側は「Workbook」を選択、右側は「Open」を選択します。すると、自動的にプロシージャが挿入されます。

試しにこのプロシージャ内にコードを書いてみます。メッセージボックスで「Hello」と表示されるコードを書きました。
コードを書いてからブックを閉じて、再度ブックを開くと自動でメッセージが表示されます。


このようにコードウィンドウ左上のプルダウン選択で、イベントを発生させるモジュール、右上のプルダウン選択でイベントが発生する際の特定の処理を選択して、プロシージャ内に記述した処理をイベントとして発生させることができます。
イベントの注意点
イベントは使用者がマクロを実行しなくてもマクロを自動実行できますが、使用者が予期しないタイミングでマクロが実行されてしまう危険性があります。実際に事例を確認してみます。
VBAの画面を開き、「Sheet1」をダブルクリックしてシートモジュールを開きます。モジュール上部のプルダウンで左側は「Worksheet」を選択、右側は「Change」を選択します。すると、「Sheet1」シートのセルを変更した際のマクロが起動するプロシージャが挿入されます。
ここに以下のコードを記述します。
Target = Target + 1
このプロシージャでは、変数「Target」の引数にセルを指定しいるので、「Target」は「Sheet1」で選択されているセルを指します。よって、「セルの値を変更するとセルの変更前の値にプラス1された値がセルに代入される」処理がループ発生してしまいます。

実際にセルに「1」を入力すると自動でセルの値が「47」に切り替わりました。このことからプラス1される処理が46回繰り返されたことが分かります。


ループの発生回数はExcelのバージョンなどによって異なります。
上記のようなイベントのループを防ぐためには、以下のコードを追加します。
Application.EnableEvents = False
Target = Target + 1
Application.EnableEvents = True
「Application.EnableEvents = False」を記述すると、それ以降のイベントが発生しなくなります。

「Application.EnableEvents 」が「False」のままだとそれ以降のイベントが発生しないままになってしまうので、最後に「True」に戻す必要があります。
それでは以降にイベントの種類をまとめていきたいと思います。
ブックのイベント
ブックイベントはブックに対して発生するイベントです。コードウィンドウ左上のプルダウンで「Workbook」を選択し、右上のプルダウンでイベントプロシージャを選択します。
BeforeCloseイベント
「BeforeClose」はブックを閉じる時に発生するイベントです。イベントプロシージャを挿入し、ブックを閉じると時に各シートのセルA1を選択するコードを記述してみます。
以下のコードを記述し、ブックを閉じて再度開くと各シートのセルA1が選択された状態になっています。
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Dim ws As Worksheet
For Each ws In Worksheets
ws.Activate
Range("A1").Select
Next ws
ActiveWorkbook.Worksheets(1).Activate
ActiveWorkbook.Save
End Sub
このプロシージャでは引数「Cancel」に「True」を設定することで、その後の処理をキャンセルすることができます。
以下のマクロを実行すると、ブックは閉じられることはなく、各シートのセルA1が選択されます。
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Dim ws As Worksheet
For Each ws In Worksheets
ws.Activate
Range("A1").Select
Next ws
ActiveWorkbook.Worksheets(1).Activate
Cancel = True
End Sub

「For each」ステートメントは指定した配列やオブジェクトの要素ごとに処理を繰り返し実行する命令文です。
BeforeSaveイベント
「BeforeSave」はブックを保存する時に発生するイベントです。イベントプロシージャを挿入し、ブックを保存する時に別名で保存ができないようにコードを記述してみます。
このプロシージャでは「名前を付けて保存」しようとすると引数「SaveAsUI」に「True」が格納されます。以下のマクロを実行すると、「名前を付けて保存」した際に、別名保存ができなくなります。
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
If SaveAsUI = True Then
MsgBox "名前の変更はできません"
Cancel = True
End If
End Sub
NewSheetイベント
「NewSheet」は新しいシートを挿入する時に発生するイベントです。イベントプロシージャを挿入し、新しく挿入したシートの名前に日付を設定するマクロを記述してみます。
以下のマクロを実行すると、シートを新規作成した際にシート名に自動で日付が設定されます。
Private Sub Workbook_NewSheet(ByVal Sh As Object)
Dim today As Date, shname As String
today = Date
shname = Format(today, "yyyymmdd")
ActiveSheet.name = shname
End Sub

「Date」は今日の日付を返す関数です。シート名に「/」は設定できないため、「Format」関数で日付を数値のみの文字列に変換しています。
NewChartイベント
「NewChart」は新しい図形を挿入する時に発生するイベントです。イベントプロシージャを挿入し、新しく図形を挿入した時、自動で図形書式を整えるコードを記述してみます。
コードの中身についての解説は省略しますが、以下のマクロを実行すると図形の書式が自動で変更されます。
Private Sub Workbook_NewChart(ByVal Ch As chart)
With Ch
With .Axes(xlCategory)
.MajorTickMark = xlOutside
With .Format.Line
.Visible = msoTrue
.ForeColor.ObjectThemeColor = msoThemeColorText1
.ForeColor.TintAndShade = 0
.ForeColor.Brightness = 0
.Transparency = 0
End With
End With
With .Axes(xlValue)
.MajorTickMark = xlOutside
With .Format.Line
.Visible = msoTrue
.ForeColor.ObjectThemeColor = msoThemeColorText1
.ForeColor.TintAndShade = 0
.ForeColor.Brightness = 0
End With
.MajorGridlines.Delete
.MinimumScale = 15
.MajorUnit = 5
End With
.ChartTitle.Delete
With .PlotArea.Format.Line
.Visible = msoTrue
.ForeColor.ObjectThemeColor = msoThemeColorBackground1
.ForeColor.TintAndShade = 0
.ForeColor.Brightness = -1
End With
With .ChartArea.Format
.Fill.Visible = msoFalse
.Line.Visible = msoFalse
End With
With .FullSeriesCollection(1)
.MarkerStyle = xlMarkerStyleCircle
.MarkerSize = 7
With .Format.Fill
.Visible = msoTrue
.ForeColor.ObjectThemeColor = msoThemeColorBackground1
End With
End With
End With
End Sub
挿入したグラフ書式が初期フォーマットの状態から自動で変更されました。

シートのイベント
シートイベントはシートに対して発生するイベントです。コードウィンドウ左上のプルダウンで「Worksheet」を選択し、右上のプルダウンでイベントプロシージャを選択します。
Activateイベント
「Activate」はワークシートがアクティブになった際に発生するイベントです。イベントプロシージャを挿入し、ワークシートが開けないようにコードを記述してみます。
以下のマクロを作成し、シート2をアクティブにするとシート1のセルB1に名前が入力されていない時、再度シート1がアクティブになります。
Private Sub Worksheet_Activate()
If ActiveSheet.Index = 2 And Sheets(1).Cells(1, 2) = "" Then
Sheets(1).Select
MsgBox "名前を入力してください。"
End If
End Sub

BeforeDoubleClickイベント
「BeforeDoubleClick」はセルをダブルクリックした際に発生するイベントです。イベントプロシージャを挿入し、セルをダブルクリックした時にセルを塗りつぶすコードを記述してみます。
以下のマクロを作成し、任意のセルをダブルクリックするとセルが黄色で塗られます。
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
Target.Interior.Color = vbYellow
Cancel = True
End Sub


引数「Target」にはRangeオブジェクトが設定されています。引数「Cancel」に「True」を代入するとダブルクリックした際にセルが編集モードにならなくなります。
BeforeRightClickイベント
「BeforeRightClick」はセルを右クリックした際に発生するイベントです。イベントプロシージャを挿入し、セルを右クリックした時に文字を太文字にするコードを記述してみます。
以下のマクロを作成し、任意のセルを右クリックすると文字が太字になります。
Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean)
Target.Font.Bold = True
Cancel = True
End Sub

Calculateイベント
「Calculate」はセルで計算処理がされた際に発生するイベントです。イベントプロシージャを挿入し、セルで計算がされた際、セルを塗りつぶすコードを記述してみます。
以下のマクロを作成し、セルC3に計算式を書き込むとセルの色が値の条件によって自動変更されます。
Private Sub Worksheet_Calculate()
With Range("C1")
If .Value > 0 Then
.Interior.Color = vbRed
ElseIf .Value < 0 Then
.Interior.Color = vbGreen
Else
.Interior.Color = vbBlue
End If
End With
End Sub

SelectionChangeイベント
「SelectionChange」は選択セルが変更された際に発生するイベントです。イベントプロシージャを挿入し、選択セルが変更された時にアクティブセルの行と列全体を塗りつぶすコードを記述してみます。
以下のマクロを作成しすると、セルを選択する度にセルの行と列全体が緑で塗りつぶしされます。
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
ActiveSheet.Cells.Interior.ColorIndex = 0
ActiveCell.EntireRow.Interior.Color = vbGreen
ActiveCell.EntireColumn.Interior.Color = vbGreen
End Sub


ここまで紹介したシートイベントはマクロを記述したシート内でのみ発生します。ブック全体で同様のイベントを発生させたい時は、ブックイベントの「Sheet~」を選択します。

まとめ
いかがでしたでしょうか?今回はVBAのイベントについてまとめました。この記事はVBAの基礎シリーズとして今後も発信していきますので、良ければ他の記事も読んでいただければ嬉しいです。それでは最後までお読みいただき、ありがとうございました。