【実務・中級編】【中級者向け】表のセル内に配置された図形(オートシェイプ)を全削除するクリーンアップ – Word VBA解析バイブル

スポンサーリンク

—

Word VBA 聖典:表(Table)の純潔を保て。セル内図形を「根こそぎ」かつ「安全」に抹殺するクリーンアップ術

業務自動化の現場において、Wordの「表(Table)」は最も厄介な戦場の一つだ。
数値やテキストを流し込む際、前任者が手動で置いた「謎のオートシェイプ」や、コピペ時に混入した「透明なテキストボックス」がレイアウトを破壊し、最悪の場合、自動生成ロジックをクラッシュさせる。

諸君、単に「図形を消す」という行為を甘く見てはいけない。
`ActiveDocument.Shapes` を無策にループさせていないか? それでは文書全体の図形を破壊する「無差別爆撃」だ。我々が求めるのは、特定の表、あるいは特定のセルという限定された空間を、完全に制御下に置く外科手術的なクリーンアップである。

今回は、Word VBAのアーキテクチャを深く理解し、保守性と堅牢性を極限まで高めた「表内図形削除ロジック」を伝授する。

—

1. なぜ「単純なループ」は現場で通用しないのか

中級者へのステップアップとして、まずは以下の「アンチパターン」を理解せよ。

アンチパターン A:インデックス昇順の削除

‘ 失敗するコードの典型
For i = 1 To oTable.Range.ShapeRange.Count
oTable.Range.ShapeRange(i).Delete
Next i

これは初歩的なミスだ。要素を削除するとコレクションのインデックスが詰められるため、1つ飛ばしで削除漏れが発生する。「削除は常に末尾(Step -1)から」。これは鉄則だ。

アンチパターン B:Shape と InlineShape の混同

Wordには「浮遊している図形 (Shape)」と「文章の一部として振る舞う図形 (InlineShape)」の2種類が存在する。これらは格納されているコレクションが異なる。片方だけを掃除しても、もう片方が残っていればそれは「バグ」と呼ばれる。

アンチパターン C:スコープの欠如

`ActiveDocument.Shapes` を対象にするのは、設計思想として「疎結合」に反する。特定のテーブルを操作するメソッドは、そのテーブルの `Range` 内に閉じるべきだ。

—

2. 堅牢な設計:TableRange プロトコル

実務に耐えうるコードを書くには、以下の3つのレイヤーで思考せよ。

1. Scope(範囲)の特定: `Table.Range` もしくは `Cell.Range` を起点にする。
2. Type(型)の網羅: `Shapes` と `InlineShapes` の双方を走査する。
3. State(状態)の管理: 画面更新の停止、Undoバッファの考慮。

—

3. プロダクション・コード:Table Shape Purge Engine

このコードは、単にコピペして動くだけではない。拡張性と保守性を考慮し、特定の表オブジェクトを引数に取るプロシージャとして設計している。

”’

”’ 指定されたテーブル内の全図形(Shape/InlineShape)をクリーンアップする
”’

”’ 対象のWord.Tableオブジェクト Public Sub PurgeShapesInTable(ByRef targetTable As Word.Table)
If targetTable Is Nothing Then Exit Sub

On Error GoTo ErrorHandler

‘ パフォーマンス最適化:画面更新を停止
Application.ScreenUpdating = False

Dim i As Long

‘ 1. InlineShapes(行内図形)の削除
‘ InlineShapesはRangeオブジェクトから直接制御するのが最も安全
With targetTable.Range.InlineShapes
For i = .Count To 1 Step -1
.Item(i).Delete
Next i
End With

‘ 2. Shapes(浮遊図形)の削除
‘ Wordの仕様上、ShapeはAnchor(アンカー)がそのRange内にあるものを対象とする
‘ ShapeRangeプロパティを使用して一括制御を試みる
Dim rngTable As Word.Range
Set rngTable = targetTable.Range

‘ ShapeRangeは要素ゼロの時にエラーを吐く場合があるため、カウントを確認
If rngTable.ShapeRange.Count > 0 Then
For i = rngTable.ShapeRange.Count To 1 Step -1
rngTable.ShapeRange(i).Delete
Next i
End If

‘ ログ出力(デバッグ用)
Debug.Print “Table Cleanup Completed: ” & Now

CleanUp:
Application.ScreenUpdating = True
Exit Sub

ErrorHandler:
‘ エラーが発生しても画面更新だけは再開させるのがプロの作法
Debug.Print “Error in PurgeShapesInTable: ” & Err.Description
Resume CleanUp
End Sub

実装のポイント解説

1. ByRef targetTable As Word.Table:
グローバル変数や `ActiveDocument` に依存せず、対象を明示的に受け取る。これにより、ループ内で複数の表を処理する際も、ロジックを再利用できる。
2. Two-Step Deletion:
`InlineShapes` と `Shapes` を別々に処理している。これらは物理的な管理構造が異なるため、確実に消し去るにはこの分離が必要だ。
3. ShapeRange のトラップ回避:
`targetTable.Range.ShapeRange` は、その表の範囲内に「アンカー(碇)」が置かれている図形をすべて捕捉する。手動でセル内に配置された図形は通常ここに紐付いている。

—

4. 業務効率化ツールへの組み込み例

実際に、データベースやExcelから数値を流し込む前に、このクリーンアップを呼び出す実装イメージだ。

Sub GenerateMonthlyReport()
Dim doc As Word.Document
Set doc = ActiveDocument

Dim tbl As Word.Table
‘ 文書内の最初の表をターゲットにする(実務ではタグやブックマークで特定せよ)
Set tbl = doc.Tables(1)

‘ — 前処理:ゴミ掃除 —
PurgeShapesInTable tbl

‘ — 本処理:データの流し込み —
tbl.Cell(1, 2).Range.Text = “2023年度 営業利益”
‘ … 続く
End Sub

—

5. チーフアーキテクトからの助言:ファイル連携の注意点

Wordの表は、Excelと異なり「セルの中にさらに構造(段落やセクション)」を持つ。図形を削除した際、セル内に余計な改行(段落マーク)が残ることがある。

もし、図形を消した後に「セルの高さを最小限に詰めたい」のであれば、削除後に `Paragraphs` の間隔や、`Cells.VerticalAlignment` を再設定するロジックを追加すべきだ。

また、大規模な文書(数百ページ、数百個の表)を扱う場合、`Shape.Delete` は非常に重い処理になる。その場合は、`Undo` スタックをクリアするために、定期的に保存 (`Document.Save`) を挟むか、一度ファイルを閉じて開き直す運用も検討に値する。

結言

「動けばいい」コードと「保守に耐える」コードの差は、こうした「見えないオブジェクト(Shape)」への想像力にある。
今回提供した `PurgeShapesInTable` は、貴殿のプロジェクトにおける「表操作の標準ライブラリ」として機能するはずだ。

表の純潔を保ち、完璧な自動生成を実現せよ。それがエンジニアとしての矜持だ。

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