• Source
    1. Option Explicit
    2.  
    3. Dim dicT As Object '連想配列 キー:フォルダ名 値:行番号
    4. Dim dicN As Object '連想配列 キー:フォルダ名 値:検出時の連番
    5. Dim ws As Worksheet '処理対象シート
    6. Public Sub フォルダ検索()
    7. Dim lastrow As Long '最終行
    8. Dim lastcol As Long '最終列
    9. Dim wrow As Long '行番号
    10. Dim folder As String 'フォルダー名
    11. Dim t0 As Double '開始時間
    12. Dim t1 As Double '終了時間
    13. Set dicT = CreateObject("Scripting.Dictionary") ' 連想配列の定義
    14. Set dicN = CreateObject("Scripting.Dictionary") ' 連想配列の定義
    15. dicT.CompareMode = vbTextCompare
    16. dicN.CompareMode = vbTextCompare
    17. Set ws = Worksheets("フォルダ検索")
    18. lastrow = ws.Cells(Rows.count, "A").End(xlUp).Row 'A列の最終行取得
    19. If lastrow < 2 Then Exit Sub
    20. '検索対象のフォルダ名を取得し、連想配列に格納する
    21. For wrow = 2 To lastrow
    22. folder = ws.Cells(wrow, "A").Value
    23. 'フォルダ名が空欄はエラー
    24. If folder = "" Then
    25. MsgBox ("フォルダ名が空白")
    26. ws.Activate
    27. ws.Cells(wrow, "A").Select
    28. Exit Sub
    29. End If
    30. 'フォルダ名が連想配列に未登録なら、連想配列に登録する
    31. If dicT.exists(folder) = False Then
    32. dicT(folder) = wrow
    33. dicN(folder) = 0
    34. Else
    35. 'フォルダ名が連想配列に登録済みならエラー
    36. MsgBox (folder & "が重複")
    37. ws.Activate
    38. ws.Cells(wrow, "A").Select
    39. Exit Sub
    40. End If
    41. '当該行のB列~最終列迄をクリアする
    42. lastcol = ws.Cells(wrow, Columns.count).End(xlToLeft).Column 'wrow行目の最終列を求める
    43. ws.Cells(wrow, "B").Value = 0
    44. If lastcol > 2 Then
    45. ws.Cells(wrow, "C").Resize(1, lastcol - 2).Value = ""
    46. End If
    47. Next
    48. t0 = Timer
    49. folder = "C:"
    50. Call FindSubfolders(folder) 'Cドライブの検索
    51. folder = "D:"
    52. Call FindSubfolders(folder) 'Dドライブの検索
    53. t1 = Timer
    54. Application.StatusBar = False 'ステータスバーのクリア
    55. MsgBox ("完了 処理時間=" & (t1 - t0) & "秒")
    56. End Sub
    57. '指定フォルダー内の検索(再帰処理)
    58. Private Sub FindSubfolders(ByVal folder As String)
    59. Dim fname As String 'フォルダ名
    60. Dim fnames() As String 'フォルダ名の配列
    61. Dim fcount As Long: fcount = 0 'フォルダ数
    62. Dim i As Long
    63. Dim wrow As Long '行番号
    64. Dim fno As Long 'フォルダ検出時の連番
    65.  
    66. On Error GoTo ERROR99 'アクセス件等でエラーが発生した場合は、当該フォルダの処理を打ち切る
    67. Application.StatusBar = folder 'ステータスバーに指定フォルダ名を表示
    68. '指定フォルダ内のフォルダを全て取得し、配列に格納する
    69. fname = Dir(folder & "\*", vbDirectory)
    70. Do While fname <> ""
    71. '取得したファイルがフォルダなら、以下の処理を行う
    72. If IsFolder(folder, fname) = True Then
    73. '取得したフォルダ名が検索対象のフォルダなら、検知件数に1加算し、そのフォルダ名を結果欄に出力する
    74. If dicT.exists(fname) = True Then
    75. fno = dicN(fname) + 1
    76. dicN(fname) = fno
    77. wrow = dicT(fname)
    78. ws.Cells(wrow, 2).Value = ws.Cells(wrow, 2).Value + 1
    79. ws.Cells(wrow, 2 + fno).Value = folder & "\" & fname
    80. End If
    81. '取得したフォルダ名を配列に格納する
    82. ReDim Preserve fnames(fcount)
    83. fnames(fcount) = fname
    84. fcount = fcount + 1
    85. End If
    86. fname = Dir()
    87. Loop
    88. '取得したフォルダ名の配列を順に処理する
    89. For i = 0 To fcount - 1
    90. Dim newfolder As String
    91. newfolder = folder & "\" & fnames(i)
    92. '当該フォルダのその直下のフォルダを検索する
    93. Call FindSubfolders(newfolder)
    94. Next
    95. Exit Sub
    96. ERROR99:
    97. Err.Clear
    98. End Sub
    99. 'フォルダかフォルダ以外かのチェック
    100. '戻り値 True:フォルダ False:フォルダ以外
    101. Private Function IsFolder(ByVal folder As String, ByVal fname As String) As Boolean
    102. IsFolder = False
    103. Dim attr As Long
    104. 'フォルダ名が"."又は".."は除く
    105. If fname = "." Then Exit Function
    106. If fname = ".." Then Exit Function
    107. '属性を取得し、vbDirectoryならフォルダとする
    108. attr = GetAttr(folder & "\" & fname)
    109. If (attr And vbDirectory) <> vbDirectory Then Exit Function
    110. IsFolder = True
    111. End Function
    112.