【入門編】【中級者】FSOを駆使し、指定フォルダ以下のサブフォルダ構造を完全維持したまま、内部のすべてのPPTXファイルを一括でPDFへ変換・配置する階層維持エクスポートツール – PowerPoint VBA解析バイブル

スポンサーリンク

フォルダ構造をそのままに!FSOでPowerPointファイルを一括PDF変換する裏技(階層維持エクスポートツール)

こんにちは!PowerPoint VBAの世界へようこそ。
今回は、皆さんが日頃から「こんなの自動化できたらな…」と夢見ているであろう、あの面倒なファイル操作を劇的に効率化するテクニックをご紹介します。

「マクロの記録」でできることは一通り試したけど、もっと複雑な処理をVBAで実現したい。
特に、たくさんのPowerPointファイルがサブフォルダに散らばっていて、それをまとめてPDFにしたい。しかも、元のフォルダ構造を崩さずに、きれいに整理された状態で出力したい!

そんな悩みを抱えているあなたのために、今回は FileSystemObject(FSO) という強力なツールを使いこなして、指定したフォルダ以下のすべてのPPTXファイルを、そのサブフォルダ構造を維持したまま、指定した別のフォルダへPDFとして一括変換・配置する、まさに「階層維持エクスポートツール」を作成します。

このツールが完成すれば、

  • 大量のPowerPointファイルを、手作業で一つずつ開いてPDF保存する手間がゼロに!
  • 元のフォルダ構造がそのまま再現されるので、成果物の管理が格段に楽に!
  • 「マクロの記録」では実現できない、一歩進んだVBAの活用法が身につく!

という、まさに「魔法」のような体験ができるはずです。

さあ、一緒にPowerPoint VBAの奥深い世界へ踏み込み、この強力なツールをあなたのものにしましょう!

—

なぜFileSystemObject(FSO)を使うのか? – ファイル操作の「裏方」を理解する

PowerPoint VBAだけでもファイル操作は可能ですが、フォルダの作成、ファイルのコピー、移動、削除、そしてフォルダ構造の走査といった、より高度なファイル・フォルダ操作を効率的に行うためには、FileSystemObject(FSO) の存在が欠かせません。

FSOは、Windowsのファイルシステムを操作するための「オブジェクト」です。
例えるなら、PowerPoint VBAが「PowerPointという建物を建てるための道具」だとすると、FSOは「その建物を建てる土地(フォルダ)を整地したり、資材(ファイル)を運んだりする重機」のようなものです。

FSOの魅力:

  • 直感的で分かりやすいメソッド: `CreateFolder`(フォルダ作成)、`CopyFile`(ファイルコピー)、`DeleteFolder`(フォルダ削除)など、名前を見ただけで何をするか想像しやすいメソッドが豊富です。
  • フォルダ構造の走査が得意: `GetFolder`メソッドでフォルダオブジェクトを取得し、その中のファイルやサブフォルダを順番に処理していくことができます。これが、今回のような「サブフォルダ構造を維持する」処理に非常に役立ちます。
  • VBScriptでも標準で利用可能: PowerPoint VBAだけでなく、Windowsのスクリプト言語であるVBScriptでも標準で利用できるため、汎用性が高いです。

FSOのライフサイクル:

FSOは、利用する際に「インスタンス化」という作業が必要です。これは、「FSOという重機を現場に呼び出す」イメージです。

‘ FSOオブジェクトを作成する
Dim objFSO As Object
Set objFSO = CreateObject(“Scripting.FileSystemObject”)

‘ FSOオブジェクトを使い終わったら解放する(メモリの節約)
Set objFSO = Nothing

`CreateObject(“Scripting.FileSystemObject”)` でFSOの機能を使えるようになり、`Set objFSO = Nothing` で解放します。これは、オブジェクト指向プログラミングの基本であり、リソースの無駄遣いを防ぐために重要です。特に、ループ処理などで繰り返しFSOオブジェクトを生成・解放するのはパフォーマンスに影響を与える可能性があるため、通常は処理の最初で一度だけ作成し、最後に解放するのが定石です。

—

階層維持エクスポートツールの全体像を掴む

さて、いよいよ本題の「階層維持エクスポートツール」の全体像を見ていきましょう。

このツールがやることは、大きく分けて以下の3ステップです。

