ファイル名が重複しているときに自動ナンバリングしたファイル名を返すメソッドの改良
ファイル名が重複しているときに自動ナンバリングしたファイル名を返すメソッドの改良
これの改良。
改良後のコード
前回は、イマイチFileSystemObjectを使いこなせていなかったので、FileSystemObjectの実力をもっと活用しようと思う。
リスト1 標準モジュール
Public Function getNameWithoutDuplication( _ ByVal targetDirectoryPath As String, _ ByVal targetFilename As String) As String '……(1)' Dim fsObj As New FileSystemObject If Right(targetDirectoryPath, 1) <> "\" Then _ targetDirectoryPath = targetDirectoryPath & "\" '……(2)' '拡張子を取得' Dim nameExt As String '……(3)' nameExt = fsObj.GetExtensionName( _ targetDirectoryPath & targetFilename) '拡張子を除いた名前を取得' Dim nameBase As String '……(4)' nameBase = fsObj.GetBaseName( _ targetDirectoryPath & targetFilename) Dim n As Long n = 0 Dim tmp As String tmp = targetDirectoryPath & nameBase '接尾辞を作成' Dim suffixStr As String Do While fsObj.FileExists(tmp & suffixStr & "." & nameExt) n = n + 1 suffixStr = "(" & n & ")" Loop getNameWithoutDuplication = nameBase & suffixStr & "." & nameExt Set fsObj = Nothing End Function
まず(1)の
Public Function getNameWithoutDuplication( _ ByVal targetDirectoryPath As String, _ ByVal targetFilename As String) As String
では、引数リストを変更した。
第1引数targetDirectoryPath
で保存先のフォルダパスを受け取り、第2引数targetFileName
ではシンプルにファイル名を受け取る。
前回のやつは、拡張子抜きのフルパスとか、拡張子名とか、取り出すのに特殊な操作が必要なデータを渡す必要があったので、使い勝手が悪かった。少なくとも、三日も経てば使い方を忘れる不親切なものだった。
(2)の
If Right(targetDirectoryPath, 1) <> "\" Then _ targetDirectoryPath = targetDirectoryPath & "\"
で、フォルダパスの右端に「\」を付ける。場合によっては「\」付きで渡すこともあるかと思ったので、右端の文字を確認するようにした。
(3)からの3行(実質2行)
Dim nameExt As String nameExt = fsObj.GetExtensionName( _ targetDirectoryPath & targetFilename)
及び、
(4)からの3行(実質2行)
Dim nameBase As String nameBase = fsObj.GetBaseName( _ targetDirectoryPath & targetFilename)
では、それぞれFileSystemObject
オブジェクトのGetExtensionName
メソッド、GetBaseName
メソッドを用いて、対象ファイルの拡張子名と拡張子を除いたファイル名を取得している。
FileSystemObjectを使ったら、こんなに簡単に、しかも読みやすく書くことができる。
FileSystemObject、チョー便利じゃん!
後は前回同様、FileSystemObject
オブジェクトのFileExsists
メソッドで同名ファイルの有無を確認しながら接尾辞を作成。同名ファイルが存在しなくなるまで「()」(半角カッコ)内の数字をインクリメントさせる。
おわりに
FileSystemObject
オブジェクトのMoveFile
メソッドでファイルを移動させるとき、移動先フォルダに同名のファイルが既にあるとエラーが出るので、MoveFile
メソッドやCopyFile
メソッドにファイル名を渡すときに、このメソッドをかましてやれば安心です。
追記
空腹おやじ (id:Z1000S) さんより、コメントに曰く、
getNameWithoutDuplication = nameBase & suffixStr & "." & nameExt
これだと拡張子のないファイルの場合、末尾に "." が・・・
と。
オ、オーマイガ!!!!!!!!
……というわけで、修正。
リスト2 標準モジュール
Public Function getNameWithoutDuplication( _ ByVal targetDirectoryPath As String, _ ByVal targetFilename As String) As String Dim fsObj As New FileSystemObject If Right(targetDirectoryPath, 1) <> "\" Then '" targetDirectoryPath = targetDirectoryPath & "\" '" End If '拡張子を取得' Dim nameExt As String nameExt = fsObj.GetExtensionName( _ targetDirectoryPath & targetFilename) '「.」(ドット)付きにする。拡張子無しなら空文字になる。' If nameExt <> "" Then nameExt = "." & nameExt '……(*)' '拡張子を除いた名前を取得' Dim nameBase As String nameBase = fsObj.GetBaseName( _ targetDirectoryPath & targetFilename) Dim n As Long n = 0 Dim tmp As String tmp = targetDirectoryPath & nameBase '接尾辞を作成' Dim suffixStr As String Do While fsObj.FileExists(tmp & suffixStr & nameExt) n = n + 1 suffixStr = "(" & n & ")" Loop getNameWithoutDuplication = nameBase & suffixStr & nameExt Set fsObj = Nothing End Function
拡張子を取得した直後に、変数nameExt
の中身を「.」(ドット)付きにしてしまえば良いと考えた。拡張子なしのファイルだったら、GetExtensionName
メソッドの返り値が空文字になるので、そのときはnameExt
の中身を空文字のままにしておけば良い。