【テクニカル・上級編】多角形シェイプの頂点をVBAで動的制御:Shape.Geometryセルの行(Row)の追加・削除による図形形状の変形 – Visio VBA解析バイブル

スポンサーリンク

Visio VBAの深淵:Geometryセルの動的制御による「形状のメタモルフォーゼ」

Visioというソフトウェアを単なるドローイングツールと捉えているならば、君はまだその真の姿を見ていない。Visioの正体は「ShapeSheetという巨大なリアクティブ・データベースを内包した、2次元グラフエンジン」だ。

今回は、GUIの操作を超え、VBAから`Geometry`セクションを直接操作して、図形の頂点を動的に生成・削除する技術について深掘りする。これは単なる図形描画ではない。システムデータと連動し、リアルタイムに物理的な形状を変容させる「動的エンジニアリング」の核心である。

1. Geometryセルの本質を理解する

Visioのシェイプは、`Geometry`セクションという配列状の構造体を持っている。ここには`MoveTo`(始点)や`LineTo`(頂点)といったパスの定義が格納されている。

愚かな実装は、シェイプを削除して再生成する。それはメモリリークと再描画コストの観点から見て、自殺行為に等しい。真のエンジニアは、既存のGeometry行を「Append(追加)」または「Delete(削除)」することで、シェイプを「変形」させる。

注意すべき「行のインデックス」

`RowAdd`や`RowDelete`を用いる際、インデックスは1から始まる。また、`visRowFirst`や`visRowLast`といった定数を駆使し、現在の行数を動的に取得しなければ、スタックオーバーフローやアクセス違反を引き起こすことになる。

2. 実装:頂点を動的に追加するプロシージャ

以下は、選択中のシェイプに対し、新しい頂点を動的に追加する堅牢な実装だ。このコードは、エラーハンドリングとオブジェクトのライフサイクル管理を徹底している。

‘ 頂点を動的に追加するプロシージャ
Public Sub AddVertexToShape(shp As Visio.Shape, x As Double, y As Double)
Dim geoSec As Visio.Section
Dim newRow As Visio.Row
Dim rowIdx As Long

‘ オブジェクトの有効性チェック(Nullチェックは基本中の基本)
If shp Is Nothing Then Exit Sub

‘ Geometryセクションの取得
Set geoSec = shp.Section(visSectionFirstComponent)

‘ 新しい行を末尾に追加 (visRowLast定数を使用)
‘ LineTo型の行を生成
Set newRow = geoSec.AddRow(visSectionFirstComponent, visRowLast, visTagLineTo)

‘ セルの書き込み(SetResultを使うのが作法)
newRow.Cell(“X”).Result(“in”) = x
newRow.Cell(“Y”).Result(“in”) = y

‘ オブジェクトの明示的解放(VBAのGCを過信しない)
Set newRow = Nothing
Set geoSec = Nothing
End Sub

3. レガシー環境とメモリ最適化の極意

この作業において、以下の3点は「プロフェッショナルの境界線」となる。

A. 描画更新の抑制 (`Application.DeferRecalc`)

大量の頂点を一度に操作する場合、毎回計算が走るとVisioはフリーズする。`Application.DeferRecalc = True` を活用し、全処理終了後に `False` に戻すことで、描画パフォーマンスを劇的に向上させろ。

B. Windows APIとの連携

もし大規模なデータ変換を伴う場合、VBAのネイティブな演算では限界がある。`Kernel32.dll` の `GetTickCount` などを用いて、処理時間を計測し、一定閾値を超えたら `DoEvents` を挟むといった、非同期処理的な思想を持つこと。

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

VBAはCOMベースであり、暗黙的な参照カウントを持っている。ループ内で `Shape` や `Row` を多用する場合、確実に `Set obj = Nothing` を行うこと。これを行わないだけで、大規模な図面ではメモリ断片化が確実に発生する。

4. 応用:データ構造に基づいた変形ロジック

実務では、外部のCSVやデータベースから座標配列を取得し、シェイプを再描画する機会が多いだろう。

‘ 座標配列に基づきGeometryを再構築するロジックの骨子
Public Sub RebuildShapeGeometry(shp As Visio.Shape, coords() As Double)
‘ 1. まず全行をクリア(MoveToを残してLineToを全消去)
‘ 2. 座標配列をループで回し、AddRowで再構築
‘ 3. 最後に shp.Cells(“Geometry1.NoLine”).Formula = False などを設定し整合性を保つ
End Sub

5. チーフアーキテクトからの助言

君たちが直面するVisioのVBA開発は、しばしば「レガシーの墓場」と揶揄される。しかし、ShapeSheetという強力なエンジンを制御下に置くことができれば、それは「動的な図面データベース」として、他のどのBIツールにも負けない表現力を持つことになる。

コードを書くとき、常に「なぜこのシェイプはここに存在するのか?」を自問してほしい。単に線を描くのではない。君が書くのは、データの変化を視覚情報へと変換するアルゴリズムである。

次回の講義では、`EventSink`を用いたVisioシェイプと外部データとの「双方向同期」について触れる。それまでは、このGeometry操作をマスターし、シェイプの生命力を引き出すことに注力せよ。

健闘を祈る。

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