【テクニカル・上級編】Word VBAでフォントや段落設定を高速に変更する:Range.FormattedTextの活用と書式コピーの極意 – Word VBA解析バイブル

スポンサーリンク

Word VBAの深淵:Range.FormattedTextがもたらす「書式最適化」の極意

Wordの自動化に携わる多くのエンジニアが、初学者の段階で「Selection」という呪縛に囚われ、`.Font.Size = 12` といった個別のプロパティ設定を繰り返すループに陥る。しかし、ドキュメントの規模が数千ページ、あるいは複雑なXML構造を持つレガシー文書のパースを扱うとき、そのアプローチはシステムを死に至らしめる。

今日は、Wordのレンダリングエンジンを制御し、メモリ効率を極限まで高めるための「FormattedTextによる一括転送」という解法を共有する。

1. なぜ個別のプロパティ設定は「悪」なのか

`Range.Font` や `Range.ParagraphFormat` を逐次呼び出すことは、内部的なCOM呼び出し(マーシャリング)を増大させる。WordのDOM(Document Object Model)は、プロパティ一つを変えるたびに再計算をトリガーする可能性がある。

数万回のループでこれを実行すれば、UIスレッドは固まり、Windows API経由のイベントハンドラは悲鳴を上げる。真のアーキテクトは、「状態の更新」を最小化し、「メモリブロックのコピー」へ昇華させる。

2. FormattedTextによる「書式転送」の真髄

`FormattedText` プロパティは、Rangeオブジェクトが持つ文字データと、それに付随するすべての書式情報を保持する独立したRangeを返す。これを活用すれば、あるRangeの書式を別の場所へ「一瞬」で伝播させることが可能だ。

実践コード:書式の一括コピー

以下のコードは、ターゲットとなるRangeに対して、ソースのRangeから書式のみをバイナリに近いレベルで適用する最適解だ。

‘ 伝説的なチーフアーキテクトによる書式転送ルーチン
Public Sub ApplyFormatEfficiently(ByVal sourceRange As Range, ByVal targetRange As Range)
‘ エラーハンドリングは最小限に。ただし、COMオブジェクトの生存確認は必須。
If sourceRange Is Nothing Or targetRange Is Nothing Then Exit Sub

‘ 内部的なScreenUpdatingの停止は必須の作法。
‘ これを怠ることはエンジニアとしての怠慢である。
Application.ScreenUpdating = False

‘ 核心部分: FormattedTextを利用した書式転送
‘ 個別プロパティを設定するのではなく、Rangeそのものの書式情報を「代入」する。
‘ これにより、Word内部のCOMスタックの負荷を劇的に低減できる。
targetRange.FormattedText = sourceRange.FormattedText

‘ オブジェクトの明示的解放はVBAの作法だが、RangeはWordの管理下にあるため
‘ Set = Nothing を過剰に行うよりも、スコープの管理に注力せよ。

Application.ScreenUpdating = True
End Sub

3. パフォーマンスを極限まで引き上げるアーキテクトの戒律

① ScreenUpdating と Calculation の制御

処理の前後で必ず `Application.ScreenUpdating = False` と `ActiveDocument.UndoClear` を組み合わせる。特に大規模な置換処理を行う際、Undoバッファの増大はメモリリークの原因となる。

② 早すぎる最適化を避け、しかし「型」にはこだわる

`Range` オブジェクトをループ内で何度も取得するな。`Set rng = ActiveDocument.Range(0, 0)` のように、一度取得したRangeの `Start` と `End` を `MoveStart` / `MoveEnd` でオフセット制御する方が、メモリポインタの再生成コストを抑えられる。

③ COMオブジェクトの生存確認

レガシーシステムとの連携時、Wordが背後でクラッシュし、ゾンビプロセスが残ることがある。`On Error Resume Next` で逃げるのではなく、`Err.Number` を監視し、必要であれば `GetObject` でインスタンスを再アタッチする堅牢なラッパーを書くこと。

4. 終わりに:ツールを超えた思想を

Word VBAは「古い」と揶揄されることがあるが、それはこのエンジンの奥底に眠る「Range」と「Story」の概念を理解していない者の戯言だ。

個別のプロパティをいじるのは「点」の操作に過ぎない。`FormattedText` を操ることは「面」としてのドキュメントを制御することだ。皆さんが直面しているそのレガシーな巨大文書も、このアプローチであれば、数秒の処理時間で完璧に制御下に置けるはずだ。

技術は常に、あなたの記述するコードの「行間」に宿る。次のコミットでは、ぜひこの「一括転送」の流儀を導入してほしい。それが、世界最高峰の自動化エンジニアへの第一歩だ。

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