【テクニカル・上級編】【初心者向け】Rangeオブジェクトで特定の段落だけをピンポイントで太字にする基本操作 – Word VBA解析バイブル

スポンサーリンク

Word VBAを掌握する極限の知見:Selectionを絶滅させよ。Rangeオブジェクトで特定段落を狙い撃つ高速自動装飾

Word VBAの開発現場において、未だに画面のカーソル移動や選択(`Selection`)を伴うコードを目にすることがある。これはエンジニアリングの観点から言えば、ガソリンを垂れ流しながら走る古いトラックのようなものだ。画面描画(UIスレッドへの介入)が発生し、処理速度は桁違いに落ち、メモリ効率も最悪となる。

真にスケーラブルで堅牢なWord自動化システムを構築したいのであれば、画面を一切汚さずにメモリ上で文書構造を支配する`Range`オブジェクトの概念をマスターしなければならない。

今回は、初心者から一歩抜け出し、実務で通用する「特定のキーワードを含む段落のピンポイント太字化」を題材に、Word VBAの根本思想を解説する。

1. なぜ `Selection` は悪なのか? —— アーキテクチャの視点

Wordのオブジェクトモデルには、大きく分けて `Selection` と `Range` の2つのアプローチが存在する。

  • `Selection`(選択範囲): ユーザーが画面上でマウスやキーボードを使って選択している「視覚的な状態」をコードから操作するもの。UIとの同期が必要なため、描画コスト(重い)が発生し、予期せぬスクロールやフォーカス泥棒を引き起こす。
  • `Range`(範囲): 文書内の文字位置(開始文字位置と終了文字位置)を指し示す、メモリ上の「抽象的なポインタ」。画面描画を伴わず、バックグラウンドで高速かつ安全に文字列や書式を操作できる。

大量の段落を持つ仕様書や契約書を処理する場合、`Selection.Find` を使ったループを書けば数秒〜数十秒かかる処理も、`Range` ベースであれば一瞬で完了する。この処理速度の差は、システム連携やバッチ処理において致命的なアドバンテージとなる。

2. 実装:高速キーワード検索とピンポイント書式設定

以下のコードは、文書全体を走査し、指定したキーワードが含まれる段落の`Range`を特定した上で、書式(太字)を高速に適用する実用的なプロシージャである。

余計なオブジェクトの残留を防ぐため、ループ内でのメモリ管理にも配慮した実践的な構造にしている。

Option Explicit

‘ ==============================================================================
‘ 処理名: 指定キーワードを含む段落をRangeでピンポイント太字化する
‘ 著 者: チーフアーキテクト
‘ 概 要: Selectionを一切使用せず、メモリ上で完結させる高速・安全な一括装飾
‘ ==============================================================================
Public Sub HighlightTargetParagraphs()
‘ 1. 定数の定義
Const TARGET_KEYWORD As String = “【重要】”

‘ 2. 変数の宣言と初期化
Dim docTarget As Document
Dim rngTarget As Range
Dim para As Paragraph
Dim processedCount As Long

Set docTarget = ActiveDocument
processedCount = 0

‘ 3. 画面描画のロック(パフォーマンス劇的向上のための極意)
Application.ScreenUpdating = False
Application.DisplayAlerts = wdAlertsNone

On Error GoTo ErrorHandler

‘ 4. 段落コレクションを高速イテレーション
For Each para In docTarget.Paragraphs
‘ 各段落のRangeオブジェクトを取得
Set rngTarget = para.Range

‘ 指定キーワードが含まれているか判定
‘ ※ 文末の段落記号(Paragraph Mark)を除外するためにTrimまたはInStrを活用
If InStr(1, rngTarget.Text, TARGET_KEYWORD, vbTextCompare) > 0 Then

‘ 【重要】段落末尾の改行コード(vbCr)まで太字にしないための調整
‘ Rangeの終了位置を1文字手前に縮めることで、段落の改行汚染を防ぐ
rngTarget.End = rngTarget.End – 1

‘ フォントの太字化
rngTarget.Font.Bold = True

‘ 必要であれば文字色や背景色の変更もここで可能
‘ rngTarget.Font.Color = wdColorRed

processedCount = processedCount + 1
End If

‘ ループ内でのメモリ解放(参照の破棄)
Set rngTarget = Nothing
Next para

‘ 5. 完了通知
Application.ScreenUpdating = True
MsgBox “処理が完了しました。” & vbCrLf & _
“対象キーワード「” & TARGET_KEYWORD & “」を含む ” & _
processedCount & ” 件の段落を太字に設定しました。”, _
vbInformation, “システム通知”

CleanUp:
‘ 確実なオブジェクト解放とUI復帰
Set rngTarget = Nothing
Set para = Nothing
Set docTarget = Nothing
Application.ScreenUpdating = True
Application.DisplayAlerts = wdAlertsAll
Exit Sub

ErrorHandler:
‘ 異常系ハンドリング
MsgBox “予期せぬエラーが発生しました。” & vbCrLf & _
“Error: ” & Err.Description, vbCritical, “致命的エラー”
Resume CleanUp
End Sub

3. チーフアーキテクトが解説するコードの急所

このコードには、レガシーなVBAプログラミングの悪癖を排除し、極限までパフォーマンスと安定性を高めるための設計思想が凝縮されている。

① `Application.ScreenUpdating = False` の絶対性

Word VBAの処理が遅いと感じる原因の8割は、コードの実行に伴うGUIの再描画(Wordが画面を書き換えようとする動作)にある。これを `False` にすることで、Wordは画面描画の演算を完全に停止し、メモリ上のデータ処理に全リソースを集中させる。処理の最後には必ず `True` に戻すエラーハンドリングをセットで記述すること。

② 段落記号(`vbCr`)の罠と `Range.End` の調整

段落全体(`para.Range`)をそのまま `Bold = True` にすると、段落の末尾にある不可視の改行コード(Paragraph Mark)まで太字の属性を持ってしまう
これを放置すると、後続の段落と結合した際にスタイルが崩れるなどの致命的な不具合の温床となる。
`rngTarget.End = rngTarget.End – 1` という1行により、純粋な「文字列部分のみ」にスコープを絞り込んでいる。この細部へのこだわりこそが、システム連携時におけるバグをゼロにする。

③ 徹底的なオブジェクトの解放

VBAはガベージコレクションの挙動が非力である。ループ内で `Set rngTarget = para.Range` と再割り当てを行う際、古い参照がメモリ上に残り続けると、巨大なファイルを処理した際にメモリリーク(メモリ枯渇エラー)を引き起こす可能性がある。
ループの都度 `Set rngTarget = Nothing` を挟み、プロシージャ終了時にも確実に参照を切る。これがエンタープライズ品質のコードだ。

総括

今回解説した `Range` オブジェクトの操作と、画面描画の抑制、そしてオブジェクトの適切なライフサイクル管理は、Word VBAを「お遊びのマクロ」から「実用に耐えうる基幹システムの一部」へと昇華させるための基礎体力である。

`Selection` に別れを告げ、メモリを直接支配する高効率なコード設計をあなたの開発標準としてほしい。

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