【テクニカル・上級編】選択中のオブジェクトがない場合のエラーを防ぐ!SelectionManagerの安全な判定と例外処理 – CorelDRAW VBA解析バイブル

スポンサーリンク

【CorelDRAW VBA】SelectionManagerの罠:未選択エラーを秒速で封じる極限の防衛的プログラミング

シニアエンジニアたる者、エンドユーザーの「何をしでかすか分からない」自由奔放な操作に怯える日々とは決別すべきだ。

CorelDRAW VBAの自動化スクリプトにおいて、最も頻発し、かつ最も初歩的ながら開発者を悩ませる悪夢が 「実行時エラー 91: オブジェクト変数または With ブロック変数が見つかりません」 である。ユーザーがキャンバス上で何も選択していない状態で `ActiveSelection` や `ActiveShape` を叩いた瞬間、容赦なくマクロはクラッシュする。

本稿では、CorelDRAWのオブジェクトモデルの深部にある `SelectionManager` の挙動を暴き、例外を未然にねじ伏せる「防衛的プログラミング」の極限的手法を、アーキテクトの視点から解説する。

1. なぜ `ActiveSelection` だけでは不十分なのか?

多くの初学者は、エラー回避のために以下のようなコードを書く。

‘ 駄目な例:これでは防ぎきれないケースが存在する
Sub BadExample()
If ActiveSelection.Shapes.Count > 0 Then
MsgBox “オブジェクトが存在します”
End If
End If

このコードの何が問題か?
CorelDRAWの内部アーキテクチャにおいて、ドキュメント上にアクティブな選択範囲(`Selection`オブジェクト)が存在しない瞬間、`ActiveSelection`プロパティ自体が適切なインスタンスを返さない、あるいは`Shapes`コレクションへアクセスした瞬間にCOM例外(エラー91)を吐き出すビルドが存在するバージョンがある。

特に、ドキュメントを開いた直後や、他のアプリケーションからフォーカスを戻した直後など、COMコンテキストが不安定な状態では、この「踏み絵」を踏んだ瞬間にスクリプトは沈没する。

2. `ActiveDocument.Selection` と `SelectionManager` の真実

CorelDRAW VBAで安全な選択判定を行うには、アプリケーション全体のグローバルショートカットに頼るのではなく、明示的なドキュメントコンテキストから `Selection` を取得し、その状態を型安全に評価する必要がある。

真に堅牢なコードでは、以下の3ステップを踏む。

1. アプリケーションの生存確認(`ActiveApplication`)
2. ドキュメントの存在確認(`ActiveDocument`)
3. `Selection.Shapes.Count` または `Shapes.Count` の厳密なカウント評価

ここでメモリリークやCOMラッパーの解放漏れを防ぐため、オブジェクト変数は適切にスコープを限定し、必要に応じて `Nothing` を代入して参照カウンタを即座にデクリメントする配慮がプロフェッショナルには求められる。

3. 【実践】完全防衛型・セーフティラッパー関数

現場でそのままコピー&ペーストして使える、実用的なエンタープライズグレードのコードを提示する。このパターンをすべてのメイン処理の入口にボイラープレートとして配置せよ。

Option Explicit

” ==============================================================================
” 処理名: 選択オブジェクトの安全な取得とバリデーション
” 備考 : 選択がない場合はユーザーに優しく通知し、安全に処理を中断する
” ==============================================================================
Sub SafeProcessEntry()
‘ 1. アプリケーションおよびドキュメントの存在チェック
If Not IsDocumentActive() Then Exit Sub

Dim sr As ShapeRange
Set sr = GetSafeSelection()

‘ 2. 選択オブジェクトの有無を厳密に判定
If sr Is Nothing Then
MsgBox “オブジェクトが選択されていません。” & vbCrLf & _
“処理を行うオブジェクトを1つ以上選択してください。”, _
vbExclamation, “CorelDRAW 自動化システム”
Exit Sub
End If

