サブフォルダを含めたファイル名を一括取得するツールを作成したので作り方を解説します。
取得するファイル名について拡張子などの指定もできるようにしてみました。
今回説明するファイルにできることは以下の通りです
できること
- 取得するファイルの拡張子を指定(1種の拡張子 Or すべての拡張子)
- サブフォルダを含めたファイル名の一括取得
- 取得したファイルのディレクトリ(フルパス)
多少コードを追加・削除することで下記の作業もできるようになります
修正すればできること
- 取得するファイルの拡張子を指定(複数の拡張子を指定)
- サブフォルダ内のファイルを除外
- ファイル名だけではなくフォルダまで取得
サブフォルダを含めたファイル名の取得サンプル(全行)
下記がコードの全量となります。急ぎで利用したい方はコードをコピペして利用してください。
コピペ場所やツールの使用方法については後続に詳細を説明しているので使用前にご覧ください。
Option Explicit Dim startRow As Integer Dim folderPass As String Dim ext As String 'ファイル名を取得(サブフォルダを含む) Sub main() '処理対象のファイルを開いた際のメッセージをオフにする Application.DisplayAlerts = False '処理実行時の画面描画をオフにして処理を高速化 Application.ScreenUpdating = False '前処理 Call beforeProcess 'ファイル名取得のメイン処理を行うプロシージャを呼び出す Call mainProcess(folderPass, startRow) End Sub Sub beforeProcess() 'ファイル名一覧を出力する行番号を指定します。 startRow = 7 '対象フォルダのパスがあるセルを指定し、値を代入します。 folderPass = Range("C5").Value '拡張子の選択 ext = Range("D6").Value '指定範囲の値をクリア Range("B7:C10000").ClearContents Range("B7:E10000").Interior.ColorIndex = 0 End Sub 'ファイル名を取得(サブフォルダを含む)のメイン処理を行う Sub mainProcess(folderPass As String, startRow As Integer) Dim fso As Object Dim filePath As Object Dim subFilePath As Object '対象フォルダのパスの値があれば処理 If folderPass = "" Then MsgBox "C5セルにフォルダパスを記入してください" Exit Sub Else 'ファイルやフォルダを操作するオブジェクトFileSystemObjectを変数にセット Set fso = CreateObject("Scripting.FileSystemObject") 'ファイル情報を出力 For Each filePath In fso.GetFolder(folderPass).Files '拡張子を判定 If (LCase(fso.GetExtensionName(filePath)) = LCase(ext)) Then 'ファイル名・ファイルパスの出力 Cells(startRow, 2) = filePath.Name Cells(startRow, 3) = filePath.Path startRow = startRow + 1 ElseIf LCase(ext) = "" Then Cells(startRow, 2) = filePath.Name Cells(startRow, 3) = filePath.Path startRow = startRow + 1 End If Next filePath 'サブフォルダ内のファイル名取得の処理 For Each subFilePath In fso.GetFolder(folderPass).SubFolders If subFilePath.Name <> "" Then 'サブフォルダのパスをmainProcessに渡して再帰的に処理 Call mainProcess(subFilePath.Path, startRow) End If Next subFilePath End If Set fso = Nothing Set filePath = Nothing Set subFilePath = Nothing End Sub
ファイル名取得ツールの使用方法
ツールの画面になります。画面の通りにExcelファイルを修正してください。
ファイルの画面説明
- セルC5にファイル名を取得したいフォルダパスを記入する
- セルB7は指定したフォルダからファイル名のみを一覧化する
- セルC7はフォルダパスを含めたファイル名を一覧化する
- セルD6は拡張子をプルダウンで指定できる(何も入力されていないとすべての拡張子を取得)
- 最後にツールを実行するボタンを設置(VBEから直接実行しても良い)
- 一覧化したファイル名やパスは再度ツールを実行すると一覧がクリアされます
今回のツールのコードは上記のレイアウトを指定しているので一度同じように作成していただき、ツールの使用感を確かめてからfileのレイアウトを自分流に修正してみてください。
コードの貼り付け方
Excelのツールバーから開発⇒Visual basicを選択します。
上記の画像の通りに、挿入⇒標準モジュールを選択します。
標準モジュールの入力箇所が表示されるので上記画像の『ここに貼り付ける』にコードを貼り付けます。
貼り付けると下記3種類のプロシージャが表示されます。ツール使用者が実行するプロシージャは3番目のmain()になります。
他2つはツール内で呼び出されるプロシージャとなるので
- 前処理を記述しているbeforeProcess()
- メイン処理を行うSub mainProcess()
- 上記2つのプロシージャを呼び出して実行するmain()
あとはVBEから直接ツールを実行するか、もしくはファイルの画面説明で紹介した通りボタンを設置してマクロを登録すれば処理を実行することができます。
注意点としてVBAを利用する設定を行っていないとExcelのタスクバーには『開発』という項目は表示されません。
画面に表示のない方は下記の記事で設定方法を紹介しているのでご確認ください。
コード構成と処理の解説
それではツールの構成と処理の解説をさせていただきます。それなりに行数があるため解説が長くなりますので、不明点のある部分だけの確認でも問題ありません。
まず本ツールは3つのSubプロシージャから構成されています。
- 前処理を記述しているbeforeProcess()
- メイン処理を行うSub mainProcess()
- 上記2つのプロシージャを呼び出して実行するmain()
ツールの前処理 beforeProcess()
まずは前処理から解説していきます
Sub beforeProcess() 'ファイル名一覧を出力する行番号を指定します。 startRow = 7 '対象フォルダのパスがあるセルを指定し、値を代入します。 folderPass = Range("C5").Value '拡張子の選択 ext = Range("D6").Value '指定範囲の値をクリア Range("B7:C10000").ClearContents Range("B7:E10000").Interior.ColorIndex = 0 End Sub
4.startRow = 7
ファイル名一覧を出力する最初の行番号を変数startRowに格納しています。最初に出力されるのはファイル説明の画像からわかる通り7行目からですので7を代入しています。
7.folderPass = Range(“C5”).Value
変数folderPassにセルC5に記入されたフォルダパスを代入しています。このパスからファイル一覧を取得する場所を指定します。
綴りが間違えていることに今気が付きましたが大目に見てください。
10.ext = Range(“D6”).Value
変数extは拡張子を代入する変数です。セルD6に記載されている拡張子を格納しています。格納した値によって一覧を取得するファイル名の拡張子が変化します。
13~14.
Range(“B7:C10000”).ClearContents
Range(“B7:E10000”).Interior.ColorIndex = 0
前回のファイル名一覧取得結果をクリアする記述です。
“ClearContents“はセルの書式を残して値のみ削除します。
“Interior.ColorIndex =0″は背景色を無色にします。
一覧を取得する本処理 mainProcess()
一覧を取得する本処理の記述となります。少し長いですがしっかりと解説していきますのでお付き合いください。
Sub mainProcess(folderPass As String, startRow As Integer) Dim fso As Object Dim filePath As Object Dim subFilePath As Object '対象フォルダのパスの値があれば処理 If folderPass = "" Then MsgBox "C5セルにフォルダパスを記入してください" Exit Sub Else 'ファイルやフォルダを操作するオブジェクトFileSystemObjectを変数にセット Set fso = CreateObject("Scripting.FileSystemObject") 'ファイル情報を出力 For Each filePath In fso.GetFolder(folderPass).Files '拡張子を判定 If (LCase(fso.GetExtensionName(filePath)) = LCase(ext)) Then 'ファイル名・ファイルパスの出力 Cells(startRow, 2) = filePath.Name Cells(startRow, 3) = filePath.Path startRow = startRow + 1 ElseIf LCase(ext) = "" Then Cells(startRow, 2) = filePath.Name Cells(startRow, 3) = filePath.Path startRow = startRow + 1 End If Next filePath 'サブフォルダ内のファイル名取得の処理 For Each subFilePath In fso.GetFolder(folderPass).SubFolders If subFilePath.Name <> "" Then 'サブフォルダのパスをmainProcessに渡して再帰的に処理 Call mainProcess(subFilePath.Path, startRow) End If Next subFilePath End If Set fso = Nothing Set filePath = Nothing Set subFilePath = Nothing End Sub
11.Set fso = CreateObject(“Scripting.FileSystemObject”)
Scripting.FileSystemObjectはファイルやフォルダを操作するためVBAが用意してくれた既存のオブジェクトです。
ですが、これは単体では使用することができません。このオブジェクトを使用するにはCreateObjectメソッドを利用してインスタンス化してあげる必要があります。
インスタンス化などの専門用語も多く理解が難しいかもしれませんが、ファイル操作をするためには頻出の構文なので決まり文句だと思ってとりあえずオブジェクト変数に格納しておいてください。
ちなみに定義した変数fsoはFileSystemObjectの略でこのオブジェクトを利用する際にはよく用いられています。
14.For Each filePath In fso.GetFolder(folderPass).Files
fso.GetFolder(folderPass).Filesで指定したフォルダ内のすべてのファイルを取得しています。後は取得したファイルをfor eachで出力します。
GetFolder(folderPass)の引数として使用しているfolderPassは前処理のプロシージャでフォルダの古パスを格納した変数です。引数としては変数ではなくダブルクォーテーションで直接パスを記入しても使用することができます。
16.If (LCase(fso.GetExtensionName(filePath)) = LCase(ext)) Then
14ですべてのファイルを取得しましたが、16では取得したファイルの拡張子を出力対象としている拡張子かどうかを判定しています。
fso.GetExtensionName(filePath)は各ファイルの拡張子を取得します。判定先のextは前処理で出力対象とする拡張子を格納した変数です。
上記2つの値を囲っているLCase()は取得した拡張子の文字を小文字にするための処理です。同じ拡張子を指定しても文字の大小で正常に判定が行われないようになるのを防ぐためです。
18~19.
Cells(startRow, 2) = filePath.Name
Cells(startRow, 3) = filePath.Path
指定したセルにファイル名とファイルパスを出力する処理です。
21.ElseIf LCase(ext) = “” Then
拡張子を指定していない場合の処理です。変数の値が空であればすべての拡張子のファイルを出力します。
28.For Each subFilePath In fso.GetFolder(folderPass).SubFolders
サブフォルダのパスを取得する記述です。一つ一つfor eachで処理します。
30.If subFilePath.Name <> “” Then
サブフォルダがあるかどうかを判定しています。特になければサブフォルダを処理せずにマクロは終了します。
32.Call mainProcess(subFilePath.Path, startRow)
サブフォルダのパスが格納されていれば実行される処理です。Callで自身のプロシージャを読んでいます。
最初に呼び出されたときは第一引数がセルC5に記入されたフォルダパスでしたが、今回渡しているのはサブフォルダのパスです。ですので新しく呼び出されるとサブフォルダ内のファイルに対してこれまで解説した通りの処理を行います。
各プロシージャを呼び出す処理 main()
実際に使用者が実行するプロシージャです。前述した2つのプロシージャを呼び出すmainプロシージャです。
Option Explicit Dim startRow As Integer Dim folderPass As String Dim ext As String 'ファイル名を取得(サブフォルダを含む) Sub main() '前処理 Call beforeProcess 'ファイル名取得のメイン処理を行うプロシージャを呼び出す Call mainProcess(folderPass, startRow) End Sub
あまり説明する箇所もありませんが、宣言セクションで記載している変数に注目していただければわかる通りモジュール内のすべてのプロシージャで利用できるようにしています。
ツール作成の時は機能を追加するたびに処理を実装したプロシージャを呼び出す形式でコードを書くと修正やコードの可読性が上がります。
私もまだまだで本当は後処理なども別で作成したかったのですが力尽きました。
時間のある時にまた改修していきたいと思います。
また今回の解説で分かりにくい点などあればご連絡ください。できる限り対応したいと思います。