目次
はじめに
複数のファイル名を一括で変更したいとき、手作業では時間がかかります。Excelシートにファイルパスと新しい名前を一覧で記載しておき、VBAで一括変換できると便利です。今回は、事前にしっかりバリデーション(データが適切かどうかを確認)を行い、安全にファイル名を変更するマクロを紹介します。
完成コード
まずは完成したコードをご覧ください。A列にファイルのフルパス、B列に変更後のファイル名を入力し、このマクロを実行すると一括でファイル名が変更されます。
Sub RenameFiles()
Dim ws As Worksheet
Dim lastRow As Long
Dim i As Long
Dim oldPath As String
Dim newName As String
Dim parentPath As String
Dim newPath As String
Dim fso As Scripting.FileSystemObject
Dim errorCount As Long
Dim successCount As Long
Dim validationErrors As String
Dim emptyRowCount As Long
Set fso = New Scripting.FileSystemObject
Set ws = ActiveSheet
errorCount = 0
successCount = 0
validationErrors = ""
emptyRowCount = 0
lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
If lastRow < 2 Then
MsgBox _
"データが見つかりません。A列にファイルパス、B列に新しい名前を入力してください。", _
vbExclamation
Exit Sub
End If
For i = 2 To lastRow
oldPath = Trim(ws.Cells(i, 1).Value)
newName = Trim(ws.Cells(i, 2).Value)
If oldPath = "" Then
If newName <> "" Then
validationErrors = validationErrors & "行" & i & _
": A列(ファイルパス)が空です" & vbCrLf
Else
emptyRowCount = emptyRowCount + 1
End If
ElseIf newName = "" Then
validationErrors = validationErrors & "行" & i & _
": B列(新しい名前)が空です" & vbCrLf
ElseIf Not (Mid(oldPath, 2, 2) = ":\" Or Left(oldPath, 2) = "\\") Then
validationErrors = validationErrors & "行" & i & _
": A列がフルパスではありません(例: C:\Folder\file.txt)" & vbCrLf
ElseIf ContainsInvalidChars(newName) Then
validationErrors = validationErrors & "行" & i & _
": B列に使用できない文字が含まれています(\ / : * ? "" < > |)" & _
vbCrLf
End If
Next i
If emptyRowCount = lastRow - 1 Then
MsgBox _
"データが入力されていません。A列にファイルパス、B列に新しい名前を入力してください。", _
vbExclamation
Exit Sub
End If
If validationErrors <> "" Then
MsgBox _
"以下のエラーを修正してください:" & vbCrLf & validationErrors, _
vbExclamation, "入力エラー"
Exit Sub
End If
If MsgBox( _
lastRow - 1 & "個のファイル名を変更します。よろしいですか?", _
vbYesNo + vbQuestion _
) = vbNo Then Exit Sub
End If
For i = 2 To lastRow
oldPath = Trim(ws.Cells(i, 1).Value)
newName = Trim(ws.Cells(i, 2).Value)
If oldPath <> "" And newName <> "" Then
If fso.FileExists(oldPath) Then
parentPath = fso.GetParentFolderName(oldPath)
If Right(parentPath, 1) = "\" Then
newPath = parentPath & newName
Else
newPath = parentPath & "\" & newName
End If
If fso.FileExists(newPath) Then
ws.Cells(i, 3).Value = "エラー: 同名のファイルが既に存在"
errorCount = errorCount + 1
Else
On Error Resume Next
fso.MoveFile oldPath, newPath
If Err.Number = 0 Then
ws.Cells(i, 3).Value = "成功"
successCount = successCount + 1
Else
ws.Cells(i, 3).Value = "エラー: " & Err.Description
errorCount = errorCount + 1
Err.Clear
End If
On Error GoTo 0
End If
Else
ws.Cells(i, 3).Value = "エラー: ファイルが見つかりません"
errorCount = errorCount + 1
End If
End If
Next i
MsgBox "処理完了" & vbCrLf & _
"成功: " & successCount & "個" & vbCrLf & _
"エラー: " & errorCount & "個" & vbCrLf & vbCrLf & _
"結果はC列に記載されています。", vbInformation
Set fso = Nothing
Set ws = Nothing
End Sub
Private Function ContainsInvalidChars(fileName As String) As Boolean
Dim invalidChars As Variant
Dim i As Long
invalidChars = Array("\", "/", ":", "*", "?", """", "<", ">", "|")
For i = LBound(invalidChars) To UBound(invalidChars)
If InStr(fileName, invalidChars(i)) > 0 Then
ContainsInvalidChars = True
Exit Function
End If
Next i
ContainsInvalidChars = False
End Function
コードの解説
このマクロは大きく3つのフェーズ(段階)に分かれています。それぞれのフェーズを順番に見ていきます。
【フェーズ1】データの取得と初期チェック
最初に、Excelシートからデータの範囲を取得します。lastRow変数で最終行を特定し、2行目以降にデータがあるかを確認しています。
lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
If lastRow < 2 Then
MsgBox "データが見つかりません。", vbExclamation
Exit Sub
End If
1行目は見出し行と想定しているため、2行目未満ならデータなしと判断します。End(xlUp)は、ExcelでCtrl + ↑を押したときと同じ動作で、データがある最後の行を見つけてくれます。
【フェーズ2】全行のバリデーション
実際にファイル名を変更する前に、すべての行をチェックして問題がないか確認します。これにより、処理の途中で予期しないエラーが起きるのを防げます。
For i = 2 To lastRow
oldPath = Trim(ws.Cells(i, 1).Value)
newName = Trim(ws.Cells(i, 2).Value)
If oldPath = "" Then
If newName <> "" Then
validationErrors = validationErrors & "行" & i & _
": A列(ファイルパス)が空です" & vbCrLf
Else
emptyRowCount = emptyRowCount + 1
End If
ElseIf newName = "" Then
validationErrors = validationErrors & "行" & i & _
": B列(新しい名前)が空です" & vbCrLf
End If
Next i
空行(A列もB列も空)は無視し、片方だけ入力されている場合はエラーとして記録します。Trim関数で前後の空白を削除しているので、スペースだけの入力も空欄として扱われます。
【フェーズ3】ファイル名の変更処理
バリデーションを通過したら、実際にファイル名を変更します。FileSystemObjectのMoveFileメソッドを使用しており、これは名前変更だけでなく移動にも使えるメソッドです。
fso.MoveFile oldPath, newPath
処理結果はC列に記録されるため、後から確認できます。成功した行とエラーが出た行が一目で分かります。
バリデーションの仕組み
このマクロでは4種類のバリデーションを行っています。それぞれの仕組みを詳しく見ていきます。
【空欄チェック】
A列とB列のどちらかが空の場合、エラーとして記録されます。両方空の場合は単なる空行として扱い、エラーにはなりません。
If oldPath = "" Then
If newName <> "" Then
validationErrors = validationErrors & "行" & i & _
": A列が空です" & vbCrLf
Else
emptyRowCount = emptyRowCount + 1
End If
この処理により、「B列だけ入力してA列を忘れた」といったミスを防げます。emptyRowCountで空行の数を数えておき、全行が空行だった場合は専用のメッセージを表示します。
【フルパスチェック】
相対パス(例: Folder\file.txt)ではなく、絶対パス(例: C:\Folder\file.txt)が入力されているかをチェックします。
ElseIf Not (Mid(oldPath, 2, 2) = ":\" Or Left(oldPath, 2) = "\\") Then
validationErrors = validationErrors & "行" & i & _
": フルパスではありません" & vbCrLf
C:\のような形式か、\\server\のようなUNCパス(ネットワークパス)であるかを判定しています。Mid(oldPath, 2, 2)で2文字目から2文字分、つまり:\の部分を取り出して確認しています。
【無効な文字チェック】
Windowsのファイル名には使用できない文字があります。これらが含まれていないか、専用の関数ContainsInvalidCharsでチェックしています。
invalidChars = Array("\", "/", ":", "*", "?", """", "<", ">", "|")
For i = LBound(invalidChars) To UBound(invalidChars)
If InStr(fileName, invalidChars(i)) > 0 Then
ContainsInvalidChars = True
Exit Function
End If
Next i
これらの文字が1つでも含まれていればTrueを返し、エラーとして記録されます。InStr関数は文字列の中に特定の文字が含まれているかを調べる関数で、見つかった位置を返します。見つからない場合は0を返すので、> 0で判定しています。
【ファイルの存在チェックと重複チェック】
実際の変更処理の中で、変更元のファイルが存在するか、変更先に同名のファイルが既にないかをチェックしています。
If fso.FileExists(oldPath) Then
If fso.FileExists(newPath) Then
ws.Cells(i, 3).Value = "エラー: 同名のファイルが既に存在"
Else
fso.MoveFile oldPath, newPath
End If
Else
ws.Cells(i, 3).Value = "エラー: ファイルが見つかりません"
End If
これにより、誤って既存のファイルを上書きしてしまうことを防げます。FileExistsメソッドは、指定したパスにファイルが存在するかをTrueまたはFalseで返してくれます。
参照設定について
このコードではScripting.FileSystemObjectを使用しています。これを使うには参照設定が必要です。
参照設定を行うメリットは、コードの実行速度が速くなることと、IntelliSense(入力補完機能)が使えることです。CreateObjectを使う方法もありますが、参照設定の方が型の安全性が高く、初心者には分かりやすいです。
参照設定の方法は以下の記事で解説しています。
参照設定を行うと、fso.と入力したときに使えるメソッドの一覧が自動で表示されます。これがあると、どんな機能が使えるのかが分かりやすくなります。
まとめ
ファイルの一括リネームでは、事前のバリデーションが重要です。全行をチェックしてからまとめて処理することで、途中でエラーが起きて中途半端な状態になるのを防げます。参照設定を使ったFileSystemObjectは、ファイル操作を安全に行うための便利なツールです。