Option Explicit
Sub SearchExcelFiles()
Dim folderPath As String
Dim searchText As String
Dim includeSubfolders As Boolean
Dim startTime As Double
Dim estimatedTime As Double
Dim newWb As Workbook
Dim ws As Worksheet
Dim rowNum As Long
' フォルダ選択オプション
folderPath = InputBox("検索するフォルダのパスを入力(空の場合は選択ダイアログを使用):")
If folderPath = "" Then
With Application.FileDialog(msoFileDialogFolderPicker)
.Title = "検索するフォルダを選択"
If .Show = -1 Then
folderPath = .SelectedItems(1)
Else
Exit Sub
End If
End With
End If
searchText = InputBox("検索する文字を入力:")
If searchText = "" Then Exit Sub
includeSubfolders = (MsgBox("サブフォルダーも検索しますか?", vbYesNo) = vbYes)
' 予測時間計算 (仮の計算: 1ファイルあたり0.5秒)
Dim fileCount As Long
fileCount = CountExcelFiles(folderPath, includeSubfolders)
estimatedTime = fileCount * 0.5
MsgBox "予測時間: " & Round(estimatedTime, 2) & " 秒", vbInformation
' 新しいブックを作成
Set newWb = Workbooks.Add
Set ws = newWb.Sheets(1)
ws.Name = "検索結果"
' ヘッダーの作成とスタイル設定
With ws
.Cells(1, 1).Value = "ブック名"
.Cells(1, 2).Value = "リンク"
.Cells(1, 3).Value = "セルの文字"
.Cells(1, 4).Value = "セルアドレス"
.Cells(1, 5).Value = "フルパス"
.Cells(1, 6).Value = "開いているユーザー"
.Cells(1, 7).Value = "PC名"
.Cells(1, 8).Value = "OS名"
.Cells(1, 9).Value = "ユーザー名"
.Rows(1).Font.Bold = True
.Rows(1).Interior.Color = RGB(0, 112, 192)
.Rows(1).Font.Color = RGB(255, 255, 255)
.Columns.AutoFit
End With
rowNum = 2
' 検索開始
startTime = Timer
SearchFiles folderPath, searchText, includeSubfolders, ws, rowNum
' 列幅の自動調整
ws.Columns.AutoFit
MsgBox "検索完了! 所要時間: " & Round(Timer - startTime, 2) & " 秒", vbInformation
End Sub
Function CountExcelFiles(ByVal folderPath As String, ByVal includeSubfolders As Boolean) As Long
Dim fso As Object, folder As Object, file As Object, subFolder As Object
Dim count As Long
Set fso = CreateObject("Scripting.FileSystemObject")
Set folder = fso.GetFolder(folderPath)
' ファイルカウント
For Each file In folder.Files
If LCase(Right(file.Name, 5)) = ".xlsx" Or LCase(Right(file.Name, 4)) = ".xls" Then
count = count + 1
End If
Next file
' サブフォルダー処理
If includeSubfolders Then
For Each subFolder In folder.SubFolders
count = count + CountExcelFiles(subFolder.Path, True)
Next subFolder
End If
CountExcelFiles = count
End Function
Sub SearchFiles(ByVal folderPath As String, ByVal searchText As String, ByVal includeSubfolders As Boolean, ByVal ws As Worksheet, ByRef rowNum As Long)
Dim fso As Object, folder As Object, file As Object, subFolder As Object
Dim wb As Workbook, wsSheet As Worksheet
Dim cell As Range
Dim fullPath As String
Dim userName As String
Dim pcName As String
Dim osName As String
Dim currentUser As String
Set fso = CreateObject("Scripting.FileSystemObject")
Set folder = fso.GetFolder(folderPath)
pcName = Environ("COMPUTERNAME")
osName = Environ("OS")
currentUser = Environ("USERNAME")
Application.ScreenUpdating = False ' 高速化
' ファイルをループ
For Each file In folder.Files
If LCase(Right(file.Name, 5)) = ".xlsx" Or LCase(Right(file.Name, 4)) = ".xls" Then
fullPath = file.Path
userName = GetFileOwner(fullPath) ' 開いているユーザー名取得
On Error Resume Next
Set wb = Workbooks.Open(fullPath, ReadOnly:=True, UpdateLinks:=False)
If Err.Number <> 0 Then
Err.Clear
On Error GoTo 0
GoTo NextFile
End If
On Error GoTo 0
' 各シートをループして検索
For Each wsSheet In wb.Sheets
For Each cell In wsSheet.UsedRange
If InStr(1, cell.Value, searchText, vbTextCompare) > 0 Then
ws.Cells(rowNum, 1).Value = file.Name
ws.Hyperlinks.Add Anchor:=ws.Cells(rowNum, 2), Address:=fullPath, TextToDisplay:="開く"
ws.Cells(rowNum, 3).Value = cell.Value
ws.Cells(rowNum, 4).Value = cell.Address
ws.Cells(rowNum, 5).Value = fullPath
ws.Cells(rowNum, 6).Value = userName
ws.Cells(rowNum, 7).Value = pcName
ws.Cells(rowNum, 8).Value = osName
ws.Cells(rowNum, 9).Value = currentUser
rowNum = rowNum + 1
End If
Next cell
Next wsSheet
wb.Close False
End If
NextFile:
Next file
' サブフォルダー処理
If includeSubfolders Then
For Each subFolder In folder.SubFolders
SearchFiles subFolder.Path, searchText, True, ws, rowNum
Next subFolder
End If
Application.ScreenUpdating = True ' 画面更新再開
End Sub
Function GetFileOwner(ByVal filePath As String) As String
Dim objShell As Object, objFolder As Object, objFile As Object
Dim owner As String
On Error Resume Next
Set objShell = CreateObject("Shell.Application")
Set objFolder = objShell.Namespace(Left(filePath, InStrRev(filePath, "\\") - 1))
Set objFile = objFolder.ParseName(Right(filePath, Len(filePath) - InStrRev(filePath, "\\")))
owner = objFile.GetDetail(8) ' プロパティインデックス8: 所有者
GetFileOwner = owner
On Error GoTo 0
End Function
コメント