【実務・中級編】大規模マクロの保守性向上:Option Explicitの徹底と独自エラーログ出力クラスの設計 – CorelDRAW VBA解析バイブル

スポンサーリンク

CorelDRAW VBAを掌握する極限の知見:大規模マクロの保守性を限界まで高める設計論

業務自動化の現場において、CorelDRAW VBAは強力な武器となる。しかし、その手軽さゆえに「場当たり的なコードの積み重ね」によって破綻するプロジェクトを数多く見てきた。
動くには動くが、いざ仕様変更やエラーが発生したとき、どこがボトルネックなのか分からない――。そんな「負債まみれのマクロ」を終わらせるための設計論を授けよう。

今回は、長期運用されるCorelDRAWマクロの生命線である「Option Explicitの徹底」と、現場のトラブルを秒速で特定するための「独自エラーログ出力クラスの設計」に焦点を当てる。

なぜ「その場しのぎのVBA」は崩壊するのか?

CorelDRAWのVBA環境は、VB6時代から変わらないレガシーなものである。だからこそ、開発者の「規律」がコードの寿命を決定づける。

1. 暗黙の変数宣言(Variantの魔力)
`Option Explicit`を記述せず、タイポした変数をそのまま放置すると、VBAは勝手に新しいVariant型変数を作り出す。これがメモリ効率の悪化を招き、想定外の型不一致エラーを引き起こす最大の原因となる。
2. 「エラーが出たら止まる」だけの脆弱なハンドリング
`On Error Resume Next`を乱用し、エラーを握り潰した結果、ドキュメントが中途半端に改変され、未保存のままフリーズする。実務において、これは最悪のシナリオだ。

プロフェッショナルな開発者であれば、コンパイル時にバグを完全に排除し、万が一の障害時には「いつ、どのレイヤーの、どのオブジェクト処理で失敗したか」を正確にトレースできる仕組みを構築しなければならない。

鉄則1:コンパイルの厳格化(Option Explicit)

すべてのモジュールの先頭に `Option Explicit` を強制することは、プロとしての最低限の責務である。
VBEのオプションで「変数の宣言を強制する」にチェックを入れるのは当然として、自動生成されるクラスモジュールや標準モジュールであっても、この三文字の有無を確認する習慣をつけよ。

鉄則2:現場で生きる「独自エラーログ出力クラス」の設計

CorelDRAWの実行時エラーは、ユーザーに「予期せぬエラーが発生しました」と冷たく突き放すだけでは不親切である。どのファイルを開いているとき、どのマクロのどのステップで起きたのかを、自動的にテキストファイルへロギングする仕組みをクラスとしてカプセル化する。

以下のコードは、FSO(FileSystemObject)を用いて安全にログを蓄積するプロダクション品質のクラスモジュールである。

クラスモジュール名:`CErrorLogger`

VERSION 1.0 CLASS
BEGIN
MultiUse = -1 ‘False
END
Attribute VB_Name = “CErrorLogger”
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
‘ =================================================================oyan
‘ Class Name: CErrorLogger
‘ Description: CorelDRAW業務マクロ専用 堅牢エラーログ出力クラス
‘ =================================================================
Option Explicit

Private m_LogFilePath As String
Private m_FSO As Object

‘ クラス初期化時にログファイルの出力パスを決定
Private Sub Class_Initialize()
Dim fsoObj As Object
Set fsoObj = CreateObject(“Scripting.FileSystemObject”)

‘ デスクトップ、またはアドインと同じフォルダにログを出力
‘ ここではC1DR_Logsというフォルダを自動生成する設計とする
Dim logDir As String
logDir = Environ(“USERPROFILE”) & “\Desktop\CorelDRAW_ErrorLogs\”

If Not fsoObj.FolderExists(logDir) Then
fsoObj.CreateFolder logDir
End If

‘ ファイル名は日付ベースで日ごとに分割
m_LogFilePath = logDir & “ErrorLog_” & Format(Date, “YYYYMMDD”) & “.log”
Set m_FSO = fsoObj
End Sub

‘ クラス終了時のクリーンアップ
Private Sub Class_Terminate()
Set m_FSO = Nothing
End Sub

‘ —————————————————————-
‘ ログ書き込みメソッド
‘ —————————————————————-
Public Sub WriteLog(ByVal moduleName As String, ByVal procedureName As String, ByVal errNumber As Long, ByVal errDescription As String)
On Error GoTo SafeExit ‘ ログ書き込み失敗で本体をクラッシュさせないための二重防壁

