Visio VBAを掌握する極限の知見:シェイプシート数式ハックで図形を自在に操る
Visioの真髄は、単なる図形描画ツールに留まりません。その深奥には、図形が持つあらゆる属性と振る舞いを定義する「シェイプシート」という強力な内部データベースが息づいています。GUIでは到達できない、図形の魂とも言うべきこのシェイプシートをVBAから直接操作し、数式(FormulaU)を流し込む。これこそが、Visioを単なる作図ツールから、ビジネスロジックを内包する動的なアプリケーションへと昇華させる「極限の知見」です。
本稿では、開発プロジェクトのリーダーたるあなたが、なぜこの手法が業務効率化に不可欠なのか、そしてどう設計すべきかをロジカルかつシャープに伝授します。一般的なリファレンスの引き写しのような退屈な記事はここにはありません。オブジェクトのライフサイクルとパフォーマンスの重みを知り尽くした者だけが語れる、プロフェッショナルなVisio VBAの世界へようこそ。
—
1. シェイプシートの心臓部:Visio図形の「魂」を理解する
Visioの図形は、その見た目やテキストだけでなく、内部に膨大なデータとロジックを抱え込んでいます。これが「シェイプシート」です。位置、サイズ、色、線のスタイル、テキストの書式、コネクションポイント、さらにはユーザー定義プロパティやイベントの振る舞いまで、Visio図形に関するあらゆる情報がセルとして格納されています。
これらのセルは、単なる値を持つだけでなく、Excelのシートのように数式を持つことができます。この数式によって、図形は他の図形のプロパティと連動したり、特定の条件に基づいて自身の見た目や振る舞いを変化させたりと、非常に動的な振る舞いを実現します。
なぜVBAからこのシェイプシートを直接ハックする必要があるのでしょうか?
GUIでは、一つ一つの図形に対して手動でプロパティを設定したり、簡単な連動を設定したりはできます。しかし、数百、数千の図形に対して一貫したルールを適用したい場合、あるいは外部データ(データベース、CSV、XMLなど)に基づいて図形の振る舞いを動的に決定したい場合、手動操作は現実的ではありません。
VBAからシェイプシートの数式を直接操ることで、あなたはVisio図形を完全にプログラムの支配下に置き、以下のような強力なツールを構築できます。
- 一括自動設定: 大量の図形に対して、特定のプロパティ(サイズ、位置、色など)や動的な連動ルールを一括で適用。
- 堅牢な振る舞い: `Guard`関数などを組み込み、ユーザーによる意図しない図形の変更や破壊を防止。
- 外部データ連携: データベースから取得した値に基づいて、図形の見た目や振る舞いを動的に生成・更新。
- カスタムロジック: Visio標準の機能では実現困難な、複雑な条件分岐や計算をシェイプシート数式として埋め込む。
これは、単なるマクロの域を超え、Visioを基盤とした高度な業務アプリケーションを開発する道なのです。
—
2. VBAからシェイプシートを操る基本:CellsUとFormulaU
VBAからシェイプシートのセルにアクセスするには、主に`Shape.CellsU`プロパティを使用します。`CellsU`は、セルのユニバーサル名(英語名)を使ってセルを指定する際に使われます。
CellsUプロパティの基本
`Shape.CellsU(“セクション.行.セル名”)` の形式で、特定のセルオブジェクトを取得します。
例えば、図形の幅を取得するには `vShape.CellsU(“Width”)`、テキストの色を取得するには `vShape.CellsU(“Char.Color”)` のように指定します。
FormulaUとResultU:数式か、結果か
ここが重要です。セルの値を取得・設定する方法には、主に`FormulaU`と`ResultU`の二つがあります。
- `Cell.FormulaU`: セルに設定されている「数式文字列」そのものを取得または設定します。今回のテーマである数式ハックの主役です。数式を設定することで、図形は動的な振る舞いや連動を実現します。
‘ 幅をページの半分に固定する数式を設定
vShape.CellsU(“Width”).FormulaU = “=ThePage!PageWidth 0.5”
- `Cell.ResultU`: セルの「評価結果」(計算後の最終的な値)を取得または設定します。数式を持たないセルに値を設定する場合や、数式の結果を数値として取得したい場合に用います。
‘ 幅を特定の固定値に設定(数式は消去される)
vShape.CellsU(“Width”).ResultU = 5 ‘ 単位はドキュメントのデフォルト単位
重要ポイント: `FormulaU`で数式を設定すると、そのセルの値は数式の評価結果によって決まります。後から`ResultU`で値を設定すると、数式は削除され、固定値が設定されます。数式による動的連動を維持したい場合は、必ず`FormulaU`を使用してください。
存在しないセルへの対処
`CellsU`は、存在しないセル名を指定するとエラーになります。特に「User-defined Cells (ユーザー定義セル)」や「Shape Data (図形データ)」のように、任意の名前でセルを作成できるセクションでは、事前にセルが存在するか確認するか、エラーハンドリングが必要です。
Dim vCell As Visio.Cell
On Error Resume Next ‘ エラーを一時的に無視
Set vCell = vShape.CellsU(“User.MyCustomProperty”)
On Error GoTo 0 ‘ エラーハンドリングを元に戻す
If vCell Is Nothing Then
‘ セルが存在しない場合は追加
vShape.AddNamedRow visSectionUser, “MyCustomProperty”, visRowLast
Set vCell = vShape.CellsU(“User.MyCustomProperty”)
End If
‘ これで確実にvCellオブジェクトが使える
vCell.FormulaU = “=Sheet.1!Width 2”
—
3. シェイプシート数式ハックの極意:Guard関数を使いこなす
Visio図形をプログラムで制御する上で、ユーザーの誤操作や他のプログラムによる意図しない変更から図形を守ることは、堅牢なシステム設計の基本です。ここで登場するのが、シェイプシートの`Guard`関数です。
Guard関数の目的と効果
`Guard(数式)`という形式で数式を囲むと、そのセルはGUIからの編集がロックされます。プロパティウィンドウからの変更、図形のハンドルをドラッグしての変更など、ほとんどの対話的操作が無効になります。
例えば、図形の幅や高さを特定の比率や値に固定したい場合、単に数式を設定するだけでは、ユーザーがハンドルをドラッグすれば簡単に変更されてしまいます。しかし、`Guard`関数を使えば、その変更を強力に阻止できます。
VBAからのGuard設定例
‘ 幅を親ページ幅の半分に固定し、Guardする
vShape.CellsU(“Width”).FormulaU = “=Guard(ThePage!PageWidth 0.5)”
‘ 高さの変更を完全に禁止し、現在の高さを維持する
‘ (図形の高さが常に現在の値に固定され、外部からの変更は適用されない)
vShape.CellsU(“Height”).FormulaU = “=Guard(Height)”
‘ PinX(中心X座標)をページの中央に固定
vShape.CellsU(“PinX”).FormulaU = “=Guard(ThePage!PageWidth / 2)”
Guard関数の実用例
- 図形のサイズ・位置固定: 配置図やフロアプランで、特定のオブジェクト(壁、ドア、設備など)のサイズや位置が変更されては困る場合に強力な効力を発揮します。
- コネクションポイントの固定: 特定のコネクションポイントが移動したり、追加・削除されたりするのを防ぎ、コネクタの接続ルールを厳格に保ちます。
- テキスト編集の制限: テキストセルに数式を埋め込み、それを`Guard`することで、ユーザーが図形上のテキストを直接編集するのを防ぎます。テキストは他のプロパティや図形データに連動して動的に生成されます。
- 複雑な条件付き書式: 図形の色や線のスタイルが、特定のデータや他の図形の状態に厳密に連動するように設定し、ユーザーが手動で上書きするのを防ぎます。
注意点: `Guard`は強力ですが、多用しすぎると図形の柔軟性を損ないます。本当に変更を禁止すべきプロパティにのみ適用し、必要に応じてVBAから`FormulaU`を再設定して`Guard`を外す、あるいは別の数式に書き換えるといったロジックも考慮に入れてください。
—
4. 動的連動の構築:数式による相互作用
Visioのシェイプシート数式の真骨頂は、図形間の動的な連動と自動計算です。VBAからこれらの数式を構築することで、単なる静的な図形ではなく、ビジネスロジックを反映した「賢い」図形を作成できます。
図形プロパティ間の連動
最も基本的な連動は、図形自身のプロパティ間での参照です。
‘ 縦横比を常に2:1に保つ
vShape.CellsU(“Height”).FormulaU = “=Width 2”
‘ テキストが図形の幅に応じて変化する
vShape.CellsU(“Text”).FormulaU = “=IF(Width > 5 in, “”幅が広い””, “”幅が狭い””)”
他の図形との連動
Visioの数式は、他の図形のシェイプシートセルを参照できます。これにより、図形が相互に影響し合う複雑なシステムを構築できます。
‘ 現在の図形のPinXを、Sheet.1という名前の図形のPinXから10mm右に配置
‘ Sheet.1は、Visioの描画ウィンドウで図形を選択し、開発者タブの「図形名」で確認できる名前
vShape.CellsU(“PinX”).FormulaU = “=Sheet.1!PinX + 10 mm”
‘ 現在の図形の塗りつぶし色を、Sheet.1の図形データ(Shape Data)の値によって変える
‘ Shape Dataは”Prop.<プロパティ名>“で参照
vShape.CellsU(“FillForegnd”).FormulaU = “=IF(Sheet.1!Prop.Status=””Active””, RGB(0,255,0), RGB(255,0,0))”
ページプロパティとの連動
Visioのページ自体もシェイプシートを持っています。ページサイズや背景色など、ページ全体のプロパティに図形を連動させることも可能です。
‘ 図形を常にページの右上隅に配置する
vShape.CellsU(“PinX”).FormulaU = “=ThePage!PageWidth – Width / 2”
vShape.CellsU(“PinY”).FormulaU = “=ThePage!PageHeight – Height / 2”
‘ 図形を常にページの幅の1/4のサイズにする
vShape.CellsU(“Width”).FormulaU = “=ThePage!PageWidth / 4”
これらの数式をVBAから動的に構築することで、ユーザーがドラッグ&ドロップで配置した図形が自動的に整列したり、関連する図形のプロパティが変更されると、それに応じて他の図形も自動的に更新されるような、自己調整能力を持つVisioドキュメントを作成できるのです。
—
5. 堅牢な設計とパフォーマンスの考慮
プロフェッショナルなツールを開発する上で、堅牢性とパフォーマンスは常に念頭に置くべき要素です。特に大量の図形を操作するVisio VBAでは、これらの配慮がツールの信頼性と実用性を大きく左右します。
堅牢性:エラーハンドリングとUndoスコープ
1. エラーハンドリング:
`CellsU`プロパティは、存在しないセル名を指定すると実行時エラーになります。`AddNamedRow`のようなメソッドでセルを追加する際も、予期せぬエラーが発生する可能性があります。`On Error GoTo` を活用し、適切なエラーメッセージを表示したり、処理を中断したりする仕組みは必須です。
On Error GoTo ErrorHandler
‘ … ここにシェイプシート操作のコード …
Exit Sub
ErrorHandler:
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical
‘ 必要に応じて、Undoをキャンセルする処理などを記述
‘ …
2. Undoスコープの活用:
VBAスクリプトで複数のVisio操作(図形作成、プロパティ変更など)を行うと、ユーザーが「元に戻す(Undo)」を実行した際に、個々の操作がバラバラに元に戻されてしまいます。これはユーザー体験を著しく損ねます。
`Application.BeginUndoScope` と `Application.EndUndoScope` を使用することで、一連のVBA操作を一つのUndo単位としてまとめることができます。
Dim lUndoScopeID As Long
lUndoScopeID = vApp.BeginUndoScope(“カスタム数式適用”) ‘ 操作名
On Error GoTo ErrorHandler
‘ … ここに一連のVisio操作(例: 複数の図形への数式設定) …
vApp.EndUndoScope lUndoScopeID, False ‘ 操作を確定
Exit Sub
ErrorHandler:
If lUndoScopeID <> 0 Then
vApp.EndUndoScope lUndoScopeID, True ‘ エラー時は操作を取り消す
End If
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical
`EndUndoScope`の第二引数を`True`にすると、そのスコープ内の操作がすべてキャンセルされます。これにより、エラー発生時にもドキュメントが不安定な状態になるのを防げます。
パフォーマンス:描画と再計算の抑制
大量の図形に対してシェイプシートの数式を変更する際、Visioは変更のたびに画面を再描画したり、影響を受ける数式を再計算しようとします。これは処理速度を著しく低下させます。以下のプロパティを一時的に`False`に設定することで、パフォーマンスを劇的に改善できます。
- `Application.ScreenUpdating = False`: 画面の再描画を一時停止します。
- `Application.DeferRecalc = True`: 数式の自動再計算を一時停止します。数式を多数変更する場合に非常に効果的です。処理の最後に必ず`False`に戻してください。
- `Application.ShowChanges = False`: 図形の変更を視覚的に表示するのを一時停止します。
‘ パフォーマンス最適化
vApp.ScreenUpdating = False
vApp.DeferRecalc = True
vApp.ShowChanges = False
‘ … ここにシェイプシート操作のコード …
‘ 処理の最後に元に戻すことを忘れない
vApp.ScreenUpdating = True
vApp.DeferRecalc = False
vApp.ShowChanges = True
これらの設定は、VBAコードの最初で`False`にし、エラーハンドリングを含め、`Exit Sub`や`GoTo FinallyExit`などの直前で必ず`True`/`False`に戻すように設計してください。これにより、VBA実行中にVisioアプリケーションがフリーズしたように見えたり、動作がおかしくなったりするのを防ぎます。
オブジェクト参照の最適化
VBAでVisioオブジェクトを扱う際、不要なオブジェクト生成や冗長な参照を避けることで、わずかながらもパフォーマンスを改善できます。
- `With` ステートメントの活用: 同じオブジェクトの複数のプロパティやメソッドにアクセスする場合、`With`ステートメントを使うとコードが簡潔になり、オブジェクト参照のオーバーヘッドが減ります。
- 直接参照: `ActivePage.Shapes.Item(i)` や `ActivePage.Shapes.ItemU(“Sheet.1”)` のように、必要なオブジェクトに直接アクセスし、中間オブジェクトの変数を無駄に生成しないようにします。
- オブジェクトの解放: 処理が終わったら、`Set vObject = Nothing` でオブジェクトを明示的に解放することで、メモリの効率的な利用を促進します。特にループ内で一時的に使用するオブジェクトは、ループの最後に解放することが望ましいです。
—
6. ファイル/データベース連携と保守性
シェイプシート数式をVBAコード内に直接ハードコードすることは、短期的には便利ですが、長期的には保守性の悪夢を招きます。数式が複雑化したり、ビジネスロジックが変更されたりするたびにVBAコードを修正・再デプロイするのは非効率的です。
プロフェッショナルな設計では、数式文字列やそのテンプレートを外部化し、柔軟な管理と保守を可能にします。
数式文字列の外部化
- 設定ファイル(XML, JSON, CSV): 数式文字列を外部の設定ファイルに記述し、VBAから読み込む。これにより、開発者はVBAコードを変更することなく、設定ファイルの内容を編集するだけで数式を更新できます。
- データベース: より大規模なシステムでは、データベースに数式テンプレートを保存し、アプリケーションの起動時や必要に応じてVBAから取得します。これにより、中央集約的な管理と、バージョン管理システムとの連携が容易になります。
例:
`formulas.xml` ファイルに以下のような定義を記述。
VBAコードでは、これらのテンプレートを読み込み、必要に応じてプレースホルダー(`{SCALE}`など)を実際の値で置換してから`FormulaU`に設定します。
Function GetFormulaTemplate(formulaName As String) As String
‘ XMLファイルなどから数式テンプレートを読み込むロジック
‘ 例: “GuardedWidth” -> “=Guard(ThePage!PageWidth {SCALE})”
Select Case formulaName
Case “GuardedWidth”: GetFormulaTemplate = “=Guard(ThePage!PageWidth {SCALE})”
Case “DynamicFillColor”: GetFormulaTemplate = “=IF(User.Status=””Active””, RGB(0,255,0), RGB(255,0,0))”
Case Else: GetFormulaTemplate = “”
End Select
End Function
Sub ApplyFormulasWithExternalTemplates()
Dim vShape As Visio.Shape
Dim strTemplate As String
Dim strFormula As String
Set vShape = Visio.ActiveWindow.Selection.Item(1) ‘ 例として選択図形の1つ目
‘ 幅の数式を適用
strTemplate = GetFormulaTemplate(“GuardedWidth”)
strFormula = Replace(strTemplate, “{SCALE}”, “0.75”) ‘ 75%にスケール
vShape.CellsU(“Width”).FormulaU = strFormula
‘ ユーザー定義セルの数式を適用
‘ (User.Statusが存在しない場合は追加するロジックも必要)
vShape.CellsU(“User.Status”).FormulaU = “””Active””” ‘ まずは値を設定
strFormula = GetFormulaTemplate(“DynamicFillColor”)
vShape.CellsU(“FillForegnd”).FormulaU = strFormula
End Sub
定数化とコメント
VBAコード内で直接セル名(例: `”Width”`, `”PinX”`, `”User.MyProperty”`)を文字列として記述すると、タイプミスやVisioのバージョンアップによる名称変更(稀ですが)に対応しにくくなります。
よく使うセル名やセクション名は、VBAの`Const`キーワードで定数として定義しましょう。
Const C_CELL_WIDTH As String = “Width”
Const C_CELL_HEIGHT As String = “Height”
Const C_CELL_PINX As String = “PinX”
Const C_CELL_PINY As String = “PinY”
Const C_SECTION_USER As Visio.VisSectionIndices = visSectionUser ‘ Visio列挙体も活用
‘ 使用例
vShape.CellsU(C_CELL_WIDTH).FormulaU = “=Guard(ThePage!PageWidth 0.5)”
これにより、コードの可読性が向上し、保守性が高まります。また、複雑な数式文字列には、VBAコード内だけでなく、数式自体にもコメントを埋め込む(Visioの数式には直接コメント機能はありませんが、VBAのコメントで補足する)ことで、後からコードを読んだ開発者が意図を理解しやすくなります。
—
7. 実践的コード例:選択図形へのGuard付き数式の一括適用
それでは、これまでの知見を統合した、実用的なVBAコードの例を見ていきましょう。このコードは、選択されたすべての図形に対し、ページ幅・高さを基準とした位置とサイズを`Guard`関数で固定し、さらにユーザー定義セルを追加して動的なテキスト連動を構築します。
Option Explicit
‘================================================================================
‘ モジュールレベル定数定義
‘ シェイプシートのセル名を定数化することで、タイプミス防止と保守性向上を図る
‘================================================================================
Private Const C_CELL_WIDTH As String = “Width”
Private Const C_CELL_HEIGHT As String = “Height”
Private Const C_CELL_PINX As String = “PinX”
Private Const C_CELL_PINY As String = “PinY”
Private Const C_CELL_USER_STATUS As String = “User.ShapeStatus” ‘ ユーザー定義セルの名前
Private Const C_CELL_TEXT As String = “Text”
‘——————————————————————————–
‘ プロシージャ名: ApplyGuardedAndDynamicFormulasToSelectedShapes
‘ 概要: 選択されたVisio図形に対し、Guard関数を含む数式や動的な連動数式を適用します。
‘ – 図形の幅、高さ、位置をページのサイズに連動させ、Guardで固定します。
‘ – ユーザー定義セル (User.ShapeStatus) を追加し、幅に応じて値を変更する数式を設定します。
‘ – テキストセルに、User.ShapeStatusを参照する動的な数式を設定します。
‘ 堅牢性: エラーハンドリング、Undoスコープ、パフォーマンス最適化を含みます。
‘——————————————————————————–
Sub ApplyGuardedAndDynamicFormulasToSelectedShapes()
Dim vApp As Visio.Application
Dim vSel As Visio.Selection
Dim vShape As Visio.Shape
Dim vCell As Visio.Cell
Dim strFormula As String
Dim lUndoScopeID As Long ‘ UndoスコープIDを保持
‘ Visioアプリケーションオブジェクトを取得
Set vApp = Visio.Application
‘ 選択図形がない場合は警告して終了
If vApp.ActiveWindow.Selection.Count = 0 Then
MsgBox “処理対象の図形を選択してください。”, vbExclamation, “Visio VBA シェイプシートハック”
Exit Sub
End If
‘============================================================================
‘ パフォーマンス最適化とUndoスコープの開始
‘ 大量の図形操作において、描画と再計算を一時停止することで処理速度を向上させ、
‘ 全ての操作を一つのUndo単位としてまとめることでユーザー体験を改善します。
‘============================================================================
‘ 一連の操作を一つのUndo単位にまとめる
lUndoScopeID = vApp.BeginUndoScope(“選択図形へのシェイプシート数式適用”)
‘ エラー発生時にジャンプする処理を指定
On Error GoTo ErrorHandler
‘ 描画、再計算、変更表示を一時的に停止し、パフォーマンスを向上
vApp.ScreenUpdating = False
vApp.DeferRecalc = True ‘ 数式が多数変更される場合に特に有効
vApp.ShowChanges = False
‘ 選択図形コレクションを取得
Set vSel = vApp.ActiveWindow.Selection
‘ 選択された各図形に対して処理を実行
For Each vShape In vSel
With vShape
Debug.Print “——————————————————–”
Debug.Print “処理中の図形: ” & .NameU & ” (ID: ” & .ID & “)”
‘ — 1. 幅、高さ、位置をページに連動させ、Guardで固定する例 —
‘ 幅をページの半分に固定し、ユーザーによる変更をGuard
strFormula = “=Guard(ThePage!PageWidth 0.5)”
.CellsU(C_CELL_WIDTH).FormulaU = strFormula
Debug.Print ” ” & C_CELL_WIDTH & ” Formula: ” & .CellsU(C_CELL_WIDTH).FormulaU
‘ 高さをページの3分の1に固定し、ユーザーによる変更をGuard
strFormula = “=Guard(ThePage!PageHeight / 3)”
.CellsU(C_CELL_HEIGHT).FormulaU = strFormula
Debug.Print ” ” & C_CELL_HEIGHT & ” Formula: ” & .CellsU(C_CELL_HEIGHT).FormulaU
‘ PinX (図形の中心X座標) をページの中央にGuard
strFormula = “=Guard(ThePage!PageWidth / 2)”
.CellsU(C_CELL_PINX).FormulaU = strFormula
Debug.Print ” ” & C_CELL_PINX & ” Formula: ” & .CellsU(C_CELL_PINX).FormulaU
‘ PinY (図形の中心Y座標) をページの中央にGuard
strFormula = “=Guard(ThePage!PageHeight / 2)”
.CellsU(C_CELL_PINY).FormulaU = strFormula
Debug.Print ” ” & C_CELL_PINY & ” Formula: ” & .CellsU(C_CELL_PINY).FormulaU
‘ — 2. ユーザー定義セル (User-defined Cells) を追加し、数式を書き込む例 —
‘ User.ShapeStatusというセルが存在しない場合は追加する
On Error Resume Next ‘ セルが存在しない場合のエラーを一時的に無視
Set vCell = .CellsU(C_CELL_USER_STATUS)
On Error GoTo ErrorHandler ‘ エラーハンドリングを元に戻す
If vCell Is Nothing Then
‘ セルが存在しない場合は追加 (visSectionUserはユーザー定義セルセクション)
‘ AddNamedRowはセクションの最後に新しい行を追加し、名前を付けます
.AddNamedRow visSectionUser, “ShapeStatus”, visRowLast
Set vCell = .CellsU(C_CELL_USER_STATUS) ‘ 追加したセルを再度取得
Debug.Print ” ” & C_CELL_USER_STATUS & ” を追加しました。”
End If
‘ User.ShapeStatus に、図形の幅に応じて値を変更する数式を設定
‘ 幅が5インチより大きい場合は “Large”、そうでなければ “Small” を返す
strFormula = “=IF(” & C_CELL_WIDTH & ” > 5 in, “”Large””, “”Small””)”
vCell.FormulaU = strFormula
Debug.Print ” ” & C_CELL_USER_STATUS & ” Formula: ” & vCell.FormulaU
‘ — 3. テキストセルに動的な数式を設定する例 —
‘ 図形のテキストを User.ShapeStatus の値に連動させる
strFormula = “=” & C_CELL_USER_STATUS
.CellsU(C_CELL_TEXT).FormulaU = strFormula
Debug.Print ” ” & C_CELL_TEXT & ” Formula: ” & .CellsU(C_CELL_TEXT).FormulaU
End With ‘ With vShape
Next vShape
MsgBox “選択された図形への数式適用が完了しました。”, vbInformation, “Visio VBA シェイプシートハック”
‘ 正常終了時は、FinallyExitラベルへジャンプ
GoTo FinallyExit
‘============================================================================
‘ エラーハンドリングセクション
‘============================================================================
ErrorHandler:
MsgBox “処理中にエラーが発生しました: ” & vbCrLf & _
“エラー番号: ” & Err.Number & vbCrLf & _
“説明: ” & Err.Description, vbCritical, “Visio VBA エラー”
‘ エラー発生時はUndoスコープをキャンセルし、元の状態に戻す
If lUndoScopeID <> 0 Then
vApp.EndUndoScope lUndoScopeID, True ‘ TrueでUndoキャンセル
End If
‘============================================================================
‘ クリーンアップセクション
‘ 正常終了時もエラー終了時も、必ずここを通るようにする
‘============================================================================
FinallyExit:
‘ パフォーマンス最適化で変更した設定を元に戻す
If Not vApp Is Nothing Then
vApp.ScreenUpdating = True
vApp.DeferRecalc = False
vApp.ShowChanges = True
‘ 正常終了時はUndoスコープを確定
If lUndoScopeID <> 0 And Err.Number = 0 Then ‘ エラーが発生していない場合のみ確定
vApp.EndUndoScope lUndoScopeID, False ‘ FalseでUndo確定
End If
End If
‘ オブジェクトの解放 (メモリリーク防止)
Set vCell = Nothing
Set vShape = Nothing
Set vSel = Nothing
Set vApp = Nothing
End Sub
コードの解説とポイント
1. モジュールレベル定数: シェイプシートのセル名を定数として定義しています。これにより、コードの可読性が向上し、タイポミスによるバグを防ぎ、将来的にセル名が変更された場合でも一箇所修正するだけで済みます。
2. Undoスコープ: `vApp.BeginUndoScope` で処理を開始し、`vApp.EndUndoScope` で処理を閉じます。これにより、選択図形への一連の数式適用操作が、ユーザーにとって一つの「元に戻す」単位として扱われます。エラー発生時には`EndUndoScope lUndoScopeID, True`で操作全体をキャンセルし、Visioドキュメントを安全な状態に戻します。
3. パフォーマンス最適化: `ScreenUpdating`, `DeferRecalc`, `ShowChanges` を一時的に `False` に設定し、処理速度を向上させています。処理の最後には必ず `True`/`False` に戻すよう、`FinallyExit` ラベルを活用しています。
4. エラーハンドリング: `On Error GoTo ErrorHandler` でエラー発生時の処理フローを定義し、ユーザーに分かりやすいメッセージを表示します。`On Error Resume Next` を一時的に利用して、ユーザー定義セルの存在チェックを行っています。
5. `AddNamedRow` メソッド: ユーザー定義セル (`User.ShapeStatus`) が存在しない場合に、`vShape.AddNamedRow visSectionUser, “ShapeStatus”, visRowLast` で動的に追加しています。これは、プログラムが図形に新しいプロパティや振る舞いを付与する際に非常に有用です。
6. `Debug.Print`: 各図形にどのような数式が設定されたか、イミディエイトウィンドウで確認できるようにしています。開発中のデバッグに役立ちます。
7. オブジェクトの解放: 処理の最後には、`Set … = Nothing` で使用したオブジェクト変数を明示的に解放しています。これは、VBAにおけるメモリ管理のベストプラクティスです。
—
8. まとめ:Visioの未来を創造する者たちへ
Visio VBAにおけるシェイプシート数式ハックは、単なるマクロ作成の域を超え、Visioを強力な業務アプリケーションプラットフォームへと変貌させるための「極限の知見」です。`CellsU`と`FormulaU`を介して図形の「魂」たるシェイプシートを直接操作し、`Guard`関数で堅牢な振る舞いを実装し、数式による動的連動でインテリジェントな図形を創造する。この一連のスキルセットは、あなたの業務効率化ツール開発を次のレベルへと押し上げます。
本稿で解説した堅牢な設計原則、パフォーマンス最適化のテクニック、そして保守性を高めるための外部連携の考え方は、あなたが開発するツールの信頼性と持続性を保証します。単なるコードのコピペではなく、その背後にある「なぜそうすべきなのか」という哲学を理解し、自身のプロジェクトに応用してください。
Visioは、あなたの知見と技術によって、無限の可能性を秘めたキャンバスとなります。この極限の知見を手に、Visioの未来を創造するのは、あなた自身です。
