VBAの基本操作（ファイル）

VBAの初心者向けに基本操作方法（ファイル）を紹介したいと思います。

【FSO】
FSO(FileSystemObject)とはフォルダを操作する専用のオブジェクトで、コードを見やすく出来るのでとても重宝する機能です。使用にあたって準備が必要なので、まずは下の画像に合わせて設定をして下さい。
![参照.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/958041/fe6db664-b613-ea03-8438-34e9389b1882.png)
![参照2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/958041/9c82c62a-d615-24be-bb19-3e9099f33f84.png)
これで使用出来るようになったかと思います。

```:デスクトップにあるファイルの数をカウントする
Dim folderPath As String
folderPath = "C:\Users\jorut\OneDrive\デスクトップ"
Dim fso As Object
Set fso = CreateObject("Scripting.FileSystemObject")
Dim i As Long
i = fso.GetFolder(folderPath).Files.Count
MsgBox (i)
```
`Set fso = CreateObject("Scripting.FileSystemObject")`でfsoをオブジェクト化していますが、最初のうちは必要な「儀式」だと思って深く考えなくてもよいです。
`fso.GetFolder(folderPath).Files.Count`
`fso - 任意のフォルダ - ファイルを検知 - 数える`
みたいな感じで一つ一つの関数のを分けて翻訳すると意味がわかりやすいかと思います。

```:デスクトップにフォルダを作成し、その中にテキストファイルを作成する
Dim FolderName As String
FolderName = "C:\Users\jorut\OneDrive\デスクトップ\test"
MkDir FolderName
Dim fso As Object
Set fso = CreateObject("Scripting.FileSystemObject")
fso.CreateTextFile ("C:\Users\jorut\OneDrive\デスクトップ\test\test.txt")
```

```:ファイルの中身をセルに表示する
Dim FSO As Object, TextFile As Object, buf As String
Set FSO = CreateObject("Scripting.FileSystemObject")
Set TextFile = FSO.OpenTextFile("C:\Users\jorut\OneDrive\デスクトップ\test\test.txt")
buf = TextFile.ReadAll  'テキストファイルの中身を読み取る
Cells(1, 1) = buf
```

```:ファイルを削除する
Dim FSO As Object
Set FSO = CreateObject("Scripting.FileSystemObject")
FSO.DeleteFile "C:\Users\jorut\OneDrive\デスクトップ\test\test.txt"
```

```:フォルダ直下のファイル名を全てセルに表示する
Dim folderPath As String
With Application.FileDialog(msoFileDialogFolderPicker)
   .InitialFileName = ""
   If .Show = True Then
      folderPath = .SelectedItems(1)
   Else
      Exit Sub
   End If
End With

Dim fso As Object
Dim file As Object
Set fso = CreateObject("Scripting.FileSystemObject")
ReDim BaseNames(fso.GetFolder(folderPath).Files.Count)

For Each file In fso.GetFolder(folderPath).Files
   cnt = cnt + 1
   BaseNames(cnt) = fso.GetBaseName(file.Name)

   For i = 1 To cnt
      Cells(i, 1) = BaseNames(i)
   Next i
Next
```

```:フォルダ内のすべてのファイル名を表示する（フォルダ内にさらにフォルダがあった場合にはその中のファイル名も表示する）
Sub メイン()
    With Application.FileDialog(msoFileDialogFolderPicker)
        If Not .Show Then Exit Sub
        Call サブ(folderPath:=.SelectedItems(1))
    End With
End Sub
Sub サブ( _
    folderPath As String, Optional myCount As Long = 0)
    Dim fso As New FileSystemObject, myFolder As Folder, myFile As file
    Dim fname
    For Each myFile In fso.GetFolder(folderPath).Files
        myCount = myCount + 1
        fname = Split(myFile.Path, folderPath)
        fname = Split(fname(1), "\")
        Cells(myCount, 1) = fname(1)
    Next
    For Each myFolder In fso.GetFolder(folderPath).SubFolders
        Call サブ(myFolder.Path, myCount)
    Next
End Sub
```
ちょっと長いコードなので分けて説明しますね＾＾；

```:解説1
Sub メイン()
    'FileDialogで開くフォルダを選択させる
    With Application.FileDialog(msoFileDialogFolderPicker)

       　'もしフォルダが無ければマクロから離れる
        If Not .Show Then Exit Sub

　　　　　'サブ(...)のマクロを呼び出す
        Call サブ(folderPath:=.SelectedItems(1))

    End With
End Sub
```


```:解説2
    'フォルダパスの設定
    folderPath As String, Optional myCount As Long = 0)
    'FSOの設定
    Dim fso As New FileSystemObject, myFolder As Folder, myFile As file
    '変数fnameの設定
    Dim fname

    'フォルダがある限りカウントする
    For Each myFile In fso.GetFolder(folderPath).Files
        myCount = myCount + 1
　　　　　
       'fnameは「パス名＋\＋〇〇.xlsx」になっているので分ける
        fname = Split(myFile.Path, folderPath)
        fname = Split(fname(1), "\")
        Cells(myCount, 1) = fname(1)
    Next
```

```:解説3
    'フォルダ内にフォルダがあるか検知
    For Each myFolder In fso.GetFolder(folderPath).SubFolders
        'フォルダがあった場合はサブ関数をもう一度呼び出す
        Call サブ(myFolder.Path, myCount)
    Next
```
　上記のコードのようにマクロの中でもう一度マクロ（正確にはモジュール）を呼び出す処理を`再帰処理`と言います。

　今回のコードのように関数内で別の関数を呼び出し、呼び出した先で元の関数を呼び出すソースのことを再帰処理と言います。かなり難しい内容ですがここまで出来ると実務に携われるようになります（だそうです＾＾；）
　今回の内容は丸々覚えなくてもコードを読めてさえすればコピペで組み合わせていくことで、それなりの処理が行えるようになるかと思いますので関数や変数の一つ一つの意味を読めるようになると良いと思います。