1. 元となるフォルダ(ソースフォルダ)と、PDFの出力先フォルダ(デスティネーションフォルダ)を指定する。
2. ソースフォルダを起点に、その中のすべてのサブフォルダとファイルを再帰的に(子フォルダの中もずっと)探索する。
3. 探索で見つかったPowerPointファイル(.pptx)を、PowerPointアプリケーションを介してPDFに変換する。
4. 変換したPDFファイルを、ソースフォルダでの元の位置と同じ階層構造を維持しながら、デスティネーションフォルダに配置する。

これを実現するために、FSOの「フォルダ構造を走査する能力」と、PowerPoint VBAの「ファイルをPDFとして保存する能力」を組み合わせます。

開発のポイント:

  • 再帰処理: サブフォルダの中にもさらにサブフォルダがあるような、入れ子構造を処理するために「再帰処理」というテクニックを使います。これは、ある処理の中で、自分自身を呼び出すことで、階層を深く掘り下げていく方法です。
  • パスの操作: ファイルやフォルダのパス(場所を示す文字列)を正確に扱うことが非常に重要です。FSOのメソッドを駆使して、ソースフォルダとデスティネーションフォルダのパスを組み合わせて、正しい場所にファイルを配置します。
  • エラーハンドリング: ファイルが見つからなかったり、保存権限がなかったり…といった予期せぬ事態に備えて、エラー処理を組み込むことで、ツールの安定性を高めます。

—

実践! VBAコードで実現する階層維持エクスポートツール

それでは、いよいよ実際のVBAコードを見ていきましょう。
まずは、このツールの中核となる、フォルダ構造を走査してPDF変換を行うメインのプロシージャです。

コード例1:メイン処理(フォルダ走査とPDF変換)

Sub ExportAllPPTXAsPDF_WithHierarchy()

‘ — 設定項目 —
Const SOURCE_FOLDER_PATH As String = “C:\Users\YourUser\Documents\SourcePresentations” ‘ ★★★ ここをあなたのソースフォルダパスに変更してください ★★★
Const DESTINATION_FOLDER_PATH As String = “C:\Users\YourUser\Documents\ExportedPDFs” ‘ ★★★ ここをあなたの出力先フォルダパスに変更してください ★★★
‘ —————-

Dim objFSO As Object ‘ FileSystemObject
Dim objSourceFolder As Object ‘ ソースフォルダを表すオブジェクト
Dim objDestFolder As Object ‘ デスティネーションフォルダを表すオブジェクト
Dim pptApp As PowerPoint.Application ‘ PowerPointアプリケーションオブジェクト

‘ PowerPointアプリケーションオブジェクトの準備
On Error Resume Next ‘ 既にPowerPointが起動している場合のエラーを無視
Set pptApp = GetObject(, “PowerPoint.Application”)
If pptApp Is Nothing Then ‘ PowerPointが起動していない場合は新規作成
Set pptApp = CreateObject(“PowerPoint.Application”)
‘ PowerPointを非表示にする(ユーザーに意識させないため)
pptApp.Visible = msoFalse
End If
On Error GoTo 0 ‘ エラーハンドリングを元に戻す

‘ FileSystemObjectのインスタンスを作成
Set objFSO = CreateObject(“Scripting.FileSystemObject”)

‘ — フォルダの存在チェックと作成 —
‘ ソースフォルダが存在するかチェック
If Not objFSO.FolderExists(SOURCE_FOLDER_PATH) Then
MsgBox “指定されたソースフォルダが見つかりません:” & vbCrLf & SOURCE_FOLDER_PATH, vbCritical, “エラー”
GoTo CleanExit ‘ 処理を終了
End If

‘ デスティネーションフォルダが存在しない場合は作成
If Not objFSO.FolderExists(DESTINATION_FOLDER_PATH) Then
On Error Resume Next ‘ フォルダ作成時のエラーを無視
objFSO.CreateFolder DESTINATION_FOLDER_PATH
If Err.Number <> 0 Then
MsgBox “デスティネーションフォルダを作成できませんでした:” & vbCrLf & DESTINATION_FOLDER_PATH, vbCritical, “エラー”
Err.Clear
GoTo CleanExit ‘ 処理を終了
End If
On Error GoTo 0 ‘ エラーハンドリングを元に戻す
End If

