VBAでファイルやフォルダを操作する方法は、VBAに最初から入っている命令(Dir・MkDir・FileCopy・Name・Kill・RmDir)を使う方法と、FileSystemObject(FSO)を使う方法の2つです。 単体のファイルを1つ扱うだけなら標準の命令が短く書け、サブフォルダをたどる・フォルダごとコピーする・更新日時やサイズを調べるといった操作は FileSystemObject が向いています。

この記事では、存在確認・一覧取得・作成・コピー・移動・名前変更・削除の7つの操作を、2つの方法で並べた対応早見表と、そのまま貼れるコードで整理します。

確認環境:Windows 版 Excel の VBA を前提に、ファイル操作の命令とメソッドの構文・引数・注意書きを Microsoft Learn の VBA リファレンス(2026年10月5日閲覧)と照合して書いています。コードは標準モジュールに貼る形で、画面の出力例は載せていません。パスの C:\work は、手元のフォルダーに置き換えてください。

VBA標準とFileSystemObjectの対応早見表

fso は FileSystemObject の変数です(作り方は次の章)。

操作 VBA標準 FileSystemObject
ファイルの存在確認 Dir(パス) <> "" fso.FileExists(パス)
フォルダーの存在確認 (GetAttr(パス) And vbDirectory) = vbDirectory fso.FolderExists(パス)
ファイル一覧の取得 Dir(パス\*.xlsx) → Dir() を繰り返す For Each f In fso.GetFolder(パス).Files
サブフォルダーの一覧 Dir(パス\*, vbDirectory) と GetAttr For Each d In fso.GetFolder(パス).SubFolders
フォルダーの作成 MkDir パス fso.CreateFolder パス
ファイルのコピー FileCopy 元, 先 fso.CopyFile 元, 先, 上書き
フォルダーのコピー (該当する命令なし) fso.CopyFolder 元, 先, 上書き
ファイルの移動 Name 元 As 先 fso.MoveFile 元, 先
フォルダーの移動 Name 元 As 先(同じドライブ内) fso.MoveFolder 元, 先
名前の変更 Name 元 As 先 fso.GetFile(パス).Name = "新しい名前"
ファイルの削除 Kill パス fso.DeleteFile パス, 強制
フォルダーの削除 RmDir パス(空のフォルダーのみ) fso.DeleteFolder パス, 強制(中身ごと)
拡張子の取り出し (文字列関数で切り出す) fso.GetExtensionName(パス)
更新日時・サイズ - f.DateLastModified、f.Size

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「VBAファイル・フォルダ操作|DirとFileSystemObject早見表」

FileSystemObjectの準備(参照設定とCreateObject)

FileSystemObject を使う書き方は2通りあります。

CreateObjectで作る(設定なしで動く書き方)

Sub UseFsoLateBinding()
    Dim fso As Object
    Set fso = CreateObject("Scripting.FileSystemObject")

    MsgBox fso.FolderExists("C:\work")
End Sub

参照設定をして型を指定する

VBE の[ツール]→[参照設定]で「Microsoft Scripting Runtime」にチェックを入れると、型を指定して宣言できます。

Sub UseFsoEarlyBinding()
    Dim fso As Scripting.FileSystemObject
    Set fso = New Scripting.FileSystemObject

    MsgBox fso.FolderExists("C:\work")
End Sub
比べる点 CreateObject 参照設定
事前の設定 不要 ブックごとに参照設定が必要
宣言 Dim fso As Object Dim fso As Scripting.FileSystemObject
入力候補の表示 出ない 出る
向いている場面 ほかの人に配るブック 自分で書き進めるとき

この記事のコードは、貼るだけで使えるように CreateObject の形で統一しています。 参照設定をした場合は、As Object を As Scripting.FileSystemObject、As Scripting.Folder、As Scripting.File に置き換えられます。

存在を確認する

ファイルがあるか

