【実務・中級編】【バッチ処理とページ制御】フォルダ内の複数CDRファイルを開き、全ページの特定レイヤーの表示状態を一括変更して上書き保存 – CorelDRAW VBA解析バイブル

スポンサーリンク

1. 現場の惨状と「自動化」の本質

数百ファイルに及ぶCorelDRAWデータ(`.cdr`)に対し、「特定のレイヤー(例: “ガイド線”, “印刷不可”, “DTP_Note” など)を一括で非表示にして上書き保存してほしい」という指示が下りたとき、あなたはどう対応しているだろうか?

1つずつファイルを開き、レイヤーウインドウをクリックし、保存して閉じる……。このような手作業を繰り返すのは、貴重なエンジニアリングリソースの著しい浪費であり、人間の集中力低下に伴うポカミスの温床でしかない。

しかし、安易にVBAマクロを書いてバッチ処理を組むと、別の地獄が待っている。

  • 処理が極端に重く、CorelDRAWがフリーズする
  • 処理途中でエラーが発生し、どのファイルまで正常終了したか分からなくなる
  • Undoバッファが肥大化し、メモリリークを起こしてクラッシュする
  • マスターレイヤーと通常レイヤーの判定を誤り、意図しない描画要素を消去してしまう

本記事では、CorelDRAW VBAの内部構造とオブジェクトのライフサイクルを考慮した、「高速・堅牢・落とさない」完全無人バッチ処理プログラムの構築手法を解説する。単なるサンプルコードの掲載にとどまらず、プロデュース環境で耐えうる設計思想を叩き込む。

—

2. パフォーマンスと堅牢性を担保するアーキテクチャ設計

CorelDRAW VBAでバッチ処理を組む際、絶対に外してはならない鉄則が3つ存在する。

① UI描画とイベントの完全遮断(Optimization)

CorelDRAWはデフォルトで、ドキュメントの変更が発生するたびに画面描画(UI再描画)とイベント発火を行う。100ページのドキュメントでレイヤーの表示状態を変更するたびに画面を再描画していては、処理速度は数十〜数百倍に低下する。

必ず処理の最初で描画最適化を有効化(UI描画を停止)し、エラー時であっても確実に元に戻すよう `Try-Catch-Finally` 構造(VBAでは `On Error GoTo` とクリーンアップセクション)を構築しなければならない。

‘ UI描画の停止(超高速化)
Application.Optimization = True
Application.EventsEnabled = False

② `ActiveDocument` 依存の排除と明示的参照

初心者コードにありがちな最大の間違いが `ActiveDocument.Pages(1)…` や `ActivePage.Layers(…)` という記述だ。
バッチ処理で複数のドキュメントを連続して開閉する場合、アクティブなドキュメントの遷移タイミングとVBAの非同期的な内部状態がずれ、意図しない別のドキュメントを書き換えてしまう大事故が発生する。

必ず `Dim doc As Document` 変数を用意し、`Set doc = Application.OpenDocument(…)` で取得したオブジェクトに対して厳格に操作を行うこと。

③ マスターレイヤーと通常レイヤーの厳密な区別

CorelDRAWのレイヤー構造には、全ページに共通して存在する「マスターレイヤー(Master Layer)」と、該当ページだけに閉じる「通常レイヤー」が存在する。

全ページループ(`For Each page In doc.Pages`)を回しながらレイヤーを検索する場合、マスターレイヤーのプロパティを何度も無駄に変更してしまう(最悪の場合、予期せぬ状態変化を引き起こす)リスクがある。

構造を正確に理解し、ターゲットレイヤーがドキュメント全体(マスター)のものか、個別ページのものかを識別して処理するロジックが必要だ。

—

3. プロダクション環境仕様のVBA実装コード

以下のコードは、指定フォルダ内の全 `.cdr` ファイルを検索し、全ページにおける特定レイヤー(例: `”Guide”`)の「表示(Visible)」「印刷(Printable)」状態を一括変更して上書き保存する完成版プログラムである。

そのままモジュールに貼り付けて運用可能なレベルで構築している。

Option Explicit

”
‘ 【CorelDRAW VBA】フォルダ内CDRファイル レイヤー制御バッチ処理
‘
‘ 概要: 指定されたフォルダ内の全CDRファイルを順次開き、
‘ 指定された名称のレイヤーの表示・印刷状態を変更して上書き保存する。
‘ 注意: 事前に参照設定で “Microsoft Scripting Runtime” を有効化推奨(FileSystemObject使用のため)
”
Public Sub BatchChangeLayerState()
Dim targetFolderPath As String
Dim targetLayerName As String
Dim setVisible As Boolean
Dim setPrintable As Boolean

