VBA検索結果を出す。

テーマ:

以下は、指定したフォルダ内のExcel、Word、PowerPointファイルに対して単語を検索し、検索結果をリストとして表示し、さらにその結果をテキストファイルに履歴として保存するVBAコードです。また、検索結果のファイルにはリンクを付けて、クリックして直接アクセスできるようにしています。


### 改良したVBAコード


```vba

' フォームのボタンがクリックされたときの処理

Private Sub btnSearch_Click()

    Dim folderPath As String

    Dim searchText As String


    ' テキストボックスからフォルダパスと検索テキストを取得

    folderPath = Me.txtFolderPath.Text

    searchText = Me.txtSearchText.Text


    If folderPath = "" Or searchText = "" Then

        MsgBox "フォルダパスと検索する単語を入力してください。", vbExclamation

        Exit Sub

    End If


    ' 検索履歴をクリア

    Me.lstResults.Clear

    

    ' 検索履歴ファイルの作成

    Dim logFile As String

    logFile = folderPath & "\search_history.txt"

    Open logFile For Append As #1

    Print #1, "検索文字列: " & searchText & " | フォルダ: " & folderPath & " | 日付: " & Now


    ' 検索処理を実行

    SearchInExcelFiles folderPath, searchText, Me.lstResults, logFile

    SearchInWordFiles folderPath, searchText, Me.lstResults, logFile

    SearchInPowerPointFiles folderPath, searchText, Me.lstResults, logFile


    Close #1

    MsgBox "検索が完了しました。", vbInformation

End Sub


' Excelファイル内で検索

Sub SearchInExcelFiles(folderPath As String, searchText As String, resultsList As MSForms.ListBox, logFile As String)

    Dim excelApp As Object

    Dim excelBook As Object

    Dim sheet As Object

    Dim filePath As String

    Dim fileSystem As Object

    Dim file As Object

    Dim found As Boolean

    Dim cell As Object


    Set fileSystem = CreateObject("Scripting.FileSystemObject")

    Set excelApp = CreateObject("Excel.Application")

    excelApp.Visible = False


    ' 指定したフォルダ内の全Excelファイルをループ

    For Each file In fileSystem.GetFolder(folderPath).Files

        If LCase(fileSystem.GetExtensionName(file.Name)) = "xlsx" Or LCase(fileSystem.GetExtensionName(file.Name)) = "xls" Then

            filePath = file.Path

            Set excelBook = excelApp.Workbooks.Open(filePath)

            

            found = False

            

            ' シート内のすべてのセルを検索

            For Each sheet In excelBook.Sheets

                For Each cell In sheet.UsedRange

                    If InStr(1, cell.Value, searchText, vbTextCompare) > 0 Then

                        found = True

                        Exit For

                    End If

                Next cell

                If found Then Exit For

            Next sheet

            

            If found Then

                ' 検索結果リストに追加

                resultsList.AddItem "Excelファイル: " & filePath

                ' テキストファイルに記録

                Print #1, "Excelファイル: " & filePath

            End If

            

            excelBook.Close False

        End If

    Next file


    excelApp.Quit

    Set excelApp = Nothing

    Set fileSystem = Nothing

End Sub


' Wordファイル内で検索

Sub SearchInWordFiles(folderPath As String, searchText As String, resultsList As MSForms.ListBox, logFile As String)

    Dim wordApp As Object

    Dim wordDoc As Object

    Dim filePath As String

    Dim fileSystem As Object

    Dim file As Object

    Dim found As Boolean


    Set fileSystem = CreateObject("Scripting.FileSystemObject")

    Set wordApp = CreateObject("Word.Application")

    wordApp.Visible = False


    ' 指定したフォルダ内の全Wordファイルをループ

    For Each file In fileSystem.GetFolder(folderPath).Files

        If LCase(fileSystem.GetExtensionName(file.Name)) = "docx" Or LCase(fileSystem.GetExtensionName(file.Name)) = "doc" Then

            filePath = file.Path

            Set wordDoc = wordApp.Documents.Open(filePath)

            

            found = False

            wordApp.Selection.Find.ClearFormatting

            With wordApp.Selection.Find

                .Text = searchText

                .MatchCase = False

                .MatchWholeWord = False

                .MatchWildcards = False

                .MatchSoundsLike = False

                .MatchAllWordForms = False

                .Forward = True

                .Wrap = 1

            End With

            

            Do While wordApp.Selection.Find.Execute

                found = True

                Exit Do

            Loop

            

            If found Then

                ' 検索結果リストに追加

                resultsList.AddItem "Wordファイル: " & filePath

                ' テキストファイルに記録

                Print #1, "Wordファイル: " & filePath

            End If

            

            wordDoc.Close False

        End If

    Next file


    wordApp.Quit

    Set wordApp = Nothing

    Set fileSystem = Nothing

End Sub


' PowerPointファイル内で検索

Sub SearchInPowerPointFiles(folderPath As String, searchText As String, resultsList As MSForms.ListBox, logFile As String)

    Dim pptApp As Object

    Dim pptPresentation As Object

    Dim slide As Object

    Dim shape As Object

    Dim filePath As String

    Dim fileSystem As Object

    Dim file As Object

    Dim found As Boolean


    Set fileSystem = CreateObject("Scripting.FileSystemObject")

    Set pptApp = CreateObject("PowerPoint.Application")

    pptApp.Visible = msoTrue


    ' 指定したフォルダ内の全PowerPointファイルをループ

    For Each file In fileSystem.GetFolder(folderPath).Files

        If LCase(fileSystem.GetExtensionName(file.Name)) = "pptx" Or LCase(fileSystem.GetExtensionName(file.Name)) = "ppt" Then

            filePath = file.Path

            Set pptPresentation = pptApp.Presentations.Open(filePath)

            

            found = False

            

            ' スライド内の全シェイプをチェック

            For Each slide In pptPresentation.Slides

                For Each shape In slide.Shapes

                    If shape.HasTextFrame Then

                        If shape.TextFrame.HasText Then

                            If InStr(1, shape.TextFrame.TextRange.Text, searchText, vbTextCompare) > 0 Then

                                found = True

                                Exit For

                            End If

                        End If

                    End If

                Next shape

                If found Then Exit For

            Next slide

            

            If found Then

                ' 検索結果リストに追加

                resultsList.AddItem "PowerPointファイル: " & filePath

                ' テキストファイルに記録

                Print #1, "PowerPointファイル: " & filePath

            End If

            

            pptPresentation.Close

        End If

    Next file


    pptApp.Quit

    Set pptApp = Nothing

    Set fileSystem = Nothing

End Sub

```


