【ExcelVBA】フルパスからフォルダとファイルどちらなのかを特定するには

この記事では、フルパスからフォルダとファイルどちらなのかを特定する方法についてご説明します。

【動画】フルパスからフォルダとファイルどちらなのかを特定する実際の動き

本題に入る前に、まずは次の動画をご覧ください。


指定したフォルダからファイルとフォルダのフルパスをCSVファイルに出力し、そのフルパスからフォルダとファイルどちらなのかを特定しています。

フルパスからフォルダとファイルどちらなのかを特定する方法

フルパスからフォルダとファイルどちらなのかを特定するには、次の流れの通りマクロを作成します。

マクロ作成の流れ

STEP.1
コマンドプロンプトを呼び出してサブフォルダ含めてフォルダ内の全てのフォルダ名とファイル名を取得したいディレクトリをCSVファイルに書き出す
コマンドプロンプトを呼び出してサブフォルダ含めてフォルダ内の全てのフォルダ名とファイル名を取得したいディレクトリをCSVファイルに書き出します。
STEP.2
STEP.1のCSVファイルを読み込む
STEP.1のCSVファイルを読み込みます。
STEP.3
読み込んだCSVファイルから、フォルダかファイルかを判定する
読み込んだCSVファイルから、フォルダかファイルかを判定します。

マクロを実行するExcelファイル(例)

今回ご紹介するマクロを実行するExcelファイル(例)は次の画像の通りです。

「searchpath」という名前が付けられたオレンジ色のセルに、格納されているフォルダとファイルのどちらかを判定するフォルダパスを入力して実行ボタンをクリックするとマクロが実行されます。

マクロが実行されると、フルパスに対してフォルダなのかファイルなのかをセル(D列)に書き出します。(下の画像が、マクロ実行後に拡張子が出力された後のイメージ)

コードの例

Excelのマクロとバッチファイルのコードは次の通りに記述していきます。

Option Explicit

Private Sub btn_exec_Click()

    Dim buf                 As String                   '一時的な値の格納先変数
    Dim getPath             As String                   '確認したいフォルダとファイルが格納されたフォルダパス
    Dim cmdTxt              As String                   'コマンドプロンプトのコード用変数
    Dim fldrFileNMExptTxt   As String                   'フォルダ名とファイル名が出力されたファイル名
    Dim st                  As ADODB.Stream             'バイナリ データまたはテキストのストリームのインスタンス用変数
    Dim wshObj              As WshShell                 'WshShellオブジェクト
    Dim fso                 As FileSystemObject         'FileSystemObjectのインスタンス用変数
    Dim rowCnt              As Long                     '行位置用カウンタ
    Dim itmNumCnt           As Long                     '項番用カウンタ
    
    'フォルダ名とファイル名を出力させるCSVファイル名を取得する
    fldrFileNMExptTxt = ActiveWorkbook.Path & "\" & "data.csv"
    
    '確認したいフォルダとファイルが格納されたフォルダパスを取得する
    getPath = Sheets("top").Range("searchpath").Value
    
    'フォルダかファイル化を確認した結果を出力する最初のセルの行を設定する
    rowCnt = 11
    
    '項番の初期値を設定する
    itmNumCnt = 1
    
    'バイナリ データまたはテキストのストリームのインスタンスを生成する
    Set st = New ADODB.Stream
    
    'FileSystemObjectのインスタンスを生成する
    Set fso = New FileSystemObject
    
    'WshShellオブジェクトからインスタンスを生成する
    Set wshObj = New WshShell
    
    If Right(getPath, 1) <> "\" Then
    
        '入力されたパスの末尾に「\」が付いていない場合に付ける
        getPath = getPath & "\"
        
    End If
    
    '実行するコマンド:dirコマンドでフルパスをCSVファイルに書き出す
    cmdTxt = "chcp 65001 | dir /b " & """" & getPath & """" & " > " & fldrFileNMExptTxt
    
    'コマンドプロンプトで変数「cmdTxt」のコマンドを実行する
    Call wshObj.Run("%ComSpec% /c " & cmdTxt, 1, WaitOnReturn:=True)
        
    With st
    
        .Charset = "UTF-8"                              '文字セットにUTF-8を設定する
        .Open                                           'streamを開く
        .LoadFromFile fldrFileNMExptTxt                 'フォルダ名とファイル名が出力されたファイルから読み込む
        
        If fso.GetFile(fldrFileNMExptTxt).Size = 0 Then
        
            '検索対象のデータが存在しない場合
            
            MsgBox "ファイルがありません。"
            
            '処理終了
            Exit Sub

        End If
        
        'Streamの末尾まで繰り返す
        Do Until .EOS
                
            '取り出したテキストを変数「buf」に格納する
            buf = getPath & .ReadText(adReadLine)
            
            '項番をB列のセルに出力する
            Sheets("top").Range("B" & rowCnt).Value = itmNumCnt
            
            'フォルダ名/ファイル名をC列のセルに出力する
            Sheets("top").Range("C" & rowCnt).Value = buf
            
            'フルパスがフォルダなのかファイルなのかを判定する(True:ファイル/False:フォルダ)
            If fso.FileExists(buf) Then
                
                'ファイルの場合
                
                '「ファイル」の文言をD列のセルに出力する
                Sheets("top").Range("D" & rowCnt).Value = "ファイル"
                
            Else
            
                'フォルダの場合
                
                '「フォルダ」の文言をD列のセルに出力する
                Sheets("top").Range("D" & rowCnt).Value = "フォルダ"                
                                                                           
            End If
            
            'カウンタを1つ増やす
            rowCnt = rowCnt + 1
            
            '項番の値を1つ増やす
            itmNumCnt = itmNumCnt + 1
            
            DoEvents
            
        Loop
        
        'Streamの末尾まで処理が終わったので、streamを閉じる
        .Close
           
    End With
    
    '後処理
    
    'フォルダ名とファイル名が出力されたファイルを削除する
    Call fso.DeleteFile(fldrFileNMExptTxt, True)
    
    Set wshObj = Nothing
    Set st = Nothing
    Set fso = Nothing
    
    MsgBox "完了"

