【Visio VBA極意】CellsSRCによるShapeSheetの直接制御:名前依存という名の「毒」を断つ
Visioの自動化において、`Shape.Cells(“Width”)` や `Shape.CellsU(“User.MyProp”)` といった文字列ベースのアクセサを多用していないだろうか?
もしそうなら、君のコードは大規模図面において深刻なパフォーマンス・ボトルネックを抱え、さらに「名前の変更」という些細な修正でシステム全体が崩壊するリスクを孕んでいる。
本稿では、Visioの心臓部であるShapeSheetの構造を数値インデックスで直接操作する、`CellsSRC`を用いた極限の最適化手法を伝授する。これは、レガシーを熟知し、数万個のシェイプを瞬時に制御せねばならない現場のエンジニアだけが到達できる領域だ。
—
なぜ `CellsU` は悪手なのか
`Cells(“文字列”)` を実行するたび、Visio内部では以下のプロセスが走る。
1. 文字列の構文解析(String Parsing)
2. 名前から内部インデックスへの動的なハッシュテーブル探索
シェイプが10個なら誤差だが、1万個のシェイプに対してループ内でこれを実行すればどうなるか。文字列の比較と探索コストが積み重なり、処理時間は指数関数的に増大する。
一方、`CellsSRC` は `Section`、`Row`、`Cell` という3つの数値(インデックス)を直接指定する。これはメモリ上のアドレスを直接叩くのに等しい行為であり、Visioエンジンにとって最も「親切」な指示だ。
—
CellsSRCの真髄:定数による型安全な設計
`CellsSRC` は以下の引数を取る。
`CellsSRC(SectionIndex, RowIndex, CellIndex)`
これらを毎回数値で書くのは可読性の観点から自殺行為だ。まずは、Visioの型ライブラリに隠された定数を活用し、構造化されたアクセスを実現する。
‘ Visioのセクション・行・列の定数を定義するモジュールを作成せよ
Public Const visSectionObject As Integer = 1
Public Const visRowXFormOut As Integer = 1
Public Const visXFormWidth As Integer = 0
Public Const visXFormHeight As Integer = 1
‘ 【極意】名前ではなくインデックスで直接叩く
Public Sub OptimizeShapeSize(shp As Visio.Shape)
‘ 内部的には Cells(“Width”) と同等だが、探索コストは皆無
Dim cellWidth As Visio.Cell
Set cellWidth = shp.CellsSRC(visSectionObject, visRowXFormOut, visXFormWidth)
cellWidth.FormulaU = “100 mm”
‘ オブジェクトの明示的解放(VBAの弱点を補完)
Set cellWidth = Nothing
End Sub
—
大規模図面での一括書き換え:メモリと計算資源の最適化
数千のシェイプを操作する際、`Application.ScreenUpdating = False` は当然の前提だが、それだけでは足りない。`EventEnabled` の制御と、再計算(Recalculation)の抑制が不可欠だ。
Public Sub BatchProcessShapes(doc As Visio.Document)
Dim pg As Visio.Page
Dim shp As Visio.Shape
‘ 1. イベントを停止し、再計算のオーバーヘッドを抑える
Dim originalEvents As Boolean
originalEvents = Application.EventEnabled
Application.EventEnabled = False
On Error GoTo Cleanup
For Each pg In doc.Pages
For Each shp In pg.Shapes
‘ ShapeSheetの直接操作(例:Widthの定数化)
‘ 名前が変更されても、このインデックスなら絶対に壊れない
shp.CellsSRC(1, 1, 0).ResultIU = 50.0
Next shp
Next pg
Cleanup:
Application.EventEnabled = originalEvents
‘ オブジェクトの解放を徹底し、メモリリークを根絶する
Set shp = Nothing
Set pg = Nothing
End Sub
—
シニアエンジニアへの警鐘:なぜ「名前依存」を捨てるのか
システム間連携や長期保守において、最も恐ろしいのは「ユーザーによるShapeSheetのカスタム」だ。ユーザーがGUI上で「Width」を「幅」とリネームしたり、カスタムプロパティの順序を入れ替えただけで、`Cells(“…”)` は例外を吐く。
しかし、`CellsSRC` は違う。
「第1セクションの第1行の第0番目のセル」というアクセスは、Visioの内部構造そのものに依存しているため、表面上のラベル名や言語設定(日本語版/英語版)に左右されない。
さらなる最適化のヒント:Windows APIの活用
もし、さらに深い制御が必要なら、`GetModuleHandle` や `SendMessage` を使用して、Visioのウィンドウメッセージをフックし、再描画のタイミングを完全に制御することも可能だ。だが、それは劇薬である。まずは `CellsSRC` の徹底活用から始めてほしい。
結び:エンジニアの誇り
優れた自動化コードとは、単に動くものではない。
「何が起きても壊れない堅牢さ」と「計算資源を無駄にしない効率性」が両立したコードこそが、真にプロフェッショナルの仕事だ。
Visioという、一見するとGUI主体のレガシーなソフトウェアであっても、その深層には洗練されたオブジェクトモデルが眠っている。その深淵に潜り、インデックスという名の「鍵」を使って直接制御する。それこそが、我々エンジニアが追求すべき自動化の極みである。
君のコードが、次の10年、どの環境でも完璧に動作し続けることを願う。
