search string in folder (text file or word file) and put all result in column

darkhangelsk

New Member
Joined
Feb 10, 2013
Messages
27
Hi,

I would like to ask a macro where it will search through a folder and subfolder and put the result in columns in excel.

Sample is : words to look in a note file - 'Note', 'black", 'white', 'blue'

if 2 words found:

column1 column 2
C:\document\txt1 Note
C:\document\txt1 black

if 3 words in different file found:

column1 column 2
C:\document\txt1 Note
C:\document\txt2 black
C:\document\txt2 white


Thanks in advance!
 

Excel Facts

Does the VLOOKUP table have to be sorted?
No! when you are using an exact match, the VLOOKUP table can be in any order. Best-selling items at the top is actually the best.
There's many ways to do this, one is to use VBA.
For this you need reference to:
- Microsoft Shell controls and automation
- Microsoft scripting runtime

Try to paste this code into your editor, rember to use a separate workbook while testing!
You should also consider adding some errorhandling.

Code:
Option Explicit


Private Type Sheet_Dest
  Path_Col As Integer ' Column with Path
  Word_Col As Integer ' Column with search phrase
End Type


Private lRow As Long
Private Print_Col As Sheet_Dest
Private wDest_Sheet As Excel.Worksheet
Private Shell As Shell32.Shell
Private FSO As Scripting.FileSystemObject


'/ Under Tools - References Add:
' - Microsoft Shell controls and automation
' - Microsoft scripting runtime
Sub Find_Content( _
)


'' Variables
Const sPath As String = "F:\VBA" '** Change to parentfolder, e.g "C:\Myfolder"
Dim sSearch_For(1) As String


'' Var Init
' ** Change to your worksheet
Set wDest_Sheet = ThisWorkbook.Worksheets(1)
'' ** Add searchphrases here
sSearch_For(0) = "Note"
sSearch_For(1) = "Black"


Set Shell = New Shell32.Shell
Set FSO = New Scripting.FileSystemObject


lRow = 2 ' Header is row 1
With Print_Col
  .Path_Col = 1 ' Column A
  .Word_Col = 2 ' COlumn B
End With


' Turn off screen updating, events and calculations for speed
With Excel.Application
  .ScreenUpdating = False
  .EnableEvents = False
  .Calculation = xlCalculationManual
End With


'' Procedure
Call Search_Folder(sPath, sSearch_For)


'' End proc
With Excel.Application
  .ScreenUpdating = True
  .EnableEvents = True
  .Calculation = xlCalculationAutomatic
  
  .StatusBar = ""
End With


End Sub




'/ Search folders and subfolders for string
Private Sub Search_Folder( _
Parent As String, _
Search_For() As String _
)


'' Var
Dim i As Integer
Dim iEnd As Integer
Dim sLine As String


Dim Fldr_Items As Shell32.FolderItems3
Dim Item As Shell32.FolderItem
Dim fStream As Scripting.TextStream


'' Init
iEnd = UBound(Search_For)
Set Fldr_Items = Shell.Namespace(Parent).Items ' Folder and files in parentfolder


'' Procedure
For Each Item In Fldr_Items
  ' call recursively if folder
  If Item.IsFolder Then
    Call Search_Folder(Item.Path, Search_For)
  Else
    
    ' Read all lines and look for the textphras
    ' if one phrase is found then:
    '   Print to sheet
    '   exit the loop
    Set fStream = FSO.GetFile(Item.Path).OpenAsTextStream(ForReading)
    Application.StatusBar = "Reading from " & Item.Name & "..."
    
    ' Read all lines in textstreamobject
    Do While Not fStream.AtEndOfStream
      sLine = fStream.ReadLine
      For i = 0 To iEnd
        
        ' change cbTextCompare for increased speed
        If InStr(1, Search_For(i), sLine, vbTextCompare) Then


          wDest_Sheet.Cells(lRow, Print_Col.Path_Col) = Item.Path
          wDest_Sheet.Cells(lRow, Print_Col.Word_Col) = Search_For(i)


          lRow = lRow + 1


        End If


      Next i
      
    Loop
    
    fStream.Close
  End If
Next


End Sub
 
Upvote 0
Thanks for this! however, it's not working due to no Microsoft scripting runtime on my reference. (User-defined type not defined <<< error)