End Sub

コードの解説

注目すべきコード①

最初に見て頂きたいのは44行目から47行目です。

    '実行するコマンド:dirコマンドでフルパスをCSVファイルに書き出す
    cmdTxt = "chcp 65001 | dir /b " & """" & getPath & """" & " > " & fldrFileNMExptTxt
    
    'コマンドプロンプトで変数「cmdTxt」のコマンドを実行する
    Call wshObj.Run("%ComSpec% /c " & cmdTxt, 1, WaitOnReturn:=True)

44行目でフォルダ名とファイル名を出力させるCSVファイルの出力を行うコマンド文(dirコマンド)を変数「cmdTxt」に格納し、47行目でそのコマンドをコマンドプロンプトで実行します。

なぜわざわざコマンドプロンプトを使っているのか(呼び出しているのか)というと、dirコマンド一つだけでフォルダ名とファイル名を一気に書き出してくれるからです。

フォルダ名やファイル名を取得するのにFileSystemObjectオブジェクトのGetFileNameメソッドやdir関数を使うやり方もありますが、本記事ではファイル名やフォルダ名を取得するのにコマンドプロンプトのdirコマンドを使う方法を採用しました。

なお、コマンドプロンプトで実行するコマンド文は、実は2つのコマンドを1行で実行しています。

2つのコマンド(例)は次の通りです。(コマンド文は「部分一致」のコマンド文)
①chcp 65001
②dir /b “C:\work\” > C:\work\data.csv

コマンドの説明
  1. ①のコマンドは、文字コードをUTF-8に設定するコマンドで、文字化けしないように文字コードをUTF-8に設定しています。
    (文字コードをUTF-8に設定すると文字化けしない)
  2. ②のコマンドは、dirコマンドを実行して、サブフォルダ含めて全ファイルと全フォルダの一覧をファイル「data.csv」に出力しています。
コマンドの「|」とは?
コマンドで使われている「|」の文字は、実行する複数のコマンドを1行で記述したい時に使う文字です。

以上、上記のコマンドが実行されると、フォルダ名とファイル名が出力された「data.csv」というファイルが出力されます。

この「data.csv」をExcelマクロが読み込んでフォルダかファイルかを判定し、ファイルの場合は拡張子を取得します。

ちなみに、フォルダ名とファイル名を全てセルに書き出したら、必要がなくなるので114行目で削除します。

    'フォルダ名とファイル名が出力されたファイルを削除する
    Call fso.DeleteFile(fldrFileNMExptTxt, True)
注目すべきコード②

次に見て頂きたいのは49行目から53行目です。

    With st
    
        .Charset = "UTF-8"                              '文字セットにUTF-8を設定する
        .Open                                           'streamを開く
        .LoadFromFile fldrFileNMExptTxt                 'フォルダ名とファイル名が出力されたファイルから読み込む

51行目で文字コードをUTF-8に設定し、フォルダ名とファイル名が出力された「data.csv」をExcelマクロが読み込むためにCharsetプロパティに「UTF-8」の文字列を設定しています。

