みなさまは片付け得意でしょうか?
私は片付けが非常に苦手です。。。
自分の部屋も、気づいたらいつもごちゃごちゃになっていきます。。。
実生活もそうですが、パソコンの中も同じように、
気づいたらごちゃごちゃになって、目当てのファイルを探すのも一苦労です。。。
同じような経験をされている方もおられるのではないでしょうか。
今回はそんな方々向けに、家庭用・仕事用、どちらでも使えるような
『フォルダ一覧化マクロ』を作っていきます。
パソコン内を整理する、というよりも、
ごちゃごちゃのままでも目当てのファイルを見つけ出す!という思想です♪
一緒に作って作業効率アップをしていきましょう!
【本記事の目標】
1つのフォルダ内を検索
その1、その2-1をまだ読まれていない方は、過去の投稿もご確認ください。
フォルダ操作
前回までで、マクロ作成に必要な下準備と、検索したいフォルダのフルパスを入力するマクロの構築まで終わりました。
それでは今回は、さっそく前回準備したFileSystemObjectを使って、検索したいフォルダの中身を調べていきましょう!
現時点で入力済みのメインのプロシージャのマクロは下記のようになっています。
(今回は参照設定を使用するので、
参照設定を使用しない場合の部分はコメントブロックで止めています)
また、以降で検索したいフォルダのフルパスを頻繁に使うので、SearchFolderPath1という変数にフルパスを入れるようにしています。
(検索したいフォルダのフルパスは、『検索結果一覧』のシートの”B1”セルに記入されているはずです)
Option Explicit
Sub FolderSearchMain()
'フォルダ検索のメイン部分
'参照設定を使用する場合(fso1は任意に設定OK)
Dim fso1 As Scripting.FileSystemObject 'FileSystemObjectの変数
Set fso1 = New Scripting.FileSystemObject
''参照設定を使用しない場合(fso2は任意に設定OK)
'Dim fso2 As Object
'Set fso2 = CreateObject("Scripting.FileSystemObject")
'検索したいフォルダのフルパスを入れる変数
Dim SearchFolderPath1 As String
SearchFolderPath1 = ThisWorkbook.Sheets("検索結果一覧").Range("B1").Value
End Sub
コメントブロックとは
上記でサラッと書きましたが、コメントブロックというのはマクロの中で
『これは人間が分かりやすくするために書いた部分なので、パソコンは無視してください』
という指示を出す記号のことで、VBAでは【’】(アポストロフィー)を使います。
この記号より右側に書いた内容はパソコンが無視してくれます。
ただし効果があるのはその行だけで、次の行までは影響しません。
プログラムは基本的に、書かれたコードを上から下に全てパソコン側が読んで実行していきます。
そのため必要なコード以外のことを書いてしまうと、パソコン側が読み取れずにエラーが出ます。
ただ、コードは人間が書いていくので、要所要所にメモ書きしたいですよね。
特に複数人で1つのプログラミングをしている場合は、メモ書きをしておかないと一緒にプログラミングをしているメンバー同士で意思疎通が取れなくなります。
このようなときに使うのが『コメントブロック』です。
・ここに書いてあるコードはこういう動きをさせようと書いてますよ
・この変数の定義はこういくことをするために定義していますよ
等をコメントブロックでメモしておけば、後で見返したときにすぐに内容を把握できるようになり、より効率的にコードを書くことができます。
FileSystemObjectを使って検索したいフォルダの中を調べる
FileSystemObjectには色々なコマンドがあり、それを使うことでフォルダやファイル関係の色々なことができるようになります。
できることがあまりに多すぎるので、今回はフォルダ検索に必要な部分だけ紹介します。
もし「もっと知りたい!」と思われる場合は『FileSystemObject』で色々調べてみてください。
今回は検索したいフォルダの中を調べたいので、GetFolderというメソッドを使います。
このメソッドはフォルダのフルパスを与えてあげれば、そのフォルダのいろんな情報をとってきてくれます。
使い方としては、
fso1.GetFolder(SearchFolderPath1).(必要な情報のプロパティ)
という形で使います。
ここで「必要な情報のプロパティ」の例として下記があります。
プロパティ | 説明 | 返すもの |
Name | フォルダの名前 | 文字列 |
Path | フォルダのフルパス | 文字列 |
Size | フォルダのサイズ | 数値 |
DataLastModified | 最終更新日 | 日時 |
DataLastAccessed | 最後にアクセスした日時 | 日時 |
Files | フォルダの中にあるファイル | Fileコレクション |
SubFolders | フォルダの中にあるフォルダ | Folderコレクション |
今回はフォルダの中にあるファイルとフォルダを確認したいので、
fso1.GetFolder(SearchFolderPath1).Files
fso1.GetFolder(SearchFolderPath1).SubFolders
で良いように思いますが、
これで帰ってくるのは『Fileコレクション』や『Folderコレクション』といった形式のデータです。
この『コレクション』というのは、文字列や数値のような1つのデータではなく、複数のデータが入っている詰め合わせパックのような状態のものになっています。
なので、この中から1つ1つのファイルの名前等の情報を取り出していこうと思うと、
その詰め合わせパックになっている『コレクション』の中から、ファイルを1つずつ取り出していく必要があります。
そういった、『コレクション』の中から1つ1つ物を取り出してきて繰り返し操作をするときに使うのが For Each です。
コレクションの中を1つずつ確認する ~For Each~
繰り返しでよく使う構文としてFor文がありますが、これは下記のように
For 変数 = (繰り返し範囲)
という指定をして、繰り返しの範囲の最初の数値から最後の数値までを変数に入れて繰り返しを行い、全て繰り返したら終了します。
基本的な考え方はFor Each文でも同じで、
For Each 変数 In (コレクション)
という指定をして、コレクションの中にあるものを1つずつ変数に入れて繰り返しを行い、
コレクションの中を全て出し切ったら終了します。
今回の場合だと、FilesとSubFoldersで2つのコレクションが出てくるので、プロシージャに書くと下記のようになります。
Option Explicit
Sub FolderSearchMain()
'フォルダ検索のメイン部分
'参照設定を使用する場合(fso1は任意に設定OK)
Dim fso1 As Scripting.FileSystemObject 'FileSystemObjectの変数
Set fso1 = New Scripting.FileSystemObject
''参照設定を使用しない場合(fso2は任意に設定OK)
'Dim fso2 As Object
'Set fso2 = CreateObject("Scripting.FileSystemObject")
'検索したいフォルダのフルパスを入れる変数
Dim SearchFolderPath1 As String
SearchFolderPath1 = ThisWorkbook.Sheets("検索結果一覧").Range("B1").Value
'For Eachで使う変数の定義
Dim FilesList1 As Variant
Dim FoldersList1 As Variant
'Filesコレクションの操作
For Each FilesList1 In fso1.GetFolder(SearchFolderPath1).Files
'ここで繰り返しする作業内容を書く(ファイルの場合の操作)
Next FilesList1
'SubFoldersコレクションの操作
For Each FoldersList1 In fso1.GetFolder(SearchFolderPath1).SubFolders
'ここで繰り返しする作業内容を書く(フォルダの場合の操作)
Next FilesList1
End Sub
For Eachで使う変数の定義に使っている【Variant】というデータ形式ですが、
これは「なんにでもなれるデータ形式」です。
変数を「文字列」として定義した場合、その変数には文字列しか入れられませんが、
この『Variant』の形式で定義した変数には、
文字列を入れると文字列のデータ形式に、
数値を入れると数値のデータ形式に、
データを入れるたびに変化することができます。
変数を定義する場合、
Dim 変数 As (データ形式)
という形で定義しますが、この「As (データ形式)」の部分は省略することができ、その場合のデータ形式も『Variant』になります。
非常に使い勝手の良いデータ形式ですが、欠点としては2つあります。
1つ目はデータ量が重くなってしまうこと。ただ、個人で作るマクロのレベルであればほとんど気づかないレベルなので、気にしなくても問題ないと思います。
2つ目はデータ形式に合わせた参照機能(入力補助機能)が使えなくなることです。
文字列や数値のデータ形式だとほとんど使うことはないですが、色んなオブジェクト(FileSystemObjectもその1つ)のデータ形式で変数を定義するようになってきたときに、ちょっと苦労するかもしれないです。
勉強の意味もかねて、できればあまり使わない方が良いですが、
非常に使い勝手が良いデータ形式ですので、困ったときは使ってもらったらいいかと思います。
ファイルの情報を取得する
あとは、For Each文の中で、そのファイルの名前やパス、更新日の情報等を取り出していけばOKです。
フォルダの場合は、上記のようにGetFolderを使えば名前やパスなどの情報を取り出せることが分かってます。
じゃあファイルの場合は?
同じようにGetFileを使えばいいんです。
プロパティはGetFolderの時と基本は同じです。
(ファイルなので、SubFolder等が使えない程度です)
ただ、ファイルの拡張子についてはGetFileのプロパティには無いので、
別の方法で取得する必要があります。
拡張子を取り出すメソッドもFileSystemObjectにはあって、GetExtensionNameを使います。
fso1.GetExtensionName(ファイルのフルパス)
と書けば、ファイルの拡張子も取得できます。
これらを踏まえた上でコードを書くと、下記のようになります。
Option Explicit
Sub FolderSearchMain()
'フォルダ検索のメイン部分
'参照設定を使用する場合(fso1は任意に設定OK)
Dim fso1 As Scripting.FileSystemObject 'FileSystemObjectの変数
Set fso1 = New Scripting.FileSystemObject
''参照設定を使用しない場合(fso2は任意に設定OK)
'Dim fso2 As Object
'Set fso2 = CreateObject("Scripting.FileSystemObject")
'検索したいフォルダのフルパスを入れる変数
Dim SearchFolderPath1 As String
SearchFolderPath1 = ThisWorkbook.Sheets("検索結果一覧").Range("B1").Value
'For Eachで使う変数の定義
Dim FilesList1 As Variant
Dim FoldersList1 As Variant
'ファイルの情報を一旦入れておくための変数
Dim FileName1 As String
Dim FilePath1 As String
Dim FileExtensionName1 As String
Dim FileChangeDate As Variant
'シートの最終行の変数
Dim LastRow1 As Integer
'Filesコレクションの操作
For Each FilesList1 In fso1.GetFolder(SearchFolderPath1).Files
FileName1 = fso1.GetFile(FilesList1).Name
FilePath1 = fso1.GetFile(FilesList1).Path
FileChangeDate = fso1.GetFile(FilesList1).DateLastModified
FileExtensionName1 = fso1.GetExtensionName(FilePath1)
'データをシートに記載
With ThisWorkbook.Sheets("検索結果一覧")
LastRow1 = .Cells(.Rows.Count, 1).End(xlUp).Row
LastRow1 = LastRow1 + 1
.Cells(LastRow1, 1).Value = FileName1
.Cells(LastRow1, 2).Value = FilePath1
.Cells(LastRow1, 3).Value = FileExtensionName1
.Cells(LastRow1, 4).Value = FileChangeDate
End With
Next FilesList1
'SubFoldersコレクションの操作
For Each FoldersList1 In fso1.GetFolder(SearchFolderPath1).SubFolders
'ここで繰り返しする作業内容を書く(フォルダの場合の操作)
Next FoldersList1
End Sub
取得した情報をシートに記載する部分でシートの最終行を確認するコードを記載していますが、
これは『家計簿アプリ』を作った際に使った手法ですので、もしご存じない方は過去の投稿もご確認ください。
このマクロも、シートにボタンを作ってマクロを登録すれば、一旦は動くようになります。
試しに下記のようなフォルダを検索すると、シートにファイルのリストが表示されると思います。
検索結果↓
ひとまずこれで、フォルダの中にあるファイルのリストは出せるようになりました。
ただ、問題はここからです。
For Each文でSubFoldersコレクションの操作の部分は、あえてまだ何も書いていないですが、
ここに、フォルダの中にあるフォルダの中を調べていくコードを書いていく必要があり、
その時に使うのが『再帰呼び出し』という方法です。
次の記事ではこの『再帰呼び出し』について書いていこうと思います。
次の記事へ
コメント