' VBA標準
Function FileExistsStd(ByVal filePath As String) As Boolean
    FileExistsStd = (Dir(filePath) <> "")
End Function

' FileSystemObject
Function FileExistsFso(ByVal filePath As String) As Boolean
    FileExistsFso = CreateObject("Scripting.FileSystemObject").FileExists(filePath)
End Function

Dir は、見つかったファイルの名前を返し、見つからないときは長さ0の文字列("")を返します。

フォルダーがあるか

' VBA標準:GetAttr の戻り値にフォルダーの属性が含まれるかを調べる
Function FolderExistsStd(ByVal folderPath As String) As Boolean
    On Error Resume Next
    FolderExistsStd = ((GetAttr(folderPath) And vbDirectory) = vbDirectory)
    On Error GoTo 0
End Function

' FileSystemObject
Function FolderExistsFso(ByVal folderPath As String) As Boolean
    FolderExistsFso = CreateObject("Scripting.FileSystemObject").FolderExists(folderPath)
End Function

GetAttr は属性の合計値を返すので、And vbDirectory でフォルダーの属性(16)が立っているかを取り出します。パスが存在しないとエラーになるため、On Error Resume Next で受けて False のまま返しています。FolderExists は True か False を返すだけなので、エラー処理なしで書けます。

ファイル一覧を取得する

1つのフォルダーの中だけを一覧にする

アクティブシートの A 列にファイル名を書き出します。

' VBA標準:Dir を繰り返す
Sub ListFilesDir()
    Const FOLDER_PATH As String = "C:\work\data"
    Dim fileName As String
    Dim r As Long

    r = 1
    fileName = Dir(FOLDER_PATH & "\*.xlsx")
    Do While fileName <> ""
        Cells(r, 1).Value = fileName
        r = r + 1
        fileName = Dir()        ' 引数なしで次のファイル名を取り出す
    Loop
End Sub
' FileSystemObject:Files コレクションを For Each で回す
Sub ListFilesFso()
    Const FOLDER_PATH As String = "C:\work\data"
    Dim fso As Object, f As Object
    Dim r As Long

    Set fso = CreateObject("Scripting.FileSystemObject")
    r = 1
    For Each f In fso.GetFolder(FOLDER_PATH).Files
        If LCase$(fso.GetExtensionName(f.Name)) = "xlsx" Then
            Cells(r, 1).Value = f.Name
            Cells(r, 2).Value = f.Size
            Cells(r, 3).Value = f.DateLastModified
            r = r + 1
        End If
    Next f
End Sub
比べる点 Dir FileSystemObject
絞り込み パスにワイルドカード(*、?)を書く Files は全ファイルを返すので、If で絞る
返ってくるもの ファイル名の文字列 File オブジェクト(Name・Path・Size・DateLastModified など)
次の1件 Dir() を引数なしで呼ぶ For Each が順に取り出す
隠しファイル 属性の引数(vbHidden など)で指定 Files に含まれる
フォルダーが無いとき "" が返る GetFolder でエラーになる

GetFolder は、指定したフォルダーが無いとエラーになります。先に FolderExists で確かめておくと、メッセージを自分で決められます。

拡張子で絞り込む

' 複数の拡張子を対象にする(FileSystemObject)
Function IsTargetExt(ByVal fso As Object, ByVal fileName As String) As Boolean
    Select Case LCase$(fso.GetExtensionName(fileName))
        Case "xlsx", "xlsm", "csv"
            IsTargetExt = True
    End Select
End Function

GetExtensionName は、ピリオドを含まない拡張子の文字列を返します。大文字の拡張子(.XLSX)も拾えるように、LCase$ で小文字にそろえてから比べています。

Dir のワイルドカードで絞ったうえで拡張子を厳密にそろえたいときは、取り出した名前をもう一度確かめる条件を足します。

If LCase$(Right$(fileName, 5)) = ".xlsx" Then
    ' .xlsx で終わる名前だけを処理する
