【テクニカル・上級編】プログラミングによる図形描画:Shape.DrawRectangleとDrawOvalを組み合わせた動的アイコン生成エンジン – Visio VBA解析バイブル

スポンサーリンク

Visio VBAを掌握する極限の知見:コードによる動的アイコン生成エンジンの構築

Visioのデフォルトステンシルに依存した開発は、配布時のバージョン差異やステンシルファイルのパス切れ(いわゆる「リンク切れ地獄」)という、レガシーシステム特有の爆弾を抱え込むことに他ならない。

真のシニアアーキテクトが目指すべきは、「コードのみで完結する自己完結型の描画エンジン」の構築である。`Shape.DrawRectangle`や`DrawOval`といった基本プリミティブを組み合わせ、プログラムの実行コンテキスト上でピクセル単位の制御を行い、動的にステータスインジケーターやカスタムアイコンを生成する。

本稿では、オブジェクトモデルのライフサイクル、メモリ管理、そしてマルチシェイプ合成におけるパフォーマンスの極限を引き出すVBAコードの全貌を解説する。

1. Visioオブジェクトモデルの深層とメモリ最適化の哲学

VBAにおけるVisio開発の最大の罠は、COMオブジェクトの参照リークと、暗黙的な`ActivePage`への依存である。

`Shape`オブジェクトを生成・操作する際、アプリケーションの背後では常にCOMのマーシャリングとVBAの参照カウンタが動作している。これを明示的に管理しないコードは、大規模な図面生成時に確実にメモリリークを引き起こし、Visioのプロセスを不安定にする。

鉄則:オブジェクト変数の明示的解放とスコープの限定

複数の基本図形(矩形、円、線)を組み合わせて1つの「カスタムアイコン(グループ形状)」を動的生成する場合、インスタンスの生成と破棄をコードレベルで完全にコントロールしなければならない。

‘ ==============================================================================
‘ 建築・インフラ監視システム向け 動式ステータスアイコン生成エンジン
‘ ==============================================================================
Public Sub GenerateStatusIndicator(ByVal targetPage As Visio.Page, _
ByVal posX As Double, _
ByVal posY As Double, _
ByVal statusType As String)

‘ 厳密な型定義によるパフォーマンス最適化
Dim vsoShapeRect As Visio.Shape
Dim vsoShapeOval As Visio.Shape
Dim vsoShapeGroup As Visio.Shape
Dim shpArray(1 To 2) As Visio.Shape

‘ 画面描画の凍結による爆発的な高速化(ScreenUpdatingの制御)
Application.ScreenUpdating = False

On Error GoTo ErrorHandler

‘ 1. ベースとなる矩形を描画 (DrawRectangleの引数は PinX, PinY, Width, Height ではなく X1, Y1, X2, Y2)
‘ ※ Visio VBAのプリミティブは内部的にインチ単位(DBC)で処理される点に注意
Set vsoShapeRect = targetPage.DrawRectangle(posX, posY, posX + 1.2, posY + 0.8)
vsoShapeRect.Text = “SYS-01”

‘ 2. ステータスを示す円(インジケーター)を描画
Set vsoShapeOval = targetPage.DrawOval(posX + 0.1, posY + 0.1, posX + 0.4, posY + 0.4)

‘ ステータスに応じた動的カラーリング(RGB関数とCells[“FillForegnd”]の直接操作)
Select Case UCase(statusType)
Case “CRITICAL”
vsoShapeOval.Cells(“FillForegnd”).FormulaU = “RGB(255,0,0)”
Case “WARNING”
vsoShapeOval.Cells(“FillForegnd”).FormulaU = “RGB(255,165,0)”
Case “NORMAL”
vsoShapeOval.Cells(“FillForegnd”).FormulaU = “RGB(0,255,0)”
Case Else
vsoShapeOval.Cells(“FillForegnd”).FormulaU = “RGB(128,128,128)”
End Select

‘ 3. 形状のグループ化処理
‘ グループ化するシェイプを配列に格納
Set shpArray(1) = vsoShapeRect
Set shpArray(2) = vsoShapeOval

Set vsoShapeGroup = targetPage.Group(shpArray)

‘ グループ全体のメタデータ(User定義セルの動的追加と値設定)
vsoShapeGroup.AddNamedRow visSectionUser, “StatusMeta”, visTagDefault
vsoShapeGroup.CellsU(“User.StatusMeta”).FormulaU = “””” & statusType & “”””

