【テクニカル・上級編】Visio VBAにおけるカスタムクラスモジュールの活用:Shapeオブジェクトをラップした独自業務クラスの設計 – Visio VBA解析バイブル

スポンサーリンク

Visio VBAの深淵:Shapeオブジェクトを「神クラス」から解き放つ設計術

VisioのVBAで書かれたコードの多くは、なぜこうも脆いのか。それは、`ActivePage.Shapes(i)`といった生のオブジェクトをコードのそこかしこで直接操作する「スパゲッティ・アーキテクチャ」が蔓延しているからだ。

`CellsU(“Width”).Formula = “10mm”` といった記述をビジネスロジックの中に散りばめてはならない。仕様変更のたびにVisioの迷宮を彷徨うことになる。本稿では、VisioのShapeを「単なる描画要素」から「振る舞いを持つ業務エンティティ」へと昇華させる、クラスモジュールを活用した設計手法を伝授する。

1. なぜ「ラッパー・クラス」が必要なのか

標準の`Shape`オブジェクトは、プロパティが膨大すぎて、意図しない書き換え(副作用)が起きやすい。特に`CellsU`によるセルの直接操作は、計算結果が予期せぬ依存関係を生み、ファイルサイズを肥大化させる。

我々が目指すべきは、「業務ドメイン言語」でVisioを操作することだ。
例えば、「ボックスの幅を広げる」のではなく、「プロセスユニットの処理能力を更新する」というインターフェースを定義する。

2. 独自クラスによる抽象化:`ProcessUnit`クラスの実装

まずは、Shapeをラップするクラスモジュール(仮名:`CProcessUnit`)を設計する。

‘ クラスモジュール: CProcessUnit
Option Explicit

Private m_shp As Visio.Shape

‘ コンストラクタ(的な初期化メソッド)
Public Sub Initialize(ByVal targetShape As Visio.Shape)
If targetShape Is Nothing Then Err.Raise 91, , “Shape is empty.”
Set m_shp = targetShape
End Sub

‘ プロパティ:業務ロジックをカプセル化
Public Property Let Capacity(ByVal value As Double)
‘ 内部のCellsU操作を隠蔽
‘ 単位変換やバリデーションをここに集約する
m_shp.CellsU(“User.Capacity”).Formula = value
m_shp.Text = “Capacity: ” & value
End Property

‘ メソッド:状態変化をメソッド名で表現
Public Sub Highlight(ByVal isError As Boolean)
If isError Then
m_shp.CellsU(“FillForegnd”).Formula = “RGB(255,0,0)”
Else
m_shp.CellsU(“FillForegnd”).Formula = “RGB(255,255,255)”
End If
End Sub

‘ 終了処理:メモリ管理の鉄則
Private Sub Class_Terminate()
Set m_shp = Nothing
End Sub

この設計の肝

  • カプセル化: `CellsU`の文字列指定や複雑な数式を外部から隠蔽する。
  • バリデーション: 値の書き込み時に型チェックや範囲チェックを挟むことが容易になる。
  • 保守性: Visioのシェイプシートの構造が変わっても、修正はクラス内の一箇所で済む。

3. パフォーマンスとメモリの極限制御

VBAにおけるVisio操作で最も忌むべきは、「不必要なオブジェクトの参照保持」「再描画の頻発」である。

オブジェクトの明示的解放

VBAは参照カウンタ方式のGCを採用しているが、VisioのオブジェクトモデルはCOMの層が厚い。`Nothing`への明示的なセットは、巨大なVisioファイルを扱う際のメモリリークを確実に防ぐ。

描画の抑制

ループ処理内で`CellsU`を何度も叩くのは、CPUをドブに捨てるのと同じだ。

‘ 高速化の定石:画面更新を止める
Application.ScreenUpdating = False

‘ 処理ロジック…

Application.ScreenUpdating = True

4. 高度な応用:Windows APIとの連携

Visio単体では解決できない要件(例えば、特定の業務データベースとの同期や、ファイルシステム上の他ファイル情報の取得)には、`Declare PtrSafe`を使用してWindows APIを呼び出す。

特に、大規模なVisioシステムでは「処理の完了通知」や「進捗状況の表示」をWin32 API(`User32.dll`など)で制御することで、ユーザー体験を劇的に向上させることができる。

‘ API宣言例:ユーザーに処理の完了を知らせるために
Private Declare PtrSafe Function Beep Lib “user32” (ByVal dwFreq As Long, ByVal dwDuration As Long) As Long

Public Sub NotifySuccess()
‘ 成功時に音を鳴らす等のUX向上
Beep 750, 300
End Sub

結論:アーキテクトとしての矜持

VBAは、決して「簡易スクリプト」のための言語ではない。適切な設計思想(クラス設計、カプセル化、リソース管理)を持ち込めば、Windows環境において極めて強力な自動化プラットフォームへと変貌する。

今回紹介した「Shapeのラッパー」は、その第一歩に過ぎない。
次にあなたが書くコードでは、`ActivePage.Shapes(1)`といった即物的なコードを捨て、ドメインを体現するオブジェクトたちを生成してほしい。それが、レガシーな環境で生き残る真のエンジニアの流儀である。

コードは美しく、メモリは潔く、そしてシステムは誰よりも速く。
それが、我々がVisio VBAに求める至高の姿だ。

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