【テクニカル・上級編】【初心者】Pageオブジェクトを巡回して全図形のテキストを一括置換する:Find & Replaceの自動化 – Visio VBA解析バイブル

スポンサーリンク

Visio自動化の深淵:全ページ・全シェイプを掌握する「テキスト置換」の極意

多くのエンジニアがVisioの自動化に挑み、そして「オブジェクトの迷宮」で挫折する。
特に、ドキュメント全体を走査するような処理は、単にループを回せば良いというものではない。Visioのオブジェクトモデルは、階層が深くなるほどメモリリークのリスクとパフォーマンスの劣化が顕著になるからだ。

今回は、全ページ・全シェイプを走査してテキストを一括置換する処理を題材に、現場で生き残るための「真のアーキテクチャ」を伝授する。

1. Visioオブジェクトモデルの「階層」を理解せよ

Visioの構造は `Application > Document > Page > Shape` という階層構造を持つ。初心者はこの階層を安易にネストするが、大規模なドキュメントではそれが命取りになる。

回避すべき罠

  • 不要な再帰呼び出し: Shapeの中にShape(グループ化)が含まれる場合、再帰処理を適切に行わないとスタックオーバーフローや循環参照を招く。
  • オブジェクトの放置: VBAはガベージコレクションが脆弱だ。`Set obj = Nothing` を怠れば、Visioプロセスが背後で肥大化し、メモリリークの温床となる。

2. 実装:堅牢なテキスト置換エンジン

以下に、実戦投入レベルのコードを示す。ポイントは「再帰的なシェイプ走査」と「オブジェクトの確実な解放」である。

Option Explicit

‘ メイン処理:ドキュメント内の全ページ・全シェイプを走査
Public Sub BatchReplaceText(ByVal findText As String, ByVal replaceText As String)
Dim doc As Visio.Document
Dim pg As Visio.Page
Dim shp As Visio.Shape

Set doc = ActiveDocument

‘ 画面描画を停止し、パフォーマンスを最大化する(重要)
Application.ScreenUpdating = False

On Error GoTo Cleanup

For Each pg In doc.Pages
For Each shp In pg.Shapes
‘ 再帰的にグループ内のシェイプも走査する
Call ProcessShape(shp, findText, replaceText)
Next shp
Next pg

Cleanup:
‘ オブジェクトの明示的解放(伝説的エンジニアの嗜み)
Set shp = Nothing
Set pg = Nothing
Set doc = Nothing
Application.ScreenUpdating = True

If Err.Number <> 0 Then
MsgBox “エラー発生: ” & Err.Description, vbCritical
End If
End Sub

‘ 再帰的なシェイプ走査関数
Private Sub ProcessShape(ByVal shp As Visio.Shape, ByVal findText As String, ByVal replaceText As String)
Dim subShp As Visio.Shape

‘ テキスト置換処理
If InStr(shp.Text, findText) > 0 Then
shp.Text = Replace(shp.Text, findText, replaceText)
End If

‘ グループ化されている場合は再帰的に掘り下げる
If shp.Shapes.Count > 0 Then
For Each subShp In shp.Shapes
Call ProcessShape(subShp, findText, replaceText)
Next subShp
End If

Set subShp = Nothing
End Sub

3. シニアエンジニアが押さえるべき「最適化の要諦」

① `ScreenUpdating` の制御

VisioのAPIはGUIと密接に結合している。ループごとに描画更新が発生すれば、処理時間は指数関数的に増大する。必ず `Application.ScreenUpdating = False` で停止させよ。これはパフォーマンス最適化の基本中の基本だ。

② シェイプの「Text」プロパティの限界

上記のコードは `shp.Text` を使用しているが、これは単純なテキストフィールド用だ。もしシェイプが「フィールド(数式など)」を含む場合、`shp.Text` では置換できないケースがある。
その場合は `shp.Cells(“Prop.xxx”)` や `shp.Characters` オブジェクトを直接操作する低レイヤーな制御が必要となる。これは難易度が跳ね上がるが、真に自動化を極めるならば避けては通れない道だ。

③ Windows APIの活用(発展)

もし数万シェイプを超える巨大ドキュメントを扱う場合、VBAのネイティブ処理ですら遅いと感じる時が来る。その際は、`User32.dll` を呼び出し、ウィンドウのメッセージキューを一時的に停止させるなどのハックが必要となる。

結論:システムは「美しく」あるべきだ

コードは単なる命令の羅列ではない。それはエンジニアの思考そのものだ。
今回提示した「再帰的な走査」と「徹底したオブジェクト管理」は、Visioに限らず、ExcelやWordの自動化にも通ずる普遍的なアーキテクチャである。

レガシーなシステムを保守することは、先人が遺した複雑なコードの意図を汲み取り、それを現代の最適化手法で昇華させる行為に他ならない。貴殿がこのコードをベースに、より強固な自動化基盤を築くことを期待する。

何かあればまた来たまえ。深淵の先で待っている。

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