【実務・中級編】Word VBAで『図形(Shape)』のアンカー位置をRangeで制御する:テキストと図形の連動配置 – Word VBA解析バイブル

スポンサーリンク

Word VBAの悪夢を終わらせる:ShapeとRangeの「絶対結合」技術

Word VBAを触るエンジニアの多くが、最初の数週間で深い絶望を味わう。「なぜ図形は勝手にどこかへ飛んでいくのか」「なぜRangeを指定したはずなのに、図形が文書の先頭に張り付くのか」。

結論から言おう。Wordのオブジェクトモデルにおいて、`Shape`は`Range`の「子供」ではない。`Canvas`という別の次元に住む存在だ。こいつをテキストの流れ(`Range`)に完璧に同期させるためには、Wordが裏側で何をしているかという「アンカー」の概念を掌握しなければならない。

今日は、業務自動化ツールを開発する諸君に向けて、図形をテキストに物理的に追従させる「極限の制御術」を伝授する。

1. なぜ「行」を基準にしてはいけないのか

初心者はよく `Selection` を使って図形を挿入する。だが、これはプロの所業ではない。`Selection`は表示状態に依存し、ユーザーが画面をスクロールしただけで崩壊する脆いオブジェクトだ。

図形をテキストに連動させるには、「アンカー(Anchor)」という概念を理解する必要がある。

  • Shape: ページ上の座標を持つ存在
  • Anchor: その図形が所属するパラグラフ(段落)を示すRange

図形を動的に生成する際、`Anchor`を明示的に指定しないと、Wordはデフォルトで「現在の段落」をアンカーにする。だが、テキストの挿入や削除で段落が再計算される際、この紐付けが解けて図形が迷子になることが多々ある。

2. 堅牢な「テキスト連動型」図形生成コード

実務で使える、保守性の高いプロダクションコードを提示する。ポイントは `Shapes.AddShape` の `Anchor` 引数に、特定の `Range` を確実に渡すことだ。

‘ @description 特定のキーワードの直後に図形を挿入し、テキストと連動させる
‘ @param targetRange 挿入位置を示すRangeオブジェクト
Public Sub InsertManagedShape(ByVal targetRange As Range)
Dim shp As Shape

‘ 1. Anchorを明確に指定してShapeを生成
‘ Anchor引数にRangeを渡すことで、その段落と物理的な紐付けを行う
Set shp = ActiveDocument.Shapes.AddShape( _
Type:=msoShapeRectangle, _
Left:=0, Top:=0, Width:=100, Height:=50, _
Anchor:=targetRange)

‘ 2. 折り返し設定を「行内(InLine)」または「前面」かを選択
‘ 自動化ツールでは「前面」に置くことが多いが、その場合は必ず相対位置を定義する
With shp
.RelativeHorizontalPosition = wdRelativeHorizontalPositionCharacter
.RelativeVerticalPosition = wdRelativeVerticalPositionParagraph

‘ テキスト移動と追従させるための設定
.LockAnchor = True ‘ 重要:アンカーを固定し、勝手な移動を防ぐ
.WrapFormat.Type = wdWrapSquare
End With

‘ 3. 後始末:Rangeを解放し、メモリリークを防ぐ
Set shp = Nothing
End Sub

3. プロが教える「陥りやすい罠」と回避策

① `.LockAnchor = True` を忘れるな

これを設定しないと、ユーザーが他の箇所で誤って図形をドラッグした際、アンカー位置が別の段落にワープする。ツールで生成した図形は、意図しない変更をさせないのが鉄則だ。

② ファイル連携・DB出力時の「相対パス」の呪い

もしこの図形に画像を挿入する場合(`UserPicture`メソッドなど)、画像パスは必ずフルパスで指定せよ。Wordのオブジェクトモデルは、カレントディレクトリの解釈が不安定だ。DBから取得したパスを`FileSystemObject`で存在チェックしてから渡すのが、堅牢なシステムの共通言語である。

③ パフォーマンスの重み

`Shapes`コレクションへのアクセスは、文書が巨大化するほど重くなる。大量の図形を挿入する場合、`Application.ScreenUpdating = False` を忘れずに行うこと。これだけで処理速度は10倍変わる。

4. アーキテクトからの助言:Rangeを使いこなせ

いいか、良いコードとは「次に修正する誰か(あるいは未来の自分)」が絶望しないコードだ。

図形を配置する際、`ActiveDocument.Content.Find` で検索した結果の `Range` をそのまま `Anchor` に放り込むのは推奨しない。必ず `Range` の `Collapse` メソッドを使い、挿入地点を一点に絞り込んでから処理を開始せよ。

‘ プロのRange操作例
Dim rng As Range
Set rng = ActiveDocument.Content
With rng.Find
.Text = “★挿入地点★”
If .Execute Then
rng.Collapse Direction:=wdCollapseEnd ‘ 検索キーワードの直後に絞る
Call InsertManagedShape(rng)
End If
End With

この設計思想に従えば、図形がページを飛び越えて暴走することはない。Word VBAは「予測不能な挙動」との戦いだが、オブジェクトのライフサイクルと、その配置基準(アンカー)さえ制御下に置けば、これほど強力な自動化武器はない。

さあ、恐れずにコードを書け。ただし、細部への敬意を忘れるな。それが、伝説のエンジニアへの第一歩だ。

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