End If

サブフォルダーも再帰でたどる(FileSystemObject)

フォルダーの中のファイルを書き出したあと、SubFolders の1つひとつについて同じプロシージャを呼び直します。

Sub ListFilesRecursiveFso()
    Const ROOT_PATH As String = "C:\work\data"
    Dim fso As Object
    Dim r As Long

    Set fso = CreateObject("Scripting.FileSystemObject")
    If Not fso.FolderExists(ROOT_PATH) Then
        MsgBox "フォルダーが見つかりません:" & ROOT_PATH
        Exit Sub
    End If

    Range("A1:D1").Value = Array("パス", "ファイル名", "サイズ", "更新日時")
    r = 2
    WalkFolderFso fso, fso.GetFolder(ROOT_PATH), "xlsx", r
End Sub

' ext に "" を渡すと、すべてのファイルを対象にする
Private Sub WalkFolderFso(ByVal fso As Object, ByVal fld As Object, _
                          ByVal ext As String, ByRef r As Long)
    Dim f As Object
    Dim subFld As Object

    For Each f In fld.Files
        If ext = "" Or LCase$(fso.GetExtensionName(f.Name)) = LCase$(ext) Then
            Cells(r, 1).Value = f.Path
            Cells(r, 2).Value = f.Name
            Cells(r, 3).Value = f.Size
            Cells(r, 4).Value = f.DateLastModified
            r = r + 1
        End If
    Next f

    For Each subFld In fld.SubFolders
        WalkFolderFso fso, subFld, ext, r     ' 自分自身を呼び直す
    Next subFld
End Sub

行番号 r は ByRef で渡しているので、呼び直した先で進んだ行がそのまま引き継がれます。

サブフォルダーも再帰でたどる(Dir)

Microsoft Learn の Dir 関数のページには、Dir を再帰的に呼び出すことはできないと書かれています。Dir は「前回の続き」を1つだけ覚えているため、繰り返しの途中で別のフォルダーに対して Dir を呼ぶと、元の続きが取り出せなくなります。そこで、サブフォルダーの名前を先に Collection にためて、Dir の繰り返しが終わってから1つずつたどります。

Sub ListFilesRecursiveDir()
    Dim r As Long
    r = 1
    WalkFolderDir "C:\work\data", "*.xlsx", r
End Sub

