【入門編】【上級】Shape.SetFormulasUと配列を用いたバルク更新:数式ハックによる図形間の動的連携 – Visio VBA解析バイブル

スポンサーリンク

こんにちは!Visio VBAの世界へようこそ。
マクロの記録ボタンを押して生成されたコードを眺め、「なんだか動きがカクカクするし、コードが無駄に長くて読めない……」と悩んでいませんか?

もしあなたが、数千個の図形が並ぶ巨大なダイアグラムを構築しようとしているなら、図形を1つずつ選択して値を代入するようなアプローチは、今すぐ捨てなければなりません。なぜなら、Visioのオブジェクトモデルにおいて、画面を不必要に再描画させたり、ドキュメントのセルを1つずつ叩いたりする処理は、パフォーマンス上の「禁忌」だからです。

今回は、Visio VBAの真骨頂である`Shape.SetFormulasU`を用いた配列によるバルク更新(一括処理)と、数式ハックによる図形間の動的連携の極意を伝授します。ここをクリアすれば、あなたも単なる「マクロの記録ユーザー」から、高速かつスマートなシステムを組み上げる「真のVisioアーキテクト」へと進化できます。

一緒に、Visio VBAの本質をマスターしていきましょう!

—

1. なぜ「個別の代入」ではダメなのか?Visioの裏側を知る

Visioのすべての図形(Shape)は、Excelのセルと同じように、位置やサイズ、色などのプロパティが「セル(Cell)」という単位で管理されています。例えば、図形の幅(Width)を変えるとき、私たちは無意識に次のようなコードを書きがちです。

‘ 【アンチパターン】絶対にやってはいけない個別代入
shape1.CellsU(“Width”).ResultIU = 50
shape2.CellsU(“Width”).ResultIU = 50
shape3.CellsUName(“Width”).FormulaU = “50 mm”

これの何が問題なのでしょうか?
Visioは、1つのセルが変更されるたびに、シート全体の依存関係を計算し、画面の再描画(レンダリング)を走らせようとします。つまり、図形が100個あれば、100回重たい再計算と描画のコストが発生するのです。これが、大量の図形を扱うマクロが「フリーズしたように遅い」最大の原因です。

バルク更新(一括処理)という救世主

プロフェッショナルなエンジニアは、OSやアプリケーションに負荷をかける「コンテキストの切り替え」を極限まで嫌います。
`SetFormulasU`メソッドを使えば、複数の図形、複数のセルの数式を「たった1回のメモリ操作」で一気に書き換えることができます。Visioのエンジンにとっても、これほど慈悲深い処理はありません。

—

2. `SetFormulasU` と配列の基本構造を理解する

まずは、`SetFormulasU`の構文の正体を暴いておきましょう。

object.SetFormulasU (StreamCount, SID_SRCStream, FormulaStream, Flags)

見慣れない引数にクラクラするかもしれませんが、恐れる必要はありません。覚えるべきポイントは以下の3つだけです。

1. StreamCount(処理するセルの総数)
いくつ一括書き換えを行うかという「数」を指定します。
2. SID_SRCStream(どこを書き換えるかの指定配列)
「どの図形の(Shape ID)、どのセルの(Section, Row, Cell)」というアドレスを格納する、1次元の整数型(Integer)配列です。
3. FormulaStream(何を書き込むかの指定配列)
各セルに流し込む「数式(文字列)」を格納する、1次元の文字列型(String)配列です。

※末尾の `U` は「Universal(言語非依存の不変な形式)」を意味します。コードを英語圏の環境や将来のバージョンでも正しく動かすための、プロの常識です。

—

3. 【実践】数式ハックで図形同士を動的に連動させる

ここからが本題です。単に値を流し込むだけでなく、「数式(Formula)」を書き込むことで、図形同士を動的にリンクさせます。

例えば、「親図形(Master)」を動かすと、それに追随する「子図形(Slave)」の幅やX座標が自動で連動する仕組みを、VBAの配列一括処理で構築してみましょう。

実装コード例

以下のコードをVBAエディタに貼り付けて実行してみてください。アクティブページ上に親図形と子図形が生成され、一瞬で数式によって結びつけられます。

Sub MasterSlaveBulkLinkDemo()
Dim vsoPage As Visio.Page
Set vsoPage = ActivePage

‘ 1. テスト用の図形を2つ作成(親と子)
Dim shpParent As Visio.Shape
Dim shpSlave As Visio.Shape
Set shpParent = vsoPage.DrawRectangle(2, 5, 4, 4)
shpParent.Text = “親図形”

Set shpSlave = vsoPage.DrawRectangle(6, 5, 8, 4)
shpSlave.Text = “子図形”

‘ 2. バルク更新用の配列を定義
‘ 今回は「幅(Width)」と「X座標(PinX)」の2つのセルを、子図形に対して一括設定します。
‘ 配列のサイズは (要素数 4) が必要になります(後述のSRC指定のルールのため)
Dim streamCount As Long
streamCount = 2