### 機能

1. **フォームを使って検索**: フォームの`txtFolderPath`テキストボックスにフォルダパスを入力し、`txtSearchText`に検索ワードを入力します。

2. **リストに結果を表示**: 検索結果は`lstResults`というリストボックスに表示されます。

3. **検索履歴を保存**: 検索結果は指定フォルダ内に「`search_history.txt`」という名前でテキストファイルに保存され、今後の履歴として確認できます。

4. **結果からファイルを開く**: リストボックスに表示されたファイルパスをクリックすると、そのファイルを開くことができます。


### リストボックスからファイルを開く機能の追加


以下のコードをフォームの`lstResults`に追加することで、リストに表示されたファイルをダブルクリックして開けるようにします。


```vba

Private Sub lstResults_DblClick(ByVal Cancel As MSForms.ReturnBoolean)

    Dim selectedFile As String

    If lstResults.ListIndex >= 0 Then

        selectedFile = lstResults.List(lstResults.ListIndex)

        ' 検索結果のファイルを開く

        Shell "explorer.exe """ & selectedFile & """", vbNormalFocus

    End If

End Sub

```


これで、リストボックスに表示された検索結果から直接ファイルを開ける機能が追加されます。



' フォームのボタンがクリックされたときの処理

Private Sub btnSearch_Click()
    Dim folderPath As String
    Dim searchText As String

    ' テキストボックスからフォルダパスと検索テキストを取得
    folderPath = Me.txtFolderPath.Text
    searchText = Me.txtSearchText.Text

    If folderPath = "" Or searchText = "" Then
        MsgBox "フォルダパスと検索する単語を入力してください。", vbExclamation
        Exit Sub
    End If

    ' 検索履歴をクリア
    Me.lstResults.Clear
    
    ' 検索履歴ファイルの作成
    Dim logFile As String
    logFile = folderPath & "\search_history.txt"
    Open logFile For Append As #1
    Print #1, "検索文字列: " & searchText & " | フォルダ: " & folderPath & " | 日付: " & Now

    ' 検索処理を実行
    SearchInExcelFiles folderPath, searchText, Me.lstResults, logFile
    SearchInWordFiles folderPath, searchText, Me.lstResults, logFile
    SearchInPowerPointFiles folderPath, searchText, Me.lstResults, logFile

    Close #1
    MsgBox "検索が完了しました。", vbInformation
End Sub

