フルパスをパスとファイル名に分ける


先日メールで質問されたネタです。「"C:\Sample\Sub\Book1.xls"というフルパスを"C:\Sample\Sub\"と"Book1.xls"に分割するにはどうしたらいいのですか?」と。・・・当サイトではTipsなどで普通にやってますけど、あらためて「よくわからない」と言われたので独立したコンテンツとして解説しましょう。

ここでは次のようなファイルを対象にします。

基本的な考え方

まずは古典的なやり方から。この方法は手間がかかりますけど、応用すればいろいろなケースに応用できます。

パス+ファイル名という文字列を「パス」と「ファイル名」に分けるには、どこで分割すればいいかを考えます。パスの区切りは「\」記号で表されますので、(1)文字列を後ろから1文字ずつ見ていって最初に存在する「\」の位置を調べなければなりません。次に(2)その位置から左側(パス)と右側(ファイル名)に分割します。

(1)の位置を調べるにはInstrRev関数を使います。InstrRev関数は、指定した文字を後ろから探して、見つかった(先頭からの)位置を返す関数です。次のコードは「14」を表示します。

Sub Sample1()
    Dim PathName As String, FileName As String, pos As Long
    pos = InStrRev("C:\Sample\Sub\Book1.xls", "\")
    MsgBox pos
End Sub

分割する位置がわかりました。次は(2)の処理です。文字列の左側を抜き出すのはLeft関数、ある位置から後ろを抜き出すにはMid関数を使います。次のコードは、フルパス文字列を「左から14文字」と「15文字より後ろ全部」に分割して表示します。

Sub Sample2()
    Dim PathName As String, FileName As String, pos As Long
    pos = InStrRev("C:\Sample\Sub\Book1.xls", "\")
    PathName = Left("C:\Sample\Sub\Book1.xls", pos)
    FileName = Mid("C:\Sample\Sub\Book1.xls", pos + 1)
    MsgBox PathName & vbCrLf & FileName
End Sub

"Dir関数の特性"と"置換の応用"

さて、考え方を工夫すると、もっとシンプルに処理することも可能です。

まず使うのはDir関数です。Dir関数は指定したファイルが存在するとき、そのファイル名を返す関数です。このとき、Dir関数が返すファイル名にはパスが含まれません。つまり、純粋なファイル名だけならDir関数だけで取得することができるのです。

次のコードは、Dir関数で「C:\Sample\Sub\Book1.xls」の存在を確認します。

Sub Sample3()
    Dim PathName As String, FileName As String
    FileName = Dir("C:\Sample\Sub\Book1.xls")
    MsgBox FileName
End Sub

これでファイル名は取得できました。さてパスはどうしましょう。ここでは「左から○文字を抜き出す」と考えるのではなく「C:\Sample\Sub\Book1.xls」を「C:\Sample\Sub\」に変換します。「C:\Sample\Sub\Book1.xls」から「Book1.xls」を消し去れば「C:\Sample\Sub\」が残ります。つまりパスとは、「パス」+「ファイル名」から「ファイル名」を除去した部分と考えられます。

ファイル名(Book1.xls)を除去するということは、ファイル名(Book1.xls)を空欄に置換するのと同じことです。任意の文字列を置換するにはReplace関数を使います。ちょっとテストしてみましょう。

Sub Sample4()
    MsgBox Replace("田中亨", "亨", "達也")
End Sub

「パス」+「ファイル名」の「ファイル名」を空欄に置換するのですから、

    Replace("C:\Sample\Sub\Book1.xls", "Book1.xls", "")

となります。先に「Book1.xls」はDir関数で取得して変数に格納していますから、次のように書けますね。

Sub Sample5()
    Dim PathName As String, FileName As String
    FileName = Dir("C:\Sample\Sub\Book1.xls")
    PathName = Replace("C:\Sample\Sub\Book1.xls", FileName, "")
    MsgBox PathName & vbCrLf & FileName
End Sub

ファイルが存在しない場合

上記のDir関数とReplace関数を使うやり方はとてもシンプルです。しかし問題点もあります。それは存在しないファイルには使えないということです。Replace関数で置換するファイル名はDir関数で取得しています。ところがDir関数は、ファイルが存在しないとき空欄を返すのです。これは困りました。

ファイルが存在しない、あるいは存在するかどうかわからない場合は、最初に解説した最後の「\」を調べるやり方で対処できます。あるいは、FileSystemObjectオブジェクトを使う手もあります。FileSystemObjectオブジェクトの詳しい解説は「FileSystemObjectオブジェクト」をご覧ください。

FileSystemObjectオブジェクトのGetFileNameメソッドは、指定した「パス」+「ファイル名」の「ファイル名」部分を返します。実際に存在しないファイル名でもエラーにならず、最後の「\」から後ろを返してくれます。

存在しないファイルでも、ファイル名をGetFileNameメソッドで取得できるのですから、先のようにReplace関数で「パス」部分を作り出すことも可能です。しかし、せっかくFileSystemObjectオブジェクトを使うのですから、パスも専用のコマンドを覚えましょう。「パス」+「ファイル名」の形式から「パス」部分を取得するにはGetParentFolderNameメソッドを使います。

Sub Sample6()
    Dim FSO, PathName As String, FileName As String
    Set FSO = CreateObject("Scripting.FileSystemObject")
    FileName = FSO.GetFileName("C:\Sample\Sub\Book1.xls")
    PathName = FSO.GetParentFolderName("C:\Sample\Sub\Book1.xls")
    Set FSO = Nothing
    MsgBox PathName & vbCrLf & FileName
End Sub

GetParentFolderNameメソッドが返すパスは、末尾に「\」がつかない点に留意してください。