CorelDRAW VBAを掌握する極限の知見:肥大化したCDRファイルを極限まで軽量化する無音クレンジング自動化
長年運用されたCorelDRAW(CDR)ファイルは、度重なるコピペ、外部からのアセットインポート、無数のデザイナーの手を経ることで、目に見えない「ゴミデータ」の温床となる。
ドキュメント内に出現しない未使用のパレット、名前だけが残るパージ不可能なスタイルシート、そしてオブジェクトのライフサイクル管理の不備によって残置されたメタデータ。これらはファイルサイズを徒らに膨らませ、VBAによる一括処理のパフォーマンスを致命的に低下させる。
本稿では、レガシーなCorelDRAW VBAのメモリモデルとオブジェクト構造の裏側を暴き、APIレベルの知見を駆使して「CDRファイル内の未使用カラーパレットや埋め込みフォントスタイルを一掃し、劇的に軽量化する」ための実践的かつ極限まで最適化されたコードベースを提示する。
—
1. 肥大化の元凶:CorelDRAWの内部構造とゴミデータの正体
CorelDRAWのファイルフォーマット(.cdr)は実質的にZIP圧縮されたXMLおよびバイアグラフィックのコンテナである。しかし、アプリケーションがメモリ上に展開し、ドキュメントインスタンス(`Document`)として保持するデータ構造には、次のようなシニアエンジニアにとって看過できない問題が存在する。
1. 孤立したスタイル(Styles / StyleSheets): オブジェクトを削除しても、それらに適用されていたグラフィックやテキストのスタイル定義はドキュメントのシンボルテーブルに残存する。
2. 未使用のパレット(Color Profiles & Palettes): スウォッチパネルに登録されたまま一度も描画に使われなかったスポットカラーやカスタムパレットは、シリアライズ時にそのままストレージを圧迫する。
3. VBAオブジェクトの参照リーク: `ActiveDocument.Pages` や `Layer.Shapes` をループ処理する際、不適切な変数スコープやオブジェクトの解放漏れがメモリリークを引き起こし、CorelDRAWのCOMコンポーネント自体を不安定にする。
これらをGUIの手動操作でクレンジングするのは、数百ファイルを抱える制作現場においては悪夢でしかない。我々はこれを完全自動化しなければならない。
—
2. 厳格なオブジェクトライフサイクル管理と高速化の鉄則
CorelDRAW VBAにおけるパフォーマンスチューニングの第一歩は、「画面描画の完全な抑制」と「COMオブジェクトの明示的破棄(`Nothing`代入)」である。
特に大量のシェイプやスタイルを走査・削除する際、描画更新(`Optimization = True`)を行わないと、Windowsメッセージキューが溢れ、処理速度が何十倍も低下する。
最適化の基本定石
- `Application.Optimization = True` により、イベント、画面描画、アンドゥバッファの記録を一時停止する。
- ループ内で生成・取得したオブジェクト参照は、処理の都度 `Set obj = Nothing` で解放し、VBAのガベージコレクションを意図的に誘導する。
- エラーハンドリング(`On Error Resume Next` の乱用に頼らない構造)を徹底し、異常終了時のメモリリークを防ぐ。
—
3. 実装コード:極限軽量化クレンジングエンジン
以下のVBAモジュールは、アクティブなドキュメントから未使用のスタイル、不要なカラーリファレンス、およびメタデータのパージを行い、最小限のフットプリントで別名保存する実用スクリプトである。
Option Explicit
‘ ==============================================================================
‘ 致命的なファイル肥大化を解消するCDRクレンジング・エンジン
‘ Architecture: CorelDRAW VBA Advanced Memory & Document Optimization
‘ ==============================================================================
Public Sub PurgeAndOptimizeCDR()
Dim startTime As Double
startTime = Timer
‘ 1. システム環境の凍結(描画・イベント・アンドゥの完全停止による爆速化)
With Application
.Optimization = True
.EventsEnabled = False
.UndoLock 1 ‘ アンドゥロック開始
End With
On Error GoTo ErrorHandler
Dim doc As Document
Set doc = Application.ActiveDocument
If doc Is Nothing Then
MsgBox “アクティブなドキュメントが存在しません。”, vbCritical, “致命的エラー”
GoTo CleanUp
End If
Dim originalSize As Double
originalSize = GetFileSizeBytes(doc.FullFileName)
‘ 2. 未使用スタイル(StyleSheets)のパージ
Call PurgeUnusedStyles(doc)
‘ 3. 未使用カラー・パレットのクレンジング
Call PurgeUnusedColors(doc)
‘ 4. ドキュメント全体のガベージコレクション的再構築(セーブ&リロード効果)
Dim targetPath As String
targetPath = GetOptimizedFilePath(doc.FullFileName)
‘ 最適化された状態で別名保存(冗長なメタデータを削ぎ落とす)
doc.SaveAs targetPath, cdrCDR, , cdrFileVersion19 ‘ バージョンは環境に応じて調整
Dim finalSize As Double
finalSize = GetFileSizeBytes(targetPath)
‘ 完了通知
Dim msg As String
msg = “クレンジングが完了しました。” & vbCrLf & _
“処理前: ” & FormatBytes(originalSize) & vbCrLf & _
“処理後: ” & FormatBytes(finalSize) & vbCrLf & _
“削減率: ” & FormatPercent((originalSize – finalSize) / originalSize, 2) & vbCrLf & _
“処理時間: ” & Format(Timer – startTime, “0.00”) & ” 秒”
MsgBox msg, vbInformation, “CorelDRAW メンテナンス完了”
CleanUp:
‘ 5. システム環境の復元(順序の厳守)
With Application
.UndoLock 0
.EventsEnabled = True
.Optimization = False
.Refresh
End With
Set doc = Nothing
Exit Sub
ErrorHandler:
MsgBox “予期せぬエラーが発生しました: ” & Err.Description, vbCritical, “Engine Failure”
Resume CleanUp
End Sub
‘ ——————————————————————————
‘ 未使用スタイルの網羅的削除
‘ ——————————————————————————
Private Sub PurgeUnusedStyles(ByRef doc As Document)
Dim st As Style
Dim i As Long
‘ コレクションの末尾から逆順で走査・削除(インデックスずれを防ぐ定石)
For i = doc.StyleSheets.Count To 1 Step -1
Set st = doc.StyleSheets(i)
‘ デフォルトスタイル(Normal等)の削除を防ぐための保護条件
If Not IsDefaultStyle(st.Name) Then
On Error Resume Next
‘ CorelDRAWのAPI仕様上、使用中のスタイルを削除しようとするとエラーが発生するためこれを逆手に取る
st.Delete
On Error GoTo 0
End If
Set st = Nothing
Next i
End Sub
‘ ——————————————————————————
‘ デフォルトスタイルの判定関数
‘ ——————————————————————————
Private Function IsDefaultStyle(ByVal styleName As String) As Boolean
Select Case LCase(styleName)
Case “normal”, “graphic”, “text”, “寸法”, “default”, “standard”
IsDefaultStyle = True
Case Else
IsDefaultStyle = False
End Select
End Function
‘ ——————————————————————————
‘ 未使用カラーパレット・スウォッチのクレンジング
‘ ——————————————————————————
Private Sub PurgeUnusedColors(ByRef doc As Document)
‘ パレットコレクションの不要な参照をパージ
Dim cp As Palette
Dim i As Long
On Error Resume Next
For i = doc.PaletteCollections.Count To 1 Step -1
Set cp = doc.PaletteCollections(i)
‘ ドキュメントに埋め込まれたカスタムパレットのうち、アクティブでないものを解放
If cp.Name <> doc.ActivePalette.Name Then
‘ 外部参照または内部未使用パレットのアンロード
doc.PaletteCollections.Item(i).Delete
End If
Set cp = Nothing
Next i
On Error GoTo 0
End Sub
‘ ——————————————————————————
‘ ユーティリティ: 最適化ファイルパスの生成
‘ ——————————————————————————
Private Function GetOptimizedFilePath(ByVal originalPath As String) As String
If originalPath = “” Then
GetOptimizedFilePath = CreateObject(“WScript.Shell”).SpecialFolders(“Desktop”) & “\Optimized_Output.cdr”
Exit Function
End If
Dim fso As Object
Set fso = CreateObject(“Scripting.FileSystemObject”)
Dim folder As String, baseName As String, ext As String
folder = fso.GetParentFolderName(originalPath)
baseName = fso.GetBaseName(originalPath)
ext = fso.GetExtensionName(originalPath)
GetOptimizedFilePath = folder & “\” & baseName & “_opt.” & ext
Set fso = Nothing
End Function
‘ ——————————————————————————
‘ ユーティリティ: ファイルサイズ取得
‘ ——————————————————————————
Private Function GetFileSizeBytes(ByVal filePath As String) As Double
Dim fso As Object
Set fso = CreateObject(“Scripting.FileSystemObject”)
If fso.FileExists(filePath) Then
GetFileSizeBytes = fso.GetFile(filePath).Size
Else
GetFileSizeBytes = 0
End If
Set fso = Nothing
End Function
‘ ——————————————————————————
‘ ユーティリティ: バイト数フォーマット
‘ ——————————————————————————
Private Function FormatBytes(ByVal bytes As Double) As String
If bytes >= 1024 1024 Then
FormatBytes = Format(bytes / (1024 1024), “0.00”) & ” MB”
ElseIf bytes >= 1024 Then
FormatBytes = Format(bytes / 1024, “0.00”) & ” KB”
Else
FormatBytes = Format(bytes, “0”) & ” Bytes”
End If
End Function
—
4. チーフアーキテクトの視点:実運用における注意点
この自動化スクリプトを企業の生産環境に導入するにあたり、以下のアーキテクチャ上の制約を必ず考慮しなければならない。
1. フォントスタイルの埋め込み解除について:
CorelDRAWの内部APIでは、文書内の文字オブジェクトが参照しているフォントのアウトラインやスタイルを直接コードから「部分的にアンロード」することは制限されている。完全なフォント埋め込みの削減が必要な場合は、テキストオブジェクトを事前にカーブ(パス)に変換するか、システムフォントに置き換えるプリプロセスを挟む必要がある。ただし、編集可能性が失われるトレードオフが存在するため、本スクリプトでは「スタイル定義のクレンジング」に主眼を置いている。
2. 逆順ループ(Decrement Loop)の鉄則:
コレクションオブジェクト(`StyleSheets` や `PaletteCollections`)を操作する際、先頭から順に削除していくとインデックスがずれてハンドリングエラーや無限ループを引き起こす。必ず末尾から先頭に向かってループ(`Step -1`)させること。
3. COM解放の徹底:
VBAのランタイムは賢くない。特にCorelDRAWのAPIはCOMラッパーの背後でネイティブなC++メモリを保持しているため、変数のスコープが切れるのを待たずに `Set obj = Nothing` を明示的に記述することが、長時間のバッチ処理(大量ファイルの一括クレンジングなど)におけるメモリリークを防ぐ唯一の盾となる。
シニアエンジニア諸君、場当たり的な手作業によるメンテナンスの時代は終わった。このコードをベースに自社のワークフローへ組み込み、真に最適化されたモダンなベクターグラフィックス管理基盤を構築してほしい。
