Visio VBAで「勝手に広がるキャンバス」を制圧する:AutoSizeの動的制御術
Visioの「自動サイズ調整(AutoSize)」機能は、初心者にとっては親切な設計だが、自動化ツールを開発する我々エンジニアにとっては「悪魔の機能」になり得る。
プログラムで座標計算を行い、ミリ単位で図形を配置しようとしているのに、背後のキャンバスが勝手に拡張され、座標系が再計算される……。この「予測不能な挙動」を放置しては、堅牢な業務ツールなど作れるはずがない。
今回は、Visio 2013以降のAutoSize機能をVBAで完全制御し、レイアウトの整合性を死守するための「禁断のテクニック」を伝授する。
—
1. なぜAutoSizeを制御すべきなのか
Visioの`Page.AutoSize`プロパティは、ページの境界を超えて図形を配置した瞬間に、ページサイズを動的に変更する。
- 問題点: レイアウトエンジンが計算中にページサイズが変わると、一部のシェイプ(特にグループ化されたものや複雑なコネクタ)の相対位置が意図せずズレることがある。
- 現場の鉄則: ツール実行時はAutoSizeを「OFF」にし、全ての配置・演算が完了した最後に「ON」にするか、あるいは厳格に固定するのがプロの流儀だ。
2. 制御の核となるプロパティ
Visioのオブジェクトモデルにおいて、この設定は`Page`オブジェクトの`AutoSize`プロパティが握っている。
- `Page.AutoSize = True`: 自動拡張を有効化。
- `Page.AutoSize = False`: 自動拡張を無効化(サイズを固定)。
たったこれだけだが、注意が必要なのは「現在のページ状態をどう保存・復元するか」というライフサイクル管理である。
—
3. 実践:プロダクションコード
以下は、処理中にAutoSizeを無効化し、終了時に元の状態へ戻すためのラッパー関数である。保守性を高めるため、エラーハンドリングを組み込んだ設計にしている。
‘ —————————————————————————
‘ @brief ページのAutoSizeを制御し、レイアウトの不整合を防ぐ
‘ @param targetPage 対象のPageオブジェクト
‘ @param isEnabled True:自動拡張ON / False:自動拡張OFF
‘ —————————————————————————
Public Sub SetAutoSize(ByRef targetPage As Visio.Page, ByVal isEnabled As Boolean)
On Error GoTo ErrorHandler
‘ VisioのAutoSizeプロパティは、Pageのページ設定の一部である
‘ 頻繁に切り替えると描画負荷が高まるため、状態変更時のみ反映する
If targetPage.AutoSize <> isEnabled Then
targetPage.AutoSize = isEnabled
End If
Exit Sub
ErrorHandler:
Debug.Print “AutoSize制御エラー: ” & Err.Description
End Sub
‘ —————————————————————————
‘ @brief 使用例:一括配置処理の定石
‘ —————————————————————————
Public Sub RunLayoutTask()
Dim pg As Visio.Page
Set pg = ActivePage
‘ 1. 事前処理:レイアウト中の自動拡張を禁止
Dim originalState As Boolean
originalState = pg.AutoSize
SetAutoSize pg, False
‘ — ここに図形配置やコネクタ接続の重い処理を記述 —
‘ 座標計算が狂う心配はもうない
‘ 2. 事後処理:元の状態に戻す(または強制的に有効化)
SetAutoSize pg, originalState
End Sub
—
4. 開発現場でハマる「落とし穴」
① ページ設定との競合
`Page.AutoSize = True` に設定していても、`PageSheet`(ページ自体のシェイプ)でサイズが固定されていると、うまく機能しない場合がある。ツールが意図したサイズでページを固定したい場合は、`AutoSize`を`False`にした上で、`Page.PageWidth`と`Page.PageHeight`を明示的に指定するのが最も堅牢だ。
② データベース連携時の座標系
データベースから座標を読み込み、Visio上に展開する場合、「AutoSizeによるページ拡張」が発生すると、座標の原点(PinX/PinY)が意図しない挙動を見せることがある。 特に、複数のページにまたがって一括生成するツールの場合、必ず処理開始前に全ページのAutoSizeをループでOFFにする設計を推奨する。
③ パフォーマンスへの配慮
`AutoSize = True` にした状態で、数百個のシェイプをループで作成すると、Visioは「シェイプを置く→ページを広げる→描画更新」を毎回繰り返す。これはツールを劇的に重くする要因だ。
大量配置を行う際は、必ず `Application.ScreenUpdating = False` と組み合わせ、最後にAutoSizeを制御し、最後に `Application.ScreenUpdating = True` に戻すという「サンドイッチ構造」を徹底してほしい。
—
5. チーフアーキテクトからの助言
Visio VBAにおける「自動化」とは、Visioが親切心で行っている「お節介」をいかに封じ込めるかという戦いである。
AutoLayoutやAutoSizeのような「動的な機能」は、インタラクティブな編集時には役立つが、機械的な一括生成には邪魔でしかない。君たちが作るツールが、ユーザーの作業を楽にするためのものならば、まずは「Visioの挙動を完全に掌握すること」から始めてほしい。
設計に迷ったら、常にこう自問自答すること。
「このプロパティは、今の処理において『親切』か、それとも『ノイズ』か?」
それができれば、君の書くコードは確実に、世界中のエンジニアが参考にするレベルの「製品」になるはずだ。健闘を祈る。
