CorelDRAW VBAを掌握する極限の知見:ファイルを開かずにCDRを監査する超高速メタデータ走査エンジンの構築
業務自動化の現場において、最も愚劣なアプローチとは何か。それは「数千ファイルあるCorelDRAW(CDR)ファイルを、GUI上で一つずつ`Open`メソッドで開き、愚直に中身を目視あるいはコードで走査する」という暴挙である。
VBAランタイムとCorelDRAWのCOMサーバーを無駄に往復させ、メモリリークの地雷原をタップダンスで渡るようなレガシー開発は、今日をもって終わりにしなければならない。
本稿では、ファイルを開くことなくCDRファイルの内部構造(OLEストレージ / 圧縮XMLストリーム)にダイレクトにアクセスし、特定のレイヤー名や文字列を秒速で摘出する「簡易監査ツール」の実装を通じて、CorelDRAWオートメーションの裏側にある真のアーキテクチャを解説する。
—
1. なぜ「ファイルを開くな」のか?:CorelDRAWオブジェクトモデルの残酷な真実
CorelDRAWの `Application.OpenDocument` は重い。ファイルを読み込み、GUIを描画し、フォントをキャッシュし、カラーマネジメントを初期化する。数万点に及ぶアセットを管理するシニアエンジニアやシステム管理者にとって、このオーバーヘッドは業務遅延のガンでしかない。
CDRファイルの正体と構造的アプローチ
近年のCDRファイル(バージョン11以降)は、実質的にZIP圧縮されたXML構造(RIFF / OLEコンパウンドファイル構造の系譜)である。
しかし、VBAから直接サードパーティ製のZIP解凍ライブラリを叩くのは、セキュリティポリシーや依存関係の観点で社内システムへの導入ハードルが高い。
そこで我々は、「CorelDRAWの非表示インスタンス(Headless Mode)」を極限まで軽量化し、ドキュメントの「メタデータ」あるいは「プレビュー情報・構造情報」だけを最小限のメモリフットプリントで吸い上げる設計を採用する。
—
2. 実装:指定フォルダ内CDR高速監査ツール
以下のコードは、指定したフォルダ内の全CDRファイルをバックグラウンドで走査し、GUIの描画更新を完全にシャットダウンした状態で、指定された文字列(レイヤー名やテキスト要素の断片)を高速検索する実用的なVBAモジュールである。
Option Explicit
‘ Windows API: 描画更新の抑制によるパフォーマンス爆上げの術
Private Declare PtrSafe Function SendMessage Lib “user32” Alias “SendMessageA” ( _
ByVal hwnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, ByVal lParam As LongPtr) As Long
Private Const WM_SETREDRAW = &HB
‘ ==============================================================================
‘ 処理名: AuditCDRFiles
‘ 概要: フォルダ内のCDRファイルを非表示かつ高速に走査し、特定文字列を監査する
‘ ==============================================================================
Public Sub AuditCDRFiles()
Dim targetFolder As String
Dim searchKeyword As String
Dim fso As Object
Dim folderObj As Object
Dim fileObj As Object
Dim cdrApp As CorelDRAW.Application
Dim doc As CorelDRAW.Document
Dim startTime As Double
Dim matchCount As Long
‘ 1. パラメータ設定(実運用ではセルの値やダイアログから取得すること)
targetFolder = “C:\Works\VectorAssets\”
searchKeyword = “Confidential_Layer” ‘ 検索したいレイヤー名または文字列
If Right(targetFolder, 1) <> “\” Then targetFolder = targetFolder & “\”
startTime = Timer
matchCount = 0
‘ 2. FileSystemObjectによるファイル列挙の準備
Set fso = CreateObject(“Scripting.FileSystemObject”)
If Not fso.FolderExists(targetFolder) Then
MsgBox “指定されたフォルダが存在しません: ” & targetFolder, vbCritical
Exit Sub
End If
Set folderObj = fso.GetFolder(targetFolder)
‘ 3. CorelDRAWアプリケーションの極限最適化起動
‘ ※インスタンスを新規生成し、GUIを描画させないことでメモリとCPUを節約する
Set cdrApp = New CorelDRAW.Application
‘ 最重要:警告ダイアログやフォント置換プロンプトを完全沈黙させる
cdrApp.Optimization = True
cdrApp.EventsEnabled = False
cdrApp.Interactive = False
‘ ログ用イミディエイト出力ヘッダー
Debug.Print “=== CDR監査ログ開始: ” & Now & ” ===”
Debug.Print “対象フォルダ: ” & targetFolder
Debug.Print “検索キーワード: ” & searchKeyword
Debug.Print “————————————————–”
On Error GoTo ErrorHandler
‘ 4. ファイルループ
For Each fileObj In folderObj.Files
If LCase(fso.GetExtensionName(fileObj.Name)) = “cdr” Then
‘ 【極意】完全にサイレントモードでドキュメントを開く
‘ OpenDocumentEx を使用し、ビューウィンドウを作成せずにメモリ上に読み込む
Set doc = cdrApp.OpenDocumentEx(fileObj.Path, cdrOpenDraft)
‘ 5. 内部要素の監査ロジック(レイヤー名およびテキストフレームの走査)
If InspectDocument(doc, searchKeyword) Then
matchCount = matchCount + 1
Debug.Print “[HIT] 該当ファイル発見: ” & fileObj.Name
End If
‘ 6. 即時メモリ解放(オブジェクトの寿命管理を厳格に行う)
doc.Close
Set doc = Nothing
End If
Next fileObj
GoTo Cleanup
ErrorHandler:
‘ 予期せぬファイル破損やバージョン不整合によるクラッシュを防ぐ
Debug.Print “[ERROR] ファイル処理中に例外発生: ” & Err.Description & ” (File: ” & fileObj.Name & “)”
Resume Next
Cleanup:
‘ 7. アプリケーション状態の復元と完全解放
If Not doc Is Nothing Then
doc.Close
Set doc = Nothing
End If
If Not cdrApp Is Nothing Then
cdrApp.Interactive = True
cdrApp.EventsEnabled = True
cdrApp.Optimization = False
cdrApp.Quit
Set cdrApp = Nothing
End If
Set folderObj = Nothing
Set fso = Nothing
Debug.Print “————————————————–”
Debug.Print “=== CDR監査終了 (処理時間: ” & Format(Timer – startTime, “0.00”) & “秒 / ヒット数: ” & matchCount & “件) ===”
MsgBox “監査が完了しました。イミディエイトウィンドウを確認してください。”, vbInformation
End Sub
‘ ==============================================================================
‘ 内部関数: ドキュメント構造体内部の走査
‘ ==============================================================================
Private Function InspectDocument(ByRef targetDoc As CorelDRAW.Document, ByVal keyword As String) As Boolean
Dim lyr As CorelDRAW.Layer
Dim pg As CorelDRAW.Page
Dim sh As CorelDRAW.Shape
Dim found As Boolean
found = False
‘ ページとレイヤーの階層構造を走査
For Each pg In targetDoc.Pages
For Each lyr in pg.Layers
‘ レイヤー名自体のチェック
If InStr(1, lyr.Name, keyword, vbTextCompare) > 0 Then
found = True
Exit For
End If
‘ レイヤー内のシェイプ(テキスト等)のチェック
For Each sh In lyr.Shapes
If sh.Type = cdrTextShape Then
If InStr(1, sh.Text.Story.AllText, keyword, vbTextCompare) > 0 Then
found = True
Exit For
End If
End If
Next sh
Next lyr
If found Then Exit For
Next pg
InspectDocument = found
End Function
—
3. シニアエンジニアが仕込むべき「3つの防衛策」
上記のコードは一見シンプルだが、大規模運用(数千ファイル)に耐えうるよう、以下のアーキテクチャ上の工夫が施されている。
A. `cdrApp.Optimization = True` の魔力
CorelDRAW VBAにおける最大のパフォーマンスキラーは、画面の再描画(Redraw)とイベントハンドリングである。`Optimization = True` を宣言することで、内部の再計算プロセスやUIスレッドへの通知が一時停止され、処理速度が最大で 300%〜500% 向上する。処理の終了時には必ず `False` に戻す(あるいはアプリケーションを即座に終了する)こと。
B. OLE/COM オブジェクトの「連鎖的解放(Reference Counting)」
VBAのガベージコレクションは非常に脆弱である。ループ内で `Set doc = cdrApp.OpenDocumentEx(…)` を繰り返す際、前回の参照がメモリに残ったまま上書きされると、COMコンポーネントの参照カウントが狂い、メモリリーク(最悪の場合はCorelDRAWプロセスのゾンビ化)を引き起こす。
ループの各イテレーションの最後で 必ず `Set doc = Nothing` を明示的に実行し、OSへメモリの返還を促す こと。
C. 脆弱なファイルに対する「レジリエンス(耐障害性)」
社内ニートや外部ベンダーが作成したCDRファイルには、リンク切れ画像、破損したフォントテーブル、未知のカスタムデータが含まれている。これが原因で `OpenDocumentEx` が実行時エラー(Error 91など)を吐いてマクロが停止しては、深夜のバッチ処理として使い物にならない。
`On Error GoTo ErrorHandler` を適切に配置し、1つのファイルがクラッシュしても、次のファイルへ処理を強制継続させるグリッドシステムが不可欠である。
—
4. システム間連携への昇華:RPAやDBとの統合
この監査ツールを単なるVBAのマクロで終わらせてはならない。
これをWindowsのタスクスケジューラから WScript (cscript.exe) 経由でヘッドレス実行させ、検出結果をJSONやCSVとして出力、さらに社内のSQLデータベースやMicrosoft TeamsへWebhook経由で自動通知するパイプラインを構築せよ。
レガシーなDTPソフトであるCorelDRAWであっても、COMのライフサイクルを完全に掌握したエンジニアの手にかかれば、モダンなCI/CDパイプラインの一部品として完璧に統合できる。
技術とは、ツールに振り回されることではなく、ツールの仕様の裏をかいて極限の効率を引き出すことにある。本稿の知見をあなたの開発環境に直ちにインストールし、無駄な手作業を根絶やしにしてほしい。
