こんにちは!Visio VBAの奥深い世界へようこそ。
マクロの記録ボタンを押して、生成されたコードを眺めて「うわ、なんだこの呪文は……」と途方に暮れた経験はありませんか?そして、少し慣れてくると「ShapeSheet(シェープシート)に一時的なデータを保存したいけれど、文字列しか入らないし、複雑なデータ構造を保持できないぞ?」という壁にぶつかるはずです。
今回は、そんなVisio開発者の悩みを鮮やかに解決する「Dictionaryクラスを活用したShapeオブジェクトのプロパティ拡張とメタデータ一時保持パターン」を伝授します。
ここをクリアすれば、単なる「お絵描きマクロの自動化」から脱却し、本格的な「Visioベースの業務システム開発者」への扉が開きます。しっかりついてきてくださいね!
—
1. なぜVisioのShapeSheetだけでは限界なのか?
Visioの図形(Shape)は、内部に「ShapeSheet」という強力なデータベースを持っています。`User.MyProp` のようなセルを追加すれば、そこにテキストや数値を保存できますよね。
しかし、現場で複雑なロジックを組むと、こんな壁にぶつかります。
- 「文字列しか入らない」:配列や、自作のクラスインスタンス、複雑なフラグ構造体をそのまま突っ込めない。
- 「パフォーマンスの劣化」:図形を移動したりコピーするたびにShapeSheetへの書き込みが発生し、処理が重くなる。
- 「揮発性(あるいは永続性)の問題」:図形を消したらデータも消えるべきだが、セルのゴミが残る。
そこで登場するのが、VBAの `Scripting.Dictionary` を使った「メモリ内メタデータ・マネージャー」というアプローチです。図形(Shape)の `ID` をキーにして、メモリ上に構築したリッチなデータ構造を紐付けることで、Visioの弱点を完璧にカバーします。
—
2. 全体像のイメージ:Shape ID をキーにした紐付け
言葉だけだとイメージしにくいので、概念図を頭に思い浮かべてみてください。
[ Visioの画面 ] [ メモリ上のVBA空間 (Dictionary) ]
Shape A (ID: 1) ——-> Key: “1” –> Value: [高度なカスタムオブジェクト / 配列]
Shape B (ID: 2) ——-> Key: “2” –> Value: [高度なカスタムオブジェクト / 配列]
Visioの図形自体には余計な負担をかけず、VBA側で「どのIDの図形に、どんなリッチなデータが紐づいているか」を高速に管理します。
—
3. 実践!Dictionaryを使ったメタデータ管理コード
それでは、実際に動くコードを見てみましょう。
このコードを動かすには、VBAの「ツール」>「参照設定」から 「Microsoft Scripting Runtime」 にチェックを入れておいてください(※シームレスに動かすためのマニアの必須テクニックです)。
準備:カスタムデータ用クラス(`clsNodeMetadata`)
まずは、図形に持たせたい「複雑なデータ」の入れ物として、簡単なクラスモジュールを一つ用意します。名前を `clsNodeMetadata` としてください。
‘ ==========================================
‘ クラスモジュール: clsNodeMetadata
‘ ==========================================
Public OwnerName As String
Public ProcessCost As Currency
Public IsValidated As Boolean
メインモジュール:Dictionaryによる一元管理
次に、標準モジュールに以下のコードを記述します。
‘ ==========================================
‘ 標準モジュール: 処理本体
‘ ==========================================
Option Explicit
Sub RunShapeMetadataManager()
‘ 1. 参照設定済みのDictionaryを生成
Dim shapeDataDict As Scripting.Dictionary
Set shapeDataDict = New Scripting.Dictionary
Dim activePage As Visio.Page
Set activePage = ActivePage
Dim targetShape As Visio.Shape
Dim meta As clsNodeMetadata
‘ 2. ページ上の図形をループしてメタデータを割り当て
Dim shp As Visio.Shape
For Each shp In activePage.Shapes
‘ 例として、すべての矩形図形に対してメタデータを生成して紐付ける
‘ Shape.ID は図形が一意に持つ不変の識別子です(ここがキモ!)
Set meta = New clsNodeMetadata
meta.OwnerName = “担当者_” & shp.ID
meta.ProcessCost = shp.ID 1500 ‘ 適当な計算
meta.IsValidated = True
‘ Dictionaryにキー(IDの文字列化)と値(クラスインスタンス)を格納
shapeDataDict.Add CStr(shp.ID), meta
Next shp
‘ 3. メモリ上のデータから情報を安全に取り出して活用する例
‘ (図形の位置が変わろうが、IDさえ変わらなければデータは安全)
For Each shp In activePage.Shapes
Dim key As String
key = CStr(shp.ID)
If shapeDataDict.Exists(key) Then
‘ Dictionaryからオブジェクトを取り出す
Set meta = shapeDataDict(key)
‘ デバッグ窓に出力してみる
Debug.Print “Shape ID: ” & shp.ID & _
” | 担当者: ” & meta.OwnerName & _
” | コスト: ” & meta.ProcessCost
End If
Next shp
‘ 4. ライフサイクルの終了(メモリ解放)
shapeDataDict.RemoveAll
Set shapeDataDict = Nothing
MsgBox “メタデータの管理と処理が完了しました!”, vbInformation
End Sub
—
4. ここで陥りやすい罠とエンジニアの知見
このパターンを実務で使うとき、プログラミング初学者がハマりがちな「落とし穴」がいくつかあります。プロの知見として共有しておきますね。
罠①:Shape.Name をキーにしてしまう
`shp.Name`(例: “Sheet.1″)をDictionaryのキーにしてしまう人がいますが、これはNGです。Visioは図形をコピー&ペーストしたり、削除して新しく作ったりすると、名前が簡単に重複したり変わったりします。
- 正解:常に不変かつ一意な `shp.ID` を `CStr(shp.ID)` としてキーにすること。
罠②:図形の削除とDictionaryの不整合
マクロ実行中に図形が削除された場合、Dictionaryに残った古いキーをそのまま参照するとエラー(実行時エラー 9: インデックスが有効範囲にありません)になります。
- 対策:必ず `shapeDataDict.Exists(key)` で存在確認を行うか、図形コレクション側を基準にループを回す設計にしてください。
罠③:参照設定のし忘れ(早期バインディングの恩恵)
`New Scripting.Dictionary` を使う際、参照設定をサボって `CreateObject(“Scripting.Dictionary”)` (遅延バインディング)で書く人がいますが、大規模な図面を扱うとパフォーマンスが落ちます。型を明確にする早期バインディングこそが、プロのエディットです。
—
5. まとめ
いかがでしたでしょうか?
今回は、Visio VBAにおける「Dictionaryクラスを活用したShapeオブジェクトのプロパティ拡張とメタデータ一時保持パターン」を解説しました。
- VisioのShapeSheetに収まらない複雑なデータは、無理に図形に書かずVBAのメモリ上に逃がす。
- その際のインデックスには、絶対的な信頼性を誇る `Shape.ID` を利用する。
- 処理が終わったらしっかりとメモリを解放する。
このアプローチをマスターすれば、何百個もの図形が入り組んだ複雑なワークフロー図の自動生成や、外部システムとのデータ同期ツールも、驚くほど軽快かつエレガントに構築できるようになります。
ここをクリアしたあなたなら、もう「マクロの記録」の卒業生です。自信を持って、次のオートメーションの世界へ進んでください!応援しています。
