【Word VBA】行高自動調整の「その先」へ—レイアウト崩れを根絶するメモリ最適化の極意
Wordの表(Table)を扱う際、「文字量に応じて行の高さを自動調整する」という要件は、一見すると初歩的な課題に見える。しかし、数千行規模の帳票や、外部システムから流し込まれた不定形のテキストを扱う際、Wordのレンダリングエンジンはしばしば悲鳴を上げる。
我々プロフェッショナルは、単に`Row.HeightRule = wdRowHeightAuto`を設定するだけでは満足しない。なぜなら、Wordの表は「オブジェクトの断片化」によるメモリリークや、再描画時のパフォーマンス低下を招きやすいからだ。
今回は、堅牢かつ高速な表操作を実現するための、エンジニア視点での「行高自動調整」の真髄を解説する。
—
1. なぜ「自動調整」でレイアウトが崩壊するのか
Wordにおいて、行の高さが「固定(wdRowHeightExactly)」であるか「自動(wdRowHeightAuto)」であるかは、単なる見た目の問題ではない。これはWordのレイアウトエンジンに対する「再計算の許可」を意味する。
数千行のテーブルで全行を再計算させると、Wordの内部DOM(Document Object Model)は複雑な再帰処理を行い、結果としてUIがフリーズする。特に、「セル内結合」と「自動改行」が混在する環境では、計算コストが指数関数的に増大する。
極限の知見:再描画の抑制
大規模な表操作を行う際は、必ず以下の定石を徹底せよ。
- `Application.ScreenUpdating = False` は必須だが、さらに `ActiveDocument.UndoClear` を併用し、Undoスタックへのオブジェクト保存を一時的に抑制することが、メモリ枯渇を防ぐ鍵となる。
—
2. 実装:パフォーマンスを追求した行高制御
以下のコードは、単なるプロパティ設定を超え、オブジェクトの生存期間を意識した設計となっている。
Option Explicit
”’
”’
Public Sub OptimizeTableRowHeight(ByRef targetTable As Table)
‘ オブジェクトの明示的解放とエラーハンドリングの徹底
On Error GoTo Cleanup
‘ 再描画とヒストリースタックの抑制
Application.ScreenUpdating = False
ActiveDocument.UndoClear
Dim rowItem As Row
For Each rowItem In targetTable.Rows
‘ 既にwdRowHeightAutoであればスキップし、不要なプロパティ書き込みを避ける
‘ 変更が必要な行のみにアクセスすることがパフォーマンスの要諦
If rowItem.HeightRule <> wdRowHeightAuto Then
rowItem.HeightRule = wdRowHeightAuto
End If
Next rowItem
Cleanup:
‘ 明示的にオブジェクトを破棄(VBAでは参照カウンタの解放を促す)
Set rowItem = Nothing
Application.ScreenUpdating = True
If Err.Number <> 0 Then
Debug.Print “Error: ” & Err.Description
End If
End Sub
—
3. レガシーシステム連携時の「落とし穴」
社内システムや外部DBからデータを流し込む際、もっとも警戒すべきは「改行コードの混入」である。
Wordのテーブルにおいて、テキストに `vbCr`(キャリッジリターン)が含まれると、行高が自動であっても「セル内の行数」として扱われる。このとき、前述の `wdRowHeightAuto` を適用していても、Wordが内部的に「この行は高さが可変である」と認識するまでに、予期せぬスクロールバーの出現やレイアウトのガタつきが発生することがある。
回避策:Windows APIの活用
もし、特定のセルが極端に長くなる可能性がある場合、Windows APIの `SendMessage` を使用して、Wordのウィンドウ更新を強制的に同期させるテクニックがある。しかし、これはWordの安定性を損なうリスクがあるため、推奨されるのは「行高設定後に、対象範囲の `Range.Information(wdVerticalPositionRelativeToPage)` を参照すること」だ。このプロパティにアクセスすることで、Wordに強制的にレイアウト計算を完了させることができる。
—
4. チーフアーキテクトからの提言
あなたがこれから保守・開発するシステムにおいて、Word VBAは単なる「事務作業の自動化」ではない。それは、複雑なドキュメント構造という「巨大なメモリ構造体」を制御するタスクだ。
- オブジェクトの再利用: `Selection` オブジェクトを極力避け、`Range` オブジェクトを直接操作せよ。`Selection` はUIと同期するため、極めて低速である。
- メモリの解放: `Set obj = Nothing` は、VBAにおいては「気休め」に近いが、大規模なループ処理において参照カウンタを適切に下げることは、Wordのプロセスが肥大化するのを遅らせる。
- 例外処理の構造化: 巨大な表操作は途中でクラッシュするリスクがある。必ず `Err.Number` を監視し、途中で止まってもドキュメントが破損しないよう、安全な状態を維持するロジックを組むこと。
Wordの行高調整は、単純な設定に見えて、実はエンジニアの「誠実さ」が出る場所だ。コードを書き終えたとき、それがただ動くだけのものではなく、後続のメンテナンスを考慮した「静かなる傑作」であることを期待する。
