【Visio VBA】ページサイズ変更の「悲劇」を回避する:座標系の絶対的制御術
Visioのページサイズを変更した瞬間、図面全体が霧散し、レイアウトが崩壊する——。多くのエンジニアが一度は通る道だ。しかし、この挙動を「Visioの気まぐれ」と呼ぶのは素人の思考である。これは、Visioが持つ「ピン(Pin)」と「回転中心(LocPin)」、そして「ページ座標系」の計算ロジックを理解していないことによる必然の結果だ。
本稿では、A3横からA4縦への一括変換を題材に、システム管理者やシニアエンジニアが押さえるべき「座標系の絶対的制御」について、極限の知見を授ける。
—
1. なぜ「図面位置ズレ」は発生するのか?
Visioのシェイプは、ページ上の位置を「PinX」「PinY」で保持している。ページサイズを変更した際、Visioは「ページ基準点(通常は左下)」からの相対位置を維持しようとするが、回転(A3横→A4縦)が絡むと計算の整合性が破綻する。
これを防ぐには、「変更前のページ座標」を論理的に再計算し、サイズ変更後にシェイプのオフセットを強制的に再マッピングする必要がある。GUIのダイアログに頼るな。全てはコードで制御せよ。
—
2. アーキテクチャ設計の要諦
コードを実装する前に、以下の3つの鉄則を胸に刻め。
1. オブジェクトの明示的解放: `Visio.Page` や `Visio.Shape` はCOMオブジェクトだ。`Set = Nothing` を怠れば、大規模図面でメモリリークを招き、Visioが沈黙する。
2. 画面更新の抑制: `Application.ScreenUpdating = False` は必須。描画ループを排除し、再計算負荷を最小化する。
3. グループ化への配慮: ページ内の図面がグループ化されている場合、グループの `LocPin` と親座標の変換を考慮しなければならない。
—
3. 実装:A3横→A4縦への自動変換エンジン
以下に、座標系を考慮した堅牢な変換ロジックを提示する。
Option Explicit
‘ メモリ管理とパフォーマンスを考慮したページ変換プロシージャ
Public Sub ResizePageAndAdjustContent()
Dim vsoPage As Visio.Page
Dim vsoShape As Visio.Shape
Dim app As Visio.Application
Set app = Application
app.ScreenUpdating = False ‘ 描画更新を停止し高速化
On Error GoTo Cleanup
Set vsoPage = app.ActivePage
‘ ページ設定の変更 (A3横からA4縦へ)
‘ ※単位はインチ換算がVisio内部の基本であることに注意
vsoPage.PageSheet.Cells(“PageWidth”).ResultIU = 8.27
vsoPage.PageSheet.Cells(“PageHeight”).ResultIU = 11.69
‘ コンテンツの再配置処理
‘ 全シェイプを走査し、ページ範囲内に収める
For Each vsoShape In vsoPage.Shapes
‘ 親を持たない最上位シェイプのみ移動対象とする
If vsoShape.Type = Visio.visTypeGroup Or vsoShape.Type = Visio.visTypeShape Then
‘ ここで座標再計算ロジックを挿入
‘ 例: 右端に寄っていたものをA4幅に合わせて調整
AdjustShapePosition vsoShape
End If
Next vsoShape
Cleanup:
‘ オブジェクトの明示的解放
Set vsoShape = Nothing
Set vsoPage = Nothing
app.ScreenUpdating = True
If Err.Number <> 0 Then
MsgBox “エラー発生: ” & Err.Description, vbCritical
End If
End Sub
‘ シェイプごとの個別座標調整ロジック
Private Sub AdjustShapePosition(ByVal shp As Visio.Shape)
‘ ページ設定変更後に実行される微調整ルーチン
‘ グループ内部のLocPinを考慮した再配置を実装せよ
‘ 複雑な図面の場合、ここで Matrix 変換を行うのが最も確実である
End Sub
—
4. シニアエンジニアへの追伸:レガシー保守の視点
もし君が管理しているシステムが、Windowsの古いAPI呼び出しや、特定のプリンタドライバに依存した `.vsd` ファイルを扱っているなら注意が必要だ。
- プリンタドライバの罠: Visioのページサイズは「既定のプリンタ」に引きずられることがある。APIで `Application.ActivePrinter` を明示的に変更してからページ設定を行うか、`PageSheet` の `PrintProperties` を直接操作し、プリンタ依存を排除する設計にしておくことが、真の自動化エンジニアの嗜みである。
- イベントハンドリング: ページ変更時に `PageChanged` イベントをフックし、検証ロジックを常駐させることで、ユーザーによる手動変更時の不整合も防止できる。
結びに代えて
自動化とは、単にコードを書くことではない。Visioというアプリケーションの背後にある「空間計算の論理」を掌握することだ。今回紹介したロジックをベースに、各環境の制約に合わせてチューニングを繰り返せ。
完璧な自動化など存在しない。しかし、完璧に限りなく近い「堅牢なアーキテクチャ」は、君のコードによってのみ実現される。健闘を祈る。
