「動けばいい」を卒業する。CorelDRAW VBAでプロが実践する「絶対に落ちない」堅牢な設計思想
こんにちは。現場の自動化を支えるエンジニアの皆さん。
「マクロの記録」機能を使って、便利なツールを作り始めたのは素晴らしい一歩です。しかし、ある日突然、昨日まで動いていたマクロが「実行時エラー」で止まり、作業を中断させてしまった……そんな経験はありませんか?
実は、マクロの記録で作られたコードは、いわば「理想的な世界」の記録に過ぎません。
現実の制作現場では、「指定した名前のレイヤーが存在しない」「図形がロックされている」「単位設定が勝手に変わっている」といった、予測不能な事態が日常茶飯事です。
今日は、単なる「コードの書き方」ではなく、プロフェッショナルとして必須となる「例外状況を完璧に制御し、ユーザーを迷わせない堅牢なエラーハンドリング(例外処理)」の極意を伝授します。ここをクリアすれば、あなたの作るツールは「便利」から「信頼できる武器」へと進化します。
1. なぜ、あなたのマクロは「脆い」のか?
マクロの記録で作られたコードの最大の問題は、「前提条件が崩れた瞬間に、プログラムが思考停止(クラッシュ)する」ことです。
例えば、以下のようなコードを見てみましょう。
' ⚠️ 初心者が陥りやすい「脆い」コードの例
Sub BadExample()
' 「Work」という名前のレイヤーにガイド線を引く
ActiveDocument.Layers("Work").Guides.Add cdrGuideHorizontal, 0
End Sub
このコードは、もし「Work」というレイヤーが削除されていたり、名前が変わっていたりしたらどうなるでしょうか?
即座に 「実行時エラー ‘438’: オブジェクトは、このプロパティまたはメソッドをサポートしていません」 もしくは 「レイヤーが見つかりません」 と表示され、マクロは強制終了します。
プロの設計は、「もしレイヤーがなかったらどうするか?」という問いに対する答えを、あらかじめコードの中に組み込んでおくのです。
2. 防御的プログラミング:存在を確認してから動く
プロのエンジニアは、いきなり命令を下しません。まず「状況を確認」します。これを「防御的プログラミング(Defensive Programming)」と呼びます。
レイヤーやページを操作する場合、いきなりアクセスするのではなく、「存在チェック」のロジックを挟むのが鉄則です。
実践例:安全なレイヤー取得関数
以下のコードは、指定した名前のレイヤーを探し、なければ作成する、という「プロ仕様」の関数です。
''' <summary>
''' 指定した名前のレイヤーを取得する。存在しない場合は新規作成する。
''' </summary>
''' <param name="layerName">探したいレイヤーの名前</param>
''' <returns>Layerオブジェクト</returns>
Function GetOrCreateLayer(layerName As String) As Layer
Dim lyr As Layer
' 1. まずはエラーを無視して、対象のレイヤーにアクセスを試みる
On Error Resume Next
Set lyr = ActiveDocument.Layers(layerName)
On Error GoTo 0 ' エラー無視状態を即座に解除するのが鉄則!
' 2. もし lyr が Nothing(見つからなかった)なら、新しく作る
If lyr Is Nothing Then
Set lyr = ActiveDocument.Layers.Create(layerName)
' ここでログを出したり、ユーザーに通知しても良い
Debug.Print "Layer '" & layerName & "' was not found. Created a new one."
End If
' 3. 結果を返す
Set GetOrCreateLayer = lyr
End Function
【ここがプロの知見!】
`On Error Resume Next` を使った後は、必ずすぐに `On Error GoTo 0` でエラー検知モードに戻してください。 これを忘れると、その後の本当のバグ(打ち間違いなど)を見逃してしまい、デバッグが地獄になります。
3. 座標の罠:単位系とガイド線の自動配置
次に、ガイド線の配置について考えてみましょう。
「座標 10 にガイドを引く」という命令は、ドキュメントの単位が「ミリメートル」なのか「インチ」なのか「ピクセル」なのかによって、結果が天と地ほど変わります。
ユーザーが勝手に単位設定を変更した状態でマクロを動かすと、ガイド線が画面の外(宇宙の果て)に飛んでいくことになります。
実践例:単位を固定して安全にガイドを引く
Sub SafeGuidePlacement()
Dim targetLayer As Layer
Dim targetPos As Double
Dim originalUnit As cdrUnit
' --- 準備フェーズ ---
' 1. 現在の単位を保存しておく(後で元に戻すため)
originalUnit = ActiveDocument.Unit
' 2. 単位を強制的に「ミリメートル」に設定(計算の狂いを防ぐ)
ActiveDocument.Unit = cdrMillimeter
' 3. 安全にレイヤーを取得
Set targetLayer = GetOrCreateLayer("Guide_Layer")
' 4. 配置したい座標(例: 50mmの位置)
targetPos = 50
' --- 実行フェーズ ---
' エラーハンドリングの開始
On Error GoTo ErrorHandler
' Undo(元に戻す)を一回で済ませるためのグループ化
ActiveDocument.BeginCommandGroup "Add Safe Guides"
' ガイド線の追加
targetLayer.Guides.Add cdrGuideHorizontal, targetPos
targetLayer.Guides.Add cdrGuideVertical, targetPos
' コマンドグループの終了
ActiveDocument.EndCommandGroup
MsgBox "ガイド線の配置が完了しました。", vbInformation
CleanUp:
' --- 後片付けフェーズ ---
' 5. 単位を元の設定に戻す(ユーザーへの礼儀)
ActiveDocument.Unit = originalUnit
Exit Sub
ErrorHandler:
' エラーが発生した場合のリカバリー
ActiveDocument.EndCommandGroup ' 失敗してもグループを閉じる
MsgBox "エラーが発生しました。" & vbCrLf & _
"エラー内容: " & Err.Description, vbCritical, "システムエラー"
Resume CleanUp
End Sub
このコードの「凄み」を解説
1. `BeginCommandGroup` / `EndCommandGroup`:
これを使わないと、ガイドを2本引いた場合、ユーザーは「Ctrl+Z」を2回押さなければなりません。プロのツールは、「失敗しても、成功しても、やり直しは1回で済む」ように設計します。
2. 単位の保存と復元:
`originalUnit` に現在の設定を退避させています。マクロが勝手に単位を変えて、そのまま放置するのは、道具を使い終わった後にボロボロのまま放置するのと同じです。
3. `ErrorHandler` による一括管理:
エラーが起きても `CleanUp` ラベルを経由させることで、必ず「単位の復元」が行われるように設計されています。これが「堅牢な設計」の正体です。
4. まとめ:プロへのロードマップ
マクロの記録から脱却し、プロのエンジニアへ近づくためのチェックリストを授けます。
- [ ] 「もし〜がなかったら?」を常に考える(レイヤー、ページ、選択オブジェクト)。
- [ ] `On Error Resume Next` は「確認」の時だけ使い、すぐに解除する。
- [ ] 計算を行う前に、必ず `ActiveDocument.Unit` を明示的に指定する。
- [ ] `BeginCommandGroup` を使い、ユーザーの「元に戻す」操作を尊重する。
- [ ] エラーが起きても、必ず「元の状態(単位や設定)」に戻して終了する。
最初は難しく感じるかもしれません。でも、一度この「型」を身につければ、あなたの書くコードは、どんな複雑なドキュメントが来ても動じない、鉄壁の自動化ツールへと生まれ変わります。
さあ、次のコードを書くときは、ぜひ「もしもの時」の準備を始めてみてください。応援していますよ!