‘ ==========================================
‘ 設定パラメータ(業務要件に合わせて変更)
‘ ==========================================
targetFolderPath = “C:\DTP_Work\BatchTarget\” ‘ 処理対象のフォルダ(末尾は\)
targetLayerName = “ガイド線” ‘ 変更対象のレイヤー名
setVisible = False ‘ 非表示にする場合は False
setPrintable = False ‘ 印刷不可にする場合は False
‘ ==========================================

Dim fso As Object
Dim folder As Object
Dim file As Object
Dim doc As Document
Dim processedCount As Long
Dim errorCount As Long
Dim startTime As Double

startTime = Timer
processedCount = 0
errorCount = 0

‘ FileSystemObjectの生成
Set fso = CreateObject(“Scripting.FileSystemObject”)

If Not fso.FolderExists(targetFolderPath) Then
MsgBox “指定されたフォルダが存在しません: ” & targetFolderPath, vbCritical, “エラー”
Exit Sub
End If

‘ CorelDRAW アプリケーション状態の最適化(高速化と警告抑制)
On Error GoTo ErrorGlobalHandler
Application.Optimization = True
Application.EventsEnabled = False
Application.SuppressHeaderWarnings = True

Set folder = fso.GetFolder(targetFolderPath)

‘ フォルダ内のファイルループ
For Each file In folder.Files
‘ 拡張子が .cdr かつ 一時ファイル(~$で始まるもの)を除外
If LCase(fso.GetExtensionName(file.Name)) = “cdr” And Left(file.Name, 2) <> “~$” Then

Dim currentDocPath As String
currentDocPath = file.Path

‘ 個別ファイル処理のエラーハンドリング
On Error GoTo FileErrorHandler

‘ ドキュメントを非可視(UI更新なし)に近い状態で安全に開く
Set doc = Application.OpenDocument(currentDocPath)

If Not doc Is Nothing Then
‘ レイヤー状態変更の核となるロジック呼び出し
Call ProcessDocumentLayers(doc, targetLayerName, setVisible, setPrintable)

‘ ドキュメントの上書き保存
doc.Save

‘ メモリ解放のために確実に閉じる
doc.Close
Set doc = Nothing

processedCount = processedCount + 1
End If

On Error GoTo ErrorGlobalHandler
End If
ContinueLoop:
Next file

‘ 処理完了の復元
GoTo CleanUp

FileErrorHandler:
‘ ファイル個別エラーが発生した場合の処理(全体を止めずにログを記録して次へ)
errorCount = errorCount + 1
Debug.Print “エラー発生 [” & file.Name & “]: ” & Err.Description

If Not doc Is Nothing Then
On Error Resume Next
doc.Close ‘ 異常終了したドキュメントを閉じる
Set doc = Nothing
On Error GoTo ErrorGlobalHandler
End If
Resume ContinueLoop

CleanUp:
‘ アプリケーション設定の確実な復元(最重要)
Application.Optimization = False
Application.EventsEnabled = True
Application.SuppressHeaderWarnings = False
Application.Refresh

Dim elapsedTime As Double
elapsedTime = Round(Timer – startTime, 2)

MsgBox “バッチ処理が完了しました。” & vbCrLf & _
“成功: ” & processedCount & ” 件” & vbCrLf & _
“失敗: ” & errorCount & ” 件” & vbCrLf & _
“所要時間: ” & elapsedTime & ” 秒”, vbInformation, “処理完了”
Exit Sub

ErrorGlobalHandler:
MsgBox “致命的なエラーが発生しました: ” & Err.Description, vbCritical, “システムエラー”
GoTo CleanUp
End Sub

”
‘ ドキュメント内の全ページ・マスターレイヤーを走査し、指定レイヤーの状態を変更する内部手続き
”
Private Sub ProcessDocumentLayers(ByRef doc As Document, ByVal layerName As String, ByVal isVisible As Boolean, ByVal isPrintable As Boolean)
Dim pg As Page
Dim ly As Layer

