【入門編】Page.GetResults超高速データ取得:超大量シェイプのセル値を配列で一瞬で読み込む手法 – Visio VBA解析バイブル

スポンサーリンク

【Visio VBA極意】数千のシェイプも一瞬!Page.GetResultsで「脱・低速ループ」を実現せよ

VisioのVBAを書いていると、一度はこんな壁にぶつかりませんか?
「シェイプを全ループして値を拾っていたら、読み込みだけで数分かかる……」

その原因は、「1つずつCellsUプロパティを叩いているから」です。Visioのオブジェクトモデルを直列に叩くのは、窓口一つしかない役所に数百人が列を作っているようなもの。非常に非効率です。

今回は、プロの現場で必須となる「Page.GetResults」を用いた超高速データ取得術を伝授します。これを知れば、あなたのマクロは「重たい事務作業」から「電光石火の処理」へと劇的に進化します。

なぜ `CellsU` は遅いのか?

ループ内で `Shape.CellsU(“Width”).ResultIU` を呼び出すと、そのたびにVBAからVisioのレンダリングエンジンへ「値をよこせ」というリクエストが飛びます。この往復回数が多ければ多いほど、オーバーヘッド(無駄な待ち時間)が蓄積されます。

対して `Page.GetResults` は、「このページにある全シェイプの、このセル値を、一気にメモリに返せ!」と命令を一発で送る、いわば「まとめ買い」の手法です。

Page.GetResultsの実装パターン

さっそく、実践的なコードを見てみましょう。ここでは、ページ内の全シェイプの「幅(Width)」を一括取得する例を挙げます。

Sub GetShapeWidthsFast()
Dim vsoPage As Visio.Page
Dim vsoShapes As Visio.Shapes
Dim count As Long
Dim i As Long

‘ 1. 対象のページとシェイプ群を特定
Set vsoPage = ActivePage
Set vsoShapes = vsoPage.Shapes
count = vsoShapes.count

If count = 0 Then Exit Sub

‘ 2. 取得するセル名の配列を定義(全シェイプ分用意)
Dim cellNames() As String
ReDim cellNames(1 To count)
For i = 1 To count
cellNames(i) = “Width”
Next

‘ 3. 結果を受け取るための配列を用意
Dim results() As Double
ReDim results(1 To count)

‘ 4. GetResultsメソッドで一括取得!
‘ 引数:取得対象のパス(ユニークID)、セル名配列、単位、結果格納配列、フラグ
vsoPage.GetResults cellNames, visGetResultsDouble, results

‘ 5. 結果の確認
For i = 1 To count
Debug.Print “シェイプID: ” & vsoShapes(i).ID & ” / 幅: ” & results(i)
Next i
End Sub

コードのここがポイント!

  • `cellNames` の作成: `GetResults` は「どのシェイプのどのセルが欲しいか」を配列として渡す必要があります。今回は全シェイプ共通の「Width」をセットしましたが、シェイプごとに異なるセルを狙うことも可能です。
  • `results` 配列: 取得した値は、Variant型ではなく、あらかじめ定義したDouble型の配列に格納されます。型が明確なのでメモリ効率も抜群です。
  • `visGetResultsDouble`: 取得する値の型を指定します。数値ならDouble、文字列なら `visGetResultsString` を選びましょう。

陥りやすいエラーと回避策

初心者がよくやる間違いを先回りして解説します。

1. インデックスの不一致

`vsoShapes` のインデックスは1から始まります。配列のループ処理とVisioのシェイプIDは混同しやすいので、常に「1 to Shapes.Count」で管理する習慣をつけましょう。

2. シェイプの数と配列のサイズの不一致

`GetResults` に渡す配列のサイズが、シェイプの数と1つでもズレていると、VBAは「型が一致しません」という分かりにくいエラーを吐くことがあります。`ReDim` する際は必ず `Shapes.Count` を使いましょう。

3. 取得できないセルの扱い

もし、特定のシェイプにそのセルが存在しない場合、`GetResults` はエラーを返します。事前に `Shape.CellExists` で確認するか、エラーハンドラ(`On Error Resume Next` 等)で防御的に書くのがプロの流儀です。

先輩エンジニアからのアドバイス

「マクロの記録」で生成されたコードは、あくまで「初心者の手引き」です。そこから一歩進むには、「オブジェクトへのアクセス回数を減らすこと」を常に意識してください。

`GetResults` を使いこなせるようになれば、数千個のシェイプを扱うような大規模な図面データでも、処理時間は数秒以内(場合によってはミリ秒単位)に収まります。

これができれば、あなたはもうVisio VBAの初級者ではありません。次はぜひ、「`SetResults` を使った一括書き込み」にも挑戦してみてください。読み込みと書き込み、この2つを制する者がVisio自動化を制します。

分からないことがあれば、いつでも聞いてくださいね。一緒に最強の自動化を目指しましょう!

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