CleanUp:
‘ 画面描画の復元
Application.ScreenUpdating = True

‘ オブジェクト変数の明示的解放(メモリリークの完全防止)
Set vsoShapeOval = Nothing
Set vsoShapeRect = Nothing
Set vsoShapeGroup = Nothing
Exit Sub

ErrorHandler:
MsgBox “アイコン生成エラー: ” & Err.Description, vbCritical, “DynamicIconEngine”
Resume CleanUp
End Sub

2. 座標系の罠:`DrawRectangle` と `DrawOval` の数学的解釈

Visio VBA初心者が最も躓くのが、描画メソッドの引数の仕様である。
多くの開発者が「X, Y, 幅, 高さ」を指定するものと誤解しているが、VisioのネイティブAPIである `DrawRectangle` や `DrawOval` は、「始点座標 (x1, y1) と 終点座標 (x2, y2)」を受け取る仕様になっている。

(x1, y2) +——-+ (x2, y2)
| |
| 形状 |
| |
(x1, y1) +——-+ (x2, y1) ※Visioのページ座標系は左下原点

動的レイアウト計算の実際

アイコン内に複数の図形を相対配置する場合、親シェイプの基準位置(PinX, PinY)を起点としたオフセット計算を完全にマスターしなければならない。

‘ 相対座標を用いたアイコン内部パーツの緻密な配置ロジック
Public Sub DrawComplexMetricIcon(ByVal pg As Visio.Page, ByVal baseX As Double, ByVal baseY As Double)
Dim shpBg As Visio.Shape
Dim shpBar1 As Visio.Shape
Dim shpBar2 As Visio.Shape

‘ 背景パネル
Set shpBg = pg.DrawRectangle(baseX, baseY, baseX + 2.0, baseY + 1.0)
shpBg.Cells(“FillForegnd”).FormulaU = “RGB(240,240,240)”

‘ メトリック表示用プログレスバー1 (CPU使用率など)
Set shpBar1 = pg.DrawRectangle(baseX + 0.2, baseY + 0.6, baseX + 1.8, baseY + 0.8)
shpBar1.Cells(“FillForegnd”).FormulaU = “RGB(0, 120, 215)”

‘ メトリック表示用プログレスバー2 (メモリ使用率など)
Set shpBar2 = pg.DrawRectangle(baseX + 0.2, baseY + 0.2, baseX + 1.2, baseY + 0.4)
shpBar2.Cells(“FillForegnd”).FormulaU = “RGB(16, 124, 65)”

‘ オブジェクト解放
Set shpBg = Nothing
Set shpBar1 = Nothing
Set shpBar2 = Nothing
End Sub

このアプローチにより、外部データソース(SQL ServerやREST APIからのJSON)をバインドした際に、データの増減やステータス変化に応じて、完全にゼロからカスタムアイコンをリアルタイム構築するエンジンが完成する。

3. レガシー環境とパフォーマンスの極限チューニング

数千点に及ぶノードやアイコンを動的描画するプラント図やネットワーク図の自動生成において、コードの書き方次第で処理時間が「数秒」から「数時間(フリーズ)」に化ける。

以下の3点祖を遵守することが、プロフェッショナルエンジニアの条件である。

1. `Application.ScreenUpdating = False` の徹底
Visioは1つの図形を描画するたびにUIを再描画しようとする。これを抑制するだけで、実行速度は最大50倍以上向上する。
2. イベントハンドラの無効化 (`Application.EnableEvents = False`)
図形の追加やグループ化の際、意図しない `ShapeAdded` などのイベントトリガーが発火して処理が重くなるのを防ぐため、バルク処理の前後はイベントを遮断する。
3. 無駄なセルの再計算の回避
プロパティ(`FormulaU`など)を変更する際、シート全体の再計算が走る。大量のパラメータを設定する場合は、最後に一括して再計算させるか、数式(Formula)ではなく値(Result)で直接流し込む設計思想を持つこと。

結言:ステンシルからの脱却

ステンシルファイル(.vss / .vssx)のバージョン管理やネットワーク共有フォルダからの読み込みエラーに悩まされる時代は終わった。

ここで解説した `Shape.DrawRectangle` / `DrawOval` を駆使した動的描画エンジンは、コードベースだけで完全なUI表現力を担保する。堅牢で、速く、環境依存のないVisio自動化アーキテクチャを、あなたのシステムにも実装してほしい。

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