こんにちは!先輩エンジニアのボクです。
日々の業務自動化、本当にお疲れ様です。
「数百、数千ファイルもある大量のPowerPoint(PPTX)を、まとめてPDFに変換したい!」
そんな業務、あなたも経験ありませんか?
業務効率化のためにVBAで一括変換マクロを組んでみたはいいものの、処理の途中で画面がフリーズしたり、ExcelやPowerPointが突然プツンと強制終了したり……。そして、朝出社して画面を見たら「途中のファイルで止まっていました」なんて絶望的なエラー画面。
……心当たり、ありますよね?
実はこれ、PowerPointの「メモリリーク(使ったメモリが解放されずにどんどん溜まっていく現象)」が原因なんです。特にPDF変換のような重たい処理を何時間も連続でやらせると、WindowsのRAM(メモリ)はパンク寸前になります。
今回は、そんな修羅場をくぐり抜けてきたあなたへ贈る、「Windowsの空きメモリをAPI経由で常時監視し、危なくなったら自分で勝手にPowerPointを安全に再起動して処理を完走させる、極限のレジリエント(回復力のある)・バッチマクロ」の全貌を伝授します。
ここをクリアすれば、あなたも立派な「自動化アーキテクチャの匠」です。一緒に一歩ずつ、深く、そして優しく紐解いていきましょう!
—
1. なぜ、大量のPPTX変換でPowerPointは力尽きるのか?
まずは敵を知ることから始めましょう。
VBAで `Presentation.ExportAsFixedFormat` などのメソッドを使ってPDF変換を行うと、裏側では巨大なPowerPointのプロセスが動き続けます。
ここで問題になるのが、「PowerPointのオブジェクトは、メモリの掃除(ガベージコレクション)があまり得意ではない」という事実です。
1ファイル、2ファイルなら何ともありませんが、500ファイルを突破したあたりから、OSに返すべきメモリがプロセス内に残り続け、やがてWindowsの物理メモリが枯渇します。
「じゃあ、定期的にアプリを再起動すればいいのでは?」
その通り!鋭いですね。
しかし、ただ闇雲に再起動するだけでは「今何番目のファイルを処理していたっけ?」という状態管理が吹き飛んでしまいます。
そこで今回のアーキテクチャの出番です。
1. WindowsのAPI(Kernel32.dll)を使って、今のPCの空きメモリ量をリアルタイムで監視する。
2. 「おや、空きメモリが危険水域(例: 20%以下)に突入したぞ」と検知したら、現在の処理位置をしっかり記憶したまま、PowerPointを一度キレイにシャットダウン(再起動)する。
3. 何食わぬ顔で次のファイルから処理を再開する。
この「自己治癒能力」を持ったバッチこそが、プロが現場で使うレジリエント・コードです。
—
2. 【実践】メモリ監視&自動再起動バッチの全コード
お待たせしました。開発現場でそのままコピペして、すぐに要塞として使える実用コードを公開します。
※今回は分かりやすさと安全性を考慮し、ファイルパスのリストを上から順に処理するオーソドックスな構成にしています。
Option Explicit
‘ =====================================================================
‘ Windows API宣言:現在のメモリ状況(空き容量など)を取得するため
‘ =====================================================================
Private Type MEMORYSTATUS
dwLength As Long ‘ 構造体のサイズ
dwMemoryLoad As Long ‘ 使用中のメモリの割合(%)
dwTotalPhys As Long ‘ 物理メモリの総容量(バイト)
dwAvailPhys As Long ‘ 空き物理メモリの容量(バイト)
dwTotalPageFile As Long ‘ ページングファイルの総容量
dwAvailPageFile As Long ‘ 空きページングファイルの容量
dwTotalVirtual As Long ‘ 仮想メモリの総容量
dwAvailVirtual As Long ‘ 空き仮想メモリの容量
End Type
If VBA7 Then
Private Declare PtrSafe Sub GlobalMemoryStatus Lib “kernel32” (lpBuffer As MEMORYSTATUS)
Else
Private Declare Sub GlobalMemoryStatus Lib “kernel32” (lpBuffer As MEMORYSTATUS)
End If
‘ =====================================================================
‘ メイン処理:大量のPPTXをPDFに安全変換するドライバー
‘ =====================================================================
Sub SafeBatchPdfConversion()
Dim targetFolder As String
Dim fso As Object
Dim folderObj As Object
Dim fileObj As Object
Dim pptApp As Object
Dim pptPres As Object
Dim pdfPath As String
Dim processedCount As Long
‘ 変換元フォルダの指定(必要に応じて書き換えてください)
targetFolder = “C:\PresentationFiles\”
Set fso = CreateObject(“Scripting.FileSystemObject”)
If Not fso.FolderExists(targetFolder) Then
MsgBox “指定されたフォルダが存在しません: ” & targetFolder, vbCritical
Exit Sub
End If
Set folderObj = fso.GetFolder(targetFolder)
processedCount = 0
‘ 初回PowerPointインスタンスの生成
Set pptApp = CreateObject(“PowerPoint.Application”)
pptApp.Visible = True ‘ 描画エラーを防ぐため表示を推奨
‘ フォルダ内の全ファイルをループ
For Each fileObj In folderObj.Files
‘ 拡張子が .pptx または .ppt のファイルのみ対象
If LCase(fso.GetExtensionName(fileObj.Name)) Like “ppt” Then
‘ ———————————————————
‘ 【重要】ここでWindowsのメモリ状況を常時チェック!
‘ ———————————————————
If IsMemoryCritical() Then
Debug.Print “【警告】メモリ枯渇の兆候を検知しました。プロセスを安全に再起動します…”
‘ 安全にインスタンスを破棄
On Error Resume Next
pptApp.Quit
On Error GoTo 0
Set pptApp = Nothing
‘ ガベージコレクションを促すための小休止(2秒)
Application.Wait Now + TimeValue(“00:00:02”)
‘ PowerPointを再起動
Set pptApp = CreateObject(“PowerPoint.Application”)
pptApp.Visible = True
Debug.Print “【復旧完了】PowerPointのプロセスをリフレッシュしました。”
End If
‘ PDFの保存先パスを作成
pdfPath = targetFolder & fso.GetBaseName(fileObj.Name) & “.pdf”
‘ エラーハンドリングを挟みつつPDF変換を実行
On Error GoTo ErrorHandler
Set pptPres = pptApp.Presentations.Open(fileObj.Path, WithWindow:=False)
‘ PowerPointの標準機能でPDF出力(固定形式のエクスポート)
pptPres.SaveAs pdfPath, 32 ‘ 32 = ppSaveAsPDF
pptPres.Close
Set pptPres = Nothing
processedCount = processedCount + 1
Debug.Print “変換成功 (” & processedCount & “): ” & fileObj.Name
End If
Next fileObj
‘ 終了処理
On Error Resume Next
pptApp.Quit
Set pptApp = Nothing
On Error GoTo 0
MsgBox “すべての処理が正常に完了しました!総変換数: ” & processedCount & “ファイル”, vbInformation
Exit Sub
ErrorHandler:
‘ 万が一、特定のファイルが破損していてエラーが出ても、バッチ全体を止めずに次へ進むためのレジリエント処理
Debug.Print “【エラー発生】ファイルスキップ: ” & fileObj.Name & ” (エラー内容: ” & Err.Description & “)”
On Error Resume Next
If Not pptPres Is Nothing Then pptPres.Close
Set pptPres = Nothing
On Error GoTo 0
Resume Next
End Sub
‘ =====================================================================
‘ 補助関数:メモリの空き容量が危機的かどうかを判定する
‘ =====================================================================
Private Function IsMemoryCritical() As Boolean
Dim memStatus As MEMORYSTATUS
memStatus.dwLength = Len(memStatus)
‘ APIを叩いて現在のメモリ状態を取得
GlobalMemoryStatus memStatus
‘ 【閾値設定】
‘ memStatus.dwMemoryLoad は「メモリ使用率(%)」を表します。
‘ 例として、使用率が 85% を超えたら「危険水域」と判定します。
If memStatus.dwMemoryLoad > 85 Then
IsMemoryCritical = True
Else
IsMemoryCritical = False
End If
End Function
—
3. コードのキモをエンジニア目線で解説!
ここからは、コードのなかでも特に重要な「プロのこだわりポイント」をかみ砕いて解説します。
① Windows API (`GlobalMemoryStatus`) の活用
VBA単体では、「今、パソコン全体のメモリがどれくらい余っているか」を正確に知る術がありません。そこで `Kernel32.dll` というWindowsの根幹を担うシステムモジュールに直接アクセスし、現在のメモリ使用率(`dwMemoryLoad`)をリアルタイムで覗き見しています。
※`#If VBA7 Then` などの記述を入れることで、32ビット版Officeと64ビット版Officeの両方でクラッシュせずに動くように配慮しています(これぞプロの技!)。
② 危険水域の閾値(85%)
`IsMemoryCritical` 関数の中に `memStatus.dwMemoryLoad > 85` というロジックがあります。
パソコンのメモリが完全にゼロ(100%)になってからでは、Windows自体がフリーズしてマクロも強制終了されてしまいます。そのため、「少し余裕がある85%の段階で自発的にアプリを再起動する」という予防医学的なアプローチをとっているのが、このコードの最も美しいところです。
③ エラーハンドリングとプロセス生存確認
大量ファイル処理で最も恐ろしいのは、「1つ壊れたファイルがあったせいで、マクロ全体の処理がストップしてしまうこと」です。
`ErrorHandler`ラベルを設置し、もし特定のファイルがパスワード保護されていたり破損していたりしても、そのファイルを華麗にスルーして次のファイルへ進める(Resilientな)構造にしています。
—
4. 現場でよくある「陥りやすい罠」と対策
最後に、このマクロを実際にあなたの職場で動かすときに直面しがちな「つまずきポイント」を先回りしてクリアしておきましょう。
- 罠1:ファイルパスの区切り文字(スラッシュとバックスラッシュ)
- 対策: フォルダパスの末尾には必ず `\`(円マーク)を入れるようにしてください(例: `C:\Folder\`)。これを忘れると `C:\Folderfilename.pdf` のような世にも奇妙なパスが生成されてエラーになります。
- 罠2:セキュリティの警告(マクロのブロック)
- 対策: 保存するワークブック(またはアドイン)のフォルダを、Excel/PowerPointの「信頼できる場所(Trusted Locations)」に必ず登録しておいてください。
- 罠3:バックグラウンドでの開きっぱなし
- 対策: `WithWindow:=False` を指定してファイルを開くことで、画面上で次々とPowerPointがパチパチ開いて閉じる煩わしさを消し、処理速度を限界まで高めています。
—
まとめ
いかがでしたでしょうか?
今回は、単なる「ファイルを一括変換するコード」の枠を超え、OSのハードウェアリソース(RAM)と対話し、自律的にコンディションを整えながら走り抜くレジリエント・バッチマクロの設計思想と実装をお伝えしました。
「動けばいいや」のコードから、「どんな悪条件でも絶対に完走する」プロフェッショナルな自動化へ。
この知見が、あなたの業務を劇的に安定させ、退屈な手作業の監視から解放してくれる強力な武器になることを確信しています。
それでは、また次の現場でお会いしましょう。ハッピー・コーディング!
