From: MP on
I'm trying to use cFileSearch cls but am doing something wrong getting the
correct subdirectory
when searchdepth = -1 (all sub dirs)
I'm getting back filenames where the file is out of sync with the folder in
which it really exists

oFileSearch.search
oFileSearch.BuildTreeIndexes
For i = 0 To oFileSearch.DirsCount - 1
With oFileSearch.DirsTree(i)
For N = 0 To .FoundFilesCount - 1
colRtn.Add oFileSearch.GetDirPath(i) & "\" & .FoundFiles(N).Name
Next N
End With
Next i

anyone see what I'm doing wrong?
thanks
mark

'filtering for files *.dwg

Public Function DwgsInFolder(FolderName As String, _
Optional FileNameMatch As String, _
Optional lSearchDepthMax As Long = -1) _
As Collection
On Error GoTo GetDwgsInFolder2_Error

Dim bSuccess As Boolean
Dim oFileSearch As CFileSearch
Dim colRtn As Collection
Dim i As Long, N As Long

Set oFileSearch = New CFileSearch
Set colRtn = New Collection

If Len(FolderName) = 0 Then
GoTo ExitHere
End If

If FolderExists(FolderName) Then
oFileSearch.StartPath = FolderName
End If

'SearchDepthMax constrains the search depth.
'Possible Values:
'<0: no search depth constraint, all dirs below the start dir are searched
'0 : only the start dir is scanned
'1 : the start dir and its subdirs are scanned
'2 : the start dir, its subdirs and their subdirs are scanned
'n : and so on
oFileSearch.SearchDepthMax = lSearchDepthMax

If FileNameMatch = "*" Or FileNameMatch = "*.*" Then
oFileSearch.FileNameFilter = "*.dwg"

ElseIf Len(FileNameMatch) > 0 Then
If Not Right$(FileNameMatch, 4) = ".dwg" Then
oFileSearch.FileNameFilter = FileNameMatch & "*.dwg"
End If
Else
oFileSearch.FileNameFilter = "*.dwg"
End If

oFileSearch.search
oFileSearch.BuildTreeIndexes
' LogEntry "oFileSearch.FoundFilesCount ", oFileSearch.FoundFilesCount
For i = 0 To oFileSearch.DirsCount - 1
DoEvents

With oFileSearch.DirsTree(i)


For N = 0 To .FoundFilesCount - 1
colRtn.Add oFileSearch.GetDirPath(i) & "\" & .FoundFiles(N).Name
Next N
End With
Next i


Set DwgsInFolder = colRtn

ExitHere:
On Error GoTo 0
Exit Function
GetDwgsInFolder2_Error:
LogError ProcName
Resume ExitHere
End Function


From: MP on
think i got it
i needed DirIdxFromTreeIdx

For i = 0 To oFileSearch.DirsCount - 1
With oFileSearch.DirsTree(i)
lDirIdx = oFileSearch.DirIdxFromTreeIdx(i)
sThisFolder = oFileSearch.GetDirPath(lDirIdx, True)
For N = 0 To .FoundFilesCount - 1
colRtn.Add sThisFolder & "\" & .FoundFiles(N).Name
Next N
End With
Next i

"MP" <NoSpam(a)Thanks.com> wrote in message
news:OyLglqmTJHA.4680(a)TK2MSFTNGP06.phx.gbl...
> I'm trying to use cFileSearch cls but am doing something wrong getting the
> correct subdirectory
> when searchdepth = -1 (all sub dirs)
> I'm getting back filenames where the file is out of sync with the folder
> in which it really exists
>
> oFileSearch.search
> oFileSearch.BuildTreeIndexes
> For i = 0 To oFileSearch.DirsCount - 1
> With oFileSearch.DirsTree(i)
> For N = 0 To .FoundFilesCount - 1
> colRtn.Add oFileSearch.GetDirPath(i) & "\" & .FoundFiles(N).Name
> Next N
> End With
> Next i
>
> anyone see what I'm doing wrong?
> thanks
> mark
>
> 'filtering for files *.dwg
>
snip
>


