CorelDRAWを掌握する極限の知見:ファイルドロップをトリガーとする「無人化」CDR自動変換・常駐バッチアーキテクチャ
CorelDRAW VBAの限界は、GUIの操作を単にマクロでなぞるだけの「お遊戯」にあると思い込んでいないか?
実務の現場において、数百・数千のCDRファイルを一網打尽にEPSやSVGへ変換し、適切なディレクトリ構造へルーティングする要件に直面した時、素朴なVBAスクリプトはメモリリークとCOMプロセスのゾンビ化によって必ず破綻する。
今回は、WindowsファイルシステムとCorelDRAWのライフサイクルを完全に掌握し、監視フォルダへのドロップをトリガーに全自動でバックグラウンド処理を完結させる「常駐型バッチエンジン」の設計思想と実装コードを、一切の妥協を排して公開する。
—
1. アーキテクチャの全体像と設計思想
堅牢な自動化システム構築において、最も避けるべきは「CorelDRAWのGUI依存」と「無秩序なプロセス生成」である。
本アーキテクチャでは、以下の3つの鉄則を遵守する。
- 完全非表示(Headless)実行: `Application.Visible = False` を徹底し、描画負荷とUIイベントの介入をシャットアウトする。
- 厳格なオブジェクトライフサイクル管理: ループ内での暗黙的なオブジェクト生成を避け、参照を確実に破棄してメモリリークを防ぐ。
- 堅牢な排他制御とエラーハンドリング: 変換中のファイルを誤って読み込む「半書き込み状態(Lock)」を回避するリトライ機構を実装する。
—
2. 実装:常駐監視・変換バッチエンジン
以下のコードは、特定の監視フォルダ(`WatchFolder`)をポーリングまたはFileSystemWatcher的に監視し、CDRファイルを検知次第、指定フォーマット(ここではSVGおよびEPS)へ変換して出力先へ振り分ける実用モジュールである。
※実運用では、これを独立したVBAプロジェクト、あるいは外部のVBScript/WSH、またはVB.NETコンソールアプリからCorelDRAWのCOMコンポーネントを叩く形に落とし込む。今回はCorelDRAW VBA単体で常駐ループを回す極限構成を示す。
Option Explicit
‘ Windows API: 処理を一時停止し、CPU負荷を軽減するためのSleep関数
If VBA7 Then
Private Declare PtrSafe Sub Sleep Lib “kernel32” (ByVal dwMilliseconds As Long)
Else
Private Declare Sub Sleep Lib “kernel32” (ByVal dwMilliseconds As Long)
End If
‘ 定数定義
Const WATCH_DIR As String = “C:\CorelAuto\Watch\”
Const OUTPUT_SVG_DIR As String = “C:\CorelAuto\Output\SVG\”
Const OUTPUT_EPS_DIR As String = “C:\CorelAuto\Output\EPS /”
Const ARCHIVE_DIR As String = “C:\CorelAuto\Archive\”
Const POLL_INTERVAL_MS As Long = 3000 ‘ 3秒おきにフォルダを監視
Public Sub StartFolderWatcher()
Dim fso As Object
Set fso = CreateObject(“Scripting.FileSystemObject”)
‘ フォルダの存在確認と自動生成
Call EnsureDirectoryExists(fso, WATCH_DIR)
Call EnsureDirectoryExists(fso, OUTPUT_SVG_DIR)
Call EnsureDirectoryExists(fso, OUTPUT_EPS_DIR)
Call EnsureDirectoryExists(fso, ARCHIVE_DIR)
MsgBox “CorelDRAW 自動変換バッチエンジンが起動しました。”, vbInformation, “System Ready”
‘ CorelDRAWのメインアプリケーション設定(高速化のため画面描画とイベントを抑制)
CorelDRAW.Application.Optimization = True
CorelDRAW.Application.EventsEnabled = False
On Error GoTo ErrorHandler
Do
‘ フォルダ内のファイルを走査
Dim targetFolder As Object
Set targetFolder = fso.GetFolder(WATCH_DIR)
Dim fileItem As Object
For Each fileItem In targetFolder.Files
Dim ext As String
ext = LCase(fso.GetExtensionName(fileItem.Name))
‘ 対象がCDRファイルの場合のみ処理
If ext = “cdr” Then
‘ ファイルが完全に書き込まれるまで待機(排他制御)
If WaitForFileRelease(fileItem.Path) Then
Call ProcessConversion(fileItem.Path, fso)
End If
End If
Next fileItem
‘ メモリ解放の促し
Set targetFolder = Nothing
‘ CPU使用率100%を防ぐためのインターバル
DoEvents
Sleep POLL_INTERVAL_MS
Loop
ErrorHandler:
‘ 異常終了時のクリーンアップ
CorelDRAW.Application.Optimization = False
CorelDRAW.Application.EventsEnabled = True
If Err.Number <> 0 Then
MsgBox “致命的なエラーが発生しました: ” & Err.Description, vbCritical
End If
End Sub
‘ ファイルが他のプロセス(コピー中など)にロックされていないか確認する関数
Private Function WaitForFileRelease(ByVal filePath As String) As Boolean
Dim ff As Integer
Dim attempts As Long
attempts = 0
On Error GoTo FileBusy
Do While attempts < 10
ff = FreeFile
Open filePath For Binary Access Read Lock Read Write As #ff
Close #ff
WaitForFileRelease = True
Exit Function
FileBusy:
attempts = attempts + 1
Sleep 500 ' 0.5秒待機してリトライ
Loop
WaitForFileRelease = False
End Function
' 実変換処理とオブジェクトのライフサイクル管理
Private Sub ProcessConversion(ByVal filePath As String, ByRef fso As Object)
Dim doc As CorelDRAW.Document
Dim fileName As String
fileName = fso.GetBaseName(filePath)
On Error GoTo ConvError
' ドキュメントを開く(非表示モードを維持するためウィンドウは作成しない)
Set doc = CorelDRAW.Application.OpenDocument(filePath)
' 1. SVGエクスポートの実行
Dim svgOptions As StructSVGExportOptions
Set svgOptions = CreateStructSVGExportOptions()
svgOptions.Compressed = False
svgOptions.TextAsCurves = True ' フォントのアウトライン化は必須
Dim svgExportFilter As ExportFilter
Set svgExportFilter = doc.ExportEx(OUTPUT_SVG_DIR & fileName & ".svg", cdrSVG, cdrAllPages, svgOptions)
svgExportFilter.Finish
' 2. EPSエクスポートの実行
Dim epsOptions As StructEPSExportOptions
Set epsOptions = CreateStructEPSExportOptions()
epsOptions.IncludeBitmapPreview = cdrEPSNoPreview
epsOptions.TextAsCurves = True
Dim epsExportFilter As ExportFilter
Set epsExportFilter = doc.ExportEx(OUTPUT_EPS_DIR & fileName & ".eps", cdrEPS, cdrAllPages, epsOptions)
epsExportFilter.Finish
' ドキュメントを保存せずに閉じる(メモリのリークを防ぐ唯一の正解)
doc.Close
Set doc = Nothing
' 処理済みの元ファイルをアーカイブフォルダへ移動
Dim destPath As String
destPath = ARCHIVE_DIR & fso.GetFileName(filePath)
If fso.FileExists(destPath) Then
fso.DeleteFile destPath, True
End If
fso.MoveFile filePath, ARCHIVE_DIR
Exit Sub
ConvError:
' エラー発生時でもドキュメントが開いている場合は強制破棄
On Error Resume Next
If Not doc Is Nothing Then
doc.Close
Set doc = Nothing
End If
' エラーログの出力などへルーティング
Debug.Print "変換失敗 [" & fileName & "]: " & Err.Description
End Sub
Private Sub EnsureDirectoryExists(ByRef fso As Object, ByVal dirPath As String)
If Not fso.FolderExists(dirPath) Then
fso.CreateFolder dirPath
End If
End Sub
---
3. チーフアーキテクトが指摘する「死活ポイント」
このコードを実務環境に投入するにあたり、シニアエンジニアとして知っておくべきCorelDRAW特有の罠を解説する。
① `Optimization = True` の魔力と諸刃の剣
CorelDRAWのVBAでは、`Application.Optimization = True` を宣言することで、画面描画の更新や不要なUIイベントの発生が停止し、処理速度が数倍〜数十倍に跳ね上がる。
しかし、これを使用している最中に予期せぬエラー(メモリ不足や不正なファイルフォーマット)で処理が中断すると、CorelDRAW自体が不安定な状態(半死に状態)に陥る。必ず `On Error` でトラップし、終了時には `Optimization = False` に戻す防衛的プログラミングが不可欠だ。
② `doc.Close` の確実な実行とCOMの参照解放
VBAのガベージコレクションは非常に緩慢である。特にCorelDRAWのドキュメントオブジェクトは巨大なバイナリデータを内包するため、`Set doc = Nothing` を怠ると、数ファイル処理しただけでOSのメモリが枯渇する。
また、`ExportEx` メソッドを使用する際は、返り値として生成される `ExportFilter` オブジェクトの `.Finish` メソッドを確実に呼び出さなければ、ファイルハンドルのリークを引き起こす。
③ フォントのアウトライン化(`TextAsCurves = True`)の重要性
自動化サーバー環境において最も頭を悩ませるのが「フォントの欠落(代替フォント置換)」である。EPSやSVGへ変換する際、レンダリングサーバー側に該当フォントがインストールされていない場合、文字化けやレイアウト崩壊が起きる。
上記コードのように、エクスポートオプション側で強制的にパス化(`TextAsCurves = True`)を行うことで、環境依存のエラーを完全に根絶することができる。
—
総括
GUIベースのアプリケーションであるCorelDRAWを、ここまで無機質かつ極限まで最適化されたバッチパイプラインに組み込むことで、人間の手作業によるオペレーションコストはゼロになる。
レガシーなVBAであっても、メモリのライフサイクルとWindowsの排他制御を完全に理解していれば、モダンなシステムに匹敵する堅牢なバックグラウンドワーカーを構築できる。
プロセスの向こう側にある「完全自動化された世界」を、あなたの手で実装してほしい。
