はじめに
ExcelVBAで業務用のちょっとしたツールを作る時に、ファイルパスからファイル名を取り出す処理を作ることがあります。
ファイル名を取り出す方法として、組み込みのDir
関数を使う方法と、FileSystemObject.GetFileName
を使う方法の2つが知られていますが、両者の機能的な違いをよく理解せずに使っていたので、少し調べてみた結果を記事としてまとめてみました。
Dir関数を使う方法
Dir関数のリファレンスを読むと、「Dirは、pathname に一致する最初のファイル名を返します。」と書かれています。
加えて、「一致するファイル名がなくなると、Dir は長さ 0 の文字列 ("") を返す」という仕様も書かれていました。
つまり、Dir
関数の引数としてファイルパスを指定した時、以下のような挙動になることが分かります。
- 引数で指定したファイルパスが存在する時、ファイル名が返される。
- 引数で指定したファイルパスが存在しない時、空文字が返される。
Option Explicit
' 存在するファイルパス
Private Const FILE_PATH As String = "C:\Users\NKOJIMA\Documents\sample.txt"
' 存在しないファイルパス
Private Const INVALID_FILE_PATH As String = "C:\Users\NKOJIMA\Documents\sample2.txt"
' Dir関数を使って、ファイルパスからファイル名を抽出する。
Sub GetFileNameByDir()
Debug.Print Dir(FILE_PATH) ' 存在するファイルの場合、ファイル名が返される
Debug.Print Dir(INVALID_FILE_PATH) ' 存在しないファイルの場合、空文字が返される
End Sub
sample.txt
←空文字が出力されている
FileSystemObjectを使う方法
FileSystemObject.GetFileNameのリファレンスを読むと、「指定したパスの最後のコンポーネントを、ドライブの指定の一部ではないものとして返します」と書かれています。
加えて、以下の注意書きもありました。
- (引数の)pathspecが名前付きのコンポーネントで終了していない場合、GetFileNameメソッドは長さがゼロの文字列 ("") を返します。
- GetFileNameメソッドは指定されたパス文字列のみを処理します。 パスの解決は試行されず、指定されたパスの存在も確認しません。
つまり、FileSystemObject.GetFileNameの引数としてファイルパスを指定した時、以下のような挙動になることが分かります。
- 引数で指定したファイルパスの存在をチェックせず、機械的にファイルパスの最後のコンポーネント(≒ファイル名)が返される。
また、以下のテストコードで確認したところ、引数で指定したファイルパスがドライブレターの時は空文字が返されました。
リファレンスが分かりにくい日本語ですが、どうやらドライブレターを引数にすると「引数が名前付きのコンポーネントで終了していない場合」に該当するようです。
Option Explicit
' 存在するファイルパス
Private Const FILE_PATH As String = "C:\Users\NKOJIMA\Documents\sample.txt"
' 存在しないファイルパス
Private Const INVALID_FILE_PATH As String = "C:\Users\NKOJIMA\Documents\sample2.txt"
' FileSystemObjectを使って、ファイルパスからファイル名を抽出する。
Sub GetFileNameByFSO()
Dim fso As Object
Set fso = CreateObject("Scripting.FileSystemObject")
' 存在するファイルの場合、ファイル名が返される
Debug.Print fso.GetFileName(FILE_PATH)
' 存在しないファイルの場合でも、ファイル名が返される。
Debug.Print fso.GetFileName(INVALID_FILE_PATH)
' ドライブレターを指定すると、空文字が返される。
Debug.Print fso.GetFileName("C:\")
End Sub
sample.txt
sample2.txt
←空文字が出力されている
どちらが実用的か?
Dir
関数は実質的に「引数で指定したファイルパスの存在をチェックしてくれる」という機能も内包しているため、様々なシーンで使いやすいと思います。
こちらのページを見ると、ファイルパスからファイル名を取り出すシンプルな方法としてDir
関数が紹介されています。
一方で、FileSystemObject
は引数で指定したファイルパスの存在をチェックしないため、存在しない可能性のあるファイルパスや架空のファイルパスに対する処理には向いていると思います。
またVBAに不慣れな人がコードを保守する場合、「Dir
関数の戻り値がファイル名」というのはパッと想像しづらいと思うので、FileSystemObject
を使った方がコードの可読性が向上するのではと感じました。
両者とも甲乙つけ難い...というより、帯に短し襷に長しという感じなので、状況に応じて使い分けるのが良いのかもしれません。