do we have other option without using it?

I have a code, but it's only giving me one result instead of giving me every 'word' found:

HTML:
' These 5 lines must go at' the top of the module:
Const ForReading = 1
Dim m_vntSearchItems As Variant
Dim m_astrResults() As String
Dim m_objFileSystem As Object
Dim m_lngCounter As Long
Public Sub SearchFiles()
' ++++++++++++++++++' 
RUN THIS PROCEDURE'
 ++++++++++++++++++
 Const strFOLDER_PATH = "C:\Doucments\Logs" ' <-- the folder you want to search  
Dim i As Integer  
Dim j As Long    

On Error GoTo ErrorHandler  
m_vntSearchItems = Array("white", "note", "gray", "black") ' <-- the items you want to search for  
Erase m_astrResults  
m_lngCounter = 0    

Set m_objFileSystem = CreateObject("Scripting.FileSystemObject")  
Call SearchFilesInFolder(strFOLDER_PATH)    

If m_lngCounter > 0 Then    
With ThisWorkbook.Sheets.Add      
   With .Range("A1:C1")        
   .Value = Array("Folder Path", "File Name", "Text Found")        
   .Font.Bold = True      
End With
      For j = 1 To m_lngCounter
        For i = 1 To UBound(m_astrResults)
          .Cells(j + 1, i).Value = m_astrResults(i, j) 
       Next i
      Next j
      With .Columns("A:C")
        .AutoFilter
        .AutoFit
      End With
    End With
    With ThisWorkbook.Windows(1)
      .SplitRow = 1
      .FreezePanes = True
    End With
  End If
    MsgBox Format(m_lngCounter, "#,0") & " file(s) were found.", vbInformation

ExitHandler:
  Set m_objFileSystem = Nothing
  Exit Sub  ErrorHandler:
  MsgBox Err.Description, vbExclamation
  Resume ExitHandler
End Sub

Private Sub SearchFilesInFolder(strFolderPath As String)
  Dim strFileExtension As String
  Dim objTextStream As Object
  Dim objSubfolder As Object
  Dim strFilePath As String
  Dim strFileText As String
  Dim objFolder As Object
  Dim objFile As Object
  Dim i As Integer
    On Error GoTo ExitHandler
  Set objFolder = m_objFileSystem.GetFolder(strFolderPath)
    For Each objFile In objFolder.Files 
   On Error GoTo FileHandler
    strFilePath = objFile.Path
    strFileExtension = LCase(m_objFileSystem.GetExtensionName(strFilePath))
    If strFileExtension = "txt" Or strFileExtension = "csv" Then
      Set objTextStream = m_objFileSystem.OpenTextFile(strFilePath, ForReading)
      strFileText = objTextStream.ReadAll()
      objTextStream.Close
      For i = LBound(m_vntSearchItems) To UBound(m_vntSearchItems)
        If InStr(1, strFileText, m_vntSearchItems(i), vbTextCompare) > 0 Then
          m_lngCounter = m_lngCounter + 1
          ReDim Preserve m_astrResults(1 To 3, 1 To m_lngCounter)
          m_astrResults(1, m_lngCounter) = objFile.ParentFolder
          m_astrResults(2, m_lngCounter) = objFile.Name 
         m_astrResults(3, m_lngCounter) = m_vntSearchItems(i)
          Exit For
        End If
      Next i
    End If
    GoTo NextFileFileHandler:
    Err.Clear
    Resume NextFileNextFile:
    On Error Resume Next
    objTextStream.Close
  Next objFile
    On Error
 GoTo ExitHandler
  For Each objSubfolder In objFolder.SubFolders
    On Error GoTo SubFolderHandler
    Call SearchFilesInFolder(objSubfolder.Path)
    GoTo NextSubFolderSubFolderHandler:
    Err.Clear
    Resume NextSubFolderNextSubFolder:
  Next objSubfolder
  ExitHandler:
  Set objTextStream = Nothing
  Set objSubfolder = Nothing
  Set objFolder = Nothing
  Set objFile = Nothing
End Sub

can we utilize this code or we have other workaround for FSO?

Thanks A lot!
 
Upvote 0
I tried to edit your code;

