こんにちは!PowerPoint VBAの世界へようこそ。
マクロの記録ボタンを押して「なんとなく動くコード」を作るフェーズは、もう卒業しませんか?
今回は、業務自動化の現場で即戦力となる「プロ仕様のファイル管理・PDF一括変換ツール」の作り方を解説します。
単にファイルをPDFにするだけではありません。Windowsの底深い機能である「Windows API」をVBAから呼び出し、変換元のファイルを安全にゴミ箱へ送りつつ、成果物を美しい階層構造で自動整理する――そんなシステムライクなアプローチを一緒に紐解いていきましょう。
ここをクリアすれば、あなたのVBAスキルは「ただの自動化お助けツール」から「堅牢なエンタープライズ・アプリケーション」へと劇的に進化します。さあ、一緒に本質を学んでいきましょう!
—
なぜ「Killステートメント」ではプロ失格なのか?
PowerPoint VBAでファイルを削除しようとすると、真っ先に思い浮かぶのが `Kill` ステートメントですよね。
‘ 絶対にやってはいけない生データ削除の例
Kill “C:\Work\Important_Presentation.pptx”
ちょっと待ってください!もし、そのファイルが「間違えて選択されたもの」だったら?あるいは、上司から「やっぱり元のファイルも残しておいて!」と言われたらどうしますか?
`Kill` はファイルを一瞬で、完全に、復元不可能な形で消去します。これは業務自動化において「凶器」になり得ます。
プロのエンジニアが目指すべきは、「ユーザーに優しく、万が一の誤操作にも耐えるシステム」です。
そこで登場するのが、Windowsが標準で備えているシェル機能、Windows API (`SHFileOperation`) です。これを使えば、VBAから直接ファイルを「Windowsのゴミ箱」へ安全に移動させることができます。
—
実装の全体像:このツールがやること
今回作成するプロ仕様のマクロは、以下のステップを全自動で実行します。
1. 出力先フォルダの自動生成: 変換先のディレクトリが存在しない場合、VBAから一瞬でディレクトリツリーを構築します。
2. PDF一括変換: 指定フォルダ内のPowerPointファイルを次々と開き、高精度なPDFへ書き出します。
3. 安全なゴミ箱送り: 変換が完全に成功したファイルだけを、Windows API経由でゴミ箱へ移動します。
それでは、実際のコードを見ていきましょう。開発環境の標準モジュールに、そのままコピペして貼り付けられるフルスクリプトです。
—
【実用コード】プロ仕様・安全PDF変換&ゴミ箱送りツール
Option Explicit
‘ ==============================================================================
‘ Windows API 定義領域
‘ 32ビット版および64ビット版のExcel/PowerPoint両方に対応するシグネチャ
‘ ==============================================================================
If VBA7 Then
Private Declare PtrSafe Function SHFileOperation Lib “shell32.dll” Alias “SHFileOperationA” (lpFileOp As SHFILEOPSTRUCT) As Long
Else
Private Declare Function SHFileOperation Lib “shell32.dll” Alias “SHFileOperationA” (lpFileOp As SHFILEOPSTRUCT) As Long
End If
‘ SHFileOperationで使用する構造体
Private Type SHFILEOPSTRUCT
hwnd As LongPtr
wFunc As Long
pFrom As String
pTo As String
fFlags As Integer
fAnyOperationsAborted As Long
hNameMappings As LongPtr
lpszProgressTitle As String
End Type
‘ API定数
Private Const FO_MOVE As Long = &H3 ‘ 移動操作
Private Const FO_DELETE As Long = &H3 ‘ 削除操作
Private Const FOF_ALLOWUNDO As Long = &H40 ‘ ゴミ箱へ送るフラグ(これ重要!)
Private Const FOF_NOCONFIRMATION As Long = &H10 ‘ 削除時の確認ダイアログを非表示
‘ ==============================================================================
‘ メインプロシージャ
‘ ==============================================================================
Sub SafeConvertAndTrash()
Dim targetDir As String
Dim outputDir As String
Dim fileName As String
Dim fullPath As String
objDim pdfPath As String
‘ フォルダパスの定義(環境に合わせて書き換えてください)
targetDir = “C:\PresentationWork\Source\”
outputDir = “C:\PresentationWork\Output_PDF\”
‘ 1. 出力先フォルダがなければ自動生成する
Call EnsureDirectoryExists(outputDir)
‘ 2. フォルダ内のPPTXファイルを走査
fileName = Dir(targetDir & “.pptx”)
If fileName = “” Then
MsgBox “処理対象のPowerPointファイルが見つかりませんでした。”, vbExclamation, “通知”
Exit Sub
End If
‘ 画面描画を停止してパフォーマンスを極限まで高める
Application.ScreenUpdating = False
Do While fileName <> “”
fullPath = targetDir & fileName
pdfPath = outputDir & Replace(fileName, “.pptx”, “.pdf”, , , vbTextCompare)
On Error GoTo ErrorHandler
‘ プレゼンテーションを開く(非表示で開くことでチラつきを防止)
Dim pptDoc As Presentation
Set pptDoc = Presentations.Open(FileName:=fullPath, ReadOnly:=True, WithWindow:=msoFalse)
‘ PDFとして保存
pptDoc.SaveAs FileName:=pdfPath, FileFormat:=ppSaveAsPDF
‘ ドキュメントを閉じる
pptDoc.Close
Set pptDoc = Nothing
‘ 3. 変換成功を確認後、元のファイルを「ゴミ箱」へ安全に移動
If Dir(pdfPath) <> “” Then
Call MoveToTrash(fullPath)
End If
NextFile:
fileName = Dir() ‘ 次のファイルへ
Loop
Application.ScreenUpdating = True
MsgBox “すべての処理が正常に完了しました!成果物はフォルダを確認してください。”, vbInformation, “完了”
Exit Sub
ErrorHandler:
Application.ScreenUpdating = True
MsgBox “エラーが発生しました。” & vbCrLf & _
“ファイル名: ” & fileName & vbCrLf & _
“内容: ” & Err.Description, vbCritical, “エラー”
If Not pptDoc Is Nothing Then
pptDoc.Close
Set pptDoc = Nothing
End If
End Sub
‘ ==============================================================================
‘ サブルーチン: 指定パスのフォルダが存在しない場合に再帰的に作成する
‘ ==============================================================================
Private Sub EnsureDirectoryExists(ByVal dirPath As String)
If Right(dirPath, 1) <> “\” Then dirPath = dirPath & “\”
If Len(Dir(dirPath, vbDirectory)) = 0 Then
‘ 親フォルダも含めて一括作成
Dim parentPath As String
parentPath = Left(dirPath, InStrRev(dirPath, “\”, Len(dirPath) – 1))
If Len(Dir(parentPath, vbDirectory)) = 0 Then
EnsureDirectoryExists parentPath
End If
MkDir dirPath
End If
End Sub
‘ ==============================================================================
‘ サブルーチン: Windows APIを使用してファイルをゴミ箱へ送る
‘ ==============================================================================
Private Sub MoveToTrash(ByVal filePath As String)
Dim shFile As SHFILEOPSTRUCT
‘ APIに渡す文字列は必ず「Null文字(vbNullChar)」で2重に終わらせる必要がある(Windows APIの鉄則)
shFile.wFunc = FO_DELETE
shFile.pFrom = filePath & vbNullChar & vbNullChar
shFile.fFlags = FOF_ALLOWUNDO + FOF_NOCONFIRMATION
‘ API実行
SHFileOperation shFile
End Sub
—
Description: コードの深掘りと、初心者がハマりやすい「罠」の回避策
1. なぜ `#If VBA7 Then` が必要なのか?(API呼び出しの極意)
現代のOfficeは、32ビット版と64ビット版が混在しています。従来の古いVBAコードを64ビット版のPowerPointで実行すると、メモリポインタのサイズ不一致でExcelやPowerPointごと強制終了(クラッシュ)します。
このコードでは、コンパイル条件分岐を使い、32ビット/64ビットのどちらの環境であっても安全に `PtrSafe` 宣言でWindows APIを叩けるよう設計されています。ここがプロとアマの分水嶺です。
2. Windows APIのストリング終端(`vbNullChar & vbNullChar`)
`MoveToTrash` プロシージャの中にある `shFile.pFrom = filePath & vbNullChar & vbNullChar` という記述。ここ、ものすごく重要です。
WindowsのC言語ベースのAPIは、文字列の終わりを「ゼロ(Null文字)」で判断します。VBAの文字列の末尾には通常これが含まれていないため、APIに渡すときは意図的にNull文字を2つ連結してメモリ破壊を防ぐ必要があります。理由が分からなくても、このお作法を守るだけでバグ知らずになりますよ。
3. パフォーマンスとリリースの美学
処理の冒頭で `Application.ScreenUpdating = False` をかけ、ファイルを処理するたびにきっちり `pptDoc.Close` と `Set pptDoc = Nothing` を行っています。
VBAにおけるオブジェクトの解放(メモリ掃除)を怠ると、大量のファイルを処理した際にメモリリークを起こし、PCの動作が極端に重くなります。使い終わったオブジェクトは速やかに解放する、これがプロの作法です。
—
ここをクリアすれば、PowerPoint VBAの基本はバッチリですよ!
いかがでしたでしょうか?
「ただファイルを操作するマクロ」から、「WindowsのOS機能まで手懐けたシステム構築」へのステップアップを感じていただけたなら嬉しいです。
- フォルダの自動生成(`MkDir` とパスの分解)
- 堅牢なエラーハンドリング(`On Error GoTo` と確実なオブジェクト解放)
- Windows API(`SHFileOperation`)による安全なゴミ箱送り
これらを自分のものにしたあなたなら、どんなに膨大なプレゼン資料の整理・変換依頼が来ても、涼しい顔で一瞬にして自動化ツールを組んでしまえるはずです。
業務を効率化する快感と、美しいコードを書く知的興奮を、ぜひ次の開発でも味わってくださいね。応援しています!
