こんにちは!Visioの自動化の世界へようこそ。
マクロの記録ボタンを押して、生成されたコードをそのまま動かしてみたものの、「別の図形を選択したら急にエラーで止まった……」なんて壁にぶつかっていませんか?
Visio VBAの世界では、すべての図形(Shape)が同じパーツ(ShapeSheetのセル)を持っているとは限りません。特に外部からインポートした図形や、手製で作り込んだカスタムシェイプを相手にする時、「存在しないセルにアクセスしようとした瞬間、容赦なくマクロがクラッシュする」というトラップが待ち受けています。
今回は、そんな恐怖の実行時エラーを華麗に回避し、あなたのマクロを「絶対に止まらない金剛不壊の防衛システム」へと生まれ変わらせる王道テクニック、`CellExistsU` を徹底解説します。
ここをクリアすれば、Visio VBAの基本はバッチリですよ!一緒に本質をマスターしていきましょう。
—
なぜ、Visio VBAは突然エラーで止まるのか?
Visioの図形(Shape)は、いわば「小さなExcelシート」をその身に宿しています。これを ShapeSheet(シェイプシート) と呼びます。
例えば、図形の幅(Width)や高さ(Height)は、どの図形にも必ず存在します。しかし、あなたが独自に定義した「カスタムプロパティ(例: `Prop.Cost` や `Prop.Vendor`)」や、特定の計算用セルは、すべての図形にデフォルトで用意されているわけではありません。
もし、そのデータを持っていない図形に対して、次のようなコードを実行すると……。
‘ 【危険なコードの例】
‘ ユーザー定義プロパティ「Prop.Cost」がない図形を選ぶと、ここで即死(エラー9: インデックスが有効範囲にありません)します
Dim myCost As Double
myCost = ActivePage.Shapes(1).Cells(“Prop.Cost”).ResultIU
「いやいや、ちゃんと図形を選んでるんだからあるはずだろ!」と思っても、ユーザーが違う図形をクリックしていたり、別のステンシルから持ってきた図形だったりすると、容赦なくエラーが飛んできます。
これでは、実務で使える自動化ツールとは言えませんよね。ここで登場するのが、防衛的プログラミングの切り札 `CellExistsU` です。
—
`CellExistsU` とは何か?(基本の文法)
`CellExistsU` は、対象のシェイプの中に「指定した名前のセルが存在するかどうか」を、エラーを出す前に真偽値(`True` または `False`)でこっそり教えてくれる凄腕の関数です。
構文の形
‘ 戻り値は Integer型(実質 Boolean: 存在すれば -1(True)、なければ 0(False))
isExist = Shapeオブジェクト.CellExistsU(“セルの名前”, 照合フラグ)
- セルの名前: `”Prop.Cost”` や `”LineColor”` など、調べたいShapeSheetセルの名前を文字列で指定します(※ `U` はUniversal(普遍的)の意。言語依存しない英語名で指定するのがプロの作法です)。
- 照合フラグ: 基本的には `visExistsLocally`(0:その図形自身に直接定義されているか)などを指定します。通常は `0`(または定数)を指定すれば間違いありません。
—
実践!エラーを完全にいなす安全なコード
それでは、実際に現場で使える「安全なプロパティ参照コード」を見てみましょう。
選択している図形の中に、特定のカスタムプロパティがある場合だけ値を読み取り、なければ優しくスキップする処理です。
Sub SafeReadCustomProperty()
Dim shp As Visio.Shape
Dim targetCellName As String
targetCellName = “Prop.Cost” ‘ チェックしたいカスタムプロパティ名
‘ 1. 現在選択されている図形があるかチェック
If ActiveWindow.Selection.Count = 0 Then
MsgBox “図形が選択されていません。”, vbExclamation
Exit Sub
End If
‘ 先頭の図形をターゲットにする
Set shp = ActiveWindow.Selection(1)
‘ 2. CellExistsU でセルの存在を事前チェック!
‘ 第2引数の「0」は、その図形自身にセルが存在するかをローカルに判定します
If shp.CellExistsU(targetCellName, 0) Then
‘ — 存在する場合の処理 —
Dim costValue As Double
costValue = shp.CellsU(targetCellName).ResultIU
MsgBox “コストは ” & costValue & ” です。”, vbInformation, “判定:成功”
Else
‘ — 存在しない場合の処理(エラーにならない!) —
MsgBox “この図形にはコストプロパティが設定されていません。”, vbExclamation, “判定:安全に回避”
End If
End Sub
このコードの美しいポイント
1. 事前の身元確認: いきなり `CellsU` を叩くのではなく、`CellExistsU` で「いるか?」とノックしています。
2. クラッシュの完全防止: 対象プロパティがない図形を選択して実行しても、エラーメッセージで優しく案内され、マクロが途中で止まることがありません。
3. `CellsU` の使用: ここでも `Cells` ではなく `CellsU` を使っています。グローバル対応(多言語対応)において、`.CellsU` と `CellExistsU` は常にセットで覚えるべき相棒です。
—
プロが教える応用テクニック:存在しないなら、その場で作れ!
「セルが存在しないなら、エラーで弾くだけじゃなく、自動でその場で作ってしまいたい」という高度な要件もありますよね。
`CellExistsU` は、そんなアグレッシブな自動化の判定にも大活躍します。
Sub EnsureAndSetProperty()
Dim shp As Visio.Shape
Dim propName As String
propName = “Prop.Status”
Set shp = ActiveWindow.Selection(1)
‘ セルが存在するか確認し、なければ追加する
If Not shp.CellExistsU(propName, 0) Then
‘ 存在しないので、カスタムプロパティの行を追加する(例:インデックス指定等)
‘ ※実際には AddNamedRow などを組み合わせて動的に追加します
MsgBox “プロパティが存在しないため、新しく定義します。”, vbInformation
‘ ここでプロパティを追加する処理を記述(今回は割愛しますがCellExistsUがトリガーになります)
End If
‘ 安心して値を代入
‘ shp.CellsU(propName).FormulaU = “””進行中”””
End Sub
—
まとめ:防衛的コードがあなたを救う
Visio VBAにおけるオブジェクト操作は、見えないデータ構造との戦いです。「図形ならこれを持っているはずだ」という人間の思い込みを、容赦なく裏切ってくるのがマクロの世界です。
- アクセスする前に、まず `CellExistsU` で確認する。
- メソッドは言語に依存しない `CellsU` や `CellExistsU` を使う。
たったこれだけのルールを守るだけで、あなたの書くVisioマクロの信頼性はプロ基準へと跳ね上がります。エラーにおびえる日々にサヨナラして、スマートで強靭な自動化ライフを楽しみましょう!
