Visio VBAの深淵:CellsSRCによるShapeSheet高速直撃の実践
Visio開発で「遅い」「動かない」と悩む諸君。君たちのコードは、なぜ低速なのか?
それは、Visioが内部で管理している「ShapeSheet」という巨大なデータベースに対し、名前という曖昧なインターフェースを介して問い合わせを繰り返しているからだ。
`CellsU(“Width”)` と書くのは、プログラミング学習の初歩としては許される。だが、数千個のシェイプを持つ図面でそれを実行すれば、Visioの描画エンジンは文字列解析と名前解決のオーバーヘッドで悲鳴を上げる。
今日伝授するのは、ShapeSheetの「番地」を直接叩く `CellsSRC` を用いた、極限の高速化と堅牢な設計だ。
—
1. なぜ `CellsU` は悪手なのか
`CellsU(“Width”)` を呼び出すたび、Visioは内部テーブルをスキャンして該当プロパティを探し出す。数千回繰り返せば、そのコストは指数関数的に増大する。
一方、`CellsSRC(Section, Row, Cell)` は、メモリアドレスに直結するインデックスを指定する。Visioにとって、これ以上の高速なアクセス手段は存在しない。 プロダクション環境でパフォーマンスを語るなら、この層まで降りるのがエンジニアの流儀だ。
—
2. 実践:CellsSRCによる高速化実装
まずは、定数(Enumeration)を用いて「可読性」と「高速性」を両立させる設計例を見てほしい。
‘ Visioのセクション・行・列を定数で管理する
‘ これにより、コードの可読性を確保しつつ、直接メモリを叩く
Public Sub OptimizeShapeWidth()
Dim shp As Visio.Shape
Dim cellObj As Visio.Cell
‘ セクション、行、列のインデックス(Visioの仕様に基づく固定値)
‘ visSectionObject = 1, visRowShapeWidth = 0, visHorzAlign = 0 (例)
Const sec As Integer = Visio.VisSectionIndices.visSectionObject
Const row As Integer = Visio.VisRowIndices.visRowXFormOut
Const col As Integer = Visio.VisCellIndices.visXFormWidth
Set shp = ActivePage.Shapes(1)
‘ 名前解決をスキップして直接セルを特定
Set cellObj = shp.CellsSRC(sec, row, col)
‘ 書き込み(FormulaUではなくResultIUを使うのが鉄則)
‘ 数式計算の再評価を最小限に抑える
cellObj.ResultIU = 5.0 ‘ 単位はインチ(Visioの内部単位)
‘ 最後に再計算を実行(大量処理時はループの外で一回呼ぶのがコツ)
‘ shp.Document.Calculate
End Sub
この設計の重要ポイント
1. `ResultIU` を使う: `Formula` は文字列をパースするため遅い。`ResultIU` は内部単位(Internal Units)で直接数値を注入するため、演算コストが極めて低い。
2. インデックスの固定化: `visSectionObject` などの組み込み定数を使うことで、バージョンアップによる名前の変化というリスクを物理的に遮断できる。
3. Calculateの制御: ループ内で何度も再計算を走らせない。処理の最後に一度だけ `Application.Calculate` を呼び出すのが、大規模図面処理の黄金律だ。
—
3. 堅牢なデータ連携のための「守り」の設計
データベースや外部ファイル(Excel/JSON)からVisioを制御する場合、最も恐ろしいのは「型不一致」と「保護されたセル」だ。
Public Sub SafeCellUpdate(shp As Visio.Shape, sec As Integer, row As Integer, col As Integer, val As Double)
‘ エラーハンドリングは必須。保護されているセルへの書き込みを防ぐ
On Error Resume Next
Dim cell As Visio.Cell
Set cell = shp.CellsSRC(sec, row, col)
If Not cell Is Nothing Then
If Not cell.Locked Then
cell.ResultIU = val
Else
Debug.Print “Warning: Cell is locked: ” & shp.Name
End If
End If
On Error GoTo 0
End Sub
エンジニアへの助言:
外部DBと連携する場合、Visio側の「User-defined Cells(ユーザー定義セル)」を有効活用せよ。`CellsSRC` でこのユーザー定義領域を操作し、そこに計算結果やIDを格納する。これにより、レイアウトとデータが分離され、保守性が劇的に向上する。
—
4. 最後に:プロフェッショナルであるために
Visio VBAは「レガシー」などではない。CADライクな正確な配置と、リレーショナルなデータ構造を同時に扱える唯一無二のツールだ。
`CellsSRC` をマスターするということは、Visioの「深層」に触れるということだ。可読性を捨てて速度を取るのではなく、定数化によって「高速性と可読性を両立させた設計」を体現してほしい。
君たちのコードが、明日からの業務を劇的に変えることを期待している。
もし、さらに深いパフォーマンスチューニング(例:`EventMask` の制限による再描画停止など)が必要であれば、いつでも尋ねてくれ。アーキテクトは常に君たちの背後にいる。