From: Ulrich Korndoerfer on
Hi,

MP schrieb:

> I'm trying to use cFileSearch cls but am doing something wrong getting the
> correct subdirectory
> when searchdepth = -1 (all sub dirs)
> I'm getting back filenames where the file is out of sync with the folder in
> which it really exists
>
> oFileSearch.search
> oFileSearch.BuildTreeIndexes
> For i = 0 To oFileSearch.DirsCount - 1
> With oFileSearch.DirsTree(i)
> For N = 0 To .FoundFilesCount - 1
> colRtn.Add oFileSearch.GetDirPath(i) & "\" & .FoundFiles(N).Name
> Next N
> End With
> Next i
>
> anyone see what I'm doing wrong?
> thanks
> mark
>

You should use

colRtn.Add oFileSearch.GetDirPath(oFileSearch.DirIdxFromTreeIdx(i)) _
& "\" & .FoundFiles(N).Name

In your loop you use an index i to adress an dir entry in the DirsTree
view of the Dirs list (by using oFileSearch.DirsTree(i)), but then to
return the dirs path you use the same index to address a directory in
the Dirs list (by using oFileSearch.GetDirPath(i)). However GetDirPath
expects an index adressing an entry in the Dirs list, not an index for
the DirsTree view on the Dirs list! So for GetDirPath in your case you
must use oFileSearch.DirIdxFromTreeIdx(i) to "translate" an DirsTree
index to a Dirs index.

Please note (copied from the accompanying source code of CFileSearch):

<cite>

'The Dirs list holds in its name member only the name of the dir.
'To get the path to the dir, call GetDirPath. *DirIdx must be an
'index to the Dirs list.*

'If AbsPath is True, it returns a path starting with StartPath,
'that is an absolute path to the dir, otherwise it returns a
'relative path starting with StartDir.

'The returned path does not have a trailing backslash!

Public Function GetDirPath(ByVal DirIdx As Long, _
Optional ByVal AbsPath As Boolean = True) As String
....
End Function

....

'Use it to get an index to the Dirs list from an index to
'the DirsTree view. Both indexes then reference the same dir.

Public Property Get DirIdxFromTreeIdx(ByVal DirTreeIdx As Long) As Long
....
End Property

....

'Use it to get an index to the DirsTree view from an index
'to the Dirs list. Both indexes then reference the same dir.

Public Property Get TreeIdxFromDirIdx(ByVal DirIdx As Long) As Long
....
End Property

</cite>

Some background information (also explained in the comments of
CFileSearch's source code):

CFileSearch during a search collects all found directories in an array
(I call it the Dirs list), *in the order they are detected during
search*. Each method or property named Dirs* or having an index
parameter named DirIdx uses and adresses entries in this array.

However the order the directories appear in the Dirs list is *not*
reflecting the hierarchical order the dirs have in your filesystem,
because the search algorithm first collects all subdirs in a dir, then
collects the subdirs of the subdirs.

For example for a startdir StartDir:

StartDir
SubDir1
SubSubDir
SubDir2

the Dirs list after a full search has the entries

Index 0: StartDir
Index 1: SubDir1
Index 2: SubDir2
Index 3: SubSubDir

For getting a directory list reflecting the hierarchical order, one has
to call after a search BuildTreeIndexes (that is what you did). This
creates an index array for the Dirs list like such:

Index 0: 0 (points to StartDir)
Index 1: 1 (points to SubDir1)
Index 2: 3 (points to SubSubDir)
Index 3: 2 (points to SubDir2)

You iterate over this sequence by using DirsTree(i). Therefore for eg. i
= 2 you get the dir data of the dir SubSubDir. Then you use the same
index i for getting the dir's path by calling GetDirPath(i). However
GetDirPath uses the Dirs list and therefore for i = 2 returns the path
for the dir SubDir2, and you got a mismatch.

I choose to implement CFileSearch in such a way ("breadth first" search)
because of performance reasons. Doing not a "drill down first" or "depth
first" search is faster. In many cases the user is not interested in the
hierarchical order of the dirs, eg. if he just searches for some files,
so a "depth first" algorithm would be overkill.

However, if needed, the user also can have the dirs sorted in their
hierarchical order. This can be achieved by calling BuildTreeIndexes,
which generates an index array using a recursive algorithm. This one is
very fast as it just shuffles around some long values. In fact I believe
doing a "breadth first" search first and then create an index array is
faster than doing a "depth first" search. My approach of course needs
some memory for the additional index array, but the additional memory
requirements are low: eg. for 10000 dirs 40000 Bytes.

The result is: CFileSearch has two methods for accessing dir data: one
using the Dirs list, expecting a DirIdx index and one using the DirsTree
view, expecting a DirTreeIdx index. AFAIR GetDirPath is the only method
which only works with DirIdx and does not have a DirTreeIdx counter
part. However the two properties DirIdxFromTreeIdx and TreeIdxFromDirIdx
at any time allow translation, so for methods using the Dirs list only a
DirTreeIdx can be used by calling DirIdxFromTreeIdx and vice versa.

Hope that did remove some possible confusion :-)

