【Word VBA】Undoの壁を突破せよ:UndoRecordで実装する「プロフェッショナルな自動化」
Word VBAでの自動化において、多くの開発者が突き当たる「見えない壁」がある。それは、「マクロを実行すると、Ctrl+Z(元に戻す)が効かなくなり、ユーザーに操作の取り消しを許さない」という仕様だ。
数百行の段落装飾を一括で行うツールを作った際、たった一度のミスでドキュメントが崩壊し、Ctrl+Zを押しても「元に戻す操作はありません」と無情に表示される……。これでは、どんなに高機能なツールであっても「実務での信頼」は得られない。
今回は、Word VBAのオブジェクトモデルの深淵である`UndoRecord`オブジェクトを用い、「一連の操作を一つのUndo単位としてパッケージングする」極限の設計手法を伝授する。
—
なぜマクロは「元に戻す」を破壊するのか
Wordにおいて、VBAの各処理は本来、独立した操作としてスタックに積まれる。しかし、マクロという「ブラックボックス」内で実行される数十〜数千のプロパティ変更は、Wordから見れば個別の編集履歴として処理され、スタックが溢れるか、あるいは「マクロの実行」という一点の操作として統合されず、Undoの整合性が取れなくなるのだ。
この「Undoの断絶」を防ぐ唯一の正攻法が、`Application.UndoRecord`だ。
—
UndoRecordによる堅牢な設計パターン
`UndoRecord`は、開始(StartCustomRecord)から終了(EndCustomRecord)までの処理を、ユーザーにとっての「一つの操作」としてWordの履歴管理に登録する。
プロダクションコード:段落書式の一括適用
以下のコードは、文書内の全段落に対して、スタイルとフォント属性を安全に適用し、かつ「一度の操作で完全に復元可能」にするためのテンプレートである。
Option Explicit
”’
”’
Public Sub ApplySafeFormatting()
Dim undo As UndoRecord
Set undo = Application.UndoRecord
‘ 1. Undoレコードの開始:ここからが「1つの操作」として扱われる
undo.StartCustomRecord “一括書式設定の適用”
On Error GoTo ErrorHandler
‘ 2. 処理の実体
Dim para As Paragraph
For Each para In ActiveDocument.Paragraphs
‘ パフォーマンスを考慮し、範囲オブジェクトを最小限に制御
With para.Range
.Style = “標準”
With .Font
.Name = “游明朝”
.Size = 10.5
.Color = wdColorBlack
End With
End With
Next para
CleanExit:
‘ 3. Undoレコードの終了:必須(これがないとWordが不安定になる)
undo.EndCustomRecord
Exit Sub
ErrorHandler:
‘ エラー発生時はUndoレコードを破棄し、整合性を保つ
undo.EndCustomRecord
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical
Resume CleanExit
End Sub
—
運用上のクリティカルな注意点
1. `EndCustomRecord`の漏れは許されない
もっとも注意すべきは、`On Error GoTo`の設計だ。もし処理の途中でエラーが発生し、`EndCustomRecord`が呼ばれなかった場合、WordのUndoスタックは「開始状態のまま」迷子になる。これによりWord自体がフリーズしたり、以降の操作履歴が完全に消失したりするリスクがある。必ず`Exit Sub`前と`ErrorHandler`内の双方でクローズすることを徹底せよ。
2. データベース連携時のトランザクション管理
外部APIやデータベースから取得したデータをWordに流し込む際、UndoRecordと連携させると、「データ取得」と「文書反映」を分離できる。
- 悪い例: ループ内でデータベースを叩き、その都度UndoRecordを生成する(スタックがパンクする)。
- 良い例: データを変数配列に全量ロードし、Wordへの書き込みフェーズのみを`UndoRecord`で囲む。
3. パフォーマンスへの影響
`UndoRecord`はメモリ上に編集履歴を保持する。数万行の段落を一度に処理する場合、Undoスタックの肥大化がメモリ不足を招くことがある。巨大な文書を扱う場合は、`Application.ScreenUpdating = False`を併用し、描画負荷を抑えつつ処理速度を稼ぐのが定石だ。
—
結論:エンジニアの誇りとして
「動けばいいコード」は、数ヶ月後の自分や運用者にとっての地雷でしかない。
`UndoRecord`の活用は、単なる機能要件ではなく、ユーザーに対する「もしミスをしても、君を元の場所へ連れ戻せる」というエンジニアリングの誠実さである。
Word VBAを極めるということは、Wordの内部スタックと対話することに他ならない。この実装パターンを標準装備し、あなたの書くコードに「プロフェッショナルの品格」を宿らせてほしい。