' Excelファイル内で検索
Sub SearchInExcelFiles(folderPath As String, searchText As String, resultsList As MSForms.ListBox, logFile As String)
    Dim excelApp As Object
    Dim excelBook As Object
    Dim sheet As Object
    Dim filePath As String
    Dim fileSystem As Object
    Dim file As Object
    Dim found As Boolean
    Dim cell As Object

    Set fileSystem = CreateObject("Scripting.FileSystemObject")
    Set excelApp = CreateObject("Excel.Application")
    excelApp.Visible = False

    ' 指定したフォルダ内の全Excelファイルをループ
    For Each file In fileSystem.GetFolder(folderPath).Files
        If LCase(fileSystem.GetExtensionName(file.Name)) = "xlsx" Or LCase(fileSystem.GetExtensionName(file.Name)) = "xls" Then
            filePath = file.Path
            Set excelBook = excelApp.Workbooks.Open(filePath)
            
            found = False
            
            ' シート内のすべてのセルを検索
            For Each sheet In excelBook.Sheets
                For Each cell In sheet.UsedRange
                    If InStr(1, cell.Value, searchText, vbTextCompare) > 0 Then
                        found = True
                        Exit For
                    End If
                Next cell
                If found Then Exit For
            Next sheet
            
            If found Then
                ' 検索結果リストに追加
                resultsList.AddItem "Excelファイル: " & filePath
                ' テキストファイルに記録
                Print #1, "Excelファイル: " & filePath
            End If
            
            excelBook.Close False
        End If
    Next file

    excelApp.Quit
    Set excelApp = Nothing
    Set fileSystem = Nothing
End Sub

' Wordファイル内で検索
Sub SearchInWordFiles(folderPath As String, searchText As String, resultsList As MSForms.ListBox, logFile As String)
    Dim wordApp As Object
    Dim wordDoc As Object
    Dim filePath As String
    Dim fileSystem As Object
    Dim file As Object
    Dim found As Boolean

    Set fileSystem = CreateObject("Scripting.FileSystemObject")
    Set wordApp = CreateObject("Word.Application")
    wordApp.Visible = False

    ' 指定したフォルダ内の全Wordファイルをループ
    For Each file In fileSystem.GetFolder(folderPath).Files
        If LCase(fileSystem.GetExtensionName(file.Name)) = "docx" Or LCase(fileSystem.GetExtensionName(file.Name)) = "doc" Then
            filePath = file.Path
            Set wordDoc = wordApp.Documents.Open(filePath)
            
            found = False
            wordApp.Selection.Find.ClearFormatting
            With wordApp.Selection.Find
                .Text = searchText
                .MatchCase = False
                .MatchWholeWord = False
                .MatchWildcards = False
                .MatchSoundsLike = False
                .MatchAllWordForms = False
                .Forward = True
                .Wrap = 1
            End With
            
            Do While wordApp.Selection.Find.Execute
                found = True
                Exit Do
            Loop
            
            If found Then
                ' 検索結果リストに追加
                resultsList.AddItem "Wordファイル: " & filePath
                ' テキストファイルに記録
                Print #1, "Wordファイル: " & filePath
            End If
            
            wordDoc.Close False
        End If
    Next file

    wordApp.Quit
    Set wordApp = Nothing
    Set fileSystem = Nothing
End Sub

' PowerPointファイル内で検索
Sub SearchInPowerPointFiles(folderPath As String, searchText As String, resultsList As MSForms.ListBox, logFile As String)
    Dim pptApp As Object
    Dim pptPresentation As Object
    Dim slide As Object
    Dim shape As Object
    Dim filePath As String
    Dim fileSystem As Object
    Dim file As Object
    Dim found As Boolean

    Set fileSystem = CreateObject("Scripting.FileSystemObject")
    Set pptApp = CreateObject("PowerPoint.Application")
    pptApp.Visible = msoTrue

    ' 指定したフォルダ内の全PowerPointファイルをループ
    For Each file In fileSystem.GetFolder(folderPath).Files
        If LCase(fileSystem.GetExtensionName(file.Name)) = "pptx" Or LCase(fileSystem.GetExtensionName(file.Name)) = "ppt" Then
            filePath = file.Path
            Set pptPresentation = pptApp.Presentations.Open(filePath)
            
            found = False
            
            ' スライド内の全シェイプをチェック
            For Each slide In pptPresentation.Slides
                For Each shape In slide.Shapes
                    If shape.HasTextFrame Then
                        If shape.TextFrame.HasText Then
                            If InStr(1, shape.TextFrame.TextRange.Text, searchText, vbTextCompare) > 0 Then
                                found = True
                                Exit For
                            End If
                        End If
                    End If
                Next shape
                If found Then Exit For
            Next slide
            
            If found Then
                ' 検索結果リストに追加
                resultsList.AddItem "PowerPointファイル: " & filePath
                ' テキストファイルに記録
                Print #1, "PowerPointファイル: " & filePath
            End If
            
            pptPresentation.Close
        End If
    Next file

    pptApp.Quit
    Set pptApp = Nothing
    Set fileSystem = Nothing
End Sub