【テクニカル・上級編】【初心者】Shape.IDとShape.Nameの決定的な違い:図形を特定する際の「名前が変わる」リスクを回避する – Visio VBA解析バイブル

スポンサーリンク

【Visio VBAの深淵】Shape IDとNameの境界線:なぜ「名指し」がシステムを崩壊させるのか

Visioの自動化において、多くの初心者が最初にぶつかる壁がある。「なぜコードで指定した図形が見つからないのか」あるいは「なぜ別の図形が操作されるのか」という問いだ。

答えは単純だ。君たちは「図形の識別子」という概念を誤解している。Visioのオブジェクトモデルにおいて、`Shape.ID`と`Shape.Name`は、その役割も、生存期間も、依存するコンテキストも全く異なる。

本稿では、レガシーな大規模図面を保守し、数千の図形をリアルタイムで制御するアーキテクトの視点から、堅牢な図形参照の極意を伝授する。

1. Shape.ID:一過性の「インデックス」という罠

`Shape.ID`は、現在の`Page`オブジェクト内において、その図形を一意に特定するための整数値だ。一見すると最強の識別子に見えるが、ここには大きな落とし穴がある。

  • 仕様の真実: IDは固定ではない。図形の削除、コピー&ペースト、あるいは「グループ化の解除」などによって、IDは容易に再割り当て(Re-indexing)される。
  • リスク: ループ処理の途中で図形を削除すると、IDのインデックスがズレる。これにより、予期せぬ図形を操作し、図面を破壊する事故が多発する。

結論: `Shape.ID`は、あくまで「その瞬間のメモリ上のポインタ」に近い存在である。永続的な参照には決して使ってはならない。

2. Shape.Name:ユーザーレベルの「ラベル」という幻影

`Shape.Name`(例: “Sheet.1″)は、Visioが自動生成する名前だ。GUI上の名前とプログラム上の名前は一致するが、これも脆弱だ。

  • 仕様の真実: `Shape.Name`は図形が作成された順序や位置に依存する。また、ユーザーが図面上で名前を書き換えることも可能だ。
  • リスク: システム間連携や複数の開発者が関与する図面において、この名前は「非決定論的」である。

3. 堅牢なアーキテクチャの構築:Unique ID (GUID) の活用

では、どうすれば図形を確実に特定できるのか? 答えは`UniqueID`(GUID)にある。

Visio 2003以降、すべてのShapeには`UniqueID`という永続的な文字列IDを付与できる。これは図形をコピーしても、ページを移動しても、ファイル名を変更しても変わらない。これこそが、真の「参照キー」である。

実践:UniqueIDを取得・設定するコード

‘ @brief 図形から永続的なUniqueIDを取得する。なければ生成する
‘ @param shp ターゲットのShapeオブジェクト
‘ @return 永続ID文字列
Public Function GetPersistentID(ByVal shp As Visio.Shape) As String
Dim uniqueID As String

‘ IDが存在しない場合は生成
If shp.UniqueID(Visio.VisUniqueIDArgs.visGetOrMakeGUID) = “” Then
‘ 必要に応じてログを出力
End If

GetPersistentID = shp.UniqueID(Visio.VisUniqueIDArgs.visGetOrMakeGUID)
End Function

‘ @brief IDを元に図形を確実に特定する(検索コストを考慮した実装)
Public Function FindShapeByGUID(ByVal pg As Visio.Page, ByVal targetGUID As String) As Visio.Shape
Dim shp As Visio.Shape

‘ 図形探索の最適化:ページ内の全図形を走査
‘ 大規模図面では、この走査自体をDictionaryでキャッシュすることを推奨
For Each shp In pg.Shapes
If shp.UniqueID(Visio.VisUniqueIDArgs.visGetOrMakeGUID) = targetGUID Then
Set FindShapeByGUID = shp
Exit Function
End If
Next shp
End Function

4. チーフアーキテクトからの助言:メモリとパフォーマンスの最適化

大規模なVisio自動化において、もっとも避けるべきは「オブジェクトの放置」だ。

1. オブジェクトの明示的解放:
VBAのガベージコレクションを待つな。`Set shp = Nothing`を徹底せよ。特にループ内で生成したオブジェクトは、イテレーションごとに破棄しないと、メモリリークの温床となる。
2. APIの直接利用:
Visioの`Page.Shapes`を何度も呼び出すのはコストが高い。`Shape`コレクションはメモリ上に展開されているが、アクセスするたびに内部的に検索が行われる。複雑な処理を行う際は、一度配列や`Scripting.Dictionary`に参照を格納してから処理せよ。
3. UI更新の抑制:
`Application.ScreenUpdating = False`を忘れるな。これを怠れば、描画のオーバーヘッドで処理速度は10倍以上低下する。

まとめ:エンジニアの哲学

  • IDは「一時的なインデックス」として扱い、処理スコープ内でのみ使用すること。
  • Nameは「人間向けのラベル」であり、プログラムの識別子としては信頼しないこと。
  • UniqueIDこそが「真のアイデンティティ」である。システム間連携やデータ永続化には、必ずこの値をデータベースに格納せよ。

コードは書けるものではない。システムに「耐えさせる」ものだ。Visioというレガシーかつ強力なキャンバスを支配したいのであれば、まずは図形の個体識別という、この根本的な問いから逃げないことだ。

諸君のシステムが、堅牢なアーキテクチャの上に築かれることを期待している。

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