指定したフォルダ内とサブフォルダ内全てのファイル名を取得(Excel VBA)

【本日のミッション】

Excel VBAにて指定したフォルダ内とサブフォルダ内全てのファイル名を取得し、Excelのシートに書き出せ

以前お話しした

指定したフォルダ内のファイル名全てを取得(Excel VBA)

の応用版ですね。

指定したフォルダ内のファイル名だけではなく、サブフォルダ全部のファイル名を取得したい時だってありますよね(#^.^#)

ミッションの概要

今回指定フォルダにするのはこちらです。

この第1階層フォルダのファイルとサブフォルダ内のファイル、合計21個のファイル名を取得していきます。

指定したフォルダ内とサブフォルダ内全てのファイル名を取得(Excel VBA)

 指定したフォルダ内とサブフォルダ内全てのファイル名を取得(Excel VBA)

ファイルの準備とプロシージャ

Excelマクロ有効ブック(.xlsm)のファイルを新規作成します。

そのファイルのシートに下記の通り、フォルダのパスを入力するセル(A3)、取得したファイル名を書き出すセル(6行目1列目)を準備します。

フォルダパスには、ファイル名を取得したい一番上の階層のフォルダのフルパスを入力します。

指定したフォルダ内とサブフォルダ内全てのファイル名を取得(Excel VBA)

このシートをアクティブにした状態で、Alt+F11でVsual Basic Editerを起動します。

[挿入]-[標準モジュール]で新規モジュールを作成し、下記の通りコードを記入します。

Sub 指定したフォルダ内とサブフォルダ内全部のファイル名取得()

    'アクティブシートから処理対象のフォルダパスを取得し
    'そのフォルダ内とサブフォルダ内全部のファイル名を全てアクティブシートに取得

    '【変数】
    Dim ws As Worksheet '処理対象シート
    Dim pt As String    '処理対象パス
    Dim t_row As Long   'ファイル名書出行

    '■変数セット
    Set ws = ActiveSheet '変数ws=アクティブシートをセット
    pt = ws.Range("A3")  '変数ptにセルA3のパスをセット
    t_row = 6            'ファイル名を書き出す初めのセルの行番号をセット

    '■指定したフォルダ内とサブフォルダ内全部のファイル名をセルに書き出し
    Call ファイル名一覧取得(pt, ws, t_row)
End Sub

Sub ファイル名一覧取得(pt As String, ws As Worksheet, t_row As Long)
    Dim FSO As Object       'FileSystemObject
    Dim fn As String        'ファイル名
    Dim s_fd As Object      'サブフォルダ
    fn = Dir(pt & "¥*.*")   '変数fnに1個目のファイル名を格納
    Do While fn <> ""             'fnが空欄になるまでDo While内の処理を続ける
        ws.Cells(t_row, 1) = fn   '対象セルにファイル名を書き出し
        t_row = t_row + 1         'ファイル名を書き出すセルの行番号+1(一つ下の行番号)
        fn = Dir() '変数fnに次のファイル名を格納(ファイルが無い場合は空欄になる)
    Loop
   Set FSO = CreateObject("Scripting.FileSystemObject") 'FileSystemObjectのインスタンス化
   For Each s_fd In FSO.GetFolder(pt).SubFolders        '変数s_fdに対象フォルダ内のサブフォルダを順に取得
       Call ファイル名一覧取得(s_fd.Path, ws, t_row)     '再帰処理
   Next s_fd
   Set FSO = Nothing 'FSOを空っぽにする
End Sub

今回のコードは2つのプロシージャ(Sub~End Subまで)から成り立っているんです。

「指定したフォルダ内とサブフォルダ内全部のファイル名取得」プロシージャのどこかにカーソルを置いてF5キーをクリックしてください。

Excelのシートを見てください。

指定したフォルダ内とサブフォルダ内全てのファイル名を取得(Excel VBA)

うわ~~~~!!

これ、初めてできたとき感激しました。

ファイル操作のVBAが少し使えるようになるだけで、「神」みたいに思えちゃう(#^.^#)

ファイル取得の順番

ちなみに、どんな順番でファイルを取得したかと申しますとこんな感じです。

指定したフォルダ内とサブフォルダ内全てのファイル名を取得(Excel VBA)

上の階層から順に攻めていくのかと思っていたのですが、初めに攻めたフォルダの下の階層の方が先に処理されるんですね。

Dir関数とは

Dir関数は、第1引数に指定したファイル・フォルダが存在する場合、パスを除いたファイル名・フォルダ名を返します。存在しない場合は長さ0の文字列 ”” (空欄)を返します。

Dir(ファイル・フォルダのパス,ファイル・フォルダの属性)

Dir (“C:\VBA\第1階層\File1_1.xlsx”)  の場合

  • ファイルが存在する場合(ファイル名を返す)→  File1_1.xlsx
  • ファイルが存在しない場合(空欄を返す)      →  ””

第1引数にはワイルドカードを使用することができるので、取得したいファイル名・フォルダ名の幅を広げることができます。

Dir(”C:\VBA\第1階層\*.*“)

参考:ワイルドカードとは。使い方いろいろ。(Excel)

第2引数に下記定数(値)を指定することで、特定の属性のオブジェクトのみを取得の対象とすることができます。

定数属性
vbNormal (既定)0標準ファイル
vbReadOnly1読み取り専用ファイル
vbHidden2隠しファイル
vbSystem4システム ファイル
vbVolume8ボリューム ラベル。この値を指定すると、すべての属性は無効になります。
vbDirectory16フォルダ
vbAlias64エイリアスファイル

※4、8はMacでは使えません。また、64はMacintoshのみ使えます。

今回は、規定値となっている標準ファイルを取得するため、第2引数は省略しています。

Dir関数は一度引数を指定すると、次に別の引数を指定するまで、同じ引数に対する処理を行います。

fn=Dir(”C:\VBA\第1階層\*.*”)
fn=Dir()
fn=Dir()

1行目の処理では、変数fnに「C:\VBA\第1階層\*.*」に一致するファイルが存在すれば、そのファイル名を返します。

2行目以降の「fn=Dir()」では引数を指定していませんが、「C:\VBA\第1階層\*.*」に一致する別のファイル名を返します。

その処理を繰り返し、「C:\VBA\第1階層\*.*」に一致するファイルが無くなった時、長さ0の文字列 ”” 空欄 を返します。

何度も「fn=Dir()」を書くのは面倒だし、どのタイミングでファイルが無くなるかわからないので、Do While ~ Loopを使って繰り返し処理を行います。

fn=Dir(”C:\VBA\第1階層\*.*”)
Do While fn <> ""         'fnが空欄になるまでDo While内の処理を続ける 
    ~fnで行いたい処理を記述~
    fn = Dir()            '変数fnに次のファイル名を格納(ファイルが無い場合は空欄になる) 
Loop

参考:Dir関数が取得するファイルの順番
参考:Dir関数の使い方。ファイル名やフォルダ名の取得方法。(Excel VBA)

Callとは?

他のSubプロシージャやFunctionプロシージャの処理を行います。

「Call」を省略して、プロシージャの名前だけでも処理してくれるのですが、私は後から見たとき、これナニ?ってならないように「Call」を付けるようにしています。

今回、私は

Call ファイル名一覧取得(pt, ws, t_row)

みたいに、プロシージャ名の後ろに「(引数)」を指定しています。

今日は簡単に説明しちゃいますね。

「指定したフォルダ内とサブフォルダ内全部のファイル名取得」プロシージャ内で、Callにセットした「pt」「 ws」「 t_row」を引数のお弁当箱に入れて、「ファイル名一覧取得」プロシージャに持っていきますよ~、みたいな感じです。

お弁当箱に入れて持ってきた引数は、持って行った先のプロシージャでも、それぞれが何者(データ型)か宣言し、そのプロシージャ内で利用します。

Sub ファイル名一覧取得(pt As String, ws As Worksheet, t_row As Long)

この引数の深~~~いお話はまた次の機会↓にさせて頂きますね。
参照渡し「ByRef」と値渡し「ByVal」の違い(Excel VBA)

↓Callステートメントをもう少し詳しく
Callステートメントとは

For Eachとは?

For Each 変数 In コレクション
    ***処理***
Next  

とすることで、コレクションの中にあるもの1つ目から順に変数に入れてNextまでの処理を行い、コレクションの中にあるもの全ての処理が終わったらNext以降の処理に移ります。

今回は「s_fd」という変数をObjectとして宣言しています。Objectはここではフォルダです。

For Each s_fd In FSO.GetFolder(pt).SubFolders

Call ファイル名一覧取得(s_fd.Path, ws, t_row)

Next s_fd

コレクション部の「FSO.GetFolder(pt).SubFolders」ってナゾですよね。意味合いとしては、変数pt(処理対象パス)のフォルダのサブフォルダ群のことです。

CreateObject(“Scripting.FileSystemObject”)とは

CreateObject(“Scripting.FileSystemObject”)につきましては、下記をご参照ください。

CreateObject(“Scripting.FileSystemObject”) を使ってサブフォルダを取得

再帰処理とは?

再帰処理につきましては、下記をご参照ください。

再帰処理とは?フォルダ内とサブフォルダ内全てのファイル名を取得(Excel VBA)

【参考】

指定したフォルダ内のファイル名全てを取得(Excel VBA)
変数でよく使われる「buf」「tmp」の意味
Dir関数が取得するファイルの順番
指定したフォルダ内のフォルダ名全てをGetAttrを使って「エラー53 ファイルが見つかりません。」を出さずに取得(Excel VBA)
GetAttrとは?「= vbDirectory」ではなく「And vbDirectory」となるビット演算の疑問
フォルダ名だけを取得したい時に出てくる 「.」 と 「..」 とは?
指定したフォルダ内とサブフォルダ内全てのファイル名を取得(Excel VBA)
CreateObject(“Scripting.FileSystemObject”) を使ってサブフォルダを取得
再帰処理とは?フォルダ内とサブフォルダ内全てのファイル名を取得(Excel VBA)
指定したフォルダ内のサブフォルダのフォルダ名を全部取得(Excel VBA)
再帰処理とは?フォルダ内のサブフォルダのフォルダ名を全部取得(Excel VBA)
参照渡し「ByRef」と値渡し「ByVal」の違い(Excel VBA)
ファイルのフルパスからファイル名のみを取得 InStrRev関数(Excel VBA)
指定したフォルダの全ての階層のフォルダ名・サブフォルダ名・ファイル名を取得(Excel VBA)
FileSystemObjectとは?CreateObject 関数 FolderExists・GetFolderの使い方
FileSystemObject CreateObject関数を使う方法・ 参照設定を使う方法 違いを理解してエラー防止
再帰処理とは?指定したフォルダの全ての階層のフォルダ名・サブフォルダ名・ファイル名を取得(Excel VBA)
ファイルのフルパスからファイル名のみを取得 Split関数(Excel VBA)
Callステートメントとは 引数 括弧()の使い方(Excel VBA)
指定したフォルダ内から「特定の文字を含まないファイル名」を取得(Excel VBA)
ワイルドカードとは。使い方いろいろ。(Excel)
Dir関数の使い方。ファイル名やフォルダ名の取得方法。(Excel VBA)
指定したフォルダのファイル名を取得し、そのファイル名を一括で変換(Excel VBA)
Excel起動時に「コンパイルエラー」。64ビット システムで Declareステートメントに、PtrSafe属性を設定(Excel VBA )
「ファイルを開く」ダイアログボックス から ファイル名を取得(Excel VBA)
「ファイルを開く」ダイアログボックス から 複数 ファイル名を取得(Excel VBA)
指定フォルダ内のサブフォルダ全てをフォルダ構成のみ(空フォルダ)を別フォルダにコピー(Excel VBA)
再帰処理とは?指定フォルダ内のサブフォルダ全てをフォルダ構成のみ(空フォルダ)を別フォルダにコピー(Excel VBA)

■■■スポンサーリンク■■■