Code:
' These 5 lines must go at' the top of the module:
Const ForReading = 1
Dim m_vntSearchItems As Variant
Dim m_astrResults() As String
Dim m_objFileSystem As Object
Dim m_lngCounter As Long

Public Sub SearchFiles()
' ++++++++++++++++++'RUN THIS PROCEDURE' ++++++++++++++++++
    Const strFOLDER_PATH = "C:\Doucments\Logs"    ' <-- the folder you want to search
    Dim i As Integer
    Dim j As Long


    On Error GoTo ErrorHandler
    m_vntSearchItems = Array("white", "note", "gray", "black")    ' <-- the items you want to search for
    Erase m_astrResults
    m_lngCounter = 0


    Set m_objFileSystem = CreateObject("Scripting.FileSystemObject")
    Call SearchFilesInFolder(strFOLDER_PATH)


    If m_lngCounter > 0 Then
        With ThisWorkbook.Sheets.Add
            With .Range("A1:D1")
                .Value = Array("Folder Path", "File Name", "Text Found", "Line")
                .Font.Bold = True
            End With
            For j = 1 To m_lngCounter
                For i = 1 To UBound(m_astrResults)
                    .Cells(j + 1, i).Value = m_astrResults(i, j)
                Next i
            Next j
            With .Columns("A:D")
                .AutoFilter
                .AutoFit
            End With
        End With
        With ThisWorkbook.Windows(1)
            .SplitRow = 1
            .FreezePanes = True
        End With
    End If
    MsgBox Format(m_lngCounter, "#,0") & " file(s) were found.", vbInformation
ExitHandler:
    Set m_objFileSystem = Nothing
    Exit Sub
ErrorHandler:
    MsgBox Err.Description, vbExclamation
    Resume ExitHandler
End Sub


Private Sub SearchFilesInFolder(strFolderPath As String)
    Dim strFileExtension As String
    Dim objTextStream As Object
    Dim objSubfolder As Object
    Dim strFilePath As String
    Dim strFileText As String
    Dim objFolder As Object
    Dim objFile As Object
    Dim i As Integer
    Dim ii As Long


    On Error GoTo ExitHandler
    Set objFolder = m_objFileSystem.GetFolder(strFolderPath)
    For Each objFile In objFolder.Files
        On Error GoTo FileHandler
        strFilePath = objFile.Path
        strFileExtension = LCase(m_objFileSystem.GetExtensionName(strFilePath))
        If strFileExtension = "txt" Or strFileExtension = "csv" Then
            Set objTextStream = m_objFileSystem.OpenTextFile(strFilePath, ForReading)
            ii = 0
            Do Until objTextStream.AtEndOfStream
                strFileText = objTextStream.ReadLine
                ii = ii + 1
                For i = LBound(m_vntSearchItems) To UBound(m_vntSearchItems)
                    If InStr(1, strFileText, m_vntSearchItems(i), vbTextCompare) > 0 Then
                        m_lngCounter = m_lngCounter + 1
                        ReDim Preserve m_astrResults(1 To 4, 1 To m_lngCounter)
                        m_astrResults(1, m_lngCounter) = objFile.ParentFolder
                        m_astrResults(2, m_lngCounter) = objFile.Name
                        m_astrResults(3, m_lngCounter) = m_vntSearchItems(i)
                        m_astrResults(4, m_lngCounter) = ii
                    End If
                Next i
            Loop
            objTextStream.Close
        End If
        GoTo NextFile
FileHandler:
        Err.Clear
        Resume NextFile
NextFile:
        On Error Resume Next
        objTextStream.Close
    Next objFile
    On Error GoTo ExitHandler
    For Each objSubfolder In objFolder.SubFolders
        On Error GoTo SubFolderHandler
        Call SearchFilesInFolder(objSubfolder.Path)
        GoTo NextSubFolder
SubFolderHandler:
        Err.Clear
        Resume NextSubFolder
NextSubFolder:
    Next objSubfolder
ExitHandler:
    Set objTextStream = Nothing
    Set objSubfolder = Nothing
    Set objFolder = Nothing
    Set objFile = Nothing
End Sub
 
Last edited:
Upvote 0
Solution

Forum statistics

Threads
1,223,702
Messages
6,173,932
Members
452,539
Latest member
delvey

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top