
【VBA FSO】FileSystemObjectで一番したいことは何?深い階層のフォルダからファイルを救出。
動画版「FSOの使い方」です。FileSystemObject(ファイルシステムオブジェクト)はファイルとフォルダ操作をするために用意されたオブジェクトです。オブジェクトというとそれだけで敬遠されがちです。
しかし、そこを乗り越えるととても便利で快適なExcel環境、いやPC環境が手に入ります。
今回することは 親フォルダー、子フォルダー、その中にファイル という構成から
親フォルダー 直下にファイルを上げてやる という 操作です。
以下の図はそのためにあえて分割したフォルダとfile群です。

マクロを実行すると、子フォルダーから親フォルダにファイルが移動します。 その時に 所属が不明にならないように、 ファイルが所属していた 子フォルダーの名前をファイル名の前につけるようにしています。

また、空になった子フォルダは削除するようにしました。 これにより目的のファイルへのアクセスが素早くできるようになりました。

では、どのようなコードを書いたのが説明します。
今回のコード作成にあたり、FileSystemObjectを使っています。
FileSystemObject(ファイルシステムオブジェク卜、略してFSO)は、ドライブやフォルダ一、ファイルを
操作するためのオブジェク卜です。
FSOを使用すると、ファイルやフォルダーを処理するプログラムを「オブジェクト.メソッド」や
「オブジェクト.プロパティ」といったVBAの基本構文で記述することができます。

FileSystemObjectは、下図のようなコレクションとオブジェクトにより構成されています。
最上位のオブジェクトは
FileSystemObjectオブジェクトです。そのほかのオブジェクトは、
すぺてFileSystemObjectの下位オブジェクトになります。

FileSystemObjectを使うには、[MicroSoft Scripting Runtime] への参照設定を行う必要があります。
VBEを開きから以下のステップで参照設定を行います。:
1.メニューのツールをクリックします。
2.ツールの参照設定をクリックします。
3.表示される参照可能なライブラリから、「Microsoft Scripting Runtime」を探し、
4.「Microsoft Scripting Runtime」の左にあるチェック欄にチェックを入れます。OKをクリックして閉じます。
以上で FileSystemObjectを利用できるようになります。(事前バインディング)

下図にあるように、「Microsoft Scripting Runtime」が利用できない時には、
CreateObjectメソッドを使ってFileSystemObjectを使うためのObjectを作成(インスタンス化)します。
Dim fso As Object
Set fso = CreateObject("Scripting.FileSystemObject")

両方できるからと言って、どちらでも良いと考えるよりは、
基本的には、参照設定を使うと考えてください。
では変数を見ていきましょう。

親フォルダは、 Dim ParentFolder As Object,
子フォルダ、 ChildFolder As Object,
ファイル、File As Object
選択したフォルダへのパス、Dim sParentFolderPath As String
として使っています。そして、
Dim fso As New FileSystemObject
変数fsoをFileSystemObjectのobjectとして宣言し、インスタンス化しています。

以下のWith構文では、ユーザーに使用するフォルダを選択してもらうためのコードを記述しています。
このコードを入れない場合は、直接フォルダへのパスを指定する必要があります。
コードは短くなりますが、処理を行うたびにフォルダへのパスを確認したり、書き換えたりする手間が発生するので、
汎用性を考えると、With構文で、ユーザーに使用するフォルダを選択してもらう方が簡単です。

' 親フォルダの選択
With Application.FileDialog(msoFileDialogFolderPicker)
.Title = "親フォルダ(例:TOEIC単語)を選択してください"
If .Show = -1 Then
sParentFolderPath = .SelectedItems(1)
Else
Exit Sub
End If
End With
親フォルダが決まったので、次は子フォルダをFor Each構文を使って、
ParentFolder.SubFoldersというように、親フォルダに属する
サブフォルダーコレクションの中から、それぞれ一つずつ処理します。

' 親フォルダ内の子フォルダを取得
Set ParentFolder = fso.GetFolder(sParentFolderPath)
For Each ChildFolder In ParentFolder.SubFolders
' 子フォルダ内の各ファイルを取得
For Each File In ChildFolder.Files
If Right(File.Name, 4) = ".mp3" Then
' ファイルを親フォルダに移動
File.Move sParentFolderPath & "\" & _
ChildFolder.Name & "_" & File.Name
End If
Next File
Next ChildFolder
さらにその子フォルダの中にあるファイルを処理するので、 For文を入れ子で使います。

赤線を引いたコードが今回のマクロのコードの大事な部分です。
今回の処理したい対象ファイルだったら、Moveメソッドを使い
以下の名前をつけて移動しなさい。という内容の処理です。

最後に、子フォルダに対象ファイルしか存在しない場合、空のフォルダになってしまいますから、 そのフォルダは不要です。そこでフォルダ内に他のファイルやフォルダが存在しない場合にはDeleteメソッドを使って削除しています。

今回のコード全体は以下になります。
Sub ファイルを上の階層フォルダーへ移動()
Dim ParentFolder As Object, ChildFolder As Object
Dim File As Object
Dim sParentFolderPath As String
' FileSystemObjectを初期化
' Dim fso As Object,
' Set fso = CreateObject("Scripting.FileSystemObject")
Dim fso As New FileSystemObject
' 親フォルダの選択
With Application.FileDialog(msoFileDialogFolderPicker)
.Title = "親フォルダ(例:TOEIC単語)を選択してください"
If .Show = -1 Then
sParentFolderPath = .SelectedItems(1)
Else
Exit Sub
End If
End With
' 親フォルダ内の子フォルダを取得
Set ParentFolder = fso.GetFolder(sParentFolderPath)
For Each ChildFolder In ParentFolder.SubFolders
' 子フォルダ内の各ファイルを取得
For Each File In ChildFolder.Files
If Right(File.Name, 4) = ".mp3" Then
' ファイルを親フォルダに移動
File.Move sParentFolderPath & "\" & _
ChildFolder.Name & "_" & File.Name
End If
Next File
Next ChildFolder
' 空のフォルダを削除する処理を追加
Set ParentFolder = fso.GetFolder(sParentFolderPath)
For Each ChildFolder In ParentFolder.SubFolders
If ChildFolder.Files.Count = 0 And _
ChildFolder.SubFolders.Count = 0 Then
ChildFolder.Delete
End If
Next ChildFolder
MsgBox "完了しました。", vbInformation
End Sub
