1. 発端
ファイルのフルパスから、親フォルダやファイル名を取得したいことがあった。
FileSystemObjectのGet~Nameメソッドを使えば簡単に取得できるが、毎回インスタンスするのも面倒、ということで勉強も兼ねてFunctionプロシージャで自作してみることにした。
2. 仕様
-
引数1:String
ファイル、またはフォルダーのフルパス -
戻り値:String配列
分解されたパスが入った配列
表1. 戻り値対応表
添え字 | 中身 | 対応メソッド |
---|---|---|
0 | 親フォルダへのパス | GetParentFolderName |
1 | 拡張子付きファイル名 | GetFileName |
2 | 拡張子無しファイル名 | GetBaseName |
3 | 拡張子 | GetExtensionName |
3. 結果
Option Explicit
Enum SplitPathIndex
spParentDir
spFileName
spBaseName
spExtension
End Enum
Public Function SplitPath(ByRef iFullPath As String) As String()
Const DirSeparator$ = "\", ExtSeparator$ = "."
Dim oArray(3) As String
Dim pos As Long
Let pos = InStrRev(iFullPath, DirSeparator)
Let oArray(spParentDir) = VBA.Left$(iFullPath, pos - 1&)
Let oArray(spFileName) = VBA.Mid$(iFullPath, pos + 1&)
'pos 再利用
Let pos = InStrRev(oArray(spFileName), ExtSeparator)
'拡張子無しの場合の対応
If pos = 0& Then
Let oArray(spBaseName) = oArray(spFileName)
Let oArray(spExtension) = ""
Else
Let oArray(spBaseName) = VBA.Left$(oArray(spFileName), pos - 1&)
Let oArray(spExtension) = VBA.Mid$(oArray(spFileName), pos + 1&)
End If
Let SplitPath = oArray
End Function
"SplitPath"関数にファイルのフルパスを入れると動作する。
なお、VBAで配列の戻り値を受け取る場合は、該当型の動的配列が必要である。
今回の場合は、
Dim 受け取る変数() As String
と宣言する必要がある。
また、添え字用に"SplitPathIndex"列挙体も宣言している。
4. 処理速度比較
以下のプロシージャを作成して速度の比較を行ってみた。
(要参照設定:"Microsoft Scripting Runtime" 又は "Windows Script Host Object Model")
Sub 処理速度比較()
Const TestPath$ = "C:\SampleDir\SampleFile.txt"
Const LoopCnt& = 10000
Dim start As Single, lap As Single
Dim myArray() As String
Dim i As Long
Debug.Print LoopCnt; "回ループ"
start = Timer
For i = 1 To LoopCnt
myArray = SplitPath(TestPath)
Erase myArray
Next i
lap = Timer - start
Debug.Print "自作関数"; lap; "秒"
With New FileSystemObject
start = Timer
For i = 1 To LoopCnt
ReDim myArray(3)
myArray(0) = .GetParentFolderName(TestPath)
myArray(1) = .GetFileName(TestPath)
myArray(2) = .GetBaseName(TestPath)
myArray(3) = .GetExtensionName(TestPath)
Erase myArray
Next i
lap = Timer - start
End With 'New FileSystemObject
Debug.Print "FileSystemObject"; lap; "秒"
End Sub
私の環境(Windows10 Pro64bit & MSOffice2016 64bit / Windows8.1 Pro64bit MSOffice2013 32bit)
で実行したところ、FileSystemObjectの方が処理が早く、今回作成した関数の半分程度の時間で処理が終了した。
ある程度FileSystemObjectに有利な設定にしているので、まあ当然の結果である。
なお、FileSystemObjectを毎回インスタンスし直したり、遅延バインディングしていた場合は余裕で逆転する。
特に遅延バインディングだと目に見えて実行速度が低下する。
5. まとめ
餅は餅屋、速度を考えると本職に任せた方が早い。