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

スポンサーリンク

Visio VBAの深淵:Shape.IDとShape.Nameを使い分けられない者は、自動化の夢を見るな

業務自動化の現場で、VisioのVBAコードを書いていて「なぜか意図しない図形が操作される」「昨日まで動いていたのに、図形をコピーしたらエラーが止まらない」という壁にぶつかっていないだろうか?

もしそうなら、君はVisioのオブジェクトモデルの根幹である「図形の識別子」の性質を誤解している可能性が高い。

今日は、Visio自動化における「初心者脱出」の最重要項目、`Shape.ID`と`Shape.Name`の決定的な違いと、プロとして守るべき「堅牢な参照戦略」について伝授する。

1. Shape.ID:高速だが「刹那的」な識別子

`Shape.ID`は、そのページ内における図形の一意な数値だ。

  • メリット: 処理が非常に高速。`Page.Shapes.ItemFromID(id)`によるアクセスは、オブジェクト検索のオーバーヘッドが最小限である。
  • 最大の罠: 「不変ではない」ということだ。

Visioにおいて、図形を削除したり、ページを跨いでコピペしたりすると、IDは容易に再割り当てされる。つまり、「IDはセッション内の一時的なインデックス」として扱うのが正解だ。コードの中で「この図形はID: 5だから大丈夫」とハードコーディングするのは、時限爆弾を抱えるのと同義である。

2. Shape.Name:ユーザーフレンドリーだが「重複のリスク」がある

`Shape.Name`は、開発者が読みやすい文字列(例:”Sheet.12″)だ。

  • 特徴: ユーザーインターフェースやデザイン画面で確認可能。
  • 最大の罠: 「一意性が保証されない」こと。特にコピー&ペーストを行うと、Visioは自動的に連番を振るが、ユーザーが手動で名前を変更したり、異なるステンシルから図形をドラッグ&ドロップしたりすると、予期せぬ衝突が起きる。

3. 堅牢な設計:IDとNameを使い分ける「プロの判断基準」

では、どうすればバグのないコードが書けるのか。結論は以下の3点に集約される。

1. 動的な処理(一時計算など): ページ内で完結するループ処理なら`Shape.ID`で回せ。
2. 永続的な識別(データベース連携など): 図形とDBのレコードを紐付けるなら、`Shape.Name`ではなく、`Shape.UniqueID`を使用せよ。
3. UI上の特定: 特定のボタンや固定図形を指すなら、あえて名前をユーザー側で「カスタムプロパティ(Shape Data)」に格納し、名前ではなく「データ」で検索せよ。

4. プロダクションコード:保守性の高い「安全な図形取得」

現場でそのまま使える、堅牢な図形取得のテンプレートを提示する。闇雲にIDを指定するのではなく、「存在チェック」という防衛線を張るのがプロの作法だ。

‘ @brief 特定のページから、IDを指定して安全にShapeオブジェクトを取得する
‘ @param pg 対象のPageオブジェクト
‘ @param targetID 取得したい図形のID
‘ @return 成功時はShapeオブジェクト、失敗時はNothing
Public Function GetShapeSafe(ByVal pg As Visio.Page, ByVal targetID As Long) As Visio.Shape
On Error Resume Next
‘ ID指定でのアクセスを試みる
Set GetShapeSafe = pg.Shapes.ItemFromID(targetID)

‘ エラーが発生した(IDが存在しない)場合はNothingが返る
If Err.Number <> 0 Then
Debug.Print “Warning: ID ” & targetID & ” は存在しません。”
Set GetShapeSafe = Nothing
End If
On Error GoTo 0
End Function

‘ @brief 【推奨】UniqueIDを利用して図形を特定する(永続性の確保)
‘ 図形のコピーが発生しても、UniqueIDは変わらないため、DB連携には必須である
Public Function FindShapeByGuid(ByVal pg As Visio.Page, ByVal guid As String) As Visio.Shape
Dim shp As Visio.Shape
For Each shp In pg.Shapes
‘ UniqueIDプロパティ(visGetOrMakeGUID)で比較
If shp.UniqueID(visGetOrMakeGUID) = guid Then
Set FindShapeByGuid = shp
Exit Function
End If
Next shp
End Function

最後に:なぜ「泥臭いコード」が必要なのか

初心者は、`Shapes(“Rectangle.1”)`のように名前を直接指定してコードを書く。しかし、それは「レイアウト変更があった瞬間に死ぬ」コードだ。

私が提案した`UniqueID`を使う方法は、少し記述が冗長に見えるかもしれない。だが、「変更に強い設計」こそが、業務自動化エンジニアの真価だ。

Visioの内部構造を理解し、その気まぐれなID割り当てに翻弄されない知性を持つこと。それができれば、君の作成する自動化ツールは、誰が何を触ろうとも壊れない「鉄壁のシステム」へと進化するはずだ。

次は、`ShapeData`(旧カスタムプロパティ)とメタデータの管理について深掘りしていく。準備はいいか。

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