【入門編】【中級】Document.Mastersからステンシル図形を動的ロードする:外部ファイルに依存しない図形生成 – Visio VBA解析バイブル

スポンサーリンク

こんにちは! Visioの自動化の世界へようこそ。
マクロの記録ボタンを押して、生成された呪文のようなコードをそのまま動かしてみたものの、「あれ? 別のPCで動かすとエラーになる…」「なぜか図形が見つからない…」と頭を抱えていませんか?

そう、Visio VBAの初学者が最初に直面する最大の壁、それが「外部のステンシルファイル(.vssx)依存問題」です。

「C:\Users\…\MyShapes.vssx」なんてパスをコードに直書きしているそこのあなた。そのツール、他のメンバーに配ったら一発で動かなくなりますよ。

今回は、プロの現場でも必須となる「外部ファイルに依存せず、ステンシルから必要なマスターシェイプを動的に取り込んで図形を生成する技術」を、優しく、そして本質的な部分まで徹底的に解説します。

ここをクリアすれば、あなたの作るVisioツールは「どこでも動く配付可能なプロ仕様」へと生まれ変わります。さあ、一緒に扉を開けましょう!

—

なぜ「外部ファイル依存」は悪なのか?

Visioで図形を描画するとき、私たちは通常、画面の左側にある「ステンシル」から図形をドラッグ&ドロップしますよね。VBAでこれを自動化しようとすると、つい次のようなコードを書きがちです。

‘ 【やってはいけないアンチパターン例】
Dim shp As Visio.Shape
‘ 外部のステンシルファイルを直接開こうとする
Dim stnDoc As Visio.Document
Set stnDoc = Documents.OpenEx(“C:\Work\MyCustomShapes.vssx”, visOpenDocked)

‘ マスターを取得して図形を配置
Set shp = ActivePage.Drop(stnDoc.Masters(“サーバー”), 2, 2)

このコードの何がいけないのでしょうか?

1. パスの固定化: ファイルサーバーの構成が変わったり、担当者のPCのローカル環境が変わったりした瞬間、パスが見つからずエラー(実行時エラー)になります。
2. ファイルの散逸: ツール本体(.vsmや.vsdm)のほかに、依存するステンシル(.vssx)もセットで配る必要があり、バージョン管理が破綻します。

解決策:マスターをドキュメントの「内臓」にしてしまおう!

Visioのドキュメント(`Document`オブジェクト)は、実は自分自身の中にマスターシェイプを保持する領域(`Masters`コレクション)を持っています。

つまり、「ツール起動時に、隠しフォルダーやリソースから一時的にステンシルを開き、必要なマスターだけを現在のドキュメント内にコピー(ドロップ)して、ステンシル自体は即座に閉じる」というアプローチを取れば、最終的にできあがるVisioファイルは「単一ファイルで完全に完結(スタンドアロン)」するのです。

これが、今回マスターする「動的ロード」の神髄です。

—

Visioオブジェクトモデルの基本関係

コードを書く前に、Visioの階層構造(オブジェクトモデル)を頭に焼き付けておきましょう。

Application (Visio全体)
┗ Documents (開かれているファイル群)
┗ ActiveDocument (現在のドキュメント)
┣ Pages (ページ群)
┃ ┗ ActivePage (操作中のページ)
┗ Masters (このドキュメントが持つマスターシェイプ群) ← ★ここが重要!

マスターシェイプは、ページに配置されると「Shape」になり、ドキュメントにインポートされると「Master」として `ActiveDocument.Masters` に宿ります。

—

実践!マスターシェイプ動的ロードの完全コード

それでは、現場でそのまま使える実用的なVBAコードを公開します。
このコードは、同じフォルダ内(または特定のパス)にあるステンシルから、指定したマスターを自ドキュメントに取り込み、ページ上に図形を生成するサンプルです。

Sub CreateShapeWithoutExternalDependency()
‘ — 変数の宣言 —
Dim targetStencilPath As String
Dim stnDoc As Visio.Document
Dim targetMaster As Visio.Master
Dim generatedShape As Visio.Shape
Dim masterName As String

‘ 取得したいマスターシェイプの名前(ステンシル内の名前)
masterName = “クラウドサーバー”

‘ 1. ステンシルファイルのパスを決定する
‘ ※ここではこのVBAファイル(ActiveWorkbook等に相当するもの)と同じ階層を想定
‘ Visioの場合は ThisDocument.Path を使うと、現在の図面と同じフォルダを取得できます。
targetStencilPath = Visio.ActiveDocument.Path & “Infrastructure.vssx”

‘ ファイルが存在するか簡易チェック
If Dir(targetStencilPath) = “” Then
MsgBox “必要なステンシルが見つかりません: ” & vbCrLf & targetStencilPath, vbCritical, “エラー”
Exit Sub
End If

On Error GoTo ErrorHandler

