Visio VBAの深淵:幾何学ブーリアン演算を極めるためのアーキテクチャ設計
Visioの真価は、単なるドローイングツールではない。「形状(Shape)というオブジェクトを、数学的演算によって自在に造形可能なエンジン」である点にこそある。
多くの開発者が`Shape.Union`や`Fragment`といったメソッドを「なんとなく」使用し、結果としてドキュメントの肥大化やパフォーマンスの崩壊を招いている。本稿では、レガシーなVisio VBA環境においても、メモリを枯渇させず、かつ堅牢なカスタムシンボル生成を実現するための「幾何学演算の作法」を伝授する。
—
1. 幾何学ブーリアン演算の「副作用」を制御する
`Union`, `Combine`, `Fragment`, `Intersect`, `Subtract`。これらのメソッドは非常に強力だが、裏側ではVisioの「ジオメトリエンジン」が激しく稼働する。これを乱用すると、形状データに不要な頂点(ゴミ)が蓄積され、ファイルサイズが肥大化し、最終的には「予期せぬオフセットエラー」を引き起こす。
鉄則:オブジェクトのスコープと解放
VBAはガベージコレクションが脆弱だ。特にブーリアン演算で生成された「結果としてのShape」は、スタック上に残りやすい。
‘ メモリリークを最小化するための定石
Public Sub OptimizeGeometryOperation(ByRef shp1 As Visio.Shape, ByRef shp2 As Visio.Shape)
Dim shpResult As Visio.Shape
‘ 演算前に必ずグループ化や複雑なプロパティを初期化する
‘ 演算後のオブジェクトを明示的に取得し、必要に応じてアンセットする
Set shpResult = shp1.Union(shp2)
‘ 結果に対する属性の再定義
With shpResult
.Cells(“FillForegnd”).Formula = “RGB(255,0,0)”
‘ 必要であれば、ここで形状をグループ化解除し、不要な頂点を間引く処理を行う
End With
‘ 参照の明示的破棄
Set shpResult = Nothing
End Sub
—
2. 破壊的演算の限界:フラグメント(Fragment)の真価
`Fragment`は、複雑な重なりを持つ図形を「最小単位のパーツ」に分割する。これはカスタムシンボルの動的生成において最強の武器だが、演算後の戻り値はSelectionオブジェクトであるという点に注意が必要だ。
多くの場合、`Fragment`の結果は予期せぬ数に増殖する。これを制御するには、演算前にターゲットとなるShapeの数をカウントし、演算後のSelectionをイテレートして、不要な「微小破片(ノイズ)」をフィルタリングするロジックが必須となる。
極限の実装例:ノイズを除去するフラグメント処理
Public Sub PreciseFragment(ByRef targetShp As Visio.Shape, ByRef cutterShp As Visio.Shape)
Dim selResult As Visio.Selection
Dim shp As Visio.Shape
‘ フラグメントを実行
Set selResult = targetShp.Fragment(cutterShp)
‘ 演算後のSelectionを最適化(微小な形状の削除)
For Each shp In selResult
‘ 面積が極端に小さいノイズは削除する(閾値はシステム要件に合わせる)
If shp.AreaIU < 0.001 Then
shp.Delete
End If
Next shp
Set selResult = Nothing
End Sub
---
3. レガシー環境でのパフォーマンス最適化:Windows APIの活用
Visioの演算は、時にメインスレッドを長時間占有する。UIのフリーズを防ぐには、`DoEvents`を安易に呼ぶのではなく、Windows APIを使用してイベントループを適切に制御するか、あるいは演算中にプログレスバーを更新するための最小限の割り込みを入れるのがプロの作法だ。
また、`Application.ScreenUpdating = False` は必須だが、演算が複雑な場合は、演算直前に一度 `Document.Save` を挟むことを推奨する。VisioのUndoスタックがメモリを圧迫し、大規模な演算でクラッシュするのを防ぐための「チェックポイント」となる。
—
4. シニアエンジニアへの提言:幾何学的アプローチの転換
もし君が数百、数千の形状をプログラムで合成しようとしているなら、VBAのオブジェクトモデルだけで完結させようとするのは愚策だ。
1. 中間フォーマットの利用: 複雑な形状はSVGやXML形式で一度書き出し、文字列処理で頂点計算を行った後、Visioにインポートする方が、幾何学演算を繰り返すより圧倒的に速く、かつバグが少ない。
2. グループのネスト構造: 演算後のShapeは、必ずグループ化(`Group`)してメタデータを付与すること。個々のShapeがバラバラにドキュメント上に存在すると、Visioの描画エンジンがインデックス管理でパンクする。
結論
Visioのブーリアン演算は、ブラックボックスではない。それは「頂点データの再定義」という極めて数学的なプロセスだ。`Union`や`Fragment`を使うときは、常に「結果がどのような頂点構成になるか」を想像し、生成されたゴミを即座に掃除する。この緊張感こそが、安定した描画システムを構築する唯一の道である。
君たちのコードが、単なる自動化ツールから、芸術的な幾何学エンジンへと昇華することを期待している。
