【入門編】吹き出し図形(Callout)の動的紐付け:Page.DropCalloutとShape.CalloutTargetの完全制御 – Visio VBA解析バイブル

スポンサーリンク

こんにちは!Visio VBAの世界へようこそ。
マクロの記録から一歩踏み出し、コードを使って図面を自由自在に操る領域へ踏み出そうとしているのですね。素晴らしい挑戦です!

今回は、Visioの描画自動化において非常に需要が高く、かつ手作業だとめんどくさい「吹き出し図形(Callout)の自動追加と動的ターゲット紐付け」をテーマに解説します。

図面上の特定の図形(サーバー、工程ブロック、機器など)に対して、「ここが変更点」「エラー検知箇所」といった注記テキストを全自動でぴたっと追従させるテクニックです。

ここをクリアすれば、Visio VBAのオブジェクト操作の基本と、図形同士の「関係性(リレーション)」の制御はバッチリマスターできますよ!リラックスして進めていきましょう。

1. なぜ「マクロの記録」では吹き出しの自動化がうまくいかないのか?

Visioで手作業で吹き出しを付けるとき、あなたは「図形を選択」→「挿入タブから吹き出しを選択」という操作をしますよね。
しかし、これを「マクロの記録」で記録して再現しようとすると、ほぼ確実に失敗するか、位置がずれて固定化されてしまいます。

理由はシンプルです。
手動作業の吹き出しは「見た目の配置」と「内部的なターゲット参照」がセットになっているのに対し、記録マクロは「単なる座標への図形配置(`Page.Drop`)」として記録してしまいがちだからです。

Visio VBAで「ターゲット図形を追いかける本物の吹き出し」を作るには、次の2つの強力な武器を使います。

1. `Page.DropCallout` メソッド: 吹き出しを生成し、一瞬でターゲット図形と「親子関係」を結ぶ
2. `Shape.CalloutTarget` プロパティ: 吹き出しがどの図形を指しているかを取得・変更する

2. 概念図:Visio VBAのオブジェクトモデルと吹き出しの構造

コードを書く前に、Visio内部で何が起きているのかイメージを掴んでおきましょう。

[ Document (図面) ]
└── [ Page (アクティブなページ) ]

├── [ Target Shape (注記したい対象図形) ]
│ ▲
│ │ (追従関係・自動接続)
│ │
└── [ Callout Shape (吹き出し図形) ]

└── .CalloutTarget ──> (Target Shapeを参照)

通常の図形配置(`Drop`)だと矢印の「自動接続」が作られません。
`DropCallout` を使うことで、Visioのバックグラウンドにある「ShapeSheet(図形の計算式シート)」に接続式が自動書き込みされ、ターゲットを移動したときに吹き出しの引き出し線が自動的にびよーんと伸びて追従する仕組みが完成します。

3. 完全制御のためのAPI解説

まずは中心となる2つのAPIの役割をしっかり抑えましょう。

① `Page.DropCallout(Master, TargetShape)`

  • 役割: 指定した吹き出しのマスタ(型抜き)から新しい吹き出し図形を作成し、`TargetShape` に紐付けて配置します。
  • 戻り値: 生成された吹き出しの `Visio.Shape` オブジェクト。

② `Shape.CalloutTarget`

  • 役割: 吹き出し図形が「どの図形をターゲットにしているか」を取得、または動的に再設定します。
  • 使い方:
  • 取得: `Set target = calloutShape.CalloutTarget`
  • 変更: `Set calloutShape.CalloutTarget = newTargetShape`(吹き出しの指す先をコードで変更可能!)

4. コピペで使える!吹き出し自動生成&紐付けVBAコード

それでは、実際のコードを見てみましょう。
以下のコードは、「現在選択している図形に対して、自動的に注記吹き出しを生成して追従させる」実用的なマクロです。

標準モジュール(`Module1` など)に貼り付けて試してみてください。

Option Explicit


‘ 選択中の図形に対して吹き出し(Callout)を自動生成し、動的紐付けを行うサンプル

Public Sub AutoAddCalloutToSelection()

‘ — オブジェクト変数の宣言 —
Dim visApp As Visio.Application
Dim visPage As Visio.Page
Dim targetShape As Visio.Shape
Dim calloutStencil As Visio.Document
Dim calloutMaster As Visio.Master
Dim calloutShape As Visio.Shape

‘ 1. 現在のVisioアプリケーションとアクティブページを取得
Set visApp = Visio.Application
Set visPage = visApp.ActivePage

‘ 安全装置:ページが開かれていない場合は処理を抜ける
If visPage Is Nothing Then
MsgBox “アクティブなページがありません。”, vbExclamation, “中断”
Exit Sub
End If

‘ 2. ユーザーが図形を選択しているかチェック
If visApp.ActiveWindow.Selection.Count = 0 Then
MsgBox “吹き出しを付けたい図形を1つ以上選択してから実行してください。”, vbInformation, “案内”
Exit Sub
End If

‘ 選択されている最初の図形をターゲットとして取得
Set targetShape = visApp.ActiveWindow.Selection(1)

