【上級者向け】Word表の変更をリアルタイムで監視し、ログを記録するイベント駆動型VBA
こんにちは。チーフアーキテクトの私だ。
これまで数々の巨大なWord帳票自動化プロジェクトを統括してきたが、現場からもっとも多く寄せられる悲鳴のような要望がこれだ。
「ユーザーがWordの表を勝手に書き換えた。いつ、誰が、どこをどう変えたのか、その履歴をリアルタイムで自動記録してほしい」
Excelであればシートの変更イベント(`SheetChange`)を叩けば一撃だが、Wordの世界には「表のセルが書き換わった瞬間」を捉える専用のイベントは存在しない。表(`Table`)オブジェクト自体にはイベントがないのだ。これが、多くの開発者を絶望の淵に追いやってきた。
だが、諦める必要はない。Wordのイベントモデルとコンテンツコントロール(Content Control)、そしてオブジェクトのライフサイクルを深く理解していれば、極めて堅牢な「表のリアルタイム監視・ログ記録システム」を構築できる。
今回は、実務の現場でそのまま稼働するプロダクションコードとともに、そのアーキテクトの知見を授けよう。
—
1. なぜ「ポーリング」や「保存時チェック」ではダメなのか?
素人設計のシステムでは、ドキュメントを閉じる時(`Document_Close`)に元のデータと現在のデータを比較して差分を取ろうとする。あるいは、タイマーで定期的に表を監視する(ポーリング)愚を犯す者もいる。
だが、それはプロの仕事ではない。
- パフォーマンスの劣化: 巨大な表を常時スキャンすれば、タイピングのたびにWordがフリーズする。
- トレーサビリティの喪失: 「いつ」の正確なタイムスタンプが取れない。クラッシュした瞬間の変更は闇の中だ。
我々が目指すべきは、ユーザーが入力した「その瞬間」にフックをかけ、変更を不可逆なログとして刻むイベント駆動型アーキテクトである。
—
2. アーキテクチャ設計:表を監視する「2つの武器」
Wordで表の入力を監視するには、以下の2つの要素を組み合わせる。
1. コンテンツコントロール(RichText / PlainText):
表のセルの中にコンテンツコントロールを埋め込み、その「編集完了時」のイベントをキャプチャする。
2. `Document_ContentControlOnExit` イベント:
ユーザーがコントロールからフォーマットを外した瞬間(フォーカスを失った瞬間)に発火するグローバルイベントを利用する。
これにより、「どの表の、何行何列目が、どう変わったか」をピンポイントで特定することが可能になる。
—
3. プロダクションコード実装
以下のコードは、単なるサンプルではない。エラーハンドリング、オブジェクトの解放、そして実務に耐えうる堅牢性を備えた実践的なコードだ。
① ThisDocumentモジュール(イベント受け渡し)
Wordの標準イベントをキャプチャするため、必ず `ThisDocument` クラスモジュールに記述すること。
Option Explicit
‘ =================================================================
‘ 1. Document_ContentControlOnExit イベント
‘ ユーザーが表内のコンテンツコントロールからカーソルを外した瞬間に発火
‘ =================================================================
Private Sub Document_ContentControlOnExit(ByVal ContentControl As ContentControl, ByRef Cancel As Boolean)
On Error GoTo ErrorHandler
‘ 監視対象のコンテンツコントロールかチェック(タグで識別)
If ContentControl.Tag = “LoggableCell” Then
‘ ログ記録モジュールの呼び出し
Call TableAuditLogger.RecordChange(ContentControl)
End If
Exit Sub
ErrorHandler:
MsgBox “ログ記録中に予期せぬエラーが発生しました: ” & Err.Description, vbCritical, “監査システム”
End Sub
② 標準モジュール:TableAuditLogger(ログ記録の核心)
変更検知時の差分計算と、外部ログファイル(CSV等)への非同期的な書き込みを担当する。
Option Explicit
‘ ログファイルの出力先(実務ではネットワークパスやDB接続文字列に変更すること)
Private Const LOG_FILE_PATH As String = “C:\WordAuditLogs\TableChangeHistory.csv”
Public Sub RecordChange(ByVal cc As ContentControl)
Dim cell As cell
Dim tbl As Table
Dim rowIdx As Long, colIdx As Long
Dim currentText As String
Dim timestamp As String
‘ オブジェクトの階層構造を辿り、親のセルと表を特定する
On Error Resume Next
Set cell = cc.Range.Cells(1)
If cell Is Nothing Then Exit Sub
Set tbl = cell.Range.Tables(1)
On Error GoTo 0
If tbl Is Nothing Then Exit Sub
‘ 行番号と列番号の特定
rowIdx = cell.RowIndex
colIdx = cell.ColumnIndex
currentText = cc.Range.Text
timestamp = Format(Now, “yyyy-mm-dd hh:nn:ss”)
‘ ログの書き出し(CSV形式:日時, ユーザー名, 表ID, 行, 列, 変更後テキスト)
Call WriteLogToCSV(timestamp, Environ(“USERNAME”), tbl.ID, rowIdx, colIdx, currentText)
‘ デバッグ用(実務では削除またはステータスバー表示に変更)
‘ StatusBar = “表の変更を記録しました: 行 ” & rowIdx & ” 列 ” & colIdx
End Sub
Private Sub WriteLogToCSV(ts As String, user As String, tblId As String, r As Long, c As Long, val As String)
Dim fileNum As Integer
fileNum = FreeFile
‘ 改行コードやカンマによるCSV崩れを防ぐためのサニタイズ処理
val = Replace(val, vbCr, ” “)
val = Replace(val, vbLf, “”)
val = Replace(val, “,”, “,”) ‘ 全角カンマに置換
‘ ファイル存在チェックと追記オープン
Open LOG_FILE_PATH For Append As #fileNum
Print #fileNum, ts & “,” & user & “,” & tblId & “,” & r & “,” & c & “,” & “””” & val & “”””
Close #fileNum
End Sub
—
4. 現場で絶対に押さえておくべき「3つの罠」
この仕組みを導入する際、素人が必ずハマる地雷がいくつかある。チーフとして事前に解除法を伝授しよう。
罠1: セル内のテキスト変更で改行コードが混入する
ユーザーがセル内で `Shift + Enter` を押すと、Wordは段落区切り(`vbCr`)を挿入する。これがそのままCSVログき書き込まれると、ログの行が盛大に崩壊する。
- 対策: 上記コードのように、サニタイズ処理(`Replace`)を必ず挟むこと。
罠2: ユーザーがコントロール自体を削除してしまう
コンテンツコントロールは、ユーザーがバックスペースを連打すると、枠ごと消し飛ぶことがある。枠が消えると次からイベントが発火しなくなる。
- 対策: ドキュメント保護機能(EditingRestrictions)をかけ、ユーザーがデザインやコントロール構造自体を破壊できないようロックをかけるのがプロの鉄則だ。
罠3: パフォーマンスとファイルロック
複数人が同時にネットワーク上のWordファイルを編集し、一斉にログを吐き出そうとすると、`Open For Append` でファイル競合エラー(Error 70: 書き込み権限がありません)が発生する。
- 対策: 本番環境では、ローカルのテンポラリに書き出すか、ADO経由でSQLiteやSQL ServerなどのRDBへ非同期(またはトランザクション制御下で)インサートする設計に昇華させるべきだ。
—
5. まとめ
Word VBAは「レガシーな言語」と揶揄されることがある。だが、オブジェクトモデルの挙動を完全に支配し、適切なイベントとフックを設計すれば、モダンなWebアプリケーショングレードのトレーサビリティシステムを構築できる。
今回紹介したイベント駆動型アプローチは、単なる「表の監視」にとどまらず、金融・医療・法務分野における厳格なドキュメント統制(コンプライアンス対応)の強力な武器となる。
あなたの開発するWordソリューションに、この堅牢性をぜひ組み込んでみてほしい。エンジニアとしての真価が試されるはずだ。
