【限界突破】PowerPoint大量変換のメモリ地獄を「自己修復」する。Windows APIを用いたレジリエント・バッチ処理の極意
業務自動化を志すエンジニアなら一度は直面するはずだ。「数百のPPTXをPDFに一括変換するマクロを回していたら、中盤でPowerPointが肥大化し、最後にはフリーズかクラッシュで全滅する」という悪夢。
Microsoft Officeのオブジェクトモデルは、残念ながら「長期運用」を想定して作られていない。`Presentation.Close`や`Quit`を呼んでも、メモリが完全には解放されず、プロセスが少しずつ腐敗していく。
今回は、このメモリリークの海を乗りこなし、「空きメモリを監視し、危険域に達したら自らプロセスを再起動して処理を継続する」という、極限状態でも止まらないレジリエント(回復力のある)な設計を伝授する。
—
なぜ「普通のマクロ」では死ぬのか
VBAの`Application.Quit`は、単なる終了コマンドに過ぎない。COMオブジェクトの背後では、GDIリソースやメモリキャッシュが断片化し、ループを重ねるごとにプロセスが「重く」なる。
「数時間放置して朝には終わっているはずのタスク」が止まっているのは、あなたのコードのせいではない。リソースの境界線を理解せず、プロセスを使い回している設計が原因だ。
解決策は明確だ。
1. Windows API(GlobalMemoryStatusEx)で物理メモリの残量を監視する。
2. しきい値を下回った瞬間、自ら終了し、次のプロセスを起動して「処理の続き」から再開する。
3. 状態保存(ステート管理)は外部ファイル(CSVやJSON)に逃がす。
—
堅牢な設計:リソース監視アーキテクチャ
このシステムは「司令塔」となるVBScript(または上位のコントローラー)が、PowerPointプロセスを「使い捨て」ながら管理する構成にするのが最も安全だ。VBA単体での自己再起動は不安定なため、「コントローラー(VBS)+実務者(VBA)」の二階層構造を推奨する。
1. メモリ監視用Windows API構造体定義
まずはVBA側で、システムのメモリ状態を正確に取得する準備をする。
‘ メモリ情報を取得するための構造体
Private Type MEMORYSTATUSEX
dwLength As Long
dwMemoryLoad As Long
ullTotalPhys As Currency
ullAvailPhys As Currency
ullTotalPageFile As Currency
ullAvailPageFile As Currency
ullTotalVirtual As Currency
ullAvailVirtual As Currency
ullAvailExtendedVirtual As Currency
End Type
If VBA7 Then
Private Declare PtrSafe Sub GlobalMemoryStatusEx Lib “kernel32” (lpBuffer As MEMORYSTATUSEX)
Else
Private Declare Sub GlobalMemoryStatusEx Lib “kernel32” (lpBuffer As MEMORYSTATUSEX)
End If
‘ 空きメモリの割合を0-100で返す関数
Public Function GetAvailableMemoryPercent() As Long
Dim memInfo As MEMORYSTATUSEX
memInfo.dwLength = Len(memInfo)
GlobalMemoryStatusEx memInfo
‘ 使用率を計算
GetAvailableMemoryPercent = memInfo.dwMemoryLoad
End Function
—
プロダクションコード:自己修復型ループの骨子
このロジックは、変換処理のループ内に組み込む。メモリ使用率が80%を超えたら、その時点のファイル番号を外部ファイルに保存し、プロセスを強制終了させる。
Public Sub BatchExportToPDF(startIndex As Long)
Dim i As Long
Dim appPPT As Object
Set appPPT = Application
‘ メモリ監視:80%を超えたら逃げる
If GetAvailableMemoryPercent() > 80 Then
‘ 現在の進行状況をログに書き出す
Call SaveProgressToFile(i)
‘ プロセス終了の準備
appPPT.Quit
Exit Sub
End If
‘ PDF変換のメインロジック
‘ … ここに ExportAsFixedFormat を実装 …
End Sub
—
「止まらない」を支える運用ルール
このマクロを実戦投入する際、以下の3点を徹底してほしい。
1. ステートの永続化:
処理したファイル名(インデックス)を `progress.log` のようなテキストファイルに逐次書き込むこと。再起動後、マクロはそのファイルを読み込み、未処理分から処理を開始する。これが「レジリエント」の核だ。
2. プロセスのクリーンアップ:
`Set obj = Nothing` を過信しないこと。COMオブジェクトの解放が不確実な場合は、タスクスケジューラからVBS経由でマクロを呼び出し、プロセス自体をOSレベルで定期的に入れ替えるのが正攻法だ。
3. 例外処理の徹底:
ファイルが破損している場合にマクロが停止しないよう、`On Error Resume Next` を活用しつつ、エラーログを確実に残すこと。
最後に:なぜここまでやるのか
「自動化」とは、単にコードを書くことではない。「想定外のクラッシュを想定内に収めること」こそが、プロフェッショナルなエンジニアの矜持だ。
WindowsというOSの上で、不安定なCOMオブジェクトを扱う以上、リソース管理は避けて通れない。今回紹介したAPI監視を取り入れれば、数百、数千のファイル処理でも、あなたは安心してコーヒーを飲んでいることができるはずだ。
システムを「人間に依存させない」。それが業務自動化の最終到達点である。健闘を祈る。