‘ 3. 吹き出し用のステンシル(SDCALL_M.VSSX)を開く
‘ ※日本語版Visioの標準的な吹き出しステンシル名です
On Error Resume Next
Set calloutStencil = visApp.Documents(“SDCALL_M.VSSX”)
If calloutStencil Is Nothing Then
‘ ステンシルが開いていない場合は非表示で読み込む
Set calloutStencil = visApp.Documents.OpenEx(“SDCALL_M.VSSX”, visOpenRO Or visOpenHidden)
End If
On Error GoTo 0

‘ ステンシルが見つからない場合のガード
If calloutStencil Is Nothing Then
MsgBox “吹き出しステンシル(SDCALL_M.VSSX)の読み込みに失敗しました。”, vbCritical, “エラー”
Exit Sub
End If

‘ 4. ステンシルから使用したい吹き出しの「マスタ」を取得
‘ (例: “長方形の吹き出し” や “吹き出し 1” など。インデックス1番目でも可)
Set calloutMaster = calloutStencil.Masters(1)

‘ ——————————————————————-
‘ 5. 【核心部】DropCalloutで吹き出しを生成し、ターゲットに紐付ける
‘ ——————————————————————-
Set calloutShape = visPage.DropCallout(calloutMaster, targetShape)

‘ 6. 生成された吹き出しのプロパティを操作する
With calloutShape
‘ 吹き出し内にテキストを注入
.Text = “【自動検知】” & vbCrLf & “対象名: ” & targetShape.Name

‘ テキストの文字サイズを少し調整(ポイント指定)
.CellsSRC(visSectionCharacter, 0, visCharacterSize).FormulaU = “9pt”
End With

‘ 7. 【検証】CalloutTargetを使って正しく紐付いたか確認
If Not calloutShape.CalloutTarget Is Nothing Then
Debug.Print “成功: ” & calloutShape.Name & ” は ” & _
calloutShape.CalloutTarget.Name & ” に動的接続されました。”
End If

‘ 完了メッセージ
MsgBox “図形 [” & targetShape.Name & “] に吹き出しを紐付けました!” & vbCrLf & _
“図形を動かして吹き出しが追従することを確認してください。”, vbInformation, “成功”

End Sub

5. 初心者が陥りやすい3つの罠と解決策

開発中に「あれ?動かない…」となったら、ここをチェックしてみてください。先輩エンジニアも昔全員ここでハマっています!

罠①:ステンシルファイル名が見つからない (`SDCALL_M.VSSX`)

Visioはメートル法(日本)とインチ法(米国)でステンシル名が異なります。

  • 日本語版(メートル法): `SDCALL_M.VSSX`
  • 英語版(インチ法): `SDCALL.VSSX`

コード内でファイルを開くときにエラーになる場合は、`Masters(1)` のようにインデックスで指定するか、環境に合わせてファイル名を条件分岐させると安全です。

罠②:`DropCallout` に「普通の図形マスタ」を渡してしまう

`DropCallout` の第1引数には、 Visioが「吹き出しである」と認識しているマスタを渡す必要があります。普通の四角形(`Rectangle`)マスタなどを渡すと実行時エラーになります。必ず吹き出し専用ステンシルから取得したマスタを渡してください。

罠③:吹き出しを消したのにターゲット図形まで消えてしまう?

吹き出しとターゲットはリンクしていますが、基本的には「親子関係」ではなく「参照関係」です。ただし、UI上でグループ化などを混ぜてしまうと連動して削除されることがあります。純粋にVBAでコントロールしている限りは、`calloutShape.Delete` を実行すれば吹き出しだけが安全に消去されます。

6. 一歩先へ:図面全体の全自動注記ツールへの応用

今回の基本をマスターしたら、次は「ページ内の全図形をループ処理して、特定の条件に合う図形へ一括で吹き出しをつける」という実務で大活躍するツールに拡張できます。

例えば、こんなコードに応用可能です:

‘ 応用イメージ:ShapeData(カスタム属性)の「Status」が「Error」の図形全てに吹き出しを付ける
Dim shp As Visio.Shape
For Each shp In visPage.Shapes
If shp.CellExists(“Prop.Status”, visExistsAnywhere) Then
If shp.Cells(“Prop.Status”).ResultStr(“”) = “Error” Then
‘ ここで DropCallout を呼び出す!
visPage.DropCallout calloutMaster, shp
End If
End If
Next shp

手作業なら1時間かかるような「チェック&注記作業」が、たった1秒で終わる瞬間です。VBAエンジニアとしての快感を最も味わえる瞬間ですね!

まとめ

今回の学びのポイントを整理しましょう。

  • 吹き出しの自動生成には `Page.Drop` ではなく `Page.DropCallout` を使う。
  • 紐付け状態の確認や付け替えには `Shape.CalloutTarget` を使う。
  • 吹き出しのマスタは専用ステンシル(`SDCALL_M.VSSX` など)から取得する。

Visio VBAは一見難しそうに見えますが、オブジェクトモデルの「つながり」さえ理解できれば、これほど図面操作を強力に自動化できるツールは他にありません。

まずは上のコードをそのままVBAエディタ(`Alt + F11`)に貼り付けて、図形が動いたときの感動を味わってみてください。応援しています!質問があればいつでも聞いてくださいね。

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