フォルダ内のファイル名から指定の文字列を検索する関数
以下がタイトルのVBAです。
Private Sub 使用例()
Dim filePath() As String ' ファイルパスを格納する動的配列
Dim folderPath(1) As String ' 検索するフォルダのパスを格納
folderPath(0) = "H:\temp"
folderPath(1) = "C:\TEMP"
Dim 検索文字(1) As String ' 検索する文字列の配列
検索文字(0) = "2"
検索文字(1) = "4"
Dim 除外文字(1) As String ' 除外する文字列の配列
除外文字(0) = "t"
除外文字(1) = "w"
Dim 先頭限定 As Boolean: 先頭限定 = False ' 検索文字がファイル名の先頭に限定するかどうか
' フォルダ内のファイルから条件に合致するファイルを検索
Call GetFilePathFromFolders(folderPath(), 検索文字(), 除外文字(), filePath(), 先頭限定)
' 結果をデバッグ出力
If IsInitialized(filePath) Then
Call debugPrintArray(filePath)
Else
Debug.Print "配列が空です"
End If
End Sub
'**************************************
'* 複数のフォルダから、文字列を検索して、ファイル名を返す。
'* folderPath:フォルダのパスを格納した配列
'* 検索文字():検索する文字列を格納した配列
'* 除外文字():除外する文字列を格納した配列。この文字列が含まれるファイルは除外
'* filePath:ファイル名のフルパスを返すため、参照渡しとしている
'* 先頭限定:Trueのとき、検索文字は、先頭にあるときのみ該当。省略時はFalse
Sub GetFilePathFromFolders(ByRef folderPath() As String, ByRef 検索文字() As String, _
ByRef 除外文字() As String, ByRef filePath() As String, _
Optional ByVal 先頭限定 As Boolean = False)
Dim i As Long
For i = LBound(folderPath) To UBound(folderPath)
If folderPath(i) <> "" Then
Call GetFilePath(folderPath(i), 検索文字(), 除外文字(), filePath(), 先頭限定)
End If
Next i
End Sub
'**************************************
'* 文字列を検索して、ファイル名を返す。
'* folderPath:フォルダのパス
'* 検索文字():検索する文字列を格納した配列
'* 除外文字():除外する文字列を格納した配列
'* filePath:ファイル名のフルパスを返すため、参照渡しとしている
'* 先頭限定:Trueのとき、検索文字は、先頭にあるときのみ該当。省略時はFalse
Sub GetFilePath(ByVal folderPath As String, ByRef 検索文字() As String, _
ByRef 除外文字() As String, ByRef filePath() As String, _
Optional ByVal 先頭限定 As Boolean = False)
Dim fso As Object
Dim folder As Object
Set fso = CreateObject("Scripting.FileSystemObject")
Set folder = fso.GetFolder(folderPath)
' フォルダ内のファイル検索を開始
Call FileSerch(folder, 検索文字(), 除外文字(), filePath(), 先頭限定)
' クリーンアップ
Set folder = Nothing
Set fso = Nothing
End Sub
'*******************************
'* フォルダ内のすべてのファイルから、特定の文字列を含むファイルのフルパスを取得する
'* folder:フォルダオブジェクト
'* 検索文字():検索する文字列を格納した配列
'* 除外文字():除外する文字列を格納した配列
'* filePath:ファイル名のフルパスを返すため、参照渡しとしている
'* 先頭限定:Trueのとき、検索文字は、先頭にあるときのみ該当。省略時はFalse
Private Sub FileSerch(ByRef folder As Object, ByRef 検索文字() As String, _
ByRef 除外文字() As String, ByRef filePath() As String, _
Optional ByVal 先頭限定 As Boolean = False)
Dim file As Object
Dim subFolder As Object
Dim 該当 As Boolean
Dim i As Long
' フォルダ内のすべてのファイルを処理
For Each file In folder.Files
該当 = True
' 検索条件に合致するかどうかを確認
For i = LBound(検索文字) To UBound(検索文字)
If 先頭限定 Then
If InStr(1, file.Name, 検索文字(i), vbTextCompare) <> 1 Then
該当 = False
End If
Else
If InStr(1, file.Name, 検索文字(i), vbTextCompare) = 0 Then
該当 = False
End If
End If
Next i
' 除外条件に合致しないかを確認
For i = LBound(除外文字) To UBound(除外文字)
If InStr(1, file.Name, 除外文字(i), vbTextCompare) > 0 And 除外文字(i) <> "" Then
該当 = False
End If
Next i
' 条件に合致するファイルをfilePathに追加
If 該当 Then
If IsInitialized(filePath) Then
ReDim Preserve filePath(UBound(filePath) + 1)
Else
ReDim filePath(0)
End If
filePath(UBound(filePath)) = file.path
End If
Next file
' サブフォルダも再帰的に処理
For Each subFolder In folder.SubFolders
Call FileSerch(subFolder, 検索文字(), 除外文字(), filePath, 先頭限定)
Next subFolder
End Sub
'***************************************************
'* 配列が初期化されているかをチェックする
'* https://qiita.com/nkojima/items/7f8299b3299226a97abb
'* ary:対象となる配列。
'* 戻り値:配列が初期化済みならTrue、そうでなければFalseを返す。
Function IsInitialized(ary As Variant) As Boolean
On Error GoTo NOT_INITIALIZED_ERROR
' 動的配列が初期化されていなければ、ここでエラーが発生する。
Dim length As Long: length = UBound(ary)
IsInitialized = True
Exit Function
' 配列が初期化されていない場合はここに飛ばされる。
NOT_INITIALIZED_ERROR:
IsInitialized = False
End Function
'***************************************************
'* 一次元配列の中身を見やすくイミディエイトウィンドウへ出力する
'* https://vba-create.jp/vba-array-debup-print/
'* tmp:表示させる一次配列
Sub debugPrintArray(ByVal tmp As Variant)
Dim i As Long
' 配列の各要素をイミディエイトウィンドウに出力
For i = LBound(tmp) To UBound(tmp)
Debug.Print i & vbTab & tmp(i) ' 配列要素数と配列の中身を出力
Next i
End Sub
このVBAコードは、特定のフォルダ内のファイル名から指定された文字列を検索し、条件に合致するファイルパスを配列として返す一連のサブルーチンと関数で構成されています。以下は、コード全体の流れと個々のサブルーチンおよび関数の詳細な解説です。
1. 使用例
サブルーチン
このサブルーチンは、メインのエントリーポイントとして機能します。フォルダパスや検索条件を指定し、検索結果をデバッグ出力します。
1. Dim
での変数の宣言
filePath()
:検索結果としてファイルのフルパスを格納するための動的配列です。後でサイズが変更されることを考慮して宣言されています。folderPath(1)
:検索対象のフォルダのパスを格納する固定サイズの配列です。この例では、2つのフォルダが設定されています。folderPath(0)
に「H:\temp」、folderPath(1)
に「C:\TEMP」が設定されています。検索文字(1)
:検索に使用する文字列を格納する配列です。ファイル名に「2」または「4」が含まれているファイルを検索する設定です。除外文字(1)
:検索から除外する文字列を格納する配列です。ファイル名に「t」または「w」が含まれているファイルは除外されます。先頭限定
:ブール値で、検索文字がファイル名の先頭にある場合のみファイルを該当させるかどうかを指定します。この例ではFalse
に設定されており、先頭に限定せずファイル名のどこにでも検索文字がある場合に該当します。
2. Call GetFilePathFromFolders
この部分で実際にフォルダ内のファイルを検索します。GetFilePathFromFolders
サブルーチンに対して、フォルダパスの配列、検索文字の配列、除外文字の配列、ファイルパスの参照、先頭限定のフラグを渡しています。
Call GetFilePathFromFolders(folderPath(), 検索文字(), 除外文字(), filePath(), 先頭限定)
3. If IsInitialized(filePath) Then
この部分で、filePath
配列が初期化されているかどうかを確認します。IsInitialized
という関数は、配列が初期化されているかを判定する役割を持ちます。
- 初期化されている場合、
debugPrintArray
サブルーチンを呼び出して配列の内容をイミディエイトウィンドウに出力します。 - 初期化されていない場合は、「配列が空です」というメッセージを出力します。
If IsInitialized(filePath) Then
Call debugPrintArray(filePath)
Else
Debug.Print "配列が空です"
End If
4. 動作の概要
folderPath
に設定されたフォルダ(H:\temp
とC:\TEMP
)内のファイルを検索します。- ファイル名に「2」または「4」が含まれていて、なおかつ「t」または「w」が含まれていないファイルを見つけます。
- 条件に合致したファイルのフルパスを
filePath
配列に追加します。 - 配列が空でなければ、その結果をイミディエイトウィンドウに出力します。
補足情報
- 配列の参照渡し:
filePath()
は参照渡しされているため、GetFilePathFromFolders
サブルーチン内で配列が更新され、呼び出し元でもその変更が反映されます。 - 動的配列の扱い:
ReDim
キーワードを使用することで、動的配列のサイズを変更し、検索結果に応じてファイルパスを配列に格納します。
2. GetFilePathFromFolders
サブルーチン
このサブルーチンは、複数のフォルダを処理し、各フォルダ内でファイル検索を行います。
このVBAコードでは、複数のフォルダ内から指定された条件に合うファイルを検索し、そのファイルのフルパスを配列に格納するサブルーチン GetFilePathFromFolders
の仕組みについて説明します。
GetFilePathFromFolders
の全体の流れ
- 引数の説明:
folderPath()
:検索対象の複数のフォルダパスを格納する配列です。複数フォルダの中で、特定の文字列を含むファイルを検索するために使用します。検索文字()
:検索したい特定の文字列を格納する配列です。ファイル名にこれらの文字列が含まれているファイルを探します。除外文字()
:除外したい文字列を格納する配列です。ファイル名にこの文字列が含まれる場合、そのファイルは検索結果から除外されます。filePath()
:検索結果としてフルパスを格納する配列です。参照渡しされており、処理の結果、この配列に検索で見つかったファイルのパスが追加されます。先頭限定
:オプション引数で、True
に設定すると検索文字がファイル名の先頭にある場合のみ一致と判断します。デフォルトはFalse
です。
- 繰り返し処理:
For i = LBound(folderPath) To UBound(folderPath)
:配列folderPath
の中の各フォルダに対して繰り返し処理を行います。配列の最初の要素(LBound)から最後の要素(UBound)までループします。
- フォルダが空でないことの確認:
If folderPath(i) <> "" Then
:フォルダパスが空でないことを確認します。空のフォルダパスは無視して次の処理に進みます。
- サブルーチンの呼び出し:
Call GetFilePath(folderPath(i), 検索文字(), 除外文字(), filePath(), 先頭限定)
:現在のフォルダパス(folderPath(i)
)を基に、GetFilePath
という別のサブルーチンを呼び出し、条件に合うファイルを検索します。これによって、フォルダ内のファイルの検索が実行されます。
検索の流れ
GetFilePathFromFolders
は、渡された複数のフォルダに対して一つ一つ、GetFilePath
サブルーチンを呼び出してファイル検索を行います。ファイルが見つかると、そのフルパスが filePath()
配列に追加され、呼び出し元に返されます。
この関数の利点
- 複数のフォルダを一度に検索できるため、複数フォルダの中に特定の文字列を含むファイルがあるかを一括して確認できる。
- 参照渡しでファイルパスの配列を返すため、呼び出し元のサブルーチンでも検索結果を活用することができます。
- 動的なファイル検索が可能で、検索文字や除外文字を簡単に変更して使用できる。
このサブルーチンは他のフォルダ検索処理と組み合わせることで非常に柔軟なファイル検索を実現します。
3. GetFilePath
サブルーチン
指定されたフォルダパス内でファイルを検索し、条件に合致するファイルを見つけます。
- 役割: 指定されたフォルダのファイルを検索するために
FileSerch
サブルーチンを呼び出します。 CreateObject
: FileSystemObject (FSO) を使ってファイルシステムを操作します。
このVBAコードの詳細説明を行います。このサブルーチン GetFilePath
は、指定されたフォルダ内のファイル名を検索し、条件に合ったファイルのパスを取得して配列に格納する役割を持っています。引数としては、検索対象のフォルダ、検索する文字列、除外する文字列、およびオプションの検索条件(ファイル名の先頭に限定するかどうか)を受け取ります。
概要
folderPath
: ファイルを検索する対象フォルダのパスを指定します。これは文字列型の変数です。検索文字()
: 検索したい文字列を格納する配列です。ファイル名にこの文字列が含まれているファイルを検索します。除外文字()
: 除外する文字列を格納した配列です。ファイル名にこの文字列が含まれている場合、そのファイルは検索結果から除外されます。filePath()
: 検索で見つかったファイルのフルパスを格納する配列です。参照渡し(ByRef
)で指定されているため、処理の結果、この配列に検索結果が保存されます。先頭限定
: このオプション引数がTrue
に設定されている場合、検索文字列がファイル名の先頭にある場合にのみ、そのファイルを検索結果として返します。デフォルトはFalse
です。
詳細な説明
Set fso = CreateObject("Scripting.FileSystemObject")
- この行で FileSystemObject を作成します。FileSystemObject はファイルやフォルダを操作するためのオブジェクトです。このオブジェクトを使って、指定されたフォルダ内のファイルやサブフォルダを検索します。
Set folder = fso.GetFolder(folderPath)
folderPath
で指定されたフォルダのオブジェクトを取得します。このフォルダオブジェクトを使用して、フォルダ内のファイルやサブフォルダにアクセスできます。
Call FileSerch(folder, 検索文字(), 除外文字(), filePath(), 先頭限定)
FileSerch
という別のサブルーチンを呼び出して、実際にフォルダ内のファイルを検索します。folder
は対象フォルダオブジェクトで、検索文字
や除外文字
、そしてfilePath
を渡して、条件に合うファイルを探します。このサブルーチン内で、フォルダ内のファイルをチェックし、条件に合ったファイルのフルパスがfilePath
配列に追加されます。
- クリーンアップ
- 処理が完了した後、
Set folder = Nothing
とSet fso = Nothing
でオブジェクトを解放し、メモリをクリーンアップしています。これはVBAでの標準的な手続きで、オブジェクトを使用し終わったらメモリを解放してリソースを節約するために行います。
- 処理が完了した後、
実行の流れ
- フォルダの取得:
fso.GetFolder
で指定フォルダの情報を取得します。 - ファイルの検索:
FileSerch
サブルーチンを呼び出して、フォルダ内のファイルを検索します。 - 条件に合うファイルのフルパスを取得: 検索文字や除外文字を元に条件に合致するファイルのフルパスを、参照渡しされた
filePath()
配列に追加します。
このサブルーチンでは、別のサブルーチンである FileSerch
を呼び出して、フォルダ内のファイルを実際に検索します。そのため、このサブルーチンは主にフォルダの情報を取得して、検索処理の準備をする役割を担っています。
この関数は、複数のフォルダに対して同じ検索条件でファイルを探したい場合に非常に役立ちます。また、動的配列や参照渡しを使うことで、ファイルのパスを効率よく処理できる仕組みが整っています。
4. FileSerch
サブルーチン
指定されたフォルダ内のすべてのファイルを調べ、検索条件に合致するファイルパスを取得します。
- 役割: フォルダ内のファイルを条件に基づいて検索し、結果を
filePath
に追加します。サブフォルダも再帰的に処理します。 - 検索条件:
検索文字
がファイル名に含まれているか、かつ除外文字
が含まれていないかを確認します。
このVBAコードのサブルーチン FileSerch
は、指定されたフォルダとそのサブフォルダ内の全てのファイルを検索し、特定の条件に合致するファイルのフルパスを取得します。具体的には、検索文字列を含むファイルを探し、条件に合わないファイル(除外文字を含むものなど)は無視します。また、この処理はフォルダ内のファイルだけでなく、そのサブフォルダにも再帰的に適用されます。
概要
- folder: 検索対象のフォルダオブジェクトです。このフォルダ内のファイルとサブフォルダを処理します。
- 検索文字(): 検索したい文字列が入った配列です。ファイル名にこの文字列が含まれているファイルを対象とします。
- 除外文字(): 検索から除外したい文字列が入った配列です。ファイル名にこの文字列が含まれている場合は、検索結果から除外されます。
- filePath(): 見つかったファイルのフルパスを格納する配列です。参照渡しされており、処理が終わった時点で結果が格納されます。
- 先頭限定: このオプションが
True
の場合、検索文字列がファイル名の先頭にあるかどうかを条件にします。False
の場合はファイル名のどこかに含まれていれば条件に合致します。
詳細な処理の流れ
- フォルダ内のファイルを処理
For Each file In folder.Files
で、指定されたフォルダ内の全てのファイルを順番に処理します。- 各ファイルについて、以下のステップで条件に合致するか確認します。
- 検索文字列のチェック
- 内部のループ
For i = LBound(検索文字) To UBound(検索文字)
で、指定された複数の検索文字列に対してファイル名にその文字列が含まれているかを調べます。 先頭限定
がTrue
の場合、InStr
関数を使用してファイル名の先頭から一致するかどうか確認します(InStr(1, file.Name, 検索文字(i), vbTextCompare) <> 1
)。False
の場合は、ファイル名のどこにあっても合致します(InStr(1, file.Name, 検索文字(i), vbTextCompare) = 0
だと一致しないと判断)。- もし1つでも条件に合わない場合、
該当
変数をFalse
に設定します。
- 内部のループ
- 除外文字列のチェック
- 同様に
For i = LBound(除外文字) To UBound(除外文字)
で、ファイル名に除外文字が含まれていないか確認します。 - もし除外文字が含まれている場合、
該当
をFalse
に設定し、そのファイルは無視されます。
- 同様に
- ファイルパスの保存
- 条件に合致するファイル(
該当
がTrue
のファイル)の場合、filePath
配列にそのファイルのフルパスを追加します。 IsInitialized(filePath)
でfilePath
配列が初期化されているか確認し、初期化されていない場合はReDim
で配列を初期化します。既に初期化されている場合はReDim Preserve
で配列を拡張し、現在の内容を保持しながら新しい要素を追加します。
- 条件に合致するファイル(
- サブフォルダの再帰的処理
For Each subFolder In folder.SubFolders
で、現在のフォルダ内の全てのサブフォルダを対象に再帰的にFileSerch
を呼び出します。これにより、サブフォルダ内のファイルも同じ条件で検索されます。
ポイント
- 再帰処理: このサブルーチンはサブフォルダに対して再帰的に呼び出されるため、指定されたフォルダ以下の全ての階層に対して同じ条件でファイル検索が行われます。
- 動的配列の使用:
filePath
配列は動的に拡張されるため、検索結果が何件であっても対応可能です。 - 参照渡しによる結果の取得:
filePath
は参照渡しされているため、呼び出し元のサブルーチンで検索結果を直接利用することができます。
このコードは、指定した条件(検索文字列、除外文字列、先頭限定条件)に合ったファイルを効率よく検索し、結果を収集するために設計されています。
5. IsInitialized
関数
このVBA関数 IsInitialized
は、配列が初期化されているかどうかを確認するための関数です。動的配列を扱う際に、配列が初期化されていない場合、エラーが発生する可能性があるため、それをチェックするために使用されます。
関数の概要
- 引数
ary
: チェック対象の配列。Variant
型として渡されます。 - 戻り値: 配列が初期化されている場合は
True
、初期化されていない場合はFalse
を返します。
処理の流れ
- エラーハンドリングの設定:
On Error GoTo NOT_INITIALIZED_ERROR
によって、配列が初期化されていない場合にエラーが発生すると、エラーハンドリング用のラベルNOT_INITIALIZED_ERROR
にジャンプします。これにより、エラーが発生した場合でもコードが停止せず、処理を続けられます。
- 配列の上限を確認:
UBound(ary)
によって配列の上限を取得します。この操作は、配列が初期化されていない場合にはエラーを引き起こします。初期化されていれば上限値が正常に取得でき、次の行に進みます。
- 初期化済みであることを示す:
IsInitialized = True
によって、配列が初期化されていると判断した場合にTrue
を返します。
- エラー時の処理:
- 配列が初期化されていない場合(動的配列が初期化されていない状態)では、エラーが発生し、エラーハンドリング部分
NOT_INITIALIZED_ERROR
にジャンプします。 IsInitialized = False
によって、配列が初期化されていないことを示すFalse
を返します。
- 配列が初期化されていない場合(動的配列が初期化されていない状態)では、エラーが発生し、エラーハンドリング部分
- 終了:
- 初期化されていない場合はエラーが発生し、
False
が返されます。初期化されている場合は、エラーが発生せずTrue
が返されます。
- 初期化されていない場合はエラーが発生し、
利用方法のポイント
- 動的配列のチェック: VBAでは動的配列が初期化されていない場合、アクセスしようとするとエラーが発生します。この関数はそのエラーをキャッチして、配列が初期化されているかどうかを安全に確認します。
- エラーハンドリング: エラーハンドリングを使用しているため、通常のコードの中で配列の状態を確認する際に、処理を止めることなくチェックできます。
この
IsInitialized
関数は、以下から引用しています。ありがとうございます。
6. debugPrintArray
サブルーチン
このVBAコードは、一次元配列の中身を表示するための関数です。配列の各要素をイミディエイトウィンドウ(VBAエディタ内の「デバッグ用」ウィンドウ)に出力することができます。この関数は、デバッグ目的で、配列の中身を簡単に確認するのに便利です。
関数の説明
パラメータ
tmp
: 中身を表示する一次元配列。Variant
型として渡されるため、配列の型には依存しません(文字列でも数値でも扱えます)。
処理の流れ
- 配列のループ処理:
For i = LBound(tmp) To UBound(tmp)
というループで、配列tmp
の最初のインデックス(LBound(tmp)
) から最後のインデックス(UBound(tmp)
) まで繰り返し処理を行います。
- イミディエイトウィンドウへの出力:
Debug.Print
を使用して、配列のインデックス番号と対応する配列の値を表示します。i & vbTab & tmp(i)
は、インデックス番号と配列の中身をタブ区切り(vbTab
)で表示しています。例として、インデックス番号が0
で値が"abc"
の場合、0 abc
というように表示されます。
イミディエイトウィンドウとは
VBA のイミディエイトウィンドウは、コードのデバッグや実行結果を即時に確認できる窓です。Debug.Print
を使って、コードの途中結果や変数の値などをここに出力することができ、エラーの原因を特定したり、コードの動作を確認するのに役立ちます。
この
debugPrintArray
サブルーチンは、以下から引用しています。ありがとうございます。
まとめ
このVBAコードは、フォルダ内のファイルを検索する際に、複数の条件(検索文字と除外文字)を設定してファイルを絞り込む機能を提供しています。検索対象は再帰的にサブフォルダまで処理され、条件に合致したファイルのフルパスが配列に保存されます。