Btw, I have a newer, unpublished version of CFileSearch. May be I will
publish it on my web site in the next weeks. I could add a GetDirPath
property using the dirs tree view for the users convenience.

--
Ulrich Korndoerfer

VB tips, helpers, solutions -> http://www.proSource.de/Downloads/
From: MP on
thanks Ulrich,
I found that a while ago just before your reply,
sorry, I should have seen that in the comments before posting.
But thanks for the additional info and thanks for the great class.

mark

"Ulrich Korndoerfer" <ulrich_wants_nospam(a)prosource.de> wrote in message
news:%23OOp2noTJHA.3952(a)TK2MSFTNGP06.phx.gbl...
> Hi,
>
> MP schrieb:
>
>> I'm trying to use cFileSearch cls but am doing something wrong getting
>> the correct subdirectory
>> when searchdepth = -1 (all sub dirs)
>> I'm getting back filenames where the file is out of sync with the folder
>> in which it really exists
>>
>> oFileSearch.search
>> oFileSearch.BuildTreeIndexes
>> For i = 0 To oFileSearch.DirsCount - 1
>> With oFileSearch.DirsTree(i)
>> For N = 0 To .FoundFilesCount - 1
>> colRtn.Add oFileSearch.GetDirPath(i) & "\" & .FoundFiles(N).Name
>> Next N
>> End With
>> Next i
>>
>> anyone see what I'm doing wrong?
>> thanks
>> mark
>>
>
> You should use
>
> colRtn.Add oFileSearch.GetDirPath(oFileSearch.DirIdxFromTreeIdx(i)) _
> & "\" & .FoundFiles(N).Name
>
> In your loop you use an index i to adress an dir entry in the DirsTree
> view of the Dirs list (by using oFileSearch.DirsTree(i)), but then to
> return the dirs path you use the same index to address a directory in the
> Dirs list (by using oFileSearch.GetDirPath(i)). However GetDirPath expects
> an index adressing an entry in the Dirs list, not an index for the
> DirsTree view on the Dirs list! So for GetDirPath in your case you must
> use oFileSearch.DirIdxFromTreeIdx(i) to "translate" an DirsTree index to a
> Dirs index.
>
> Please note (copied from the accompanying source code of CFileSearch):
>
> <cite>
>
> 'The Dirs list holds in its name member only the name of the dir.
> 'To get the path to the dir, call GetDirPath. *DirIdx must be an
> 'index to the Dirs list.*
>
> 'If AbsPath is True, it returns a path starting with StartPath,
> 'that is an absolute path to the dir, otherwise it returns a
> 'relative path starting with StartDir.
>
> 'The returned path does not have a trailing backslash!
>
> Public Function GetDirPath(ByVal DirIdx As Long, _
> Optional ByVal AbsPath As Boolean = True) As String
> ...
> End Function
>
> ...
>
> 'Use it to get an index to the Dirs list from an index to
> 'the DirsTree view. Both indexes then reference the same dir.
>
> Public Property Get DirIdxFromTreeIdx(ByVal DirTreeIdx As Long) As Long
> ...
> End Property
>
> ...
>
> 'Use it to get an index to the DirsTree view from an index
> 'to the Dirs list. Both indexes then reference the same dir.
>
> Public Property Get TreeIdxFromDirIdx(ByVal DirIdx As Long) As Long
> ...
> End Property
>
> </cite>
>
> Some background information (also explained in the comments of
> CFileSearch's source code):
>
> CFileSearch during a search collects all found directories in an array (I
> call it the Dirs list), *in the order they are detected during search*.
> Each method or property named Dirs* or having an index parameter named
> DirIdx uses and adresses entries in this array.
>
> However the order the directories appear in the Dirs list is *not*
> reflecting the hierarchical order the dirs have in your filesystem,
> because the search algorithm first collects all subdirs in a dir, then
> collects the subdirs of the subdirs.
>
> For example for a startdir StartDir:
>
> StartDir
> SubDir1
> SubSubDir
> SubDir2
>
> the Dirs list after a full search has the entries
>
> Index 0: StartDir
> Index 1: SubDir1
> Index 2: SubDir2
> Index 3: SubSubDir
>
> For getting a directory list reflecting the hierarchical order, one has to
> call after a search BuildTreeIndexes (that is what you did). This creates
> an index array for the Dirs list like such:
>
> Index 0: 0 (points to StartDir)
> Index 1: 1 (points to SubDir1)
> Index 2: 3 (points to SubSubDir)
> Index 3: 2 (points to SubDir2)
>
> You iterate over this sequence by using DirsTree(i). Therefore for eg. i =
> 2 you get the dir data of the dir SubSubDir. Then you use the same index i
> for getting the dir's path by calling GetDirPath(i). However GetDirPath
> uses the Dirs list and therefore for i = 2 returns the path for the dir
> SubDir2, and you got a mismatch.
>
> I choose to implement CFileSearch in such a way ("breadth first" search)
> because of performance reasons. Doing not a "drill down first" or "depth
> first" search is faster. In many cases the user is not interested in the
> hierarchical order of the dirs, eg. if he just searches for some files, so
> a "depth first" algorithm would be overkill.
>
> However, if needed, the user also can have the dirs sorted in their
> hierarchical order. This can be achieved by calling BuildTreeIndexes,
> which generates an index array using a recursive algorithm. This one is
> very fast as it just shuffles around some long values. In fact I believe
> doing a "breadth first" search first and then create an index array is
> faster than doing a "depth first" search. My approach of course needs some
> memory for the additional index array, but the additional memory
> requirements are low: eg. for 10000 dirs 40000 Bytes.
>
> The result is: CFileSearch has two methods for accessing dir data: one
> using the Dirs list, expecting a DirIdx index and one using the DirsTree
> view, expecting a DirTreeIdx index. AFAIR GetDirPath is the only method
> which only works with DirIdx and does not have a DirTreeIdx counter part.
> However the two properties DirIdxFromTreeIdx and TreeIdxFromDirIdx at any
> time allow translation, so for methods using the Dirs list only a
> DirTreeIdx can be used by calling DirIdxFromTreeIdx and vice versa.
>
> Hope that did remove some possible confusion :-)
>
> Btw, I have a newer, unpublished version of CFileSearch. May be I will
> publish it on my web site in the next weeks. I could add a GetDirPath
> property using the dirs tree view for the users convenience.
>
> --
> Ulrich Korndoerfer
>
> VB tips, helpers, solutions -> http://www.proSource.de/Downloads/