‘ 2. ステンシルファイルを「非表示(ドッキングなし)」で開く
‘ visOpenHidden を使うことで、ユーザーに余計なウィンドウを見せずに裏で開けます。
Set stnDoc = Visio.Documents.OpenEx(targetStencilPath, visOpenHidden)

‘ 3. 開いたステンシルから目的のマスターが存在するか確認しつつ取得
On Error Resume Next
Set targetMaster = stnDoc.Masters(masterName)
On Error GoTo ErrorHandler ‘ エラートラップを戻す

If targetMaster Is Nothing Then
MsgBox “指定されたマスターシェイプが見つかりません: ” & masterName, vbExclamation, “確認”
stnDoc.Close
Exit Sub
End If

‘ 4. 【核心】自ドキュメントの Masters コレクションにマスターが存在するかチェックし、なければコピー
‘ (Visio.Document.Dropを実行すると自動的に取り込まれますが、明示的に存在確認するロジックです)
Dim localMaster As Visio.Master
On Error Resume Next
Set localMaster = ActiveDocument.Masters(masterName)
On Error GoTo ErrorHandler

If localMaster Is Nothing Then
‘ ドキュメントにまだこのマスターがない場合、ステンシルからマスターをドキュメントへコピー
‘ (DropExやMasterオブジェクトの複製を利用する方法もありますが、
‘ 最も手軽で確実なのは、一度ダミーのドロップを行うか、ドキュメントのMasters.AddUを使う方法です)

‘ 今回は一番スマートな Masters.AddU を使ったマスターの取り込み手法を採用します
Set localMaster = ActiveDocument.Masters.AddU(targetMaster)
End If

‘ 5. 使い終わった外部ステンシルファイルは速やかに閉じる(メモリ解放の鉄則!)
stnDoc.Close

‘ 6. 自ドキュメント内に取り込んだ(または既存の)マスターを使って、アクティブページに図形を配置!
‘ 座標 (4.0, 5.0) の位置にドロップします(単位はインチ)
Set generatedShape = ActivePage.Drop(localMaster, 4.0, 5.0)

‘ 7. 仕上げ:生成した図形に対して初期設定を行う
generatedShape.Text = “Webサーバー 01”

MsgBox “図形の動的生成に成功しました!”, vbInformation, “完了”
Exit Sub

ErrorHandler:
‘ 予期せぬエラー時のクリーンアップ
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical, “予期せぬエラー”
If Not stnDoc Is Nothing Then
‘ エラー時でもステンシルが開いていれば確実に閉じる
stnDoc.Close
End If
End Sub

—

コードの重要ポイントとエンジニアの知見

上記のコードには、Visio VBAで飯を食っていくためのノウハウが凝縮されています。特に重要な3つのポイントを解説します。

① `visOpenHidden` で裏側でこっそり開く

`Visio.Documents.OpenEx` メソッドの第二引数に `visOpenHidden` を指定すると、ユーザーの画面にステンシルウィンドウを表示させることなく、メモリ上だけでファイルを開くことができます。
画面がガチャガチャと切り替わらない、洗練されたツールを作るための必須テクニックです。

② メモリリークを防ぐ「必ず閉じる」執念

VBAにおいて、外部ファイルを `Open`(または `OpenEx`)したら、処理の成否に関わらず絶対に `Close` するのがプロの作法です。
今回のコードでは `On Error GoTo ErrorHandler` を用意し、万が一途中でエラーが起きた場合でも、必ず `stnDoc.Close` が実行されるように保険をかけています。これを怠ると、Visioのプロセスがタスクマネージャーに残る「ゾンビプロセス問題」を引き起こします。

③ `ActiveDocument.Masters.AddU` による完全カプセル化

外部ステンシルから `targetMaster` を取得した後、`ActiveDocument.Masters.AddU(targetMaster)` を使うことで、そのマスターの遺伝子(図形の形状、マスタープロパティ、シェイプシートの数式など)のすべてが、あなたの描いているVisioファイルの中に完全にコピーされます。
これにより、後から外部の `.vssx` ファイルを削除しようが、別のPCにファイルをメールで送ろうが、図形はエラーなく完璧に描き続けられます。

—

まとめ:あなたのVisioマクロを「配布できる資産」へ

今回は、`Document.Masters` とステンシルファイルを連携させ、外部依存のない動的な図形生成を行う方法を解説しました。

  • 外部の `.vssx` はそのまま配らない。
  • 必要なマスターは、実行時に自ドキュメントの `Masters` にインポートする。
  • 開きっぱなしにせず、エラーハンドリングを含めて確実にクローズする。

この3つを守るだけで、あなたが作るVisioマクロの品質はプロレベルへと一気に跳ね上がります。
現場で「おっ、このツール使いやすいしエラーも出ないな」と言われるエンジニアを目指して、ぜひご自身の環境でも試してみてください。

それでは、快適なVisio自動化ライフを!

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