‘ —————————————————-
‘ 1. 通常ページのレイヤー走査
‘ —————————————————-
For Each pg In doc.Pages
For Each ly In pg.Layers
‘ 大文字・小文字を区別せずにレイヤー名を比較
If LCase(ly.Name) = LCase(layerName) Then
If ly.Visible <> isVisible Then ly.Visible = isVisible
If ly.Printable <> isPrintable Then ly.Printable = isPrintable
End If
Next ly
Next pg

‘ —————————————————-
‘ 2. マスターページのレイヤー走査(全ページ共通レイヤー)
‘ —————————————————-
If Not doc.MasterPage Is Nothing Then
For Each ly In doc.MasterPage.Layers
If LCase(ly.Name) = LCase(layerName) Then
If ly.Visible <> isVisible Then ly.Visible = isVisible
If ly.Printable <> isPrintable Then ly.Printable = isPrintable
End If
Next ly
End If
End Sub

—

4. コードの深掘り解説と実務上の重要ポイント

上記のコードには、大規模プロジェクトでの運用に耐えうるための「罠回避テクニック」が随所に組み込まれている。

① `On Error GoTo FileErrorHandler` による障害隔離

バッチ処理で最悪なのは、「500ファイル中、37ファイル目で壊れたCDRに遭遇して処理が全停止すること」だ。

本コードでは、大枠の `ErrorGlobalHandler` と、ファイルごとのループ内を保護する `FileErrorHandler` の二重エラーハンドリング構成をとっている。破損ファイルやパス例外が発生しても、そのファイルのログを出力してスキップし、残りの499ファイルの処理を完遂させる構造になっている。

② プロパティ書き換え時の不必要な代入防止

If ly.Visible <> isVisible Then ly.Visible = isVisible

単に `ly.Visible = isVisible` と代入するのではなく、現在の値と異なる場合のみ代入する。
CorelDRAW VBAでは、同じ値を再代入するだけでも内部の変更フラグ(Dirty Flag)が立ち、ドキュメントの再構築オブジェクトが生成される場合がある。無駄な代入を極力省くことが、数千オブジェクトを抱える重いデータでの処理速度向上につながる。

③ `Optimization = False` の絶対保護 (`CleanUp` セクション)

VBA実行中にエラーが発生してプログラムが途中終了すると、`Application.Optimization = True` が効いたまま(=画面が一切更新されない状態)でCorelDRAWがフリーズしたように見える。
この状態に陥るとユーザーはタスクマネージャーから強制終了するしかなくなる。

だからこそ、いかなるエラーが発生しようと、必ず `CleanUp` セクションを経由して `Optimization = False` と `Application.Refresh` を呼び出す設計が不可欠だ。

—

5. 応用・拡張へのガイドライン

実務においては、単一のレイヤー名を完全一致で検索するだけでは不十分なケースも多い。現場の要件に応じて以下の拡張を施すと、ツールの価値はさらに跳ね上がる。

A. ワイルドカード・部分一致による一括制御

レイヤー名が `”Guide_Page1″`, `”Guide_Page2″` のように可変である場合、`Like` オペレータを導入する。

‘ “Guide” から始まるレイヤーすべてを対象とする場合
If LCase(ly.Name) Like “guide” Then
ly.Visible = False
End If

B. レイヤーの編集不可(ロック)制御

表示・印刷状態だけでなく、作業者の不用意な改変を防ぐために「ロック(編集不能)」を掛けたい場合は、`Editable` プロパティを操作する。

‘ 編集不可(ロック)にする
ly.Editable = False

C. データベース・CSVファイルからのバッチ条件読み込み

本コードでは設定値をVBA内に直書きしているが、実務ではExcelシートやCSVファイルから「対象フォルダ」「レイヤー名」「処理パラメータ」を動的に読み込む形に拡張しやすいコンポーネント設計(`ProcessDocumentLayers` の分離)にしている。

—

6. まとめ

CorelDRAW VBAによるバッチ処理の要諦は、単に「動くコードを書くこと」ではない。

1. 描画(Optimization)とイベントを停止させ、速度を極限まで引き出すこと
2. `ActiveDocument` への依存を絶ち、明示的なオブジェクト参照で事故を防ぐこと
3. 二重エラーハンドリングにより、1つのエラーで全体を落とさないタフネスを持たせること

本記事で提示したプロダクションコードをベースに、自社のDTP・印刷ワークフローに合わせた最適なカスタマイズを実行してほしい。手作業による数時間の単純作業は、正しく設計された数十秒のVBAコードによって完全に駆逐できる。

タイトルとURLをコピーしました