概要
Excel VBAでブックを保存する際、指定した保存先フォルダが存在しないためにエラーが発生し、保存が中断されてしまうという経験はありませんか?特に、自動処理や定期的なバックアップ処理をVBAで行っている場合、この問題は深刻です。本記事では、保存先フォルダが存在しない場合に自動的にフォルダを作成し、その後、ブックを安全かつ確実に保存するためのExcel VBAコードと、その実装方法を徹底解説します。これにより、保存エラーに悩まされることなく、より堅牢な自動化処理を実現できます。
詳細解説
1. フォルダ存在チェックの重要性
VBAで`ThisWorkbook.SaveAs`や`ActiveWorkbook.SaveAs`メソッドを使用してブックを保存する際、`FilePath`引数に指定したパスのフォルダが存在しないと、実行時エラー(エラー番号1004)が発生します。このエラーは、特に以下のような状況で頻繁に遭遇します。
- 日別・月別など、日付をフォルダ名に含めて自動保存する場合
- 特定の処理結果を、その都度新規作成されるフォルダに保存する場合
- 共有サーバー上の特定の場所に保存するが、その場所がまだ作成されていない場合
これらのエラーを防ぎ、処理を円滑に進めるためには、保存処理の前に保存先フォルダの存在を確認し、存在しない場合は新規作成するロジックを組み込むことが不可欠です。
2. フォルダの存在をチェックする方法
VBAでフォルダの存在をチェックするには、主に以下の2つの方法があります。
a) Dir関数を使用する方法
`Dir`関数は、指定したパスにファイルまたはフォルダが存在するかどうかをチェックするために使用できます。フォルダパスを指定した場合、そのフォルダが存在すればフォルダ名が返され、存在しなければ空文字列を返します。
If Dir(FolderPath, vbDirectory) = “” Then
‘ フォルダは存在しない
Else
‘ フォルダは存在する
End If
`vbDirectory`引数を指定することで、ファイルではなくフォルダの存在をチェックしていることを明示します。
b) FileSystemObjectを使用する方法
`FileSystemObject` (FSO) は、ファイルやフォルダ、ドライブなどの操作をオブジェクト指向で行うための強力なオブジェクトです。FSOの`FolderExists`メソッドを使用すると、指定したフォルダパスが存在するかどうかを`True`または`False`で返します。
Dim FSO As Object
Set FSO = CreateObject(“Scripting.FileSystemObject”)
If FSO.FolderExists(FolderPath) Then
‘ フォルダは存在する
Else
‘ フォルダは存在しない
End If
Set FSO = Nothing ‘ オブジェクトの解放
`FileSystemObject`は、フォルダの作成や削除、コピーなど、より高度なファイル操作にも対応できるため、汎用性が高いです。
3. フォルダを作成する方法
フォルダを作成するには、以下の方法があります。
a) MkDirステートメントを使用する方法
VBAの組み込みステートメントである`MkDir`を使用すると、指定したパスのフォルダを作成できます。
MkDir FolderPath
このステートメントはシンプルで使いやすいですが、中間パスが存在しない場合(例:「C:\A\B\C」を作成しようとしたときに「C:\A」も「C:\A\B」も存在しない場合)はエラーとなります。
b) FileSystemObjectを使用する方法
`FileSystemObject`の`CreateFolder`メソッドを使用すると、中間パスも含めて一括でフォルダを作成できます。
Dim FSO As Object
Set FSO = CreateObject(“Scripting.FileSystemObject”)
FSO.CreateFolder FolderPath
Set FSO = Nothing ‘ オブジェクトの解放
`CreateFolder`メソッドは、`MkDir`よりも強力で、パスの途中のフォルダがなくても自動的に作成してくれるため、より安全にフォルダを作成できます。
4. フォルダ存在チェックと作成、そして保存を組み合わせる
これらの要素を組み合わせることで、目的の処理を実現します。ここでは、`FileSystemObject`を使用する方法を推奨します。なぜなら、フォルダの存在チェックと作成の両方に`FileSystemObject`を使用することで、コードが統一され、可読性と保守性が向上するためです。
**処理の流れ:**
- 保存したいブックのパスとファイル名を定義します。
- 保存先のフォルダパスを定義します。
- `FileSystemObject`を作成します。
- `FolderExists`メソッドでフォルダの存在を確認します。
- フォルダが存在しない場合、`CreateFolder`メソッドでフォルダを作成します。
- `SaveAs`メソッドでブックを保存します。
サンプルコード
ここでは、アクティブなブックを特定のフォルダに保存するVBAコード例を示します。フォルダが存在しない場合は自動的に作成されます。
Sub SaveWorkbookWithFolderCreation()
Dim savePath As String
Dim folderPath As String
Dim fileName As String
Dim FSO As Object
‘ — 設定項目 —
‘ 保存先のフォルダパスを指定します (例: C:\Backup\MonthlyReport)
folderPath = “C:\ExcelVBA_Backup\” & Format(Date, “yyyy-mm”) & “\”
‘ 保存するファイル名を指定します (例: 月次レポート_202310.xlsx)
‘ ここでは、ブック名と日付を組み合わせて動的に生成する例を示します
fileName = ThisWorkbook.Name & “_” & Format(Date, “yyyy-mm-dd”) & “.xlsm” ‘ ブックの拡張子に合わせて変更してください
‘ —————-
‘ フォルダパスとファイル名を結合して完全な保存パスを作成
savePath = folderPath & fileName
‘ FileSystemObjectを作成
On Error Resume Next ‘ エラーが発生しても続行
Set FSO = CreateObject(“Scripting.FileSystemObject”)
If Err.Number <> 0 Then
MsgBox “FileSystemObjectの作成に失敗しました。”, vbCritical
On Error GoTo 0 ‘ エラーハンドリングを元に戻す
Exit Sub
End If
On Error GoTo 0 ‘ エラーハンドリングを元に戻す
‘ フォルダが存在するかチェックし、存在しなければ作成
If Not FSO.FolderExists(folderPath) Then
On Error Resume Next ‘ フォルダ作成時のエラーを無視
FSO.CreateFolder folderPath
If Err.Number <> 0 Then
MsgBox “フォルダの作成に失敗しました: ” & folderPath & vbCrLf & _
“権限がないか、パスが長すぎる可能性があります。”, vbCritical
Set FSO = Nothing
Exit Sub
End If
On Error GoTo 0 ‘ エラーハンドリングを元に戻す
Debug.Print “フォルダを作成しました: ” & folderPath
Else
Debug.Print “フォルダは既に存在します: ” & folderPath
End If
‘ ブックを保存
On Error Resume Next ‘ 保存時のエラーを無視
ThisWorkbook.SaveAs Filename:=savePath, FileFormat:=xlOpenXMLWorkbookMacroEnabled ‘ ブックの形式に合わせてFileFormatを変更してください
If Err.Number <> 0 Then
MsgBox “ブックの保存に失敗しました: ” & savePath & vbCrLf & _
“ファイルが開かれていないか、権限がないか確認してください。”, vbCritical
Else
MsgBox “ブックを正常に保存しました: ” & savePath, vbInformation
Debug.Print “ブックを保存しました: ” & savePath
End If
On Error GoTo 0 ‘ エラーハンドリングを元に戻す
‘ FileSystemObjectを解放
Set FSO = Nothing
End Sub
**コードの解説:**
- `folderPath`変数: 保存したいフォルダのパスを指定します。ここでは、`C:\ExcelVBA_Backup\`という親フォルダの中に、`yyyy-mm`形式(例: `2023-10\`)で月ごとのサブフォルダを作成するように設定しています。
- `fileName`変数: 保存するファイル名を指定します。ここでは、元のブック名に日付を付加する形で動的に生成しています。`ThisWorkbook.Name`で現在開いているブックの名前を取得できます。
- `savePath`変数: `folderPath`と`fileName`を結合して、保存するブックの完全なパスを作成します。
- `Set FSO = CreateObject(“Scripting.FileSystemObject”)`: `FileSystemObject`を生成します。
- `If Not FSO.FolderExists(folderPath) Then`: `FolderExists`メソッドで、指定した`folderPath`が存在するかどうかを判定します。存在しない場合(`Not True`)、`Then`ブロック内の処理が実行されます。
- `FSO.CreateFolder folderPath`: `CreateFolder`メソッドでフォルダを作成します。このメソッドは、パスの途中のフォルダが存在しない場合でも、それらをすべて作成してくれます。
- `ThisWorkbook.SaveAs Filename:=savePath, FileFormat:=xlOpenXMLWorkbookMacroEnabled`: アクティブなブックを、指定した`savePath`に保存します。`FileFormat`引数は、保存するExcelのバージョンやマクロの有無に合わせて適切なものを指定してください。上記コードではマクロ有効ブック(`xlOpenXMLWorkbookMacroEnabled`)として保存する例です。
- `On Error Resume Next` / `On Error GoTo 0`: エラーハンドリングを適切に行うことで、予期せぬエラーが発生した場合でも処理が停止しないようにしています。特に、フォルダ作成やファイル保存時に権限の問題などでエラーが発生する可能性があるため、これらの処理を挟むことは重要です。エラー発生時には`MsgBox`でユーザーに通知するようにしています。
- `Debug.Print`: イミディエイトウィンドウに処理の状況を出力します。デバッグ時に役立ちます。
**注意点:**
- `folderPath`と`fileName`は、ご自身の環境や目的に合わせて必ず変更してください。
- `FileFormat`引数は、保存したいExcelのファイル形式に合わせて適切に指定してください。
- ネットワークドライブや共有フォルダに保存する場合、アクセス権限がないとエラーになることがあります。
- パスが長すぎるとエラーになる場合があります。
実務アドバイス
1. エラーハンドリングの強化
前述のサンプルコードでは`On Error Resume Next`を使用していますが、より詳細なエラーハンドリングを行うことを推奨します。例えば、フォルダ作成失敗時に具体的なエラーコードとメッセージを表示するなどです。
‘ フォルダ作成時のエラーハンドリング例
On Error GoTo ErrorHandler_CreateFolder
FSO.CreateFolder folderPath
‘ … 省略 …
Exit Sub ‘ 正常終了時はエラーハンドラをスキップ
ErrorHandler_CreateFolder:
MsgBox “フォルダの作成に失敗しました: ” & folderPath & vbCrLf & _
“エラー番号: ” & Err.Number & vbCrLf & “エラーメッセージ: ” & Err.Description, vbCritical
Set FSO = Nothing
Exit Sub
2. ログファイルの出力
保存処理の成功・失敗を記録するために、ログファイルを作成するのも有効な手段です。これにより、後から処理状況を確認したり、問題発生時の原因究明に役立てたりできます。
3. 保存先の柔軟性
保存先フォルダをハードコードするのではなく、ユーザーに入力させる、あるいは設定ファイルから読み込むようにすると、より汎用性の高いVBAコードになります。
4. バックアップ用途での活用
この機能は、重要なExcelブックの定期的なバックアップ処理に非常に役立ちます。日付や時刻をフォルダ名やファイル名に含めることで、バージョン管理も容易になります。
5. ネットワークパスへの対応
ネットワーク上の共有フォルダに保存する場合、UNCパス(例: `\\ServerName\ShareName\Folder`)を使用します。この場合も`FileSystemObject`は正常に動作しますが、アクセス権限の確認は必須です。
6. 複数ブックの保存
複数のブックをまとめて保存する場合、ループ処理で各ブックに対してこの「フォルダ存在チェック&保存」のロジックを適用します。
Dim wb As Workbook
Dim savePath As String
Dim folderPath As String
Dim fileName As String
Dim FSO As Object
Set FSO = CreateObject(“Scripting.FileSystemObject”)
‘ 例: 開いているすべてのブックを保存する場合
For Each wb In Workbooks
‘ 保存先フォルダとファイル名を定義(各ブックごとに条件を変えることも可能)
folderPath = “C:\BatchSave\” & Format(Date, “yyyy-mm”) & “\”
fileName = wb.Name & “_” & Format(Date, “yyyy-mm-dd”) & “.xlsx”
savePath = folderPath & fileName
‘ フォルダ存在チェック&作成
If Not FSO.FolderExists(folderPath) Then
On Error Resume Next
FSO.CreateFolder folderPath
If Err.Number <> 0 Then
MsgBox “フォルダ作成エラー: ” & folderPath, vbCritical
GoTo NextWorkbook ‘ 次のブックへ
End If
On Error GoTo 0
End If
‘ ブックの保存
On Error Resume Next
wb.SaveAs Filename:=savePath, FileFormat:=xlOpenXMLWorkbook ‘ マクロなしの場合
If Err.Number <> 0 Then
MsgBox “ブック保存エラー: ” & wb.Name & ” -> ” & savePath, vbCritical
Else
Debug.Print “保存完了: ” & savePath
End If
On Error GoTo 0
NextWorkbook:
Next wb
Set FSO = Nothing
MsgBox “全ブックの保存処理が完了しました。”, vbInformation
まとめ
Excel VBAでブックを保存する際に、保存先フォルダが存在しないという理由でエラーが発生することは、自動化処理の信頼性を損なう大きな原因となります。本記事で解説した`FileSystemObject`を活用した「フォルダ存在チェック&自動作成」のテクニックを習得することで、この問題を根本的に解決できます。
- `FileSystemObject`の`FolderExists`メソッドでフォルダの存在を確認する。
- `FileSystemObject`の`CreateFolder`メソッドでフォルダを新規作成する。
- これらの処理を`SaveAs`メソッドの前に挟むことで、安全かつ確実にブックを保存できる。
このコードは、日々の業務効率化はもちろん、重要なデータのバックアップや、定型的なレポート作成の自動化など、幅広いシーンで活用できます。ぜひ、ご自身の業務に合わせたカスタマイズを加えて、Excel VBAの可能性をさらに広げてください。エラーに強い、信頼性の高いVBAコード作成の一助となれば幸いです。
