記事キャッチ画像  (23) イベント連鎖と、Excel操作だけでなくVBAコード操作でもイベントが発生することを理解する! 

 1. 一つのExcel操作で、イベントは複数発生する場合あり (イベント連鎖) 

 2. VBAのイベントは「手動操作」だけでなく、「VBA(コード)操作」でも発生することを確認する 

  「広告」  
 

 (23) イベント連鎖と、Excel操作だけでなくVBAコード操作でもイベントが発生することを理解する! 

Excel メニューバーの [ヘルプ] - [更新プログラムのチェック] にて、適用されていないアップデートがあれば行ってください。 

Excel 2016 for Mac 環境での説明となりますので、 Mac版 Excel 2011 では( VBA が利用できますが )同じ結果にならない場合があるかもしれません。

現状、 VBE 内で日本語を記述すると(貼り付けのみ可能な場合あり)乱れたり、保存時にクラッシュすることが多いため、 VBAコード は「未変換の英数字のみ」で記述してください。(テキストエディタからの貼り付けは可能)

( ユーザー定義関数 のVBAコードを含んだ)前回使用した XLSM ファイルを、「マクロを有効」にして開きます。

49

[ alt ] + [ F11 ] にて VBE を開き、SheetN ではなく(上記画面赤枠の) ThisWorkbook を選択後、以下の VBAコードを入力するかコピーして貼り付け。
SheetN の N の部分は、「1」や「2」でない場合もあり )


'--------------------------------
'    Event: Workbook_BeforeClose()
'--------------------------------
Private Sub Workbook_BeforeClose(Cancel As Boolean)

    MsgBox "BeforeClose Event !"
    If Not ActiveWorkbook.Saved Then
        ActiveWorkbook.Save
    End If

End Sub
'--------------------------------
'    Event: Workbook_BeforeSave()
'--------------------------------
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)

    Dim ws As Worksheet
    Dim n As Integer
    n = 0
    MsgBox "BeforeSave Event ! "

    If MsgBox("Save the Workbook ?", vbYesNo) = vbNo Then
        ActiveWorkbook.Saved = True
        Cancel = True
    Else
        For Each ws In ActiveWorkbook.Worksheets
            n = n + 1
            MsgBox " (" & n & ")" & " Save [" & ws.Name & "]  !"
        Next ws
    End If
    
End Sub
'--------------------------------
'    Event: Workbook_AfterSave()
'--------------------------------
Private Sub Workbook_AfterSave(ByVal Success As Boolean)
    MsgBox "AfterSave Event ! "
End Sub

ThisWorkbook (Excelブック)のイベントプロシージャ を3つ記述した。
ブックを閉じる直前が Workbook_BeforeClose 、ブックを保存する直前が Workbook_BeforeSave 、ブックを保存した直後が Workbook_AfterSave イベントプロシージャとなる。

Excelブックが管理するワークシートは Workbook オブジェクトの Worksheets プロパティ で参照可能。
グラフシートを参照したい場合は Charts 、全てのシートを一緒に参照したい場合は Sheets プロパティ で参照可能。
ただし、グラフシートのみ扱う場合は Dim gs As Chart と変数を宣言し、一緒に扱いたい場合は Dim sh As Object と変数を宣言して複数のシートの型を同時に扱えるようにする必要がある。
 Worksheet ・ Chart 等のシートオブジェクトで共通のプロパティやメソッドを持つ場合は実行できるが、そうでない場合は実行時エラーとなる。
C言語等と比較して Visual Basic は変数の型に関して融通が効くため、整数 n を MsgBox で文字列結合する場合に「整数の文字列化関数 CStr(n) 」を勝手にやってくれている。

Object 型や Variant 型を用いると、コード作成時に対象オブジェクトがプロパティやメソッドを持つかどうかのチェックが省略されるため、取扱い注意!
実行時まで「型チェック」を保留しているだけなのだ。
各モジュールの先頭で「 Option Explicit 」記述推奨する理由とも関わっている。
「 Option Explicit 」無しだと、変数宣言( Dim ステートメント)を忘れても「未定義エラー」とならず Variant 型 で宣言した事になる。(暗黙の型宣言)