‘ — メイン処理:フォルダ構造の走査とPDF変換 —
‘ 開始メッセージ
Debug.Print “— PDFエクスポート処理を開始します —”
Debug.Print “ソースフォルダ: ” & SOURCE_FOLDER_PATH
Debug.Print “デスティネーションフォルダ: ” & DESTINATION_FOLDER_PATH

‘ 再帰処理を開始するための初期呼び出し
‘ ここで、ソースフォルダオブジェクトと、それに対応するデスティネーションフォルダオブジェクトを渡します。
Call ProcessFolder(objFSO, SOURCE_FOLDER_PATH, DESTINATION_FOLDER_PATH, pptApp)

‘ 完了メッセージ
MsgBox “すべてのPPTXファイルのPDF変換が完了しました!”, vbInformation, “完了”

CleanExit:
‘ — 後処理 —
‘ PowerPointアプリケーションオブジェクトの解放
‘ もし、このマクロがPowerPointを起動させた場合は終了させる(オプション)
‘ If Not pptApp Is Nothing And pptApp.Presentations.Count = 0 Then
‘ pptApp.Quit
‘ End If
Set pptApp = Nothing

‘ FSOオブジェクトの解放
Set objFSO = Nothing
Debug.Print “— PDFエクスポート処理を終了します —”

End Sub

‘ — 再帰的にフォルダを処理するサブルーチン —
Private Sub ProcessFolder(objFSO As Object, ByVal currentSourceFolderPath As String, ByVal currentDestinationFolderPath As String, ByVal pptApp As PowerPoint.Application)

Dim objCurrentFolder As Object ‘ 現在処理中のフォルダオブジェクト
Dim objFile As Object ‘ フォルダ内のファイルオブジェクト
Dim objSubFolder As Object ‘ フォルダ内のサブフォルダオブジェクト
Dim pptPresentation As Presentation ‘ PowerPointプレゼンテーションオブジェクト
Dim sourceFilePath As String ‘ ソースファイルのフルパス
Dim destinationFilePath As String ‘ 保存するPDFのフルパス
Dim fileNameWithoutExtension As String ‘ 拡張子なしのファイル名

‘ 現在のソースフォルダオブジェクトを取得
Set objCurrentFolder = objFSO.GetFolder(currentSourceFolderPath)

‘ — フォルダ内のファイルを処理 —
For Each objFile In objCurrentFolder.Files
‘ PowerPointファイル (.pptx) のみ対象とする
If LCase(objFSO.GetExtensionName(objFile.Name)) = “pptx” Then

sourceFilePath = objFile.Path ‘ ソースファイルのフルパスを取得

‘ 拡張子を除いたファイル名を取得
fileNameWithoutExtension = objFSO.GetBaseName(objFile.Name)

‘ 保存するPDFのフルパスを作成(デスティネーションフォルダ + 元のファイル名.pdf)
destinationFilePath = objFSO.BuildPath(currentDestinationFolderPath, fileNameWithoutExtension & “.pdf”)

‘ ★★★ PowerPointで開いてPDFとして保存する処理 ★★★
On Error Resume Next ‘ ファイルを開けない、保存できない場合のエラーを捕捉
Debug.Print “処理中: ” & sourceFilePath & ” -> ” & destinationFilePath

‘ PowerPointでプレゼンテーションを開く
Set pptPresentation = pptApp.Presentations.Open(sourceFilePath, WithWindow:=msoFalse) ‘ ウィンドウは非表示で開く

If Err.Number = 0 Then ‘ 正常に開けた場合
‘ PDFとしてエクスポート(保存)
‘ ExportAsFixedFormatメソッドの引数はPowerPointのバージョンによって若干異なる場合があります。
‘ 以下の例は一般的なものです。
pptPresentation.ExportAsFixedFormat destinationFilePath, ppFixedFormatTypePDF, ppFixedFormatQualityPrint
‘ ppFixedFormatQualityPrint は印刷品質、ppFixedFormatQualityScreen は画面表示品質です。必要に応じて変更してください。

If Err.Number <> 0 Then
Debug.Print ” [エラー] PDFとして保存できませんでした。Error: ” & Err.Description
Err.Clear
Else
Debug.Print ” [完了] PDFとして保存しました。”
End If

