【入門編】Page.GetResultsとSetResultsを連携させた外部CSVデータとの超高速双方向プロパティ同期 – Visio VBA解析バイブル

スポンサーリンク

こんにちは!Visio VBAの自動化の世界へようこそ。
マクロの記録ボタンを押して、生成されたコードを眺めて「うわ、なんだこれ…」と途方に暮れていませんか?大丈夫、今日でその悩みとはお別れです。

今回は、Visio VBAの真骨頂である「オブジェクトモデルの高速操作」、そして実務で必ず直面する「外部データ(CSV)との超高速・双方向プロパティ同期」について、プロのアーキテクトの視点から徹底的に解説します。

ここをクリアすれば、あなたのVisioマクロは「遅いオモチャ」から「現場を救う爆速エンジン」へと生まれ変わります。さあ、一緒に扉を開けましょう!

1. なぜ「1つずつ処理」してはいけないのか?(Visio VBAの基本思想)

Visioの図面(Page)の中には、無数の図形(Shape)が存在します。例えば、ネットワーク図やフロアマップなら、数百〜数千の図形があることも珍しくありません。

ここで多くの初心者がやってしまうのが、次のような「愚直なループ処理」です。

‘ 【やってはいけないアンチパターン】
Dim shp As Visio.Shape
For Each shp In ActivePage.Shapes
‘ 図形を1つずつ触ってプロパティを取得・書き換え
Debug.Print shp.Cells(“Prop.Cost”).Formula
shp.Cells(“Prop.Cost”).Formula = “=100”
Next shp

これ、図形が10個なら一瞬ですが、1,000個を超えたあたりから「カチカチ…(固まる)」現象が発生します。なぜなら、VBAからVisioの図形オブジェクト(COMオブジェクト)にアクセスするたびに、OSを跨いだ通信(プロキシのオーバーヘッド)が発生するからです。

伝説のエンジニアが教える解決策:一括配列処理

このボトルネックを粉砕するのが、今回紹介する `GetResults``SetResults` メソッドです。
これらは、「一歩も外に出ず、メモリ上で一網打尽に読み書きする」ためのチート級のAPIです。図形が10,000個あろうが一瞬で処理が完了します。

2. 全体アーキテクチャ:双方向同期パイプラインとは?

今回構築するシステムの流れはこうです。

1. 一括取得 (GetResults): ページ上の全図形から、指定したシェイプシートのセル(例: IPアドレスやコスト)をごっそり配列としてメモリに引き上げる。
2. 比較・加工: 外部CSVファイルのデータとメモリ上で突き合わせ、変更があった部分だけを書き換えるデータを準備する。
3. 一括書き戻し (SetResults): 変更があった図形だけを、たった1回のAPI呼び出しでVisioへ流し込む。

この仕組みにより、Visioと外部データ(ExcelやCSV)の間で、常に最新かつ高速な同期が保たれます。

3. 実装コード:爆速双方向同期マクロ

それでは、開発現場でそのままコピペして使える実用コードを公開します。
VBAの標準モジュールに貼り付けて実行してください(※事前に適当なシェイプデータ「Prop.DeviceID」を持った図形をページに配置しておいてください)。

Option Explicit

‘ ==============================================================================
‘ 外部CSVデータとVisio図形プロパティを爆速で双方向同期するメインプロシージャ
‘ ==============================================================================
Public Sub SyncVisioWithCSV()
Dim vsoPage As Visio.Page
Set vsoPage = ActivePage

Dim vsoShapes As Visio.Shapes
Set vsoShapes = vsoPage.Shapes

Dim lngCount As Long
lngCount = vsoShapes.Count

If lngCount = 0 Then
MsgBox “図形がありません。”, vbExclamation
Exit Sub
End If

‘ ————————————————————————–
‘ 1. 事前準備:配列の定義とインデックスの取得
‘ ————————————————————————–
ReDim sNames(1 To lngCount) As String
ReDim sustrCellNames(1 To lngCount) As String

Dim i As Long
For i = 1 To lngCount
sNames(i) = vsoShapes(i).Name
‘ 取得したいシェイプシートのセル名を指定(例:Prop.DeviceID)
sustrCellNames(i) = “Prop.DeviceID”
Next i

