【入門編】Applicationオブジェクトのイベントハンドラで文書の保存・印刷を強制監視する – Word VBA解析バイブル

スポンサーリンク

こんにちは!マクロの記録ボタンを押すだけの作業はもう卒業しましたか?
今回は、Word VBAの真骨頂とも言える「Applicationオブジェクトのイベントハンドラ」を使った、ちょっと高度で実用的なテクニックをお伝えします。

「ここをクリアすれば、Word VBAの基本はバッチリですよ!」と胸を張って言える領域ですので、ぜひついてきてくださいね。

1. なぜ「イベント監視」が必要なのか?

皆さんは、会社やプロジェクトでこんなルールを押し付けられた経験はありませんか?

  • 「機密文書を保存するときは、必ず特定のキーワードを含めなさい」
  • 「未完成のドラフト状態のまま印刷してはならない」

これを人間の目だけでチェックするのは、ヒューマンエラーの元です。そこで私たちエンジニアの出番です。「ユーザーが保存や印刷のボタンを押した瞬間、VBAが裏側で自動的に検知して、ルール違反ならガッチリブロックする」。そんな仕組みをWordに背負わせましょう。

ここで登場するのが、`Application` オブジェクトのイベントです。

2. Wordオブジェクトモデルの階層構造を理解する

Word VBAの世界は、ロシアの民芸品「マトリョーシカ」のように階層構造になっています。

[ Application (Wordアプリ全体) ]
└── [ Documents (開いている文書たち) ]
└── [ Document (特定の文書・Rangeなど) ]

通常、私たちが書くマクロ(標準モジュールに書くコード)は、個別の文書(`Document`)を相手にしています。しかし、「Wordで起きるすべての保存や印刷の動きを監視したい」となると、もっと上の親玉である `Application`(Wordアプリそのもの) に監視カメラを仕掛ける必要があります。

これが、今回解説する「Applicationレベルのイベントハンドラ」の本質です。

3. 実装の全体像:クラスモジュールを使う

Applicationイベントを扱うには、通常の標準モジュール(Module1など)だけでは不十分です。「クラスモジュール」という特殊な部品を使って、Wordの動きを監視する「専属エージェント」をメモリ上に生成する必要があります。

全体の設計図はこうです。
1. クラスモジュール(例:`CAppEvents`): 監視とブロックのロジックを書く。
2. 標準モジュール(例:`MainModule`): エージェントを起動(アクティブ化)する。

4. 実装コード(コピペして使えます)

それでは、実際に手を動かしてみましょう。今回は「文書の保存時に、タイトル(先頭の段落)が空っぽだったら保存を強制キャンセルする」というセキュリティ&品質管理スクリプトを作ります。

ステップ1:クラスモジュールの作成

VBAエディタを開き、メニューの `挿入` > `クラス モジュール` をクリックします。プロパティウィンドウで、このモジュールの名前を `CAppEvents` に変更してください。

そこに以下のコードを貼り付けます。

‘ =================================================================
‘ クラス名: CAppEvents
‘ 役割: Word全体の「保存」と「印刷」の動きを監視し、ルール違反を阻止する
‘ =================================================================

‘ WithEventsキーワードを使い、Wordアプリのイベントを受け取れるようにする
Public WithEvents WordApp As Word.Application

‘ 文書が保存される「直前」に発火するイベント
Private Sub WordApp_DocumentBeforeSave(ByVal Doc As Document, SaveAsUI As Boolean, Cancel As Boolean)

‘ デバッグ用(イミディエイトウィンドウに文書名を出力)
Debug.Print “保存イベント検知: ” & Doc.Name

‘ ルールチェック:先頭の段落が空、または空白スペースだけか?
Dim firstParagraph As String
firstParagraph = Trim(Doc.Paragraphs(1).Range.Text)

‘ 改行コード(vbCrなど)を取り除く処理
firstParagraph = Replace(firstParagraph, vbCr, “”)
firstParagraph = Replace(firstParagraph, vbLf, “”)