‘ 開いたプレゼンテーションを閉じる(変更は保存しない)
pptPresentation.Close
Else
Debug.Print ” [エラー] PowerPointファイルを開けませんでした。Error: ” & Err.Description
Err.Clear
End If
On Error GoTo 0 ‘ エラーハンドリングを元に戻す

‘ PowerPointプレゼンテーションオブジェクトの解放
Set pptPresentation = Nothing
End If
Next objFile

‘ — サブフォルダを再帰的に処理 —
For Each objSubFolder In objCurrentFolder.SubFolders
‘ 新しいデスティネーションフォルダパスを作成
‘ (元のデスティネーションフォルダパス + サブフォルダ名)
Dim newDestinationFolderPath As String
newDestinationFolderPath = objFSO.BuildPath(currentDestinationFolderPath, objSubFolder.Name)

‘ デスティネーションフォルダ内に、ソースフォルダと同じ名前のサブフォルダが存在しない場合は作成
If Not objFSO.FolderExists(newDestinationFolderPath) Then
On Error Resume Next ‘ フォルダ作成時のエラーを無視
objFSO.CreateFolder newDestinationFolderPath
If Err.Number <> 0 Then
Debug.Print ” [エラー] サブフォルダを作成できませんでした: ” & newDestinationFolderPath & ” Error: ” & Err.Description
Err.Clear
Else
Debug.Print ” [作成] フォルダを作成しました: ” & newDestinationFolderPath
End If
On Error GoTo 0 ‘ エラーハンドリングを元に戻す
End If

‘ 再帰呼び出し:サブフォルダに対して同じ処理を繰り返す
Call ProcessFolder(objFSO, objSubFolder.Path, newDestinationFolderPath, pptApp)
Next objSubFolder

‘ オブジェクトの解放
Set objCurrentFolder = Nothing

End Sub

