CorelDRAW VBAの深淵:マルチページドキュメントの「外科手術」的抽出術
CorelDRAWのVBA開発において、`ActiveDocument.Pages`を単にループさせるだけのコードは、趣味の自動化レベルに過ぎない。我々のような現場のアーキテクトが直面するのは、数百MBに及ぶ巨大なマルチページCDRファイル、複雑なレイヤー構造、そしてメモリリークという名の「静かなる破壊者」だ。
本稿では、特定のキーワードやレイヤー構成をトリガーに、ページ単位で別ドキュメントへ「移植」する、堅牢かつ高速な自動化エンジンを構築する。
—
1. メモリ管理という名の聖域
CorelDRAWのVBAはCOMベースであり、オブジェクトの参照を放置すれば、Corelのプロセスが終了してもメモリ上に残骸が残り、次回の実行で致命的なパフォーマンス低下を招く。
鉄則:
- 全ての`Page`, `Layer`, `Shape`オブジェクトは、用が済んだら即座に`Nothing`を代入し、参照カウントを減らすこと。
- 特に`Document`の新規作成と破棄を繰り返す際は、`Application.ProcessMessages`を適宜挟み、UIスレッドを解放せよ。
2. 抽出ロジック:Deep Copyの罠を回避する
単にページをコピーして別ドキュメントに貼り付ける際、`Copy`と`Paste`を繰り返すと、クリップボード経由の低速な処理に足をすくわれる。我々は`Page.CopyTo`メソッドを駆使し、メモリ内で直接オブジェクトを転送する。
‘ 伝説的な抽出エンジンの核となるプロシージャ
Public Sub ExtractPagesByCondition(ByVal targetKeyword As String)
Dim docSource As Document
Dim docNew As Document
Dim pg As Page
Dim lay As Layer
Set docSource = ActiveDocument
‘ プロセス開始時の最適化設定
Application.Optimization = True
For Each pg In docSource.Pages
‘ レイヤー名またはページ名にキーワードが含まれるか判定
If IsPageTarget(pg, targetKeyword) Then
‘ 新規ドキュメントを作成、または既存のバッファへ追加
If docNew Is Nothing Then
Set docNew = CreateDocument()
‘ 最初のページを削除してクリーンな状態にする
docNew.Pages(1).Delete
End If
‘ ページの複製(Deep Copy)
pg.CopyTo docNew
End If
‘ オブジェクトの明示的解放(メモリリーク対策)
Set pg = Nothing
Next pg
‘ 後処理:最適化解除とクリーンアップ
Application.Optimization = False
Application.Refresh
If Not docNew Is Nothing Then
docNew.SaveAs “C:\Output\Extracted_” & Format(Now, “hhmmss”) & “.cdr”
Set docNew = Nothing
End If
End Sub
‘ 判定ロジックの分離:保守性を担保する
Private Function IsPageTarget(pg As Page, keyword As String) As Boolean
Dim lay As Layer
‘ ページ名チェック
If InStr(pg.Name, keyword) > 0 Then IsPageTarget = True: Exit Function
‘ レイヤー内のオブジェクトプロパティチェック
For Each lay In pg.Layers
If InStr(lay.Name, keyword) > 0 Then IsPageTarget = True: Exit Function
Next lay
End Function
—
3. シニアエンジニアのための極限の知見
A. レガシー環境とWindows APIの活用
もし、ファイルパスの取得や、OSレベルでのファイルロック確認が必要ならば、`Kernel32`から`GetFileAttributes`等を呼び出す必要がある。VBA標準の`Dir`関数はネットワーク越しや権限の強いディレクトリでは不安定になるからだ。
If VBA7 Then
Private Declare PtrSafe Function GetFileAttributes Lib “kernel32” Alias “GetFileAttributesA” (ByVal lpFileName As String) As Long
Else
Private Declare Function GetFileAttributes Lib “kernel32” Alias “GetFileAttributesA” (ByVal lpFileName As String) As Long
End If
B. エラーハンドリングの真髄
巨大なCDRファイルを扱う場合、`On Error Resume Next`の乱用は禁物だ。例外が発生した際、ドキュメントが中途半端な状態でメモリに残り、プロセスがゾンビ化する。必ず`Finally`ブロックを模した構造を作り、強制的に`Application.Optimization = False`を呼び出す設計にすること。
C. パフォーマンスチューニング
`Application.Optimization = True`は、画面の描画更新だけでなく、イベントの発生も抑制する。これにより、処理速度は劇的に向上するが、同時に`Selection`系のメソッドが動作しなくなる。この設計思想は「選択」に頼らず、「オブジェクトの参照」を直接操作するプロフェッショナルなコーディングへの脱皮を意味する。
—
結び:コードは資産であり、負債でもある
我々が書くコードは、数年後の担当者が修正することになる。ページ抽出のような単純なタスクであっても、メモリ管理、エラー制御、そしてモジュール化を徹底することで、それは「保守可能なシステム」へと昇華される。
CorelDRAW VBAは古い言語かもしれない。しかし、そのAPIを完全に掌握し、メモリの海を制御下に置くことができれば、現代のどのようなモダンなワークフローよりも高速で安定した自動化を実現できる。
さあ、次はどのボトルネックを破壊しようか?
