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

スポンサーリンク

Visioを「ただの作図ツール」から「高精度データレポジトリ」へ変貌させる極限の技術

Visio VBAを単なる「図形配置の自動化」と捉えているなら、それはこの強力なプラットフォームの可能性を著しく過小評価していると言わざるを得ない。

Visioの真骨頂は、Shapeオブジェクトが持つ「データ属性の保持能力」にある。`CellsU`プロパティを制する者は、Visioを単なるベクターグラフィックスから、動的なデータベースとして駆動させることができる。本稿では、レガシーなシステム連携の現場で培った、堅牢かつ極限まで最適化されたシェイプデータ操作の流儀を伝授する。

1. CellsU vs Cells: なぜ「U」でなければならないのか

初学者は`Cells`を使いがちだが、シニアエンジニアは必ず`CellsU`(Universal)を選択する。

  • Cells: ローカル言語(日本語版Visioなら日本語)に依存する。OSの言語設定やVisioのロケールが変わった瞬間にコードは腐敗する。
  • CellsU: 言語に依存しない「ユニバーサル名(英語定義)」でセルを特定する。

システム間連携や長期保守を前提とするなら、`CellsU`一択だ。これは単なる規約ではなく、アーキテクチャ上の生存戦略である。

2. シェイプデータ操作の深淵:実装パターン

シェイプデータ(旧カスタムプロパティ)に値を書き込む際、`Shape.CellsU(“Prop.ラベル名”)`を直叩きするのは素人のやり方だ。実務では、データが存在しない場合のエラーハンドリングと、型変換のオーバーヘッドを考慮する必要がある。

以下に、メモリ効率と堅牢性を両立させた汎用プロシージャを示す。

”’

”’ 指定したシェイプデータの値を安全にセットする
”’

Public Sub SetShapeData(ByVal shp As Visio.Shape, ByVal propName As String, ByVal val As String)
Dim cell As Visio.Cell

‘ セルの存在確認(CellsUは存在しないプロパティへアクセスすると例外を投げる)
If shp.CellExistsU(“Prop.” & propName, visExistsAnywhere) Then
Set cell = shp.CellsU(“Prop.” & propName)

‘ 文字列として値を代入(数式として評価させない場合は .FormulaU ではなく .ResultStr を使う)
‘ 大規模図面では、IsFormulaなどのチェックを挟むことで再計算コストを制御可能
If Not cell.IsFormula Then
cell.ResultStr(“”) = val
End If
Else
‘ 存在しない場合の動的生成(必要に応じて実装)
Debug.Print “Property ” & propName & ” not found in shape: ” & shp.Name
End If

‘ オブジェクトの明示的解放(VBAでも参照の即時解放はメモリ肥大化抑制に寄与する)
Set cell = Nothing
End Sub

3. レガシー環境とパフォーマンス:最適化の極致

Visioの描画エンジンは、特に大量の図形を処理する際に「再描画」と「イベントハンドリング」によって著しくパフォーマンスが低下する。数千個のシェイプデータを一括更新する場合、以下の鉄則を守れ。

A. 画面更新の強制停止

ループ処理中は、`Application.ScreenUpdating` を必ずオフにする。これだけで処理速度は10倍変わる。

B. イベントの抑制

もし文書内に`ShapeAdded`や`CellChanged`イベントが定義されている場合、書き込みのたびにイベントが発火し、システムがフリーズする。

Application.EventsEnabled = False
‘ — ここで大量のデータ更新 —
Application.EventsEnabled = True

C. オブジェクトのキャッシュ

`shp.CellsU(“Prop.X”).ResultStr` をループ内で何度も呼び出すな。`CellsU`へのアクセスはCOM呼び出しのオーバーヘッドを伴う。必要なデータは一度メモリ(配列やDictionary)に引き抜き、処理後に書き戻すのがアーキテクトの矜持だ。

4. システム間連携の勘所:外部DBとの同期

Visioを「フロントエンド」として使う場合、外部データベース(SQL Server等)とのハッシュ値比較が鍵となる。

1. ユニークキーの保持: 各シェイプに `Prop.UID` を持たせ、DBの主キーと同期させる。
2. 更新フラグの活用: `Prop.SyncStatus` セルを用意し、同期済みか否かを管理する。
3. Windows APIの活用: 必要に応じて `SHGetFileInfo` や `GetSystemTime` 等を使い、外部ファイルのタイムスタンプと図面内のデータを整合させる。

もし、VBAの限界を超えた複雑な通信が必要なら、C#でCOMアドインを作成し、`Interop`経由で`Visio.Application`を制御する道を選ぶべきだ。その際、`Marshal.ReleaseComObject` を使った徹底的なメモリ解放を忘れてはならない。VisioのCOMオブジェクトは、ガベージコレクションを待っていると平気でメモリリークを引き起こす。

結論

Visioのシェイプデータ操作は、単なるプロパティの書き換えではない。それは、図形という「器」に「意味」を流し込む行為である。

今回紹介した`CellsU`の厳密な運用と、イベント抑制、そして参照解放の徹底。これらを体得した時、あなたの書くコードは「動く」から「止まらない・腐らない」堅牢なシステムへと昇華されるはずだ。

技術は常に泥臭い。だが、その泥の中にこそ、システムの寿命を延ばす真理が埋まっている。次回の記事では、`Section`オブジェクトを用いたシェイプデータの動的追加と、そのメモリ消費量について深掘りする予定だ。準備はいいか。

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