コード解説:ここをクリアすれば、基本はバッチリ!

  • `Const SOURCE_FOLDER_PATH As String = “…”`:
  • ここが一番重要!PDFにしたいPowerPointファイルが入っているフォルダのパスを指定します。`”C:\Users\YourUser\Documents\SourcePresentations”` の部分を、あなたの環境に合わせて正確に入力してください。
  • `Const` は「定数」宣言で、一度決めるとコード内で変更できません。
  • `Const DESTINATION_FOLDER_PATH As String = “…”`:
  • 変換されたPDFファイルを保存したいフォルダのパスを指定します。こちらもあなたの環境に合わせて変更してください。
  • `Dim pptApp As PowerPoint.Application`:
  • PowerPointアプリケーションそのものを操作するためのオブジェクトです。
  • `GetObject(, “PowerPoint.Application”)` で、もし既にPowerPointが起動していたら、そのインスタンスを取得します。
  • `CreateObject(“PowerPoint.Application”)` で、起動していなければ新しくPowerPointを起動します。
  • `pptApp.Visible = msoFalse` で、PowerPointのウィンドウを非表示にします。ユーザーはバックグラウンドで処理が進むことに気づきません。
  • `Set objFSO = CreateObject(“Scripting.FileSystemObject”)`:
  • FileSystemObject(FSO)のインスタンスを作成します。これで、ファイルやフォルダを操作する準備が整いました。
  • `If Not objFSO.FolderExists(SOURCE_FOLDER_PATH) Then …`:
  • 指定されたソースフォルダが存在するかどうかを確認しています。もし存在しなければ、エラーメッセージを表示して処理を中断します。
  • `If Not objFSO.FolderExists(DESTINATION_FOLDER_PATH) Then …`:
  • 指定されたデスティネーションフォルダが存在しない場合、`objFSO.CreateFolder` で自動的に作成します。
  • `Call ProcessFolder(…)`:
  • これが「再帰処理」の入り口です。`ProcessFolder`という名前のサブルーチン(別のプロシージャ)を呼び出しています。
  • この `ProcessFolder` の中で、さらに自分自身を呼び出すことで、サブフォルダの中身も処理していくのです。
  • `Private Sub ProcessFolder(…)`:
  • これが、フォルダ構造を走査して、ファイル処理とサブフォルダ処理を行う「心臓部」です。
  • `objFSO.GetFolder(currentSourceFolderPath)` で、現在処理しているフォルダのオブジェクトを取得します。
  • `For Each objFile In objCurrentFolder.Files`:
  • 現在のフォルダ内にあるすべてのファイルについて、ループ処理を行います。
  • `If LCase(objFSO.GetExtensionName(objFile.Name)) = “pptx” Then`:
  • ファイル名から拡張子を取り出し(`GetExtensionName`)、それを小文字(`LCase`)に変換して、`”pptx”` と一致するかどうかをチェックしています。こうすることで、`.PPTX` や `.Pptx` といった大文字小文字の違いも吸収できます。
  • `fileNameWithoutExtension = objFSO.GetBaseName(objFile.Name)`:
  • ファイル名から拡張子を取り除いた部分(例: “MyPresentation”)を取得します。
  • `destinationFilePath = objFSO.BuildPath(currentDestinationFolderPath, fileNameWithoutExtension & “.pdf”)`:
  • `BuildPath` は、フォルダパスとファイル名を結合して、完全なパス文字列を作成してくれる便利なメソッドです。ここでは、出力先のフォルダパスに、拡張子を`.pdf`にしたファイル名をつけて、PDFの保存先パスを生成しています。
  • `Set pptPresentation = pptApp.Presentations.Open(sourceFilePath, WithWindow:=msoFalse)`:
  • PowerPointアプリケーション(`pptApp`)を使って、PowerPointファイルを開きます。`WithWindow:=msoFalse` は、PowerPointのウィンドウを表示しない設定です。
  • `pptPresentation.ExportAsFixedFormat destinationFilePath, ppFixedFormatTypePDF, ppFixedFormatQualityPrint`:
  • ここがPDF変換の核心部分!`ExportAsFixedFormat` メソッドを使って、指定したパス(`destinationFilePath`)にPDF形式(`ppFixedFormatTypePDF`)でエクスポート(保存)します。`ppFixedFormatQualityPrint` は、印刷品質で保存することを意味します。
  • `pptPresentation.Close`:
  • 開いたプレゼンテーションを閉じます。`SaveChanges:=ppSaveFalse` が省略されていますが、`ExportAsFixedFormat` は通常、元のファイルを変更しないため、明示的に指定しなくても大丈夫です。
  • `For Each objSubFolder In objCurrentFolder.SubFolders`:
  • 現在のフォルダ内にあるすべてのサブフォルダについて、ループ処理を行います。
  • `newDestinationFolderPath = objFSO.BuildPath(currentDestinationFolderPath, objSubFolder.Name)`:
  • デスティネーションフォルダのパスに、サブフォルダの名前を付け加えて、新しい出力先フォルダパスを作成します。
  • `If Not objFSO.FolderExists(newDestinationFolderPath) Then objFSO.CreateFolder newDestinationFolderPath`:
  • もし、この新しい出力先フォルダが存在しなければ、作成します。これにより、ソースフォルダの階層構造がそのまま再現されます。
  • `Call ProcessFolder(objFSO, objSubFolder.Path, newDestinationFolderPath, pptApp)`:
  • ここが再帰処理の肝! サブフォルダに対して、`ProcessFolder` プロシージャ自身を再度呼び出しています。これにより、子フォルダ、孫フォルダ…と、どこまでも深くフォルダ構造をたどって処理を続けることができるのです。
  • `On Error Resume Next` / `On Error GoTo 0`:
  • これは「エラーハンドリング」という、VBAプログラミングで非常に重要なテクニックです。
  • `On Error Resume Next` の行以降でエラーが発生した場合、そのエラーを無視して次の行に進みます。
  • `On Error GoTo 0` で、通常のエラーハンドリングに戻します。
  • ファイルが開けない、保存権限がない、といった予期せぬ状況でマクロが止まってしまうのを防ぎ、処理を継続させるために使います。エラーが発生した場合は、`Debug.Print` でメッセージを出力するようにしているので、後で原因を特定するのに役立ちます。