‘ ————————————————————————–
‘ 2. GetResultsによる超高速・一括プロパティ取得
‘ ————————————————————————–
Dim varValues As Variant
‘ 引数: (セル名配列, フラグ, 返り値格納先, エラー格納先)
vsoPage.GetResults sustrCellNames, visGetFloats, varValues

‘ この時点で、varValuesの中に全図形のプロパティ値がメモリ上で一網打尽に格納されています。

‘ ————————————————————————–
‘ 3. 外部データ(CSV)との突合せ・変更検知
‘ ————————————————————————–
‘ ※今回はシンプル化のため、CSV読み込みの代わりに「値を強制的に書き換えるシミュレーション」を行います。
‘ 実務ではここでCSVを読み込み、varValues(i-1) と比較して差分を検知します。

Dim updateIndices() As Long
Dim updateCells() As String
Dim updateValues() As Variant

Dim updateCount As Long
updateCount = 0

ReDim updateIndices(1 To lngCount)
ReDim updateCells(1 To lngCount)
ReDim updateValues(1 To lngCount)

For i = 1 To lngCount
‘ 現在の値(Visio側)
Dim currentValue As String
currentValue = CStr(varValues(i – 1))

‘ 【シミュレーション】もし値が「Old_ID」だったら「New_ID_999」に書き換えると仮定
If currentValue = “Old_ID” Then
updateCount = updateCount + 1
updateIndices(updateCount) = i
updateCells(updateCount) = “Prop.DeviceID”
updateValues(updateCount) = “New_ID_999” ‘ 外部CSVからの新しい値
End If
Next i

‘ ————————————————————————–
‘ 4. SetResultsによる「1回のAPI呼び出し」での超高速書き戻し
‘ ————————————————————————–
If updateCount > 0 Then
‘ 配列のサイズを変更して不要な要素を削る
ReDim Preserve updateIndices(1 To updateCount)
ReDim Preserve updateCells(1 To updateCount)
ReDim Preserve updateValues(1 To updateCount)

‘ 一括書き込み実行!
vsoPage.SetResults updateIndices, updateCells, updateValues

MsgBox updateCount & “個の図形プロパティを爆速で同期しました!”, vbInformation
Else
MsgBox “変更が必要な図形はありませんでした。”, vbInformation
End If

End Sub

4. コードの急所:ここが分かればプロ級!

初心者が必ずハマるポイントと、それを回避するための知見を共有します。

① 配列のインデックスは「0始まり」と「1始まり」が混在する

Visioの `GetResults` メソッドが返す `varValues` は、0から始まる一次元配列(0-based array)になります。
一方で、VisioのShapesコレクションや自作のループは通常1から始まります。そのため、ループを回すときは `varValues(i – 1)` のようにズレを調整する必要があります。ここを間違えると「Type mismatch」や「Subscript out of range」の洗礼を受けますので注意してください。

② パフォーマンスの罠:Variant型の扱い

`GetResults` や `SetResults` は非常に強力ですが、やり取りするデータ型は `Variant` 型です。
文字列、数値、数式(Formula)のどれを扱うかによって、引数のフラグ(`visGetFloats`, `visGetFormulas` など)を適切に選ぶ必要があります。実務でセルの「表示値」ではなく「数式(計算式)」そのものを同期させたい場合は、フラグを `visGetFormulas` に変更してください。

5. まとめ:Visio VBAの基礎は「一括処理」にあり

今回は、`Page.GetResults` と `SetResults` を使った外部データとの超高速同期パイプラインを解説しました。

  • 図形を1つずつ触るな、配列でまとめて扱え。
  • 通信コスト(オーバーヘッド)を意識すれば、Visioマクロは劇的に速くなる。

ここをクリアしたあなたなら、もう「マクロの記録」に頼るだけの初学者ではありません。ぜひ、現場の業務効率化ツールとしてこのコードをカスタマイズし、まわりを驚かせてみてください。

それでは、次回の高度なVisioアーキテクチャ解説でお会いしましょう!

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