こんにちは!Visio VBAの自動化の世界へようこそ。
マクロの記録ボタンを押してコードを生成するフェーズを卒業し、「いよいよ本格的に自分だけの自動化ツールを作るぞ!」と意気込んでいるあなたへ。
今回は、Visio VBAを実務レベルで使いこなすために絶対避けて通れない「防衛的プログラミング(Defensive Programming)」の極意をお伝えします。
ここをクリアすれば、あなたの書くマクロは「ちょっとしたことですぐ止まるお騒がせプログラム」から、「どんなシェイプが来ても華麗にいなすプロ仕様のコード」へと生まれ変わりますよ。ぜひ最後までついてきてくださいね!
—
1. なぜVisio VBAでは「エラー」が頻発するのか?
Visioの図面(Drawing)を思い浮かべてみてください。そこには、四角形や丸だけでなく、複雑なネットワーク機器のアイコンや、社内ニッチなフローチャート記号など、さまざまな「シェイプ(Shape)」が配置されていますよね。
これら個々のシェイプには、「シェイプデータ(旧カスタムプロパティ)」という、メタデータを埋め込むための領域を持たせることができます。
例えば、「全てのサーバー機器シェイプから『IPアドレス』というプロパティを取り出してリスト化するマクロ」を書いたとしましょう。ここで、次のような残酷な現実があなたを襲います。
> 「図面の中に、IPアドレスというプロパティを持っていないシェイプが混ざっていた……!」
この状態で、安易に次のようなコードを実行するとどうなるでしょうか?
‘ ⚠️ やってはいけない危険なコードの例
Dim ipValue As String
ipValue = myShape.Cells(“Prop.IPAddress”).ResultStr(“”)
もし、そのシェイプに `Prop.IPAddress` が存在しなかった場合、Visioは容赦なく 「実行番号:-2147352567 (80020009) 指定された名前は見つかりませんでした。」 という冷酷なエラーを吐き、マクロは無残にクラッシュします。
これが、中級者へのステップアップを阻む「消えないエラーの呪い」です。
—
2. 救世主現る! `CellExistsU` という名の盾
この理不尽なエラーを防ぐために用意された防衛機能が、今回主役となる `CellExistsU` メソッド です。
‘ 構文の基本
isExist = shapeObject.CellExistsU(“セルの名前”, 存在確認の種類)
このメソッドは、指定したシェイプの中に、目的のセルが「存在するかどうか」を真偽値(True / False)でこっそり教えてくれるスグレモノです。エラーを事前に「予知」できるため、プログラムが強制終了するのを未然に防ぐことができます。
ここで、名前にひっそりついている「U」の意味にも触れておきましょう。
末尾の `U` は Universal(ユニバーサル) の略。Visio VBAでは、言語依存のあるローカライズされた名前(日本語版なら「行.Prop.IPAddress」など)ではなく、世界共通で使える英語ベースのU-メソッドを使うのが、バグを防ぐプロの鉄則です。
—
3. 実践!安全なプロパティ参照デザインパターン
それでは、実際の現場で即戦力として使える「防衛的プログラミング」のコードテンプレートを見てみましょう。
今回は、選択したシェイプ群の中から、特定のプロパティ(ここでは例として `Prop.Cost` というコスト情報)を持っているものだけを探し出し、合計値を計算するマクロを組んでみます。
Sub SafeCalculateCost()
Dim shp As Visio.Shape
Dim totalCost As Double
Dim checkedCount As Long
totalCost = 0
checkedCount = 0
‘ 1. 図面上で選択されているシェイプがあるかチェック
If ActiveWindow.Selection.Count = 0 Then
MsgBox “シェイプが選択されていません。”, vbExclamation, “警告”
Exit Sub
End If
‘ 2. 選択されたシェイプをひとつずつループ処理
For Each shp In ActiveWindow.Selection
‘ 3. 【最重要】Prop.Cost セルが存在するか「CellExistsU」で確認する
‘ 第2引数の「visExistsLocally」は、そのシェイプ自身が直接そのプロパティを持っているかを厳密に判定します
If shp.CellExistsU(“Prop.Cost”, visExistsLocally) Then
‘ 4. 存在することが確約されたので、安全に値を取得して加算
totalCost = totalCost + shp.Cells(“Prop.Cost”).ResultIU
checkedCount = checkedCount + 1
Else
‘ プロパティを持っていないシェイプは無視(またはログ出力)する
Debug.Print “スキップ: シェイプ名「” & shp.Name & “」にはCostプロパティがありません。”
End If
Next shp
‘ 5. 結果の通知
MsgBox “処理が完了しました。” & vbCrLf & _
“対象シェイプ数: ” & checkedCount & “個” & vbCrLf & _
“総コスト: ” & totalCost, vbInformation, “計算結果”
End Sub
コードのポイント解説
1. `ActiveWindow.Selection` による対象の絞り込み
いきなり図面全体の全シェイプをスキャンすると処理が重くなるため、まずはユーザーが選んだものに限定しています。
2. `CellExistsU(“Prop.Cost”, visExistsLocally)` の魔力
ここで `True` が返ってきたシェイプだけを処理の土俵に上げるため、エラーでマクロが止まる要素が完全に排除されます。
3. `ResultIU` の活用
Visio内部の単位系で安全に数値を取り出すプロパティです。図面の表示単位(mmやインチなど)に左右されず、純粋な数値計算ができます。
—
4. 陥りやすい罠とワンポイント・アドバイス
ここで、少し踏み込んだ「プロの知見」をひとつ。
`CellExistsU` の第2引数にはいくつかフラグを指定できますが、基本的には `visExistsLocally` (そのシェイプ自身にローカル定義されているか)を使うのが最も安全で意図通りに機能します。
マスターシェイプ(ステンシル)から引っ張ってきただけで、まだ独自のシェイプデータを上書きしていないような場合、親(マスター)側の設定を参照してしまい、予期せぬ挙動をすることがあります。`visExistsLocally` を指定することで、「今、目の前にあるこの個別シェイプが、そのデータを持っているか」を厳密にスナイプできるのです。
—
まとめ:防衛的プログラミングで、揺るぎない自動化を
今回は `Shape.CellExistsU` を使った、安全なプロパティ参照の設計パターンを解説しました。
- エラーが起きる前に、存在を確認する(CellExistsU)
- 条件分岐(If文)で処理を安全にガードする
- ローカルな存在確認(visExistsLocally)で誤作動を防ぐ
この3つを意識するだけで、あなたの書くVisio VBAのコードの信頼性は劇的に跳ね上がります。現場のユーザーから「このマクロを使うと、たまに意味不明なエラーで止まるんだけど…」と言われるストレスから、今日でサヨナラしましょう!
ここをクリアすれば、Visio VBAの基本構造、そしてオブジェクトの機嫌の取り方はもうバッチリです。ぜひ明日の実務から取り入れてみてくださいね。それでは、また次回の極限の知見でお会いしましょう!