陥りやすいエラーとその対策

  • パスの指定ミス:
  • 原因: ソースフォルダやデスティネーションフォルダのパスが間違っている。存在しないフォルダを指定している。
  • 対策: コード内の `Const` で定義されているパスを、コピー&ペーストで正確に入力し直す。フォルダパスの末尾に `\` を含めるかどうかで挙動が変わることがあるので、一貫性を持たせる。
  • ファイルを開く・保存する権限の問題:
  • 原因: 指定したフォルダへの書き込み権限がない。ファイルが他のアプリケーションで開かれている(ロックされている)。
  • 対策: エラーハンドリング `On Error Resume Next` を適切に使う。もし可能であれば、管理者権限でExcel/PowerPointを実行してみる。
  • PowerPointのバージョンによるメソッドの違い:
  • 原因: `ExportAsFixedFormat` メソッドの引数や挙動は、PowerPointのバージョンによって微妙に異なることがあります。
  • 対策: 念のため、ご自身のPowerPointバージョンで `ExportAsFixedFormat` のヘルプ(VBAエディターでF1キーを押す)を確認しておくと安心です。
  • 大量のファイル処理によるメモリ不足・処理時間:
  • 原因: 数百、数千といった大量のファイルを一度に処理しようとすると、PCのメモリが不足したり、処理に非常に時間がかかったりすることがあります。
  • 対策:
  • 一度に処理するフォルダを分割する。
  • `Debug.Print` で進捗状況を確認できるようにしておく。
  • `ExportAsFixedFormat` の品質設定を `ppFixedFormatQualityScreen` (画面表示品質)に変更すると、処理速度が向上する場合があります。
  • 可能であれば、処理中は他の重いアプリケーションを終了させる。

—

開発環境の準備と実行方法

1. PowerPointを開く: まず、PowerPointを起動します。
2. VBAエディターを開く: `Alt + F11` キーを押して、VBAエディター(Microsoft Visual Basic for Applications)を開きます。
3. 標準モジュールの挿入: VBAエディターのメニューで「挿入」→「標準モジュール」を選択します。
4. コードの貼り付け: 右側の白いコードウィンドウに、上記で提示したVBAコード(`Sub ExportAllPPTXAsPDF_WithHierarchy()` から `End Sub` まで)をすべてコピーして貼り付けます。
5. パスの編集: コード内の `Const SOURCE_FOLDER_PATH` と `Const DESTINATION_FOLDER_PATH` の値を、あなたの環境に合わせて正確に編集します。
6. 実行: VBAエディターのメニューで「実行」→「Sub/ユーザーフォームの実行」(または `F5` キー)を選択します。または、Excelの「開発」タブ(表示されていない場合は、Excelのオプションから表示させる必要があります)にある「マクロ」ボタンから、`ExportAllPPTXAsPDF_WithHierarchy` を選択して実行します。

実行前に、必ずバックアップを取ることを強くお勧めします!

—

まとめ:PowerPoint VBAとFSOで、あなたの業務は劇的に変わる!

いかがでしたでしょうか?
今回は、FileSystemObject(FSO)を駆使して、PowerPointファイルをフォルダ構造を維持したまま一括PDF変換する、実践的なツールを作成しました。

このコードを理解し、実際に動かすことができれば、あなたはもう「マクロの記録」レベルを卒業し、PowerPoint VBAの自動化の扉を大きく開いたと言えるでしょう。

  • FSO を使うことで、ファイルやフォルダ操作の幅が格段に広がることを実感できたはずです。
  • 再帰処理 の考え方を理解することで、複雑な階層構造を持つデータも効率的に扱えるようになります。
  • エラーハンドリング の重要性を学び、より堅牢なマクロを作成するための基礎を固めました。

今回ご紹介したコードは、あくまで一例です。
例えば、

  • PDFの保存品質を変える。
  • 特定のフォルダやファイル名を除外する条件を追加する。
  • 処理の進捗状況をメッセージボックスやステータスバーで表示する。
  • Excelのシートからソースフォルダやデスティネーションフォルダのパスを読み込むようにする。

など、あなたのニーズに合わせて自由にカスタマイズしていくことで、さらに強力なツールへと進化させることができます。

PowerPoint VBAの世界は、まだまだ奥深く、可能性に満ちています。
今回学んだ知識を活かして、ぜひあなたの業務をさらに効率化し、よりクリエイティブな仕事に時間を費やせるようにしていきましょう!

もし、この解説で「ここがもっと知りたい!」「こんな機能を追加したい!」といった疑問や要望があれば、ぜひコメントで教えてくださいね。皆さんのPowerPoint VBAライフを、これからも応援しています!

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