こんにちは!Visio VBAの自動化の世界へようこそ。
マクロの記録ボタンを押して生成されたコードを眺め、`ActivePage.Shapes.Item(1)` のような呪文のような記述に頭を悩ませていませんか?
「特定のシェイプの色を変えたい」「テキストを書き換えたい」――そう思ってコードを書くうちに、メインのプロシージャが何百行ものスパゲッティコードになり、どこを直せばいいか分からなくなる……。これは、誰もが通る「Visio VBAの壁」です。
今回は、その壁を鮮やかにブチ破る「クラスモジュールを使ったShapeオブジェクトのラップ」という、ワンランク上の設計手法を伝授します。ここをクリアすれば、あなたのVisioマクロは見違えるほど美しく、保守性の高い「プロのコードベース」に生まれ変わりますよ。
—
1. なぜ「そのままのShape」ではダメなのか?
Visio VBAの基本は、`Page.Shapes` コレクションから `Shape` オブジェクトを取り出し、そのプロパティをいじることです。しかし、生の `Shape` オブジェクトを直接あちこちのコードで操作していると、次のような問題に直面します。
- プロパティ名の迷子: セルの値を書き換えるために `CellsU(“Prop.MyCustomField”)` なんて長いメソッドを何度もあちこちで書くハメになる。
- 仕様変更の地獄: データ構造を変えたとき、コードのあちこちにある `CellsU` の文字列を全て書き直さなければならない。
解決策:オブジェクト指向の「ラップ(包み隠す)」
ここで登場するのがクラスモジュールです。
Visioの生々しい `Shape` オブジェクトを、自分が作りたい業務概念(例えば「タスクシェイプ」「機器ノード」など)専用のクラスで「ラップ(包み込む)」します。
これにより、外部のコードからは `myTask.Status = “完了”` や `myTask.Save()` のように、直感的で美しいメソッドやプロパティでシェイプを操作できるようになります。
—
2. 実践:タスク管理シェイプをラップするクラスを作ろう
それでは、具体的なハンズオンに入りましょう。
今回は、Visio上で「タスク」を表すシェイプをラップする、`ClsTaskShape` というクラスを作ります。
ステップ1:クラスモジュールの挿入と準備
1. VisioでVBE(Visual Basic Editor)を開きます(`Alt + F11`)。
2. メニューの [挿入] > [クラス モジュール] をクリックします。
3. プロパティウィンドウで、このモジュールの名前を `ClsTaskShape` に変更します。
ステップ2:クラスモジュールにコードを実装する
`ClsTaskShape` の中に、以下のコードを貼り付けてください。
‘ ==========================================
‘ クラス名: ClsTaskShape
‘ 概要: Visioの生Shapeオブジェクトをラップし、
‘ 「タスク」としての業務ロジックを提供する
‘ ==========================================
Option Explicit
‘ 内部で保持する本物のVisio Shapeオブジェクト
Private m_shp As Visio.Shape
‘ — 初期化(コンストラクタの役割) —
Public Sub Init(ByVal targetShape As Visio.Shape)
Set m_shp = targetShape
End Sub
‘ — 読み取り専用プロパティ:元のShapeを返す —
Public Property Get InnerShape() As Visio.Shape
Set InnerShape = m_shp
End Property
‘ — プロパティ:タスク名の取得・設定 —
Public Property Get TaskName() As String
‘ シェイプのテキストを返す
TaskName = m_shp.Text
End Property
Public Property Let TaskName(ByVal value As String)
‘ シェイプのテキストを書き換える
m_shp.Text = value
End Property
‘ — プロパティ:カスタムプロパティ(ShapeSheet)経由の状態管理 —
Public Property Get Status() As String
On Error Resume Next
‘ ShapeSheetの “Prop.Status” セルから値を取得
Status = m_shp.CellsU(“Prop.Status”).ResultStr(“”)
On Error GoTo 0
End Property
Public Property Let Status(ByVal value As String)
On Error Resume Next
‘ ShapeSheetの “Prop.Status” セルに値を書き込む
m_shp.CellsU(“Prop.Status”).FormulaU = “””” & value & “”””
‘ ステータスに応じて色を変える業務ロジックをカプセル化
Select Case value
Case “完了”
m_shp.CellsU(“FillForegnd”).FormulaU = “RGB(200, 255, 200)” ‘ 薄い緑
Case “進行中”
m_shp.CellsU(“FillForegnd”).FormulaU = “RGB(255, 255, 200)” ‘ 薄い黄色
Case Else
m_shp.CellsU(“FillForegnd”).FormulaU = “RGB(240, 240, 240)” ‘ 薄いグレー
End Select
On Error GoTo 0
End Property
‘ — メソッド:タスクを特定の座標に移動する —
Public Sub MoveTo(ByVal x As Double, ByVal y As Double)
m_shp.CellsU(“PinX”).FormulaU = x & ” mm”
m_shp.CellsU(“PinY”).FormulaU = y & ” mm”
End Sub
ここがエンジニアの知見:
- カプセル化の恩恵: 色の変更ロジック(`FillForegnd` の操作)をクラス内部に隠蔽しています。呼び出し側は「ステータスを『完了』にする」ことだけを指示すればよく、色がどう変わるかを知る必要はありません。
- エラーハンドリング: ShapeSheetのセルの存在有無によるエラーを防ぐため、最低限の `On Error Resume Next` を挟んでいます(実務ではカスタムプロパティの存在チェックを入れるとさらに堅牢になります)。
—
3. 標準モジュールから呼び出してみよう
クラスができたら、次はそれを呼び出す標準モジュールを作成します。
メニューの [挿入] > [標準モジュール] をクリックし、以下のコードを記述してください。
Option Explicit
Sub TestTaskShapeWrapper()
‘ 1. アクティブページから対象のシェイプを取得
Dim targetShp As Visio.Shape
If ActivePage.Shapes.Count = 0 {
MsgBox “シェイプが1つもありません!”, vbExclamation
Exit Sub
}
Set targetShp = ActivePage.Shapes(1) ‘ 簡単のため最初のシェイプを使用
‘ 2. 自作クラスのインスタンスを生成し、Shapeをラップする
Dim myTask As ClsTaskShape
Set myTask = New ClsTaskShape
myTask.Init targetShp
‘ 3. 直感的なプロパティ・メソッドで操作する!
myTask.TaskName = “API仕様書レビュー”
myTask.Status = “進行中”
myTask.MoveTo 100, 150 ‘ X=100mm, Y=150mm へ移動
MsgBox “ラップしたオブジェクトの操作が完了しました!”, vbInformation
End Sub
—
4. 陥りやすいエラーと回避のテクニック
クラスモジュールを導入する際、初心者が必ずハマる罠があります。ここを知っておくだけで、開発スピードが何倍も変わります。
エラー①:`Object variable or With block variable not set`(オブジェクト変数が設定されていません)
- 原因: `Dim myTask As ClsTaskShape` のあと、`Set myTask = New ClsTaskShape` を書き忘れた状態で、プロパティやメソッドを呼び出そうとしたときに出るエラーです。
- 対策: クラスを使うときは必ず `New` でインスタンス化することを忘れないでください。
エラー②:Shapeを削除したあとにクラスを参照してエラーになる
- 原因: ラップ元の Visio の `Shape` 自体がユーザー操作などで削除された後、内部の `m_shp` を操作しようとすると、Visioのオブジェクトモデルは消滅しているためエラーになります。
- 対策: クラス内に `Public Function IsValid() As Boolean` などの生存確認メソッドを持たせ、操作前にチェックする設計にするとプロフェッショナルなコードになります。
—
まとめ:オブジェクト指向でVisio VBAを「資産」に変える
今回は、Visio VBAにおけるクラスモジュールを活用した `Shape` のラップ手法を解説しました。
- 生の `Shape` をそのまま触るのではなく、業務の文脈に合わせたクラスで包み込む(ラップする)。
- プロパティやメソッドの裏側に、ShapeSheetの複雑な操作や色の変更ロジックをカプセル化する。
- 結果として、コードの可読性が劇的に向上し、仕様変更に強いシステムが構築できる。
マクロの記録の延長から抜け出し、こうしたオブジェクト指向の設計を取り入れることで、あなたの書くVBAコードは「その場しのぎの使い捨てスクリプト」から、「長くメンテナンスできる堅牢な業務システム」へと進化します。
ここをクリアしたあなたなら、もうVisio VBAの基礎はバッチリです!ぜひ実際の業務ツール開発に応用してみてくださいね。
