1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【VBA】FileSystemObjectのGet~Nameメソッドを関数で自作してみる

Posted at

1. 発端

ファイルのフルパスから、親フォルダやファイル名を取得したいことがあった。
FileSystemObjectのGet~Nameメソッドを使えば簡単に取得できるが、毎回インスタンスするのも面倒、ということで勉強も兼ねてFunctionプロシージャで自作してみることにした。

2. 仕様

  • 引数1:String
    ファイル、またはフォルダーのフルパス

  • 戻り値:String配列
    分解されたパスが入った配列

表1. 戻り値対応表

添え字 中身 対応メソッド
0 親フォルダへのパス GetParentFolderName
1 拡張子付きファイル名 GetFileName
2 拡張子無しファイル名 GetBaseName
3 拡張子 GetExtensionName

3. 結果

SplitPath.bas
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. まとめ

餅は餅屋、速度を考えると本職に任せた方が早い。

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?