Private Sub WalkFolderDir(ByVal folderPath As String, ByVal pattern As String, _
                          ByRef r As Long)
    Dim itemName As String
    Dim subFolders As Collection
    Dim v As Variant

    ' 1) このフォルダーのファイルを書き出す
    itemName = Dir(folderPath & "\" & pattern)
    Do While itemName <> ""
        Cells(r, 1).Value = folderPath & "\" & itemName
        r = r + 1
        itemName = Dir()
    Loop

    ' 2) サブフォルダーの名前を先に集める
    Set subFolders = New Collection
    itemName = Dir(folderPath & "\*", vbDirectory)
    Do While itemName <> ""
        If itemName <> "." And itemName <> ".." Then
            If (GetAttr(folderPath & "\" & itemName) And vbDirectory) = vbDirectory Then
                subFolders.Add itemName
            End If
        End If
        itemName = Dir()
    Loop

    ' 3) Dir の繰り返しが終わってから、サブフォルダーをたどる
    For Each v In subFolders
        WalkFolderDir folderPath & "\" & v, pattern, r
    Next v
End Sub

「.」「..」という名前が返る場合に備えて除外し、GetAttr でフォルダーかどうかを確かめてから Collection に入れています。

フォルダーを作成する

' VBA標準
Sub MakeFolderStd()
    Const FOLDER_PATH As String = "C:\work\output"
    If Dir(FOLDER_PATH, vbDirectory) = "" Then
        MkDir FOLDER_PATH
    End If
End Sub

' FileSystemObject
Sub MakeFolderFso()
    Const FOLDER_PATH As String = "C:\work\output"
    Dim fso As Object
    Set fso = CreateObject("Scripting.FileSystemObject")
    If Not fso.FolderExists(FOLDER_PATH) Then
        fso.CreateFolder FOLDER_PATH
    End If
End Sub

CreateFolder は、同じ名前のフォルダーがすでにあるとエラーになります。作成の前に存在確認を入れておくと、2回目以降の実行でもそのまま通ります。

途中の階層もまとめて作る

C:\work\2026\10\output のように、途中のフォルダーがまだ無い場合は、親フォルダーから順に作ります。

' 親フォルダーが無ければ先に作る(再帰)
Sub EnsureFolder(ByVal folderPath As String)
    Dim fso As Object
    Dim parentPath As String

    Set fso = CreateObject("Scripting.FileSystemObject")
    If fso.FolderExists(folderPath) Then Exit Sub

    parentPath = fso.GetParentFolderName(folderPath)
    If parentPath <> "" Then
        If Not fso.FolderExists(parentPath) Then EnsureFolder parentPath
    End If
    fso.CreateFolder folderPath
End Sub

使い方:EnsureFolder "C:\work\2026\10\output"

ファイルやフォルダーをコピーする

' VBA標準:コピー先はファイル名まで書く
Sub CopyFileStd()
    FileCopy "C:\work\data\report.xlsx", "C:\work\backup\report.xlsx"
End Sub

' FileSystemObject:3つ目の引数で上書きするかを指定(省略時は True)
Sub CopyFileFso()
    Dim fso As Object
    Set fso = CreateObject("Scripting.FileSystemObject")

    ' 1つのファイルを、名前を変えてコピー(同名があれば止める)
    fso.CopyFile "C:\work\data\report.xlsx", "C:\work\backup\report_copy.xlsx", False

    ' ワイルドカードで複数のファイルを、既存のフォルダーへコピー
    fso.CopyFile "C:\work\data\*.xlsx", "C:\work\backup\"

    ' フォルダーを中身ごとコピー
    fso.CopyFolder "C:\work\data", "C:\work\backup\data"
End Sub
項目 FileCopy fso.CopyFile fso.CopyFolder
対象 ファイル1つ ファイル(ワイルドカード可) フォルダー(中身ごと)
上書きの指定 引数なし 3つ目の引数(省略時 True) 3つ目の引数(省略時 True)
開いているファイル エラーになる - -
ワイルドカード - コピー元の最後の要素にだけ書ける コピー元の最後の要素にだけ書ける

CopyFile のコピー先の末尾に \ を付けると「既存のフォルダーの中へ」、付けないと「その名前のファイルとして」扱われます。 コピー元にワイルドカードを使ったときは、コピー先はフォルダーとして扱われます。上書きを False にして同名のファイルがあるとエラーになり、コピー先が読み取り専用のときは上書きの指定にかかわらずエラーになります。

日付入りの名前でバックアップを取る例:

Sub BackupWithDate()
    Const SRC As String = "C:\work\data\report.xlsx"
    Dim fso As Object
    Dim dst As String

    Set fso = CreateObject("Scripting.FileSystemObject")
    dst = "C:\work\backup\" & fso.GetBaseName(SRC) & "_" & _
          Format$(Date, "yyyymmdd") & "." & fso.GetExtensionName(SRC)

    If fso.FileExists(SRC) Then
        fso.CopyFile SRC, dst, False
    End If
End Sub

移動する・名前を変える

VBA標準では、移動も名前の変更も Name ステートメント1つで行います。

' VBA標準
Sub RenameAndMoveStd()
    ' 同じフォルダーの中で名前を変える
    Name "C:\work\data\old.xlsx" As "C:\work\data\new.xlsx"

    ' 別のフォルダーへ移動する(同時に名前も変えられる)
    Name "C:\work\data\new.xlsx" As "C:\work\done\new_done.xlsx"

    ' フォルダーの名前を変える
    Name "C:\work\done" As "C:\work\finished"
End Sub
' FileSystemObject
Sub RenameAndMoveFso()
    Dim fso As Object
    Set fso = CreateObject("Scripting.FileSystemObject")

    ' 名前を変える:File オブジェクトの Name に新しい名前を入れる
    fso.GetFile("C:\work\data\old.xlsx").Name = "new.xlsx"

    ' 別のフォルダーへ移動する
    fso.MoveFile "C:\work\data\new.xlsx", "C:\work\done\new.xlsx"

    ' 複数のファイルをまとめて移動する(移動先は既存のフォルダー)
    fso.MoveFile "C:\work\data\*.csv", "C:\work\done\"

    ' フォルダーを移動する
    fso.MoveFolder "C:\work\done", "C:\work\archive\done"
End Sub
項目 Name ステートメント fso.MoveFile/Name プロパティ
名前の変更 Name 元 As 先(フルパスで書く) fso.GetFile(パス).Name = "新しい名前"(名前だけ書く)
ファイルの移動 できる(ドライブをまたいでもよい) fso.MoveFile 元, 先
フォルダー 同じドライブの中での名前変更 fso.MoveFolder 元, 先、Folder の Name プロパティ
ワイルドカード 使えない 移動元の最後の要素にだけ書ける
移動先に同名がある 指定できない(先の名前は存在していないこと) エラーになる
開いているファイル エラーになる(閉じてから実行) -

FileSystemObject には「Rename」という名前のメソッドはなく、File や Folder の Name プロパティに新しい名前を代入します。Name プロパティには、パスを含めずに名前だけを書きます。

同名があるときに連番を付けて移動する例:

Sub MoveWithoutOverwrite()
    Const SRC As String = "C:\work\data\report.xlsx"
    Const DST_FOLDER As String = "C:\work\done"
    Dim fso As Object
    Dim dst As String
    Dim n As Long

    Set fso = CreateObject("Scripting.FileSystemObject")
    If Not fso.FileExists(SRC) Then Exit Sub

    dst = fso.BuildPath(DST_FOLDER, fso.GetFileName(SRC))
    Do While fso.FileExists(dst)
        n = n + 1
        dst = fso.BuildPath(DST_FOLDER, fso.GetBaseName(SRC) & "_" & n & _
                            "." & fso.GetExtensionName(SRC))
    Loop
    fso.MoveFile SRC, dst
End Sub

削除する

' VBA標準
Sub DeleteStd()
    Kill "C:\work\temp\old.csv"        ' ファイルを1つ削除
    Kill "C:\work\temp\*.tmp"          ' ワイルドカードでまとめて削除
    RmDir "C:\work\temp"               ' 空のフォルダーを削除
End Sub

' FileSystemObject
Sub DeleteFso()
    Dim fso As Object
    Set fso = CreateObject("Scripting.FileSystemObject")

    fso.DeleteFile "C:\work\temp\old.csv"          ' ファイルを1つ削除
    fso.DeleteFile "C:\work\temp\*.tmp", True      ' 読み取り専用も含めて削除
    fso.DeleteFolder "C:\work\temp"                ' フォルダーを中身ごと削除
End Sub
項目 Kill RmDir fso.DeleteFile fso.DeleteFolder
対象 ファイル フォルダー ファイル フォルダー
ワイルドカード 使える - 最後の要素にだけ書ける 最後の要素にだけ書ける
中身のあるフォルダー - エラーになる(先に Kill で中のファイルを削除) - 中身ごと削除する
読み取り専用 - - 2つ目の引数を True にすると削除 2つ目の引数を True にすると削除
対象が1つも無いとき エラー53 - エラーになる エラーになる
開いているファイル エラーになる - - -

DeleteFolder は、フォルダーに中身があるかどうかを区別せずに削除します。 対象のパスを変数で組み立てるときは、次の「On Error 付きの削除」のように、実行前の確認を入れておくと安心です。

On Error付きで安全に削除する

存在しないファイルを Kill するとエラー53、開いているファイルを Kill するとエラーになります。「あれば消す。消せなかったら理由を残して先へ進む」形にしておくと、処理全体が途中で止まりません。

' 削除できたら True、できなかったら False を返す
Function SafeDeleteFile(ByVal filePath As String) As Boolean
    On Error GoTo ErrHandler

    ' ワイルドカードを含むパスは、この関数では受け付けない
    If InStr(filePath, "*") > 0 Or InStr(filePath, "?") > 0 Then
        Debug.Print "ワイルドカードは指定できません:" & filePath
        Exit Function
    End If

    ' 無ければ何もしない(削除済みと同じ扱い)
    If Dir(filePath) = "" Then
        SafeDeleteFile = True
        Exit Function
    End If

    Kill filePath
    SafeDeleteFile = True
    Exit Function

ErrHandler:
    Debug.Print "削除できませんでした:" & filePath & _
                " / エラー " & Err.Number & ":" & Err.Description
    SafeDeleteFile = False
End Function

呼び出す側:

Sub DeleteOldFiles()
    Dim targets As Variant, t As Variant
    Dim ngCount As Long

    targets = Array("C:\work\temp\a.csv", "C:\work\temp\b.csv", "C:\work\temp\c.csv")
    For Each t In targets
        If Not SafeDeleteFile(CStr(t)) Then ngCount = ngCount + 1
    Next t

    If ngCount > 0 Then
        MsgBox ngCount & " 件は削除できませんでした。イミディエイトウィンドウを確認してください。"
    End If
End Sub

削除の代わりに退避フォルダーへ移動する

すぐに消さず、退避用のフォルダーへ移してから、後でまとめて削除する形です。

Sub MoveToTrashFolder()
    Const SRC As String = "C:\work\temp\old.csv"
    Const TRASH As String = "C:\work\_trash"
    Dim fso As Object

    Set fso = CreateObject("Scripting.FileSystemObject")
    If Not fso.FileExists(SRC) Then Exit Sub
    If Not fso.FolderExists(TRASH) Then fso.CreateFolder TRASH

    fso.MoveFile SRC, fso.BuildPath(TRASH, _
        Format$(Now, "yyyymmdd_hhnnss") & "_" & fso.GetFileName(SRC))
End Sub

中身を確認してからフォルダーを削除する

Sub DeleteFolderAfterConfirm()
    Const TARGET As String = "C:\work\temp"
    Dim fso As Object, fld As Object, f As Object
    Dim listText As String

    Set fso = CreateObject("Scripting.FileSystemObject")
    If Not fso.FolderExists(TARGET) Then Exit Sub

    Set fld = fso.GetFolder(TARGET)
    For Each f In fld.Files            ' 中のファイル名を並べる
        listText = listText & f.Name & vbCrLf
    Next f

    If MsgBox(TARGET & " を中身ごと削除します。" & vbCrLf & listText, _
              vbOKCancel + vbExclamation) = vbOK Then
        fso.DeleteFolder TARGET
    End If
End Sub

実行時エラー53・70・75・76の原因表

Microsoft Learn の各エラーのページに書かれている原因を、ファイル操作に関係するものに絞って整理しました。

番号 公式ページの見出し(意味) 公式ページに書かれている原因 対応
53 File not found(ファイルが見つからない) Kill、Name、Open などが、存在しないファイルを指している ファイル名とパスのつづりを確かめる。実行前に Dir や FileExists で存在確認をする
70 Permission denied(アクセスが許可されていない) 書き込み禁止のファイルやディスクに書き込もうとした。ほかのプロセスがロックしているファイルに書き込もうとした ファイルを開いているアプリを閉じる。読み取り専用の属性を確かめる
75 Path/File access error(パスやファイルにアクセスできない) ファイルの指定の形式が正しくない。読み取り専用のファイルを置き換える保存をしようとした。Open・MkDir・ChDir・RmDir などで、パスとファイル名を結び付けられない パスの書き方(ドライブ名、区切りの \、絶対パスか相対パスか)を見直す。読み取り専用の属性を確かめる
76 Path not found(パスが見つからない) Open・MkDir・ChDir・RmDir などで、指定したパスが見つからない 途中のフォルダーが存在するかを確かめる。無ければ親から順に作る

この記事の操作とエラーの関係

操作 エラーになる条件(公式の注意書き) 先に入れておく確認
Kill 存在しないファイル(53)、開いているファイル Dir(パス) <> ""
Name 元のファイルが無い(53)、先の名前がすでにある、開いているファイル 元は存在、先は存在しないことを確認
FileCopy 開いているファイル コピー元を閉じてから実行
MkDir 指定したパスが見つからない(76) 親フォルダーの存在確認
RmDir フォルダーの中にファイルがある、パスが見つからない(76) 先に中のファイルを Kill
fso.CreateFolder 同じ名前のフォルダーがある fso.FolderExists
fso.GetFolder フォルダーが無い fso.FolderExists
fso.CopyFile 上書き False で同名あり、コピー先が読み取り専用、ワイルドカードに一致なし fso.FileExists
fso.MoveFile 移動先に同名のファイルがある、ワイルドカードに一致なし fso.FileExists
fso.DeleteFile/DeleteFolder 一致する対象が無い fso.FileExists/fso.FolderExists

FileSystemObject のメソッドは、ワイルドカードで複数を処理している途中でエラーになると、そこで止まり、それまでに行った変更は元に戻りません(CopyFile・MoveFile・DeleteFile・DeleteFolder の各ページの注意書き)。件数が多いときは、For Each で1件ずつ処理してエラーを記録する形にすると、どこまで進んだかを追えます。

エラー番号で処理を分ける定型

Sub MoveReportWithErrorHandling()
    Const SRC As String = "C:\work\data\report.xlsx"
    Const DST As String = "C:\work\done\report.xlsx"

    On Error GoTo ErrHandler
    Name SRC As DST
    MsgBox "移動しました。"
    Exit Sub

ErrHandler:
    Select Case Err.Number
        Case 53
            MsgBox "移動元のファイルが見つかりません:" & SRC
        Case 70
            MsgBox "ファイルが使用中か、書き込みが許可されていません。"
        Case 75, 76
            MsgBox "パスを確認してください:" & DST
        Case Else
            MsgBox "エラー " & Err.Number & ":" & Err.Description
    End Select
End Sub

Case Else で番号と説明をそのまま表示しておくと、想定していなかったエラーの手がかりが残ります。

DirとFileSystemObjectの選び方

状況 選ぶ方法 理由
ファイルが1つあるかを確かめる Dir 1行で書ける
1つのフォルダーの中を、ワイルドカードで絞って一覧にする Dir パスに *.xlsx と書くだけで絞れる
サブフォルダーもたどる FileSystemObject SubFolders を For Each で回せる。Dir は再帰的に呼べないため工夫が要る
更新日時・サイズ・拡張子を使う FileSystemObject File オブジェクトのプロパティで取れる
フォルダーを中身ごとコピー・削除する FileSystemObject CopyFolder・DeleteFolder がある
ファイルの名前変更・移動だけ Name ステートメント 1行で書ける
上書きするかどうかを指定してコピーする FileSystemObject CopyFile の3つ目の引数で決められる
途中の階層もまとめてフォルダーを作る FileSystemObject GetParentFolderName で親をたどれる

2つの方法は同じプロシージャの中で混ぜて使えます。存在確認は Dir、一覧と再帰は FileSystemObject、名前変更は Name、という組み合わせでも問題ありません。

よくある質問

Q. FileSystemObjectでファイル名を変更するメソッドはどれですか? A. 名前変更用のメソッドはなく、fso.GetFile(パス).Name = "新しい名前" のように、File オブジェクトの Name プロパティへ代入します。フォルダーも同じく Folder オブジェクトの Name プロパティで変えられます。VBA標準なら Name 元 As 先 です。

Q. 参照設定とCreateObjectは、どちらで書けばよいですか? A. ほかの人に渡すブックは、設定なしで動く CreateObject が向いています。自分で書き進めるときは、参照設定をすると入力候補が出て書きやすくなります。メソッドや引数は同じです。

Q. Dirでサブフォルダーの中まで一覧にできますか? A. できます。ただし Dir は再帰的に呼び出せないので、サブフォルダーの名前を Collection にためてから、Dir の繰り返しが終わった後でたどります(この記事の WalkFolderDir)。コードを短くしたいなら FileSystemObject の SubFolders が向いています。

Q. フォルダーを削除しようとするとエラーになります。 A. RmDir は、中にファイルがあるフォルダーには使えません。先に Kill で中のファイルを削除するか、中身ごと削除する fso.DeleteFolder を使います。パスが見つからない場合はエラー76になるので、存在確認を先に入れます。

まとめ

  • ファイル操作は2系統:VBA標準(Dir・MkDir・FileCopy・Name・Kill・RmDir)と FileSystemObject。同じプロシージャで混ぜて使える
  • 存在確認は Dir(パス) <> "" か fso.FileExists/fso.FolderExists。操作の前に入れると、エラーを先回りできる
  • 一覧取得は、1フォルダーなら Dir とワイルドカード、サブフォルダーまでたどるなら FileSystemObject の Files と SubFolders
  • Dir は再帰的に呼べないので、サブフォルダー名を Collection にためてからたどる
  • 移動と名前変更は Name ステートメント1つ。FileSystemObject では MoveFile と、File・Folder の Name プロパティ
  • 削除は Kill(ファイル)と RmDir(空のフォルダー)。中身ごと消すなら DeleteFolder で、実行前の確認を入れる
  • エラー53・70・75・76 は、ファイルが無い/使用中・書き込み不可/パスの形式/パスが見つからない、の順に切り分ける

参考・出典

  • Microsoft Learn「Dir function」 https://learn.microsoft.com/en-us/office/vba/language/reference/user-interface-help/dir-function
  • Microsoft Learn「MkDir statement」「FileCopy statement」「Name statement」「Kill statement」「RmDir statement」「GetAttr function」 https://learn.microsoft.com/en-us/office/vba/language/reference/user-interface-help/name-statement
  • Microsoft Learn「FileSystemObject object」 https://learn.microsoft.com/en-us/office/vba/language/reference/user-interface-help/filesystemobject-object
  • Microsoft Learn「CopyFile method」「MoveFile method」「DeleteFile method」「DeleteFolder method」「CreateFolder method」「CopyFolder method」「MoveFolder method」 https://learn.microsoft.com/en-us/office/vba/language/reference/user-interface-help/copyfile-method
  • Microsoft Learn「Files property」「SubFolders property」「Name property (FileSystemObject object)」「File object」 https://learn.microsoft.com/en-us/office/vba/language/reference/user-interface-help/files-property
  • Microsoft Learn「Format function」 https://learn.microsoft.com/en-us/office/vba/language/reference/user-interface-help/format-function-visual-basic-for-applications
  • Microsoft Learn「File not found (Error 53)」「Permission denied (Error 70)」「Path/File access error (Error 75)」「Path not found (Error 76)」 https://learn.microsoft.com/en-us/office/vba/language/reference/user-interface-help/file-not-found-error-53

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「VBAファイル・フォルダ操作|DirとFileSystemObject早見表」

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?