次に52行目でOpenメソッドを実行し、53行目のLoadFromFile メソッドの引数に「data.csv」を設定して「data.csv」を読み込みます。

注目すべきコード③

次に見て頂きたいのは67行目から93行目です。

        'Streamの末尾まで繰り返す
        Do Until .EOS
                
            '取り出したテキストを変数「buf」に格納する
            buf = getPath & .ReadText(adReadLine)
            
            '項番をB列のセルに出力する
            Sheets("top").Range("B" & rowCnt).Value = itmNumCnt
            
            'フォルダ名/ファイル名をC列のセルに出力する
            Sheets("top").Range("C" & rowCnt).Value = buf
            
            'フルパスがフォルダなのかファイルなのかを判定する(True:ファイル/False:フォルダ)
            If fso.FileExists(buf) Then
                
                'ファイルの場合
                
                '「ファイル」の文言をD列のセルに出力する
                Sheets("top").Range("D" & rowCnt).Value = "ファイル"

            Else
            
                'フォルダの場合
                
                '「フォルダ」の文言をD列のセルに出力する
                Sheets("top").Range("D" & rowCnt).Value = "フォルダ"                
                                                                           
            End If

67行目のDo Until .EOSのコードは、CSVファイルを最後の行まで読み込む、という意味です。

70行目では、読み込んだCSVファイルを1行取り出して変数「buf」に格納しています。なお、読み込んだ1行はフォルダ名かファイル名のどちらかです。

79行目では、70行目で取得したフルパスがフォルダなのかファイルなのかを、FileSystemObjectオブジェクトのFileExistsのメソッドを使って判定しています。

FileExistsのメソッドの引数にフルパス(上記コードでは変数bufにフルパスが格納されています)を指定して実行すると、TrueかFalseが返ってきます。

Trueはファイル、Falseはフォルダを指します。

以上でフルパスからフォルダかファイルなのか特定できました。

動作確認

マクロの実行前と実行後は次の通りです。

マクロ実行前

「searchpath」という名前が付けられたオレンジ色のセルに、格納されているフォルダとファイルのどちらかを判定するフォルダパスを入力して実行ボタンをクリックするとマクロが実行されます。

マクロ実行後

マクロの処理が完了すると、フルパスに対してフォルダなのかファイルなのかがセル(D列)に書き出されています。

【注意】参照設定が必要です

一つ注意点があるのですが、先ほどのコードを動かすには参照設定が必要です。

参照設定の一覧(下の画像を参考)から次の項目(ライブラリ)にチェックを付けて「OK」ボタンをクリックします。

  1. Microsoft ActiveX Data Objects 2.8 Library(msado28.tlb)
  2. microsoft office 15.0 access database engine object library(ACEDAO.DLL)

なぜ必要かというと、先ほどのコードの9行目の「ADODB.Stream」というオブジェクトが「msado28.tlb」というファイルを、先ほどのコードの10行目の「WshShell」と11行目の「FileSystemObject」というオブジェクトが「wshom.ocx」というファイルを参照するからです。

    Dim st                  As ADODB.Stream             'バイナリ データまたはテキストのストリームのインスタンス用変数
    Dim wshObj              As WshShell                 'WshShellオブジェクト
    Dim fso                 As FileSystemObject         'FileSystemObjectのインスタンス用変数

この参照設定をしないと下の画像のエラーが出ますので必ず行う必要があります。

ここでは「msado28.tlb」と「wshom.ocx」とは何者かについては記事の本題から逸れてしまうので詳細は割愛しますが、マクロで「WshShell」「ADODB.Stream」「FileSystemObject」というオブジェクトを使う場合は参照設定しないと動かない、程度に思って頂ければと思います。

最後に

本記事では、フルパスからフォルダとファイルどちらなのかを特定する方法についてご説明しました。

FileSystemObjectオブジェクトのFileExistsメソッドを使うことで、フルパスに対してフォルダとファイルどちらかを特定することができます。

フルパスからフォルダとファイルどちらなのかを特定したい時は参考にしてみてくださいね。

プログラミングのスキルを習得するなら

プログラミングのスキルを習得したい、今のスキルをもっと高めたい、そう考えているなら「プログラミングスクール」がおすすめです。

プログラミングのスキルの基礎を身につけるなら「TechAcademy」で1週間の無料体験があるので、これで「プログラミングの基礎」を学ぶのにおすすめですよ。

→ TechAcademyの「1週間 無料体験」はこちら