Dim sidsrcArray(0 To 7) As Integer
Dim formulaArray(0 To 1) As String

‘ — セル指定の構築 (SID_SRCStream) —
‘ 構造: [ShapeID1, Section1, Row1, Cell1, ShapeID2, Section2, Row2, Cell2, …]

‘ 【設定1: 子図形の Width セル】
sidsrcArray(0) = shpSlave.ID ‘ 対象の図形ID
sidsrcArray(1) = Visio.visSectionObject ‘ セクション (Object)
sidsrcArray(2) = Visio.visRowShape ‘ 行 (Shape)
sidsrcArray(3) = Visio.visShapeWidth ‘ セル (Width)

‘ 【設定2: 子図形の PinX (X座標) セル】
sidsrcArray(4) = shpSlave.ID ‘ 対象の図形ID
sidsrcArray(5) = Visio.visSectionObject ‘ セクション (Object)
sidsrcArray(6) = Visio.visRowShape ‘ 行 (Shape)
sidsrcArray(7) = Visio.visShapePinX ‘ セル (PinX)

‘ — 流し込む数式の構築 (FormulaStream) —
‘ ここが数式ハックの核心です!
‘ 固定値を書き込むのではなく、「親図形のセルを参照する数式」を文字列として渡します。

‘ 例: 子の幅 = 親の幅 × 1.5
formulaArray(0) = “Width[sí]” & shpParent.ID & ” 1.5″ ‘ ※簡略化のため一般的なSheet参照数式を使用
‘ より安全で確実なVisio独自のユニバーサル数式構文を使います:
formulaArray(0) = “Sheet.” & shpParent.ID & “!Width 1.5”

‘ 例: 子のX座標 = 親のX座標 + 3インチ(右側に配置)
formulaArray(1) = “Sheet.” & shpParent.ID & “!PinX + 3”

‘ 3. 爆速のバルク更新を実行!
vsoPage.SetFormulasU streamCount, sidsrcArray, formulaArray, 0

MsgBox “バルク更新が完了しました!親図形を動かしてみてください。”, vbInformation
End Sub

コードの解説:なぜこれで動くのか?

`formulaArray` に代入している `”Sheet.1!Width 1.5″` という文字列に注目してください。
これはVisioの強力な数式エンジンに対する命令です。「親にあたる図形ID(例: Sheet.1)のWidthセルを監視し、常にその1.5倍の値を自分のWidthとしろ」という動的なリンク(数式による依存関係)を、VBAから一撃で植え付けています。

このコードを実行したあと、Visio上で「親図形」をマウスでグリグリと動かしたり、サイズを変えたりしてみてください。子図形がまるで影のように、完璧な比率と位置を保ったままリアルタイムに追従するはずです。個別のイベントプロシージャ(`ShapeMoved` など)を書く必要は一切ありません。Visioのエンジンが勝手に計算してくれます。

—

4. 陥りやすい罠とエラー回避の極意

この高度なテクニックを使う際、初学者が必ずハマる「3つの罠」があります。現場で迷わないよう、あらかじめ頭に入れておきましょう。

罠1:配列のインデックス計算ミス

`sidsrcArray` は、1つのセルにつき「4つの整数(ShapeID, Section, Row, Cell)」を消費します。
もしセルを $N$ 個指定したいなら、配列のサイズは必ず $N \times 4$ (0始まりなので $N \times 4 – 1$)にする必要があります。ここを間違えると、メモリ違反エラー(あるいは予期せぬ図形の暴走)が起きるので注意してください。

罠2:Sheet名やIDの勘違い

数式内の参照は必ず `Sheet.!` の形式(またはユニバーサル構文)で行います。図形を削除・再作成するとIDが変わるため、ハードコーディング(直書き)は厳禁です。必ずコード内で `shp.ID` を動的に取得して文字列を組み立てましょう。

罠3:単位の罠 (Inch vs mm)

Visioの内部数値は常に「インチ(Inches)」で保持されています。数式に直接数値を埋め込む際、ドキュメントの設定がミリメートルであっても、数式内ではインチ換算になるケースがあります。混乱を避けるため、数式内では `Width 1.5` のように既存のプロパティに対する相対倍率にするか、`”50 mm”` のように単位を明示的に文字列に含めるクセをつけましょう。

—

5. おわりに:ここをクリアすれば、Visio VBAの基本はバッチリです!

お疲れ様でした!今回は少し背伸びをして、`SetFormulasU` と配列、そして数式ハックによる図形間連携という、上級者向けの極意を解説しました。

「図形をマクロでただ並べるだけのツール」から、「数式とデータでダイアグラムを自律駆動させるシステム」へ。
このアプローチをマスターすれば、プラント図、ネットワーク構成図、組織図、座席表など、あらゆる動的システムをVisio上に高速かつ美しく構築できるようになります。

ここをクリアできたあなたなら、もうVisio VBAの基礎でつまずくことはありません。ぜひ、日々の業務自動化やシステム開発に応用してみてくださいね。あなたのエンジニアライフが、よりスリリングで知的なものになりますように!

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