VBAの一部のオブジェクトには、固有の「イベント」が定義されています。例えば、「Workbook」オブジェクトであれば「ワークブックが開いた後」や「閉じる前」、「Worksheetk」オブジェクトであれば「ワークシートがアクティブになった後」や「削除される前」などといったタイミングがイベントとして定義されています。
これらのイベントをきっかけに動作するプロシージャをイベントプロシージャと呼びます。例として幾つかのイベントプロシージャを以下にリストアップしています。
動作 | イベントプロシージャ |
---|---|
ワークブックが開いた後 | Workbook_Open |
ワークブックが閉じる前 | Workbook_BeforeClose |
ワークシートが削除される前 | Worksheet_BeforeDelete |
ワークシートがアクティブになった後 | Worksheet_Activate |
ワークシートが変更された後 | Worksheet_Change |
イベントプロシージャは標準モジュールではなく、イベントの対象となるオブジェクトモジュールに記述します。Workbookオブジェクトのイベントプロシージャであれば「ブックモジュール」に、Worksheetオブジェクトのイベントプロシージャであれば「シートモジュール」に記述します。
今回のToDo完了メール送信マクロでは、「ワークシートが変更された後」のイベントプロシージャを作成するので、シートモジュールに記述します。
VBE(Visual Basic Editor)のプロジェクトエクスプローラー内の「Sheet1(ToDo)」が対象のシートモジュールになるので、ダブルクリックして開きます。
コードウィンドウの上部に2つのプルダウンボックスが並んでいます。左側が「オブジェクトボックス」、右側が「プロシージャボックス」と言います。イベントプロシージャは、それぞれオブジェクトとプロシージャを選択することで、簡単に作成できます。
オブジェクトボックスから「Worksheet」、プロシージャボックスから「Change」を選択して、イベントプロシージャ「Worksheet_Change(ByVal Target As Range)」が挿入されることを確認しましょう。
「Target」というRange型の引数が与えられています。これは変更があったセル範囲が格納されます。イベントプロシージャ内で活用して、さまざまな処理を実現できます。
まず、以下の部分に注目しましょう。
Set myRange = Sheet1.ListObjects(1).ListColumns("ステータス").DataBodyRange
ToDoリストはテーブル化されているので、「Sheet1.ListObjects(1)」にすることで、「ListObject」オブジェクトとして取得できます。続く、「ListColumns」プロパティで、「ListColumns」コレクションを取得します。
ListObjectオブジェクト.ListColumns
また「カラム名」を指定することで、コレクションから特定の「ListColumn」オブジェクトを取得しています。
ListColumnsコレクション(カラム名)
ListColumnは、テーブルの単体の列を表すオブジェクトで、カラム名はその見出しになります。従って、カラム名「ステータス」を指定して取り出したListColumnオブジェクトは、テーブル内のステータス列を表します。
さらに、「DataBodyRange」プロパティを使用しています。これはListColumnオブジェクト内のデータ範囲のみを「Range」オブジェクトで取得するプロパティです。
ListColumnオブジェクト.DataBodyRange
つまり、今回のToDoリストの見出しを除いて「E2:E4」のセル範囲を取得できます。
次に以下の部分を見ていきましょう。
Dim r As Range For Each r In Target If Not Intersect(myRange, r) Is Nothing And r.Value = "完了" Then Call ToDo完了メール送信(r.row) End If Next r
「For Each」ステートメントで、変更のあったセル範囲であるTarget内の個々のセルについて繰り返しを行います。その内部にあるIf文ですが、以下2点の判定の「And」をとっています。
「Intersect」メソッドは「Application」オブジェクトのメンバーです。このメソッドは、引数で指定した複数の範囲の重なっている部分のセル範囲を返すメソッドです。
Intersect(セル範囲1, セル範囲2,...)
第1引数は「ステータス列のデータ範囲」を表す「myRange」。第2引数はTargetのうちの単体セルr。そのため、Intersectメソッドの戻り値や、条件式の判定値は以下のようになります。
セルが「ステータス列のデータ範囲」に含まれ、かつその値が「完了」ならば、「Sub ToDo完了メール送信(ByVal row As Long)」を呼び出します。その際に、引数として、該当セルの行番号を渡します。
「Sub ToDo完了メール送信(ByVal row As Long)」の動作は、これまでの連載を読んでいる人なら、簡単に読み解けると思います。
今回は、Outlookでのメール送信を紹介します。メールを送信するには、「MailItem」オブジェクトに対して、各プロパティを設定した上で「Send」メソッドを使います。
MailItemオブジェクト.Send
Copyright © ITmedia, Inc. All Rights Reserved.