Dim ts As Object
‘ ForAppending (8) で開き、存在しない場合は作成(True)、Unicode(-1)で書き込み
Set ts = m_FSO.OpenTextFile(m_LogFilePath, 8, True, -1)

Dim logMessage As String
logMessage = “[” & Now & “] ” & _
“[Module: ” & moduleName & “] ” & _
“[Proc: ” & procedureName & “] ” & _
“[ErrNo: ” & CStr(errNumber) & “] ” & _
“Desc: ” & errDescription

ts.WriteLine logMessage
ts.Close
Set ts = Nothing
Exit Sub

SafeExit:
‘ 万が一ログ書き込み自体が失敗した場合はイミディエイトに逃がす
Debug.Print “CRITICAL ERROR: Failed to write log. ” & Err.Description
End Sub

実践:メイン処理への組み込み方

上記の `CErrorLogger` を使って、CorelDRAWのドキュメント操作を行う標準モジュールを記述する。ここでは、選択されたシェイプの数やレイヤーの状態を安全に処理するフローを例示する。

標準モジュール:`mMain`

Option Explicit

Sub ProcessCorelDrawAutomation()
‘ 宣言の強制によるタイポ撲滅
Dim logger As CErrorLogger
Set logger = New CErrorLogger

Const MODULE_NAME As String = “mMain”
Const PROC_NAME As String = “ProcessCorelDrawAutomation”

On Error GoTo ErrorHandler

‘ — CorelDRAW固有の重い処理前の最適化 —
‘ 画面描画とイベントを抑制してパフォーマンスを爆発的に向上させる
ActiveApp.Optimization = True
EventsEnabled = False

‘ ドキュメントが開かれているか厳格にチェック
If ActiveDocument Is Nothing Then
Err.Raise vbObjectError + 1000, MODULE_NAME, “アクティブなドキュメントが存在しません。処理を中断します。”
End If

Dim doc As Document
Set doc = ActiveDocument

‘ 実際の業務処理(例:アクティブページのレイヤー走査)
Dim layerName As String
layerName = “AutoGenerated_Layer”

Dim targetLayer As Layer
Set targetLayer = doc.ActivePage.Layers.Find(layerName)

If targetLayer Is Nothing Then
Set targetLayer = doc.ActivePage.CreateLayer(layerName)
End If

‘ 意図的なテストエラー(検証用:コメントアウト解除でエラーログをテスト可能)
‘ Err.Raise 11, MODULE_NAME, “ゼロ除算テストエラー”

‘ 正常終了時の処理
MsgBox “処理が正常に完了しました。”, vbInformation, “CorelDRAW Automation”

CleanUp:
‘ — 最適化の解除(絶対に忘れてはならない) —
ActiveApp.Optimization = False
EventsEnabled = True
Set logger = Nothing
Exit Sub

ErrorHandler:
‘ 障害発生時は独自クラスでログを記録
logger.WriteLog MODULE_NAME, PROC_NAME, Err.Number, Err.Description

‘ ユーザーへは最低限の分かりやすいメッセージを通知
MsgBox “エラーが発生しました。” & vbCrLf & _
“詳細なエラー内容がデスクトップのログフォルダに記録されました。” & vbCrLf & _
“管理者へご連絡ください。”, vbCritical, “致命的なエラー”

Resume CleanUp
End Sub

チーフアーキテクトからの提言

CorelDRAWの自動化において最も恐ろしいのは、「何が起きているか分からないまま、サイレントにデータが破損すること」である。

1. `ActiveApp.Optimization = True` とのエラーハンドリングの同居
もし最適化を有効にしたままエラーでマクロが途中で停止すると、CorelDRAWの画面描画がフリーズしたままになり、ユーザーは強制終了するしかない状態に陥る。上記のコードのように、必ず `CleanUp` ラベルを用意し、エラー時であっても確実に最適化フラグを戻す構造(Try-FinallyイディオムのVBA的実装)を徹底すること。
2. ログの永続化
現場のPCローカル(デスクトップ等)にログを吐き出す設計にしておけば、「昨日まで動いていたのに突然動かなくなった」という問い合わせに対し、ユーザーからログファイルを回収するだけで一瞬で原因究明ができる。

保守性の高いコードとは、未来の自分、そして現場の作業者を救うための最大の投資である。場当たり的なコードから脱却し、プロダクション品質のアーキテクチャをあなたのプロジェクトに導入してほしい。

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