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

スポンサーリンク

Visio VBAの深淵:Shape.CellsUによるシェイプデータ操作の最適解

Visioは単なる作図ツールではない。それは「グラフィカルなデータベース」である。
多くのエンジニアがVisioを「絵を描くソフト」と誤解している間に、我々アーキテクトは図形ひとつひとつにメタデータを埋め込み、それをAPIで抽出・加工することで、構成管理や資産管理の自動化を完遂してきた。

本稿では、`Shape.CellsU`を用いたシェイプデータ(旧カスタムプロパティ)操作の作法について、メモリ管理とパフォーマンスの観点から極限の知見を共有する。

1. なぜ「Cells」ではなく「CellsU」なのか

初心者向けのリファレンスには`Cells`プロパティが頻出するが、プロフェッショナルは常に`CellsU`を使用する。
理由は明白だ。`Cells`は実行環境のロケール(言語設定)に依存する。日本語環境で書いたコードが英語環境で動かないという悲劇を避けるため、ユニバーサル名(U)を使用するのはエンジニアとしての最低限の防衛本能だ。

シェイプデータは`Prop.XXX`という名前空間に格納される。これを操作する際、単にセルを叩くのではなく、セルの存在確認とプロテクト状態を考慮する必要がある。

2. 高速化と安定性のための実装パターン

数千のシェイプを走査する場合、安易なイテレーションはメモリリークとパフォーマンス低下を招く。以下のコードは、オブジェクトのライフサイクルを制御し、最小の負荷でデータ更新を行うためのテンプレートだ。

‘ 必要なシェイプデータ行が存在するかを確認し、安全に値を書き込む
Public Sub UpdateShapeData(ByRef shp As Visio.Shape, ByVal propName As String, ByVal val As String)
Dim cellName As String
cellName = “Prop.” & propName

‘ エラーハンドリング:存在しないセルの参照によるクラッシュを防止
On Error Resume Next
Dim cel As Visio.Cell
Set cel = shp.CellsU(cellName)

If Err.Number <> 0 Then
‘ セルがない場合は行を追加(カスタムプロパティの定義)
shp.AddNamedRow visSectionProp, propName, visTagDefault
Set cel = shp.CellsU(cellName)
Err.Clear
End If
On Error GoTo 0

‘ FormulaUに値をセット(文字列は必ず引用符で囲む必要がある)
If Not cel.Locked Then
cel.FormulaU = Chr(34) & val & Chr(34)
End If

‘ オブジェクトの明示的解放(VBAでは参照カウンタを即時減らす)
Set cel = Nothing
End Sub

3. チーフアーキテクトが教える「極限の最適化」

A. 画面更新の抑制

大規模なドキュメントを一括処理する場合、`Application.ScreenUpdating`を`False`に設定するのは定石だが、Visioではこれに加えて「イベントの停止」が不可欠だ。

‘ 処理開始時
Application.ScreenUpdating = False
Application.EventsEnabled = False

‘ … 処理本体 …

‘ 処理終了時
Application.EventsEnabled = True
Application.ScreenUpdating = True

これを忘れると、シェイプの変更ごとにVisioの描画エンジンが再計算を行い、処理時間が数倍から数十倍に跳ね上がる。

B. Windows APIによるメモリ最適化

Visioがフリーズする原因の多くは、ドキュメントの肥大化とガベージコレクションの遅延にある。特にCOMオブジェクトを多用する際、明示的に`DoEvents`を挟むのではなく、Win32 APIの`Sleep`でCPU占有率を調整し、OS側に処理の優先順位を渡すのがシニアの流儀だ。

‘ 標準モジュールの宣言部
If VBA7 Then
Private Declare PtrSafe Sub Sleep Lib “kernel32” (ByVal dwMilliseconds As Long)
Else
Private Declare Sub Sleep Lib “kernel32” (ByVal dwMilliseconds As Long)
End If

4. システム間連携への布石:データ構造の抽象化

シェイプデータを単なる「メモ書き」として扱うのは素人の仕事だ。これをJSONやXMLと等価な構造として管理せよ。
`Shape.CellsU`で取得した値を連想配列(`Scripting.Dictionary`)にマッピングし、ドキュメント全体を一つのオブジェクトとして扱う設計にすることで、Web APIやRDBとの連携が容易になる。

  • キー: プロパティ名
  • 値: セル値(FormulaU)

この抽象化層を一枚挟むだけで、Visioは「作図ツール」から「エンジニアリング・オートメーション・プラットフォーム」へと進化する。

結び:コードは思想である

Visio VBAはレガシーかもしれない。しかし、その裏側にあるオブジェクトモデルは極めて堅牢で論理的だ。シェイプデータという「目に見えない属性」を制御する技術は、ITインフラの構成管理やプロジェクトの可視化において、今なお最強の武器である。

現場でトラブルが起きたとき、慌ててマクロを書き換えるのではなく、オブジェクトモデルの挙動を根本から問い直せ。それが、我々エンジニアが持つべき「技術への誠実さ」である。

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