CorelDRAW VBAを掌握する極限の知見:ファイルを開かずに数千のCDRを監査せよ
業務効率化の現場において、ファイル管理は常にエンジニアの頭を悩ませるボトルネックだ。「あのクライアントの指定レイヤーが入っているCDRファイルはどれだ?」「古いデザインデータから特定の文字列を一括で探したい」。
そんな時、素朴なプログラマは `Application.OpenDocument` をループさせ、片っ端からファイルを開いては閉じるという暴挙に出る。
待て。それはCorelDRAWのライフサイクル、ひいてはOSのI/Oに対する冒涜だ。
数千のエントリを持つフォルダに対し、GUIを伴う重厚長大なCorelDRAWのドキュメントオープン処理を毎回実行すれば、メモリリークの温床となり、PCは唸りを上げ、最終的には「応答なし」の絶望へと沈む。
今回は、CorelDRAW VBAの深淵を知るチーフアーキテクトである私が、「ファイルを開かずに」CDRのメタデータや構造を高速に監査する、実務直結の堅牢な自動化ツールを授けよう。
—
1. なぜ「ファイルを開くアプローチ」は実務で破綻するのか?
多くの初学者が陥る罠がこれだ。
‘ 【アンチパターン】絶対にやってはいけない実装
Dim doc As Document
Set doc = Application.OpenDocument(“C:\Data\sample.cdr”)
If doc.ActiveLayer.Name = “TargetLayer” Then
‘ 処理
End If
doc.Close
このコードの何が問題か?
1. 圧倒的なオーバーヘッド: ファイルを開くたびにCorelDRAWの描画エンジンが走り、メモリの割り当てと解放が繰り返される。
2. クラッシュ耐性の欠如: 破損したCDRファイルや、予期せぬフォント欠落ダイアログが出た瞬間、VBAの実行は停止し、無限のモーダルダイアログの海で人間が監視し続けなければならなくなる。
3. 不可逆な変更リスク: 読み取り専用で開いたつもりが、うっかりセーブのトリガーを踏んだ瞬間にオリジナルデータが汚染される。
プロのエンジニアが目指すべきは、「CorelDRAWのドキュメントモデルを汚さず、最小限のコストで情報を抽出する」ことだ。実は、CorelDRAWのファイルフォーマット(CDR)の内部構造、あるいはOLE/COMの特性を理解すれば、スマートな回避策が見えてくる。
—
2. 堅牢な監査ツールのアーキテクチャ設計
今回構築するツール「CDR簡易監査バッファ」の仕様は以下の通りだ。
- 対象: 指定フォルダ内の全 `.cdr` ファイル
- 方式: ファイルストリーム、または `CreateStorage` 等のOLE構造体解析、あるいは安全なバックグラウンドオープン(画面描画抑制)の最適化。
- 実務的な知見: CorelDRAWのVBA環境において、完全なリバースエンジニアリングによるバイナリ直読みはバージョン差異(X4, 2020, 2024等)で破綻しやすい。そのため、「画面描画を完全に殺し(`Optimization = True`)、バックグラウンドで極速で開いて閉じる」、あるいはファイルプロパティのメタデータをFileSystemObject(FSO)経由で叩くハイブリッドアプローチが最も堅牢かつ現実的である。
- 出力: イミディエイトウィンドウ、またはExcel/CSVへの監査ログ出力。
今回は、実用性を重視し、「描画・警告を一切排除し、エラーハンドリングを鉄壁にした高速オープン・スキャン方式」のプロダクションコードを提示する。
—
3. 【コピペ即稼働】プロダクション・VBAコード
以下のコードをCorelDRAWのVBAエディタ(Alt + F11)の標準モジュールに貼り付けて実行してほしい。実務でそのまま使えるよう、エラーハンドリングとパフォーマンスチューニングの布石を完璧に施してある。
Option Explicit
‘ ==============================================================================
‘ 2Dデザインアセット簡易監査エンジン v1.0
‘ Architected by 業務自動化チーフエンジニア
‘ ==============================================================================
Public Sub AuditCDRFiles()
Dim targetFolder As String
targetFolder = “C:\Your\Target\Folder\” ‘ ← 監査したいフォルダパスに変更してください
If targetFolder = “C:\Your\Target\Folder\” Then
MsgBox “監査対象のフォルダパスをコード内で指定してください。”, vbCritical, “設定エラー”
Exit Sub
End If
‘ 検索キーワード(レイヤー名や文字列の一部)
Const SEARCH_KEYWORD As String = “ロゴ”
Dim fso As Object
Set fso = CreateObject(“Scripting.FileSystemObject”)
If Not fso.FolderExists(targetFolder) Then
MsgBox “指定されたフォルダが存在しません: ” & targetFolder, vbCritical, “パスエラー”
Exit Sub
End If
Dim folder As Object
Dim file As Object
Set folder = fso.GetFolder(targetFolder)
‘ — パフォーマンス&安全性向上のための極限最適化 —
Dim originalOpt As Boolean
originalOpt = Application.Optimization
Application.Optimization = True ‘ 画面描画と再計算を完全に停止
Application.EventsEnabled = False ‘ ユーザーイベントを遮断して爆速化
Dim doc As Document
Dim fileCount As Long, matchCount As Long
fileCount = 0: matchCount = 0
Debug.Print “=== CDR監査ログ開始: ” & Now & ” ===”
On Error GoTo ErrorHandler
For Each file In folder.Files
If LCase(fso.GetExtensionName(file.Name)) = “cdr” Then
fileCount = fileCount + 1
‘ 【重要】エラーハンドリングをファイル単位で隔離する
On Error Resume Next
‘ 読み取り専用かつ非表示に近い状態で開く(ダイアログ抑制)
Set doc = Application.OpenDocument(file.Path, True)
If Err.Number = 0 And Not doc Is Nothing Then
On Error GoTo ErrorHandler
‘ 監査ロジックの実行
If CheckElementInDocument(doc, SEARCH_KEYWORD) Then
matchCount = matchCount + 1
Debug.Print “[HIT] ” & file.Name & ” -> 条件に一致する要素を検出しました。”
Else
Debug.Print “[PASS] ” & file.Name
End If
‘ 変更を一切加えずに即座に閉じる
doc.Close
Set doc = Nothing
Else
Debug.Print “[ERROR/CORRUPT] ” & file.Name & ” (読み込みスキップ)”
Err.Clear
End If
On Error GoTo ErrorHandler
End If
Next file
GoTo Cleanup
ErrorHandler:
MsgBox “予期せぬエラーが発生しました: ” & Err.Description, vbCritical, “致命的エラー”
If Not doc Is Nothing Then
doc.Close
Set doc = Nothing
End If
Cleanup:
‘ — 環境の復元(絶対に忘れてはならない) —
Application.Optimization = originalOpt
Application.EventsEnabled = True
Application.Refresh
Debug.Print “=== 監査完了 ===”
Debug.Print “総スキャン数: ” & fileCount & ” ファイル”
Debug.Print “ヒット数: ” & matchCount & ” ファイル”
MsgBox “監査が完了しました。” & vbCrLf & “ヒット数: ” & matchCount & ” / ” & fileCount, vbInformation, “監査終了”
End Sub
‘ ——————————————————————————
‘ ドキュメント内のレイヤー名・オブジェクトを走査するサブ関数
‘ ——————————————————————————
Private Function CheckElementInDocument(ByVal doc As Document, ByVal keyword As String) As Boolean
Dim lyr As Layer
Dim sh As Shape
Dim found As Boolean
found = False
‘ 1. レイヤー名の走査
For Each lyr In doc.Pages(1).Layers
If InStr(1, lyr.Name, keyword, vbTextCompare) > 0 Then
found = True
Exit For
End If
‘ 2. レイヤー内のシェイプ(テキスト等)の走査
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
If found Then Exit For
Next lyr
CheckElementInDocument = found
End Function
—
4. プロの現場で生きる「3つの設計思想」
このコードをただのコピペで終わらせず、自社の武器にするためのエンジニアリング視点を授けよう。
① `Application.Optimization = True` の絶対厳守
CoreldRAW VBAにおいて、UIの再描画コストは法外に高い。これを有効にしたまま大量のファイルを操作すると、CPUが描画処理にリソースを奪われ、スクリプトの速度が10分の1以下に落ちる。さらに、バッチ処理中にユーザーがマウスやキーボードに触れた際の誤作動を防ぐため、`Application.EventsEnabled = False` で外部入力を完全に遮断するのがプロの作法だ。
② ファイル単位の「エラー隔離(Error Isolation)」
数千ファイルのバッチ処理において、1つの壊れたファイルで全体の処理がアボート(強制終了)するようでは、エンジニア失格だ。
ループ内で `On Error Resume Next` を巧妙に配置し、「エラーが発生したファイルは華麗にスキップし、ログに記録して次のファイルへ進む」というレジリエンス(復元力)の高い構造を担保している。
③ クリーンアップの保証 (`Cleanup` ラベル)
処理の途中でエラーが起きた場合でも、`Optimization` や `EventsEnabled` が `False` のまま取り残されると、CorelDRAWのUIがフリーズしたような状態になり、ユーザーがパニックを起こす。必ず `GoTo Cleanup` による一元的な状態復元経路を用意すること。
—
5. さらなる高みへ:データベース・クラウド連携への布石
今回はイミディエイトウィンドウへの出力にとどめたが、実務のスケールではこれをCSV出力や、SQLite / SQL Server への直接インサートへと拡張すべきだ。
たとえば、`Debug.Print` の部分を、標準的な `Scripting.FileSystemObject` によるTextStream書き込みに置き換えれば、そのまま社内ポータル用のインベントリ台帳が完成する。
‘ 拡張のヒント: CSV出力の例
Dim ts As Object
Set ts = fso.OpenTextFile(“C:\Audit\result.csv”, 2, True)
ts.WriteLine “FileName,Status,Timestamp”
‘ … ループ内で ts.WriteLine file.Name & “,HIT,” & Now
ts.Close
ファイルを開かずに、あるいは最小限のコストで高速に資産を監査する。この設計思想をマスターすれば、君のチームの生産性は爆発的に向上するだろう。
無駄な手作業はコードに語らせ、人間はクリエイティブな領域に集中せよ。
