【実務・中級編】ページ間を跨ぐ図形の移動とコピー:DropManyを使った高速かつ安全なシェイプ一括複製手法 – Visio VBA解析バイブル

スポンサーリンク

Visio VBAの限界を超える:DropManyで実現するシェイプ一括転送の極意

業務自動化において、Visioの図面操作を「一つずつコピー&ペーストする」という原始的な手法で止めていないだろうか?
もし君が `Selection.Copy` と `Page.Paste` を繰り返しているなら、今すぐそのコードを捨てるべきだ。それはCPUのサイクルを無駄にするだけでなく、クリップボードという不安定な共有リソースに依存する、極めて脆弱な設計だからだ。

今日は、Visioの描画エンジンを効率的に叩くための「DropManyメソッド」による一括転送術を伝授する。

1. なぜ「コピペ」が禁じ手なのか

Visioにおいて `Copy/Paste` は、ユーザー操作を模倣する機能だ。これには以下の致命的な欠点がある。

  • クリップボード汚染: 実行中に他のアプリでコピーを行うと、VBAの処理が中断・失敗する。
  • パフォーマンスの欠如: 1シェイプごとに描画更新(画面の再描画)が走り、数千単位のシェイプを扱うとフリーズする。
  • イベントの暴発: コピーのたびに `ShapeAdded` などのイベントが発火し、意図せぬ連鎖反応を招く。

これに対し、`DropMany` メソッドは、Visioの内部データ構造に対して直接「配置命令」を下す。描画エンジンへの負荷を最小限に抑え、一挙にトランザクションを完了させる、いわば「バルク挿入」の技術だ。

2. DropManyによる一括複製の実装

`DropMany` の真骨頂は、シェイプのマスターや既存シェイプの情報を配列で渡し、一度の命令で全オブジェクトを配置することにある。

以下のコードは、ソースページから全シェイプを取得し、ターゲットページへ高速転送するプロトタイプだ。

‘ @brief ソースページからターゲットページへシェイプを一括複製する
‘ @param srcPage 複製元のページ
‘ @param destPage 複製先のページ
Public Sub BatchCopyShapes(srcPage As Visio.Page, destPage As Visio.Page)
Dim srcShapes As Visio.Shapes
Dim count As Long
Dim i As Long

‘ 必要な配列の準備
Set srcShapes = srcPage.Shapes
count = srcShapes.Count
If count = 0 Then Exit Sub

Dim objectsToDrop(1 To 1) As Variant
Dim xyArray() As Double
ReDim xyArray(0 To (count 2) – 1)

‘ 転送用配列の作成
‘ DropManyは、マスターまたはシェイプオブジェクトの配列を受け取る
Set objectsToDrop(1) = srcShapes ‘ 実際には個別のシェイプを指定するケースが多い

‘ 配置座標の計算(ここでは例として全て(1, 1)に置くが、本来は各シェイプのPinX/Yを計算する)
For i = 0 To count – 1
xyArray(i 2) = 1.0 ‘ PinX
xyArray(i 2 + 1) = 1.0 ‘ PinY
Next i

‘ 描画の停止(パフォーマンス向上の鉄則)
Application.ScreenUpdating = False

‘ 一括実行
‘ 第1引数: 配置するオブジェクトの配列, 第2引数: 座標配列
destPage.DropMany srcShapes, xyArray

‘ 描画の再開
Application.ScreenUpdating = True
End Sub

3. 現場で生き残るための「堅牢な設計」のポイント

ただコードを動かすだけでは「エンジニア」とは呼べない。実務環境では以下の考慮が不可欠だ。

① 描画の抑制(ScreenUpdating)

`Application.ScreenUpdating = False` を忘れるな。これを怠ると、WindowsのGDIリソースが急激に消費され、OSレベルで動作が重くなる。必ず `Error Handler` を使い、異常終了時にも `True` に戻るよう設計すること。

② 座標変換の罠

`DropMany` は座標を配列で要求する。ソースシェイプの座標をそのまま渡すと、ページ座標系の違いでシェイプが画面外に飛ぶことがある。必ず `srcShape.XYToPage` や `SpatialNeighbors` を使い、正しい位置関係を算出してから配列に格納せよ。

③ データベース連携の注意点

外部データ(ExcelやSQL Server)と連携する場合、シェイプの `ID` をキーにすると痛い目を見る。IDはページ移動やグループ化で容易に変わるからだ。必ず `UniqueID`(VisioのGUID) をプロパティとして保持し、それをキーにマッチングを行うこと。

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

VisioのVBAは、単なる「自動化ツール」ではない。君が書いたコードは、将来その図面を触る誰かの「設計思想」そのものになる。

  • マジックナンバーを排除せよ: ページ名や座標をコードに直書きするな。設定用の定数クラスを作るか、Hiddenなシェイプに設定情報を埋め込む手法を推奨する。
  • トランザクションを意識せよ: データの整合性が重要な場合、`Application.BeginUndoScope` と `EndUndoScope` で囲むことで、失敗時に一括でロールバック可能な「安全な処理」を構築できる。

効率化とは、速さだけではない。「壊れないこと」こそが、業務自動化における最高のパフォーマンスだ。

さあ、クリップボードに依存する脆弱なコードを捨て、エンジニアとして「描画エンジンを直接御する」レベルへ到達しよう。君のコードが、組織の生産性を劇的に変えることを期待している。

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