ちょっと難しかったかもしれない。
本日覚えて頂きたいことは、「 Option Explicit 」利用なら以下の一つだけ!
Object 型は(全てのオブジェクトを格納可能な型で)あえて複数の型を一つの変数で処理する場合に用い、 Variant 型 は型を決めたくない場合に用いて、 Dim ステートメントで変数宣言を行う。


 1. 一つのExcel操作で、イベントは複数発生する場合あり (イベント連鎖) 

33

まず、前回の復習も兼ねて、ブックにワークシートを一つ追加する。
「 SheetN 」のモジュールが一つ増えたことを VBE で確認して欲しい。
ワークシートのモジュールは、各ワークシート毎に作成される。

(ワークシートを追加したのでブック未保存の状態のはずだが、保存済みの方はシート上のセルに何か値を入力してブック未保存の状態にする)

イベント連鎖 確認のため、Excel か VBE 選択状態で [comand] + [Q] 等で Excel を終了しよう。
[1] BeforeClose イベント発生
[2] BeforeSave  イベント発生
が確認できるはずだ。
理由は解らないが、(せっかく実装したのだが)ブックを保存した場合も AfterSave イベントは発生しない。

 Workbook_BeforeClose イベントプロシージャ内の ActiveWorkbook.Saved プロパティは保存済みの場合は True 、未保存の場合は False を示す。
よって、未保存の場合のみ ActiveWorkbook オブジェクトの Save メソッド を実行。
この Save メソッドにて、 BeforeSave イベントが発生する。

次に、 Workbook_BeforeSave イベントプロシージャの内容を説明する。
「 Save the Workbook ? 」MsgBox で、[ はい ] を選択した場合は ブックに含まれるワークシート名を全て表示した後に ブックを保存する。
[ いいえ ] を選択した場合は ActiveWorkbook.Saved プロパティのフラグを書き換え、 Cancel = True にてブックの保存自体をキャンセルする。
フラグの整合性を取っておかないと失敗する場合があるので、注意が必要!
ブックを保存せずにExcel を終了したいのであれば、ブックの Saved プロパティを True に書き換えた直後に Excel を終了すればよい。

イベントは連鎖して発生する場合があるため、一つのExcel(VBAコード)操作で 複数のイベントが発生する場合があることを覚えて頂きたい。
例えイベントプロシージャを1行も記述していなくとも、Excel 終了時に該当ブックが未保存の場合は上記で説明した2つのイベントが最低でも発生している。


 2. VBAのイベントは「手動操作」だけでなく、「VBA(コード)操作」でも発生することを確認する 



Sub QuitExcel()
    Application.Quit
End Sub

Sub SaveWorkbook()
    ActiveWorkbook.Save
End Sub

VBA(コード)操作でも、実はイベントが発生する。
VBA実行時にイベントが次々と発生することもあり、考慮してコードを記述しないと失敗する。

上記の Module1 の末尾に追加した SaveWorkbook プロシージャは、 [command] + [S] 等で可能なブックの保存を VBAコード化したもの。

ブック保存時と「 call saveworkbook() 実行時」でイベントプロシージャが同じように呼ばれることを確認して欲しい。

QuitExcel プロシージャは  [command] + [Q] 等で可能なExcel の終了を VBAコード化したもの。
こちらも、同じようにイベント連鎖が発生することを確認して欲しい。

また、VBA でイベントを発生し続ける処理を誤って記述すると無限ループに陥ることもあるということも覚えておいて頂きたい。


次回は、「ダブルクリック時のワークシートとブックのイベントトラップ」をテストします!


お疲れ様でした!
[command] + [Q] にてExcel を終了時、「作業中のブック」を保存するか確認のダイアログ画面が表示されるため 「保存」しましょう。
現状、 VBE 内で日本語を記述すると(貼り付けのみ可能な場合あり)乱れたり、保存時にクラッシュすることが多いため、 VBAコード は「未変換の英数字のみ」で記述してください。(テキストエディタからの貼り付けは可能)


最後まで読んでいただき、ありがとうございます。
ぜひ、右側の「人気ブログランキング」投票に ご協力ください。
また、お越しくださいませ。
// アタル

  「広告」