【テクニカル・上級編】初心者でも安心のVisio VBAエラーハンドリング:On Error構文で実行時例外をスマートに捉える – Visio VBA解析バイブル

スポンサーリンク

Visio VBAを制する:堅牢なエラーハンドリングとメモリ管理の深淵

Visioの自動化において、「コードが途中で止まる」ことは単なる不具合ではない。それは、複雑に絡み合ったシェイプ階層の整合性を破壊する「システムへの冒涜」である。

ドキュメント、ページ、シェイプ。この階層構造を辿る際、存在しないオブジェクトへのアクセスや、ロックされたセルへの書き込みは日常茶飯事だ。本稿では、単なる `On Error Resume Next` の乱用から脱却し、シニアエンジニアとして備えるべき「防御的プログラミング」の真髄を伝授する。

1. 「On Error Resume Next」の禁忌と、正しいガード節

多くの初学者は、エラーを隠蔽するために `On Error Resume Next` を多用する。これは地雷原を裸足で歩くようなものだ。真のアーキテクトは、「エラーを予測し、制御可能な範囲で握りつぶす」

VisioのAPIは、特定の操作で例外を投げることを仕様としている。例えば、`Cell.Formula` へのアクセスで、そのセルがガード(Guard関数)されている場合、システムは容赦なく停止する。

推奨される堅牢なパターン

Public Sub SafeUpdateShapeText(shp As Visio.Shape, newText As String)
‘ エラーハンドラを局所化する
On Error GoTo HandleError

‘ セルがロックされているか事前にチェック
If shp.Cells(“LockTextEdit”).ResultIU <> 0 Then
Debug.Print “Warning: Shape ” & shp.Name & ” is locked.”
Exit Sub
End If

shp.Text = newText

Exit Sub

HandleError:
‘ ログ出力の責務を分離する
Logger.Log “Error in SafeUpdateShapeText: ” & Err.Description
Resume Next ‘ 処理を継続するか、あるいは安全に終了するかの判断をここで行う
End Sub

2. オブジェクトのライフサイクルと明示的解放の哲学

Visio VBAにおいて、オブジェクト変数を `Nothing` に明示的に設定しないことは、メモリリークを招く怠慢である。特にループ内で `Visio.Shape` や `Visio.Cell` を生成・取得し続ける場合、参照カウントが適切に減少しないリスクがある。

メモリ最適化の極意

Sub OptimizeShapeProcessing(pageObj As Visio.Page)
Dim shp As Visio.Shape

‘ ページ内の全シェイプを走査
For Each shp In pageObj.Shapes
‘ 処理…
Next shp

‘ 参照の明示的解放
‘ ループ変数であっても、明示的にNothingを代入する習慣が
‘ COMオブジェクトの解放遅延を防ぐ
Set shp = Nothing
End Sub

※ 大規模な図面を扱う際、この「解放」を怠るだけで、数千個のシェイプを処理する間にプロセスが肥大化する。

3. Windows APIとの連携:VBAの限界を突破する

Visioの標準APIだけでは、「現在のプロセスがバックグラウンドにあるか」「特定のウィンドウハンドルが有効か」といったOSレベルの制御が困難な場合がある。`User32.dll` を呼び出し、システムと直接対話することで、マクロの挙動をOSレベルで制御可能にする。

If VBA7 Then
Private Declare PtrSafe Function GetForegroundWindow Lib “user32” () As LongPtr
Else
Private Declare Function GetForegroundWindow Lib “user32” () As Long
End If

‘ マクロ実行中にVisioがアクティブかを確認し、予期せぬ入力を防ぐ
Public Function IsVisioForeground() As Boolean
If GetForegroundWindow() = Application.WindowHandle32 Then
IsVisioForeground = True
End If
End Function

このコードをガード節に組み込むことで、ユーザーが誤って別アプリを操作中にマクロが暴走し、誤ったシェイプを改変する事態を防げる。

4. 伝説のアーキテクトからの提言

システム開発において、エラーハンドリングは「付け足し」ではない。それはシステムの「設計思想そのもの」である。

1. 静的チェックを優先せよ: `Err` オブジェクトに頼る前に、`Shape.Type` や `Cell.Exists` で存在を確認する。
2. ログを構造化せよ: 実行時エラーが発生した際、どのページ、どのシェイプIDで発生したのかを即座に特定できるログ構造を構築せよ。
3. レガシーを恐れるな: 過去の汚いコードに手を加える際、最初に行うべきは「エラーハンドラの追加」ではなく「小さな関数単位への分解」である。

Visioという、描画とデータが混在する特異なプラットフォームにおいて、コードは「静的であると同時に動的」であるべきだ。貴殿が書くコードが、数年後のメンテナンスエンジニアにとって「迷宮」ではなく「地図」となることを切に願う。

―― 次回は、「Visioのイベントハンドラを駆使した、リアルタイム・プロパティ同期エンジンの構築」について掘り下げるとしよう。準備はいいか。

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