If sr.Count = 0 Then
‘ 念のための二重チェック(ShapeRangeが空の場合)
MsgBox “有効なシェイプが選択されていません。”, vbExclamation, “警告”
GoTo CleanUp
End If

‘ — 【ここから実際のコアビジネスロジック】 —
MsgBox “正常に ” & sr.Count & ” 個のオブジェクトを取得しました。”, vbInformation, “実行成功”

Dim sh As Shape
For Each sh In sr
‘ 例:選択されたすべてのシェイプの輪郭を赤にするなどの処理
‘ sh.Outline.Color.RGBAX 0, 255, 0, 0
Next sh
‘ ————————————————

CleanUp:
‘ 3. 明示的なメモリ(COMオブジェクト)の解放
Set sr = Nothing
Set sh = Nothing
End Sub

” ==============================================================================
” ヘルパー関数: アクティブドキュメントの存在確認
” ==============================================================================
Private Function IsDocumentActive() As Boolean
On Error GoTo ErrorHandler
If ActiveDocument Is Nothing Then
MsgBox “アクティブなドキュメントが存在しません。”, vbCritical, “エラー”
IsDocumentActive = False
Exit Function
End If
IsDocumentActive = True
Exit Function

ErrorHandler:
MsgBox “CorelDRAWのドキュメントコンテキストを取得できませんでした。”, vbCritical, “致命的エラー”
IsDocumentActive = False
End Function

” ==============================================================================
” ヘルパー関数: 例外を完全に封じ込めた安全なShapeRangeの取得
” ==============================================================================
Private Function GetSafeSelection() As ShapeRange
On Error GoTo SafeExit

‘ ActiveSelectionRange は選択がない場合にエラーを返すことがあるため、
‘ ActiveDocument.SelectionRange を経由して安全に取得する
Dim targetDoc As Document
Set targetDoc = ActiveDocument

If targetDoc.Selection.Shapes.Count > 0 Then
Set GetSafeSelection = targetDoc.SelectionRange
Else
Set GetSafeSelection = Nothing
End If

Exit Function

SafeExit:
‘ エラーが発生した場合は「選択なし」とみなして Nothing を返す
Set GetSafeSelection = Nothing
End Function

4. チーフアーキテクトからのシステム開発における知見

このコードがなぜ優れているか、シニアの視点から補足する。

オブジェクトのライフサイクル管理とCOM解放

VBAは裏側でCOM(Component Object Model)を叩いている。特にCorelDRAWのCOMラッパーはメモリ管理がデリケートであり、`ShapeRange` や `Shape` オブジェクトを変数に格納したまま放置すると、VBA終了後もメモリ上にCorelDRAWのプロセス(プロセス残骸)が残留する原因になる。
上記のコードでは、`CleanUp` ラベルを設け、処理の終端で確実に `Set sr = Nothing` を実行することで、メモリリークの発生を極限まで抑制している。

レガシー環境・外部システム連携への応用

社内ニッチな基幹システムや、外部のPDM/ERPデータベースからCorelDRAWをCOMオートメーション経由でリモート操作(VB.NETやC#、あるいはVBScriptからのLate Binding)する場合、CorelDRAW側のUIスレッドで予期せぬポップアップ(実行時エラーダイアログ)が発生すると、外部プロセスが永遠に応答待ち(フリーズ)状態に陥る

ユーザーが何も選択していない状態でマクロが勝手にクラッシュし、モーダルエラーダイアログで画面がロックされる事態を防ぐことは、無人稼働するバッチ処理や自動化パイプラインにおいて絶対的な正義である。

総括

「動けばいい」という妥協の産物は、現場に投入された瞬間にバグの温床となる。
`SelectionManager` の挙動を完全に掌握し、いかなるユーザーの奇行(未選択状態での実行)に対しても、スクリプトが優雅に、かつ毅然と身をかわす――これこそが、プロフェッショナルなCorelDRAW VBAエンジニアの流儀である。

今日からあなたのコードに「防衛的プログラメント」を標準装備し、無駄なトラブルシューティングの時間をゼロに圧縮せよ。

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