【テクニカル・上級編】【初心者】Shape.CellsUを用いたシェイプデータ(カスタムプロパティ)の読み書き入門 – Visio VBA解析バイブル

スポンサーリンク

Visio VBAの深淵:Shape.CellsUによるカスタムプロパティ操作の「真実」

Visioを単なる「お絵描きツール」と見なしているなら、君のキャリアはそこで止まる。Visioは、ShapeSheetという強力なデータベースエンジンを内包した、極めて特殊なインフォメーション・モデリング・ツールだ。

業務自動化エンジニアとして、ExcelからVisioへデータを流し込み、図面を動的に再構成する。その中核を担うのが `Shape.CellsU` を用いたカスタムプロパティ(Shape Data)の操作である。だが、公式リファレンスをなぞるだけの初歩的なコードでは、大規模な図面を扱った瞬間にシステムは死ぬ。

今日は、プロフェッショナルとして知っておくべき「Visioオブジェクトモデルの真髄」を叩き込む。

—

1. CellsUという「魔の入り口」を制御する

`CellsU` は、ShapeSheetのセルに直接アクセスするための低レイヤーな窓口だ。「U」がUniversalの名前を冠する通り、言語設定に依存しない一意なパスを指定できる。

なぜ `Cells` ではなく `CellsU` なのか?

VBAの国際化対応は地雷原だ。`Cells` はローカル環境の言語設定(日本語版なら「プロパティ」等)に依存するが、`CellsU` は「Prop.RowName」といったシステム標準の識別子でアクセスできる。保守性を担保するなら `CellsU` 一択だ。

‘ プロパティ値を安全に取得する作法
Public Function GetShapeData(shp As Visio.Shape, propName As String) As String
On Error Resume Next ‘ 存在しないプロパティへのアクセスを封じる
Dim cellName As String
cellName = “Prop.” & propName & “.Value”

If shp.CellExistsU(cellName, visExistsAnywhere) Then
GetShapeData = shp.CellsU(cellName).ResultStr(“”)
Else
GetShapeData = “”
End If
On Error GoTo 0
End Function

—

2. メモリとパフォーマンスの極限最適化

VisioのVBAは、COMオブジェクトの海の中で泳いでいる。特に `Document` や `Page` のコレクションをループ処理する際、多くのエンジニアが「暗黙の参照」によるメモリリークを放置している。

シニアであれば、以下の鉄則を忘れるな。

1. オブジェクトの明示的解放: `Set obj = Nothing` は儀式ではない。巨大な図面を回す際は、スコープを最小化し、参照を即座に破棄しろ。
2. イベントの抑制: 大量書き込み時には `Application.DeferRecalc = True` を使え。セルの再計算を一時停止することで、処理速度は数十倍に跳ね上がる。

Public Sub BulkUpdateShapeData(shp As Visio.Shape, newValue As String)
‘ 再計算を抑制してパフォーマンスを最適化
Dim app As Visio.Application
Set app = shp.Application

app.DeferRecalc = True

‘ プロパティの更新
If shp.CellExistsU(“Prop.Status.Value”, visExistsAnywhere) Then
shp.CellsU(“Prop.Status.Value”).FormulaU = Chr(34) & newValue & Chr(34)
End If

app.DeferRecalc = False

‘ 参照解放
Set app = Nothing
End Sub

—

3. レガシー環境とWindows APIの接点

もし君が担当しているシステムが、Visio 2010以前の遺物や、外部DLLとの連携が必須な環境にあるなら、`Shape.CellsU` だけでは解決できない壁にぶつかるはずだ。

例えば、Visioウィンドウのハンドルを取得し、Win32 APIを叩いて描画を強制更新する、あるいはクリップボードの挙動を厳密に制御する必要がある場合。これには `FindWindow` や `SendMessage` をVBA側で宣言する。

If VBA7 Then
Private Declare PtrSafe Function FindWindow Lib “user32” Alias “FindWindowA” (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
Else
Private Declare Function FindWindow Lib “user32” Alias “FindWindowA” (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
End If

このように、Visioのオブジェクトモデルを外側から叩く「外付けの制御」を理解することで、単なるマクロ屋から、システム全体を統括するアーキテクトへと進化できる。

—

結論:システム間連携の要諦

VisioとExcelを連携させるプロジェクトで失敗する最大の要因は、「データの同期」ではなく「図形の状態管理」の甘さにある。

  • 唯一の真実(Single Source of Truth): プロパティデータは常にExcel(またはデータベース)を正とし、Visioはあくまで「可視化されたビュー」と割り切ること。
  • 例外処理の構築: シェイプが削除されたり、グループ化されたりすることで `CellsU` のパスは容易に崩壊する。`On Error` を使いこなすだけでなく、名前付き範囲(User-defined cells)を活用した堅牢なアーキテクチャを設計せよ。

Visio VBAは古い技術ではない。データの関係性を幾何学的に表現する、唯一無二の手段だ。その深淵を覗き込み、自身のコードで図面を意のままに操る快感を、ぜひ味わってほしい。

健闘を祈る。

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