Fix for FileSearch in Office 2007

ginismo

New Member
Joined
Feb 9, 2009
Messages
12
When I noticed that FileSearch was missing after I updated to Office 2007, I decided to recreate the class and save it as a file to import anytime I needed to use it. I tried to use as little code as possible, so if there is some property you would need to add then you may have to add it yourself, but this will at least give you most of the funcitonality of the original Class without having to update your existing code too much. You have to just reference the class and then it can still be used in a with block or however you are accustomed. Here are the two class files that I have, the first I named FileSearch (go figure):

Code:
Dim pLookIn As String
Dim pSearchSubFolders As Boolean
Dim pFileName As String
Public FoundFiles As New Collection
        
Public Property Get LookIn() As String
    LookIn = pLookIn
End Property
Public Property Let LookIn(value As String)
    pLookIn = value
End Property
Public Property Get SearchSubFolders() As Boolean
    LookIn = pSearchSubFolders
End Property
Public Property Let SearchSubFolders(value As Boolean)
    pSearchSubFolders = value
End Property
Public Property Get fileName() As String
    fileName = pFileName
End Property
Public Property Let fileName(value As String)
    pFileName = value
End Property
Public Function Execute() As Long
    
        Dim ex As Long
        Dim sLookIn As String
        Dim sDirName As String
        Dim sSubDir As String
        Dim sFileName As String
        Dim ff As FilesFound
    
            Set ff = New FilesFound
            sLookIn = LookIn
            sDirName = Dir(sLookIn, vbDirectory)
            sFileName = Dir(sLookIn & "\", vbNormal)
            Do Until Len(sFileName) = 0
                If sFileName Like fileName Then
                    ff.AddFile sLookIn, sFileName
                    FoundFiles.Add (ff.FoundFileFullName)
                End If
                sFileName = Dir
            Loop
            If SearchSubFolders Then
                Do Until Len(sDirName) = 0
                    If GetAttr(sLookIn & sDirName) = vbDirectory Then
                        sSubDir = sDirName
                        Do Until Len(sFileName) = 0
                            If GetAttr(sDirName) = vbNormal Then
                                sFileName = sDirName
                                ff.AddFile sDirName, sFileName
                                FoundFiles.Add (ff)
                            End If
                        Loop
                    End If
                    sDirName = Dir
                Loop
            End If
    
    Execute = FoundFiles.Count
    
End Function
The second I named FilesFound and the code is as follows:
Public FoundFileFullName As String
Public Function AddFile(path As String, fileName As String)
    FoundFileFullName = path & "\" & fileName
End Function

That should do it.
To use it in your code just create the two class modules and then use it as such:
    Dim sFile as String
    Dim fs As New FileSearh
    With fs
        .LookIn = sPath
        .SearchSubFolders = True
        .fileName = "*"
        If .Execute > 0 Then
            For i = 1 To .FoundFiles.Count
                sFile = .FoundFiles(i)
                    ' your code here
            Next
        End If
    End With
so it works exactly the same. The only difference I know of is, if the file you're looking for may have any extension use "*" instead of "*.*" as microsoft put out. I was lazy and just did a like comparison instead of breaking out the file extensions. All others should theoretically work fine i.e. "*.xls" or "*.txt"
That's it. Enjoy!!!!!!!!

James
 
Last edited by a moderator:

Excel Facts

How to change case of text in Excel?
Use =UPPER() for upper case, =LOWER() for lower case, and =PROPER() for proper case. PROPER won't capitalize second c in Mccartney
Welcome to the forum!

The .SearchSubFolders=True did not work in my testing.

You might want to consider adding a .NewSearch.

I found that .fileName="*.*" found 125 files in the root folder and .fileName="*" found 126. The searchsubfolders should have found 2961.

I named your first class cFileSearch so that I could use it in 2003. Here is how I tested it:
Code:
'Similar to Domski, http://www.mrexcel.com/forum/showthread.php?p=1829654
Sub LIST()
  Dim fs As New cFileSearch
  Dim NextRow As Long, Filestoprocess As Long, i As Long
  Dim thisentry As String, j As Integer
  Range("A1:D1").value = Array("FILENAME", "PATH", "FILENAME", "NEWPATH")
  NextRow = 2
  With fs 'like Application.FileSearch
    .LookIn = "x:"
    .SearchSubFolders = True
    .fileName = "*" '*.* in Application.Filesearch's fileName
    .Execute
    Filestoprocess = .FoundFiles.Count
    For i = 1 To Filestoprocess
      thisentry = .FoundFiles(i)
      Cells(NextRow, 1).value = thisentry
      For j = Len(thisentry) To 1 Step -1
        If Mid(thisentry, j, 1) = Application.PathSeparator Then
        Cells(NextRow, 2) = Left(thisentry, j)
        Cells(NextRow, 3) = Mid(thisentry, j + 1)
        Exit For
        End If
      Next j
      NextRow = NextRow + 1
    Next i
  End With
 
Upvote 0
My apologies!

this was a major oversimplification of what actually needs to be done to search all sub folders. I will be working on a Win32 API for this function and hope to post that soon.

Hasty coding and posting got me in trouble.
 
Upvote 0
I was thinking of doing a vb.net solution so that I could use it in other applications too. I was playing with this example.

It is a good concept that you are pursuing.
 
Upvote 0
well I use .net for everything, and I definitely would recommend creating a class library and referencing that using System.IO, but I was trying to come up with a solution for those who do not have Visual Studio.

So here is what I have come up with, unfortunately I was unable to find an API function that would do what I wanted, so I was left to use FileSystemObject, which I don't like.

To use this code you will have to go to Tools>Reference> and Select Microsoft Scripting Runtime so you can use the FileSystemObject Class

Also, I added some error checking to skip past the folders that did not have permission. I couldn't find a better way to deal with this.

here are the revisions:


The FileSearch Class:

Code:
Dim pLookIn As String
Dim pSearchSubFolders As Boolean
Dim pFileName As String
Public FoundFiles As New Collection
        
Public Property Get LookIn() As String
    LookIn = pLookIn
End Property
Public Property Let LookIn(value As String)
    pLookIn = value
End Property
Public Property Get SearchSubFolders() As Boolean
    SearchSubFolders = pSearchSubFolders
End Property
Public Property Let SearchSubFolders(value As Boolean)
    pSearchSubFolders = value
End Property
Public Property Get FileName() As String
    FileName = pFileName
End Property
Public Property Let FileName(value As String)
    pFileName = value
End Property
Public Function Execute() As Long
        
        Dim sLookIn As String
        Dim sDirName As String
        Dim sSubDir As String
        Dim sFileName As String
        Dim sFullPath As String
        Dim sAllPaths() As String
        Dim x As Integer
        Dim ff As FilesFound
        Dim sf As SubFolder
        
            On Error Resume Next
            
            Set ff = New FilesFound
            sLookIn = LookIn
            sDirName = Dir(sLookIn, vbDirectory)
            sFileName = Dir(sLookIn & "\", vbNormal)
            Do Until Len(sFileName) = 0
                If sFileName Like FileName Then
                    ff.AddFile sLookIn, sFileName
                    FoundFiles.Add (ff.FoundFileFullName)
                End If
                sFileName = Dir
            Loop
            
            If SearchSubFolders Then
                Set sf = New SubFolder
                With sf
                    .ParentPath = sLookIn
                    If .GetList > 0 Then
                        For i = 1 To .FolderList.Count
                            sSubDir = .FolderList(i)
                            sFileName = Dir(sSubDir & "\", vbNormal)
                            Do Until Len(sFileName) = 0
                                If sFileName Like FileName Then
                                    ff.AddFile sSubDir, sFileName
                                    FoundFiles.Add (ff.FoundFileFullName)
                                End If
                                sFileName = Dir
                            Loop
                        Next
                    End If
                End With
            End If
    
    Execute = FoundFiles.Count
    
End Function
Public Sub NewSearch()
    FileName = ""
    SearchSubFolders = False
    LookIn = ""
    Set FoundFiles = Nothing
    
End Sub

'Note I added a NewSearch Sub
 
the FilesFound Class:
 
Public FoundFileFullName As String
Public Function AddFile(path As String, FileName As String)
    FoundFileFullName = path & "\" & FileName
End Function

 
and I had to add a SubFolder Class (which uses the FSO):
 
Public FolderList As New Collection
Dim pParentPath As String
Dim NOF As Integer
Public Property Get ParentPath() As String
    ParentPath = pParentPath
End Property
Public Property Let ParentPath(value As String)
    pParentPath = value
End Property
Public Function GetList() As Integer
    
    Dim fs As New FileSystemObject
    Dim fldr As Folder
    Dim subFldr As Folder
    Dim nextSub As Integer
    
    On Error Resume Next
    
    Set fldr = fs.GetFolder(ParentPath)
    
    For Each subFldr In fldr.SubFolders
        FolderList.Add (subFldr.path)
        ParentPath = subFldr.path
        nextSub = Me.GetList
    Next
    
    GetList = FolderList.Count
    
End Function


Please any revisions or ideas or add-ons I will try to do.

I may aslo try and create a .dll to reference in .Net for ppl to download and use. I really hate that Microsoft got rid of the FileSearch. I used it alot
 
Last edited by a moderator:
Upvote 0
Thanks for posting that. It is nice to have "classy" people like you on the forum. Thanks for putting your code in a code block too.

I look forward to seeing your dll solution and trying this fso method. In other threads, we have used recursive fso and dos methods as alternatives to Application.FileSearch.

I came across an API method in a class a while back that did not use fso methods. Sometime, I need to try using that method like you did in this class for those users that can not use fso methods due to administrators disabling it or not installing it.
 
Upvote 0
Folks interested in a FileSearch "replacement" in Office 2007 should also search this forum and the newsgroups for other ideas on the subject.

Compared to Dir and FileSystemObject, FileSearch supported a much richer interface. This includes entities such as the TextOrProperty property, the PropertyTests collection, the SearchScopes and the SearchFolders collections. Consequently, I don't know if anyone has implemented the full capability of FileSearch without using FileSearch.

I did not use FileSearch except in one add-in because I was never very comfortable with what appeared to me a very complex -- overly complex -- mechanism. For example, what was the relationship between TextOrProperty and the members of the PropertyTests collection? Or, the interaction between LookIn and the SearchFolders and the SearchScopes collections? I had also anecdotal evidence, primarily from other Microsoft MVPs, about problems with the results.

Why did Microsoft abandon FileSearch? Obviously, I don't know but it seems that the group(s) that support common Office functionality seem to demonstrate a pattern of not fully fleshing out products (HTML Help), not providing full fledged developer support (after all this time the macro recorder as applied to a Shape object remains iffy), and abandoning products (Binder, the Office Toolbar, and now FileSearch).
 
Upvote 0
Ginismo, I found that your routine ran even faster than Application.FileSearch, good job! It took 6.7s to run Dom's code and yours took 4.2s averaged over 5 runs each when I added my speedup routines to turn off screen updating, calculation and such. In the first run, yours found 2963 files but the other found 2964. Other runs all found 2964. I have seen this one file difference in other scenarios so I am not sure which is duplicating a filename or which is dropping one occasionally. I could find no reason for the order of the filenames returned from Application.FileSearch. Your routine seemed to sort them in ascending order as one might expect.

Tushar, if you ever find a routine that uses classes that simulate ginismo's efforts here, I would appreciate the reference. I never understood how to use all of the features in Application.FileSearch like SearchScope. My main interest is usually to put all the filenames into an array. Thanks for your comments as always.

Rescursive fso and dos methods is what I generally use to replace Application.FileSearch as in this thread at VBAExpress. Since that post, I added a routine to my dos method that waits for the text file to be written that is more efficient. In the referenced link, fso failed due to file/folder permissions. The dos method was faster than fso methods for just getting filenames after the tweak to my dos method. I will have to make a similar example to compare filenames to array to range for speed using this class method since ginismo addressed file/folder permission.
 
Upvote 0
I noticed it was faster too, which I'd like to take credit for, but it was completely circumstantial. I agree that it isn't perfect, but neither was the original. I mainly use it to search directories for files that I know the name of, but not the exact location, or to gather a list of Files for reporting or formatting. So I had no way of updating the dozen or so macros I had when I "upgraded" to Office 2007 without recoding alot. This seemed to me to be the best solution for my cause. I have only added the methods and properties that I used.

Kenneth, if you ever find the API reference you mentioned, please pass it along. I don't like having to use MS's Scripting Runtime due to it having to be added as a reference. I know some people are unable to add that reference for the reasons you mentioned, and was why I wanted to not use it. So any ideas would be great that don't involve using FileSystemObject. I tried the API's using the FindFirstFile, FindNextFile functions and even the SHGetPathFromIDList, but I couldn't figure how to use either effectively. I think using the FindFile methods would be the best option for now. I understand that Windows 7 will add a Search Function like the one they use for file search, but that's little help to most of us.
 
Upvote 0

Forum statistics

Threads
1,224,586
Messages
6,179,716
Members
452,939
Latest member
WCrawford

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