Word VBAの「Undoの断片化」を撲滅せよ:業務自動化におけるトランザクション設計の極意
VBAで文書を自動整形した際、ユーザーが「Ctrl+Z」を押して、数千回の「Undo(取り消し)」を繰り返した経験はないだろうか?
多くの開発者は、`Paragraph.Range.Font.Bold = True` のようなコードをループで実行する。だが、これはWordのUndoスタックを「ゴミ」で埋め尽くす最悪の設計だ。ユーザーにとって、自動化ツールは「魔法の杖」であるべきであって、「後始末に追われる悪夢」であってはならない。
本稿では、Word VBAにおいて「一連の書式変更を単一のUndo単位としてスタックに統合する」ための、プロフェッショナルな設計手法を伝授する。
—
1. なぜ「個別の変更」は悪手なのか
WordのUndoスタックは、Wordが内部的に監視している「アクション」の履歴だ。VBAで1行ずつプロパティを変更すると、その都度Undoスタックにイベントが積まれる。
- メモリ効率の低下: 数百箇所の変更でスタックが肥大化し、Wordの挙動が重くなる。
- UIの信頼性喪失: ユーザーが「Ctrl+Z」を1回押しても、直前の些細な変更しか戻らない。これでは、自動化ツールが「信頼できない外部プログラム」と見なされる。
我々エンジニアが目指すべきは、「自動化プロセス全体を1つのアトミックな操作(不可分な操作)として定義する」ことである。
—
2. Undoスタックを統合する「Application.UndoRecord」
Word 2013以降、Microsoftは `UndoRecord` オブジェクトを導入した。これを使えば、VBAの処理を任意のラベルで囲い込み、Undoスタック上で1つの操作として結合できる。
実装コード:堅牢な一括書式設定テンプレート
このコードは、指定した範囲内の全段落に対して、スタイルとフォントを一括適用する実務的な雛形だ。
Sub ApplyFormattingWithUndo()
Dim objUndo As UndoRecord
Dim doc As Document
Dim rng As Range
Set doc = ActiveDocument
Set rng = doc.Content
‘ UndoRecordオブジェクトの取得と初期化
Set objUndo = Application.UndoRecord
‘ Undoスタックの開始(名前を付けると履歴に表示される)
objUndo.StartCustomRecord “ドキュメントの一括整形(標準スタイル適用)”
On Error GoTo ErrorHandler
‘ — 実際の処理(ここから) —
With rng.Find
.ClearFormatting
.Replacement.ClearFormatting
.Replacement.Style = wdStyleHeading1
.Text = “ターゲット文字列”
.Replacement.Text = “^&”
.Execute Replace:=wdReplaceAll
End With
‘ — 実際の処理(ここまで) —
‘ Undoスタックの終了
objUndo.EndCustomRecord
Exit Sub
ErrorHandler:
‘ エラー発生時は必ずEndCustomRecordを呼ぶ。さもなくばスタックが壊れる。
If Not objUndo Is Nothing Then objUndo.EndCustomRecord
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical
End Sub
—
3. 実務で「絶対守るべき」3つの鉄則
① エラーハンドリングは「生命線」
`StartCustomRecord` を呼び出した後、VBAがエラーで落ちるとUndoスタックの整合性が取れなくなり、Word自体が不安定になる。必ず `On Error GoTo` を活用し、`EndCustomRecord` が確実に実行される経路を確保すること。
② 画面更新の停止(ScreenUpdating)の併用
Undoスタックの統合と併せて、`Application.ScreenUpdating = False` を必ず行うこと。画面描画を抑えることで、処理速度が飛躍的に向上する。
③ データベース・外部連携時の注意
もし外部データ(ExcelやSQL Server)から値を読み込んでWordを操作する場合、「データ読み込み」と「Wordへの書き込み」の間にUndoRecordを挟んではいけない。
外部通信などの「失敗する可能性のある処理」はスタックの外で行い、Wordのオブジェクトモデルに触れる「確定的な変更」のみを `StartCustomRecord` 内にカプセル化するのが、クリーンな設計の定石だ。
—
結論:ユーザー体験を「設計」せよ
エンジニアの仕事は、コードを動かすことではない。「ユーザーがストレスなく、業務を完遂できる環境を構築すること」にある。
「Ctrl+Z」を1回押せば、苦労して自動化した数十箇所の変更が、まるで元からそうであったかのように消える。その「心地よさ」こそが、あなたのツールが現場で愛され、生き残り続けるための最大の差別化要因になる。
さあ、今すぐ既存のコードに `UndoRecord` を組み込み、あなたの自動化ツールを「伝説」に変えてほしい。