If firstParagraph = “” Then
‘ 【違反検知】
MsgBox “【保存エラー】” & vbCrLf & _
“この文書にはタイトル(先頭の段落)が入力されていません!” & vbCrLf & _
“保存を中止します。”, vbCritical + vbOKOnly, “品質管理システム”

‘ CancelにTrueを代入することで、Wordの保存処理を強制キャンセルする!
Cancel = True
End If

End Sub

‘ 印刷される「直前」に発火するイベント(おまけのセキュリティ監視)
Private Sub WordApp_DocumentBeforePrint(ByVal Doc As Document, Cancel As Boolean)

‘ 例:特定のワードが含まれていないと印刷させない、などの応用も可能
‘ 今回はログ出力のみ
Debug.Print “印刷イベント検知: ” & Doc.Name

End Sub

ステップ2:標準モジュールでエージェントを起動する

次に、通常の `挿入` > `標準モジュール` を追加し、名前を `MainModule` とします。ここに、エージェントを目覚めさせるコードを書きます。

‘ =================================================================
‘ 標準モジュール: MainModule
‘ 役割: 監視エージェントをメモリ上に常駐させる
‘ =================================================================

‘ グローバル変数としてエージェントを宣言(変数が消えないようにする)
Public MonitoredApp As CAppEvents

Sub StartAppMonitoring()
‘ すでに起動していなければ、新しいエージェントインスタンスを作成
If MonitoredApp Is Nothing Then
Set MonitoredApp = New CAppEvents
‘ WordのApplicationをエージェントに紐付ける
Set MonitoredApp.WordApp = Word.Application

MsgBox “Wordの保存・印刷監視システムが稼働を開始しました。”, vbInformation, “起動完了”
Else
MsgBox “監視システムはすでに稼働中です。”, vbInformation, “確認”
End If
End Sub

Sub StopAppMonitoring()
‘ エージェントを解放する
Set MonitoredApp = Nothing
MsgBox “監視システムを停止しました。”, vbInformation, “停止完了”
End Sub

5. 動作確認と「陥りやすいエラー」の回避策

1. まず、`StartAppMonitoring` マクロを手動で1回実行してください(これで監視がスタートします)。
2. 新規のWord文書を開き、何も書かずにそのまま「上書き保存(Ctrl + S)」を試してみてください。
3. ジャジャーン! メッセージボックスがポップアップし、保存がガッチリとブロックされます。

⚠️ ここでよくある罠(初心者が必ずハマるポイント)

> 「あれ? マクロを実行したときは動いたのに、Wordをしばらく触っていたら監視が効かなくなった……」

これ、VBAのイベント開発で最も多い挫折ポイントです。
標準モジュールで宣言した `Public MonitoredApp As CAppEvents` は、エラーが発生したり、VBAの実行がリセットされたりすると、メモリから消滅(アンロード)してしまいます。これを「変数の初期化(リセット)」と呼びます。

実務でこのシステムを運用する場合は、Word起動時に自動実行される特殊なプロシージャ `AutoExec` を組み合わせて、Wordの立ち上がりと同時に監視がスタートする仕組みを組むのがプロの技です。

‘ Word起動時に自動で監視をスタートさせるおまじない
Sub AutoExec()
StartAppMonitoring
End Sub

6. おわりに

今回は、Applicationオブジェクトを使ったイベントハンドラで、文書の保存を物理的にブロックする強力な手法を解説しました。

  • オブジェクトの親玉(Application)を監視することで、アプリ全体をコントロールできる。
  • `WithEvents` を使ったクラスモジュールでイベントをキャッチする。
  • イベントプロシージャの `Cancel = True` で、ユーザーの不正なアクションをねじ伏せる。

この設計思想が頭に入れば、単なるマクロ職人から、組織の業務インフラを支える「自動化エンジニア」へ確実にステップアップできます。

ぜひあなたの現場でも、セキュリティや品質管理のガードマンとして導入してみてくださいね。それでは、次の極限の知見でお会いしましょう!

タイトルとURLをコピーしました