BTW, MS have acknowledged the failings of FileSearch, and dropped it from Excel 2007.Originally Posted by xld
BTW, MS have acknowledged the failings of FileSearch, and dropped it from Excel 2007.Originally Posted by xld
Thanks for the code sample Matt.
Is there any good documented information you know about so that I can read about it?Originally Posted by mvidas
As imperfect as it gets!Originally Posted by xld
Do you know if they will be replacing it with a new function?Originally Posted by xld
And Bob, does the same imperfection you mentioned happen with Dir()?
New to the forum? Check out our Introductions section to get to know some of the members here. Feel free to tell us a little about yourself as well.
Strangely I really couldn't find anything more than what I put above, just worded differently. One such example:Originally Posted by malik641 (re: path)Originally Posted by http://www.windowsitpro.com/Article/ArticleID/48074/48074.html
The Dir method in vb should not have the same thing as above, unless the file just doesn't exist. The Dir method is the same as if you went to a command line and typed "dir", except it returns a single file rather than the list of files. I'd be curious to hear if it did have any imperfections like the filesearch methoddoes the same imperfection you mentioned happen with Dir()?
This from "Inside MS-DOS 6"
PATH tells DOS where to look for a program or batch file in the event that file can't be found in the current directory."
Another way of looking at it;
A path is the drive designator ( C: ) and all the folder names down to the file, concantenated together with a '\' (Backslash.)
On my computor the path to excel.exe is
"C:\Program Files\Microsoft Office\Office"
Its' Dir is slightly different
"C:\Program Files\Microsoft Office\Office\"
And the fully qualified name of the excel program is
"C:\Program Files\Microsoft Office\Office\excel.exe"
Actual use of any of these will require double quotes because of some spaces in the string and because some of the folder names are longer than 8 characters
I was sad to see when they did this. I thought they should have worked on it and made it more reliable/robust, but they took the easy way out and just dropped it.Originally Posted by xld
@Joseph: They didn't replace it with anything (AFAIK), which would mean you're either going to use the Dir() or FSO method.
Regards, Zack Barresse
Check out the KB! :|: BOARD TAGS: WHAT ARE THEY AND HOW DO I USE THEM
What is a Microsoft MVP? | Free Microsoft Courses | My Book on Excel Tables
Why? Who needs 3 ways of doing it? If it's broke, and there are alternatives, ditch it. Makes sense to me.Originally Posted by firefytr
When FileSearch did work, it seemed to be a lot faster than FSO (not sure about Dir() though)Originally Posted by xld
And thanks SamT for the explanation
New to the forum? Check out our Introductions section to get to know some of the members here. Feel free to tell us a little about yourself as well.
Why you ask? Because I like having a native method designed and built especially for the task at hand. The Dir() function was not intentionally designed (at least I don't think so) for looping through folders and subfolders, plus it's not always the best choice as it can fail under certain conditions. The FSO method is great and I love it, but it's dependent on creating objects from a dynamic link library, which I don't mind but is not always the best solution (IMO).
I admit, I tend to use FSO more than anything else because I find it easier and more comfortable. I was more comfortable knowing there was a native method for exactly what I wanted to do. Drop it? No, by all means do not drop it just because it has some shortcomings. By that very same logic there would be no more methods to which this could be done.
Regards, Zack Barresse
Check out the KB! :|: BOARD TAGS: WHAT ARE THEY AND HOW DO I USE THEM
What is a Microsoft MVP? | Free Microsoft Courses | My Book on Excel Tables
The setup:[vba]Option ExplicitOriginally Posted by malik641
Private FSO As Object
Sub SpeedTestCheckCDrive()
Dim AnArrayDir() As String, AnArrayFSO() As String, i
Dim Timer1 As Double, Timer2 As Double
ReDim AnArrayFSO(0)
ReDim AnArrayDir(0)
Timer1 = Timer
Set FSO = CreateObject("scripting.filesystemobject")
ReturnAllFilesUsingFSO "C:\", AnArrayFSO
Set FSO = Nothing
Timer1 = Timer - Timer1
Timer2 = Timer
ReturnAllFilesUsingDir "C:\", AnArrayDir
Timer2 = Timer - Timer2
Debug.Print "FSO took " & Timer1 & " seconds, " & UBound(AnArrayFSO) + 1 & " files found"
Debug.Print "DIR took " & Timer2 & " seconds, " & UBound(AnArrayDir) + 1 & " files found"
End Sub
Function ReturnAllFilesUsingDir(ByVal vPath As String, ByRef vsArray() As String) As Boolean
Dim tempStr As String, vDirs() As String, Cnt As Long, dirCnt As Long
If Len(vsArray(0)) = 0 Then
Cnt = 0
Else
Cnt = UBound(vsArray) + 1
End If
If Right(vPath, 1) <> "\" Then vPath = vPath & "\"
On Error GoTo BadDir
tempStr = Dir(vPath, 31)
Do Until Len(tempStr) = 0
If Asc(tempStr) <> 46 Then
If GetAttr(vPath & tempStr) And vbDirectory Then
ReDim Preserve vDirs(dirCnt)
vDirs(dirCnt) = tempStr
dirCnt = dirCnt + 1
End If
BadDirGo:
End If
tempStr = Dir
SkipDir:
Loop
On Error GoTo BadFile
tempStr = Dir(vPath, 15)
Do Until Len(tempStr) = 0
ReDim Preserve vsArray(Cnt)
vsArray(Cnt) = vPath & tempStr
Cnt = Cnt + 1
tempStr = Dir
Loop
BadFileGo:
On Error GoTo 0
If dirCnt > 0 Then
For dirCnt = 0 To UBound(vDirs)
If Len(Dir(vPath & vDirs(dirCnt))) = 0 Then
ReturnAllFilesUsingDir vPath & vDirs(dirCnt), vsArray
End If
Next
End If
Exit Function
BadDir:
If tempStr = "pagefile.sys" Or tempStr = "???" Then
' Debug.Print "DIR: Skipping: " & vPath & tempStr
Resume BadDirGo
ElseIf Err.Number = 52 Then
' Debug.Print "No read rights: " & vPath & tempStr
Resume SkipDir
End If
Debug.Print "Error with DIR: " & Err.Number & " - " & Err.Description
Exit Function
BadFile:
If Err.Number = 52 Then
' Debug.Print "No read rights: " & vPath & tempStr
Else
Debug.Print "Error with DIR: " & Err.Number & " - " & Err.Description
End If
Resume BadFileGo
End Function
Function ReturnAllFilesUsingFSO(ByVal vPath As String, ByRef vsArray() As String) As Boolean
Dim f As Object, fld As Object, Cnt As Long
Set fld = FSO.GetFolder(vPath)
If Len(vsArray(0)) = 0 Then
Cnt = 0
Else
Cnt = UBound(vsArray) + 1
End If
On Error GoTo UhOhs
For Each f In fld.Files
ReDim Preserve vsArray(Cnt)
vsArray(Cnt) = f.path
Cnt = Cnt + 1
Next
For Each f In fld.SubFolders
ReturnAllFilesUsingFSO f.path, vsArray
Next
LaterGater:
Set f = Nothing
Set fld = Nothing
Exit Function
UhOhs:
If Err.Number = 70 Then
' Debug.Print "Permission denied: " & vPath
Else
Debug.Print "Error with FSO: " & Err.Number & " - " & Err.Description
End If
Resume LaterGater
End Function[/vba]
MattOriginally Posted by Immediate window
Not sure why I got the error...(error from my work computer)Originally Posted by Immediate Window
I'm going to have to look at this later (so I can fully understand what's going on), but well done
Could you add the Application.FileSearch method as part of your procedure to compare?
And by the way, about the original problem, it has to wait until this weekend because I don't have time to get with my friend (test on Friday...been studying since monday )
New to the forum? Check out our Introductions section to get to know some of the members here. Feel free to tell us a little about yourself as well.
Hmmmm... odd!
I only got the error 5 when it was checking a directory I didnt have access to (like C:\docs&settings\Administrator).
At the end of "return all files using dir", add "or err.number=5" to the 52 lines, like:[vba]' ElseIf Err.Number = 52 Then
ElseIf Err.Number = 52 Or Err.Number = 5 Then
'and
' If Err.Number = 52 Then
If Err.Number = 52 Or Err.Number = 5 Then[/vba]See if that gets rid of it.
Another thing you could try (in place of the above if you're not getting anywhere) could be to change the two lines of[vba]Debug.Print "Error with DIR: " & Err.Number & " - " & Err.Description[/vba]and identify the errorchecking part it is in, like[vba]Debug.Print "Error with DIR (BadDir): " & Err.Number & " - " & Err.Description
'and
Debug.Print "Error with DIR (BadFile): " & Err.Number & " - " & Err.Description[/vba]
The fact that you didnt get any results (despite it saying 1, just because of the +1 after ubound) makes me wonder if perhaps this line somehow got messed up in the copy/paste:[vba] ReturnAllFilesUsingDir "C:\", AnArrayDir[/vba]Matt
Woops, missed this part. Sure let me add it (though I've never used it, it shouldnt be tough to figure out, thats the point of it, right?)Originally Posted by malik641
I think I'll add the API filesearches as well
Updated code (no API yet):
[vba]Option Explicit
Private FSO As Object
Sub SpeedTestCheckCDrive()
Dim AnArrayDir() As String, AnArrayFSO() As String, i As Long, FSCnt As Long
Dim Timer1 As Double, Timer2 As Double, Timer3 As Double, Timer4 As Double
ReDim AnArrayFSO(0)
ReDim AnArrayDir(0)
Timer1 = Timer
Set FSO = CreateObject("scripting.filesystemobject")
ReturnAllFilesUsingFSO "C:\", AnArrayFSO
Set FSO = Nothing
Timer1 = Timer - Timer1
DoEvents
Timer2 = Timer
ReturnAllFilesUsingDir "C:\", AnArrayDir
Timer2 = Timer - Timer2
DoEvents
Timer3 = Timer
FSCnt = ReturnFileCountUsingFileSearch("C:\")
Timer3 = Timer - Timer3
Debug.Print "FSO took " & Timer1 & " seconds, " & UBound(AnArrayFSO) + 1 _
& " files found"
Debug.Print "DIR took " & Timer2 & " seconds, " & UBound(AnArrayDir) + 1 _
& " files found"
Debug.Print "FileSearch took " & Timer3 & " seconds, " & FSCnt & " files found"
End Sub
Function ReturnAllFilesUsingDir(ByVal vPath As String, ByRef vsArray() As String) _
As Boolean
Dim tempStr As String, vDirs() As String, Cnt As Long, dirCnt As Long
If Len(vsArray(0)) = 0 Then
Cnt = 0
Else
Cnt = UBound(vsArray) + 1
End If
If Right(vPath, 1) <> "\" Then vPath = vPath & "\"
On Error GoTo BadDir
tempStr = Dir(vPath, 31)
Do Until Len(tempStr) = 0
If Asc(tempStr) <> 46 Then
If GetAttr(vPath & tempStr) And vbDirectory Then
ReDim Preserve vDirs(dirCnt)
vDirs(dirCnt) = tempStr
dirCnt = dirCnt + 1
End If
BadDirGo:
End If
tempStr = Dir
SkipDir:
Loop
On Error GoTo BadFile
tempStr = Dir(vPath, 15)
Do Until Len(tempStr) = 0
ReDim Preserve vsArray(Cnt)
vsArray(Cnt) = vPath & tempStr
Cnt = Cnt + 1
tempStr = Dir
Loop
BadFileGo:
On Error GoTo 0
If dirCnt > 0 Then
For dirCnt = 0 To UBound(vDirs)
If Len(Dir(vPath & vDirs(dirCnt))) = 0 Then
ReturnAllFilesUsingDir vPath & vDirs(dirCnt), vsArray
End If
Next
End If
Exit Function
BadDir:
If tempStr = "pagefile.sys" Or tempStr = "???" Then
' Debug.Print "DIR: Skipping: " & vPath & tempStr
Resume BadDirGo
ElseIf Err.Number = 52 Then 'or err.number=5 then
' Debug.Print "No read rights: " & vPath & tempStr
Resume SkipDir
End If
Debug.Print "Error with DIR (BadDir): " & Err.Number & " - " & Err.Description
Debug.Print " vPath: " & vPath
Debug.Print " tempStr: " & tempStr
Exit Function
BadFile:
If Err.Number = 52 Then 'or err.number=5 then
' Debug.Print "No read rights: " & vPath & tempStr
Else
Debug.Print "Error with DIR (BadFile): " & Err.Number & " - " & Err.Description
Debug.Print " vPath: " & vPath
Debug.Print " tempStr: " & tempStr
End If
Resume BadFileGo
End Function
Function ReturnAllFilesUsingFSO(ByVal vPath As String, ByRef vsArray() As String) _
As Boolean
Dim f As Object, fld As Object, Cnt As Long
Set fld = FSO.GetFolder(vPath)
If Len(vsArray(0)) = 0 Then
Cnt = 0
Else
Cnt = UBound(vsArray) + 1
End If
On Error GoTo UhOhs
For Each f In fld.Files
ReDim Preserve vsArray(Cnt)
vsArray(Cnt) = f.path
Cnt = Cnt + 1
Next
For Each f In fld.SubFolders
ReturnAllFilesUsingFSO f.path, vsArray
Next
LaterGater:
Set f = Nothing
Set fld = Nothing
Exit Function
UhOhs:
If Err.Number = 70 Then
' Debug.Print "Permission denied: " & vPath
Else
Debug.Print "Error with FSO: " & Err.Number & " - " & Err.Description
End If
Resume LaterGater
End Function
Function ReturnFileCountUsingFileSearch(ByVal vPath As String) As Long
'just using this count for a speed test, since most people wouldnt want
' the results in an array
With Application.FileSearch
.NewSearch
.SearchSubFolders = True
.LookIn = vPath
.FileType = msoFileTypeAllFiles
' .FileName = "*.*"
If .Execute > 0 Then
ReturnFileCountUsingFileSearch = .FoundFiles.Count
End If
End With
End Function[/vba]
Didnt bother sending the results to a text file or anything to see what files weren't included. Can anyone who uses filesearch regularly tell me if my function could be improved/sped up?Originally Posted by Immediate window (ran it twice)
Interesting.. it appears that getting the filenames from FSO is what takes the longest. I changed the code on all (and added the API method) to only return file counts from the search. Rather than paste it, I'm just going to attach the exported module, but here were the results (again, simply a count):Originally Posted by immediate window
Weird.. application.filesearch returned a result to me, at least a count. Now when I'm looping through the results to add to an array, I got a 'permission denied' error on it, even when I just hover over .foundfiles(i)
Interesting, filesearch can see it, but my access privileges prevent me from seeing it. Apparently it only happened 4 times on my C:\, but still odd nonetheless that the filesearch method has more access than the currentuser.
Uhhh, now that I got past that I'm getting an "Out of Memory" error?! When I highlight the .FoundFiles(i) again I'm seeing Out of Memory. Should I be using anything like ".FoundFiles(i).FileName" or .Name or anything?
Cant be a huge deal as the .foundfiles.count at the start was 36020, and only 36007 items in the resulting array ... could this be another 'imperfection' of using filesearch?
OK, last part of my thread clutter. Changed each to return a resulting array:
My findings:Originally Posted by immediate window
-dir is fast
-fso is faster if you just need file counts
-filesearch is slow whether you need filename array or not (iterating through results doesnt add much runtime)
-these apis are fun
-internet cache takes a long time to look through
QED, for now
final module attached