【CorelDRAW VBA極限の知見】Windows APIと完全非表示化(Invisible Mode)で爆誕させる超高速一括フォーマット変換エンジン
業務用のベクターデータ大量処理において、CorelDRAWのGUIが描画を繰り返す仕様は、プログラマーにとって最大のボトルネックである。
画面がチラつき、プログレスバーがフリーズし、数千ファイルの処理が終わるのを何時間も待たされる――そんな非効率な開発スタイルは今日で終わりにしよう。
今回は、Windows APIの `ShowWindow` を駆使してCorelDRAWのウィンドウそのものを完全に隠蔽し、描画オーバーヘッドを理論上の限界までゼロに削ぎ落とした「バックグラウンド超高速一括フォーマット変換エンジン」の設計思想と実装を伝授する。
—
なぜ通常のVBAコードでは遅いのか?
多くのエンジニアが陥る罠は、`Application.Visible = False` や `Optimization = True` だけを信じ込んでいることだ。
CorelDRAWのCOMオブジェクトは強力だが、アプリケーションインスタンスを生成した瞬間、内部的にはGUIスレッドとメインメッセージループが走り始める。たとえドキュメントを開いていなくとも、OSレベルではウィンドウハンドル(HWND)が生成され、不要な描画サイクルの計算が行われている。
さらに、VBAから直接 `CorelDRAW.Application` を起動すると、タスクバーにアイコンが出現し、OSのフォーカスを奪い合う。数千ファイルのバッチ処理中にユーザーが他の作業を行うことすら困難になる。
プロフェッショナルの解:APIによるWindow完全隠蔽
COMの初期化と同時にWindows APIでウィンドウハンドルをキャッチし、即座に非表示(`SW_HIDE`)に固定する。これにより、CPUとGPUのリソースを「純粋なベクター演算とファイルI/O」に100%集中させることが可能になる。
—
堅牢な設計と実装のポイント
プロダクション環境で数千ファイルを処理する場合、以下の要件を満たさなければならない。
1. メモリリークの完全排除:COMオブジェクトはループ内で確実に解放(`Nothing`代入)し、ガベージコレクションのタイミングを制御する。
2. 例外耐性:破損したCDRファイルを読み込んだ際にエンジン全体がクラッチしないよう、個別のファイル単位で `On Error GoTo` による隔離を行う。
3. 安全なAPIフック:CorelDRAWのバージョン差異によるウィンドウタイトルの変動に耐えるハンドル取得ロジック。
—
プロダクションコード:超高速一括フォーマット変換エンジン
以下のコードは、指定フォルダ内のCDRファイルを検出し、CorelDRAWを完全に隠蔽した状態でPDF/EPS/PNG等へ一括変換する、実務直結型のVBAモジュールである。
Option Explicit
‘ ==============================================================================
‘ Windows API Declarations
‘ ==============================================================================
Private Declare PtrSafe Function FindWindow Lib “user32” Alias “FindWindowA” ( _
ByVal lpClassName As String, _
ByVal lpWindowName As String _
) As LongPtr
Private Declare PtrSafe Function ShowWindow Lib “user32” ( _
ByVal hwnd As LongPtr, _
ByVal nCmdShow As Long _
) As Long
‘ Window Show States
Private Const SW_HIDE As Long = 0
Private Const SW_SHOW As Long = 5
‘ ==============================================================================
‘ メイン処理:バックグラウンド一括変換エントリーポイント
‘ ==============================================================================
Public Sub RunInvisibleBatchConversion()
Dim cdrApp As Object
Dim srcDir As String, destDir As String
Dim fileName As String
Dim fileCount As Long
Dim startTime As Double
startTime = Timer
srcDir = “C:\Data\CDR_Source\” ‘ 変換元フォルダ
destDir = “C:\Data\Exported_PDF\” ‘ 変換先フォルダ
‘ ディレクトリの存在確認
If Dir(srcDir, vbDirectory) = “” Then
MsgBox “変換元フォルダが存在しません: ” & srcDir, vbCritical
Exit Sub
End If
If Dir(destDir, vbDirectory) = “” Then MkDir destDir
‘ 1. CorelDRAWアプリケーションの起動(この時点ではまだGUIが表示される可能性あり)
On Error GoTo ErrorHandler
Set cdrApp = CreateObject(“CorelDRAW.Application”)
‘ 2. 【極限の知見】Windows APIで即座にウィンドウを完全非表示化
HideCorelDrawWindow cdrApp
‘ 3. パフォーマンス最適化の極み
cdrApp.Optimization = True
cdrApp.EventsEnabled = False
cdrApp.Interactive = False
‘ 4. ファイルループ処理
fileName = Dir(srcDir & “.cdr”)
fileCount = 0
Do While fileName <> “”
ProcessSingleFile cdrApp, srcDir & fileName, destDir
fileCount = fileCount + 1
fileName = Dir()
Loop
‘ 5. 終了処理とクリーンアップ
cdrApp.Interactive = True
cdrApp.EventsEnabled = False ‘ 終了時はFalseのままで安全に終了
cdrApp.Optimization = False
‘ アプリケーションの終了
cdrApp.Quit
Set cdrApp = Nothing
MsgBox “一括変換が完了しました。” & vbCrLf & _
“処理ファイル数: ” & fileCount & ” 件” & vbCrLf & _
“処理時間: ” & Format(Timer – startTime, “0.00”) & ” 秒”, vbInformation, “爆速バッチ完了”
Exit Sub
ErrorHandler:
MsgBox “致命的なエラーが発生しました: ” & Err.Description, vbCritical
If Not cdrApp Is Nothing Then
cdrApp.Interactive = True
cdrApp.Optimization = False
Set cdrApp = Nothing
End If
End Sub
‘ ==============================================================================
‘ ウィンドウ隠蔽ロジック(API活用)
‘ ==============================================================================
Private Sub HideCorelDrawWindow(ByVal appRef As Object)
Dim hwnd As LongPtr
Dim windowTitle As String
‘ CorelDRAWのメインウィンドウタイトルはバージョンによって異なるためループ等で調整可能だが、
‘ 一般的にはタスク名やクラス名を特定して取得する
‘ ここでは確実にハンドルを掴むため、少しウェイトを入れるかタスク名から逆引きする
Dim i As Integer
For i = 1 to 20 ‘ 最大2秒間ウィンドウ生成を待つ
DoEvents
‘ CorelDRAWのウィンドウクラスは通常 “CorelFrameClass” 系
hwnd = FindWindow(“CorelFrameClass”, vbNullString)
If hwnd <> 0 Then Exit For
Application.Wait Now + TimeValue(“0:00:01”) / 10
Next i
If hwnd <> 0 Then
‘ 描画コンテキストを切り離して完全に隠す
ShowWindow hwnd, SW_HIDE
End If
End Sub
‘ ==============================================================================
‘ 個別ファイル処理(堅牢なエラーハンドリングとメモリ管理)
‘ ==============================================================================
Private Sub ProcessSingleFile(ByVal appRef As Object, ByVal fullPath As String, ByVal outDir As String)
Dim doc As Object
Dim exportFilter As Object
Dim baseName As String
On Error GoTo FileError
‘ ドキュメントを非表示(バックグラウンド)で開く
‘ OpenDocumentExのパラメータでUIを表示させない制御を行う
Set doc = appRef.OpenDocumentEx(fullPath, , True) ‘ True = 非表示/バックグラウンドオープン
baseName = Mid(fullPath, InStrRev(fullPath, “\”) + 1)
baseName = Left(baseName, InStrRev(baseName, “.”) – 1)
‘ PDFエクスポートの例(プレミアドキュメント設定)
Dim expParams As Object
Set expParams = appRef.CreateStruct(“PDFExportSettings”)
‘ 必要に応じてPDF設定をチューニング
Set exportFilter = doc.PublishToPDF(outDir & baseName & “.pdf”, expParams)
‘ ドキュメントを閉じる(変更を保存しない)
doc.Close
Set doc = Nothing
Exit Sub
FileError:
‘ 破損ファイルや読み込みエラー時はログを残して次のファイルへ進む
Debug.Print “Error processing file: ” & fullPath & ” | Details: ” & Err.Description
If Not doc Is Nothing Then
doc.Close 0 ‘ 変更破棄して閉じる
Set doc = Nothing
End If
Resume Next
End Sub
—
チーフアーキテクトからの実務アドバイス
1. データベース・外部連携への応用
このエンジンをベースに、SQL ServerやSQLiteなどのローカルDBから処理待ちタスクをポーリングする仕組み(キューイングシステム)を組み合わせれば、24時間稼働する完全無人の「社内ベクター変換サーバー」を構築できる。
2. マルチプロセス化の検討
近年のマルチコアCPU環境において、CorelDRAWの単一インスタンス処理はCPUパワーを余らせがちだ。処理フォルダを「A〜G」「H〜N」のように分割し、VBAから複数のCorelDRAWインスタンス(またはVBScript経由での並列実行)を立ち上げれば、処理速度はさらに倍増する。
描画を制する者が、CorelDRAW自動化を制す。
GUIの呪縛から解放された真のバックグラウンド処理の圧倒的なスピードを、ぜひ自身の開発現場で体感してほしい。
