Searching for files

I have a directory with files like
0003.dat
0004.dat
0005.dat
....
0279.dat
0456.dat
0457.dat
My question is how to extract the filename which has the lowest number and the file with the highest number as fast as possible. Note that the files are not necessarily continously numbered.
tellAsked:
Who is Participating?
 
zsiConnect With a Mentor Commented:
I accept victory.  :)

tell, sorry about the syntax error there.  When I posted the code onto the board, I made some changes to the variables so that the code would be more in line with your needs.  

For those too lazy to scroll down, here is the answer again:
-------------------------------------------------------------------------

      In [Declarations]:

      Option Explicit
      Private Declare Function FindFirstFile Lib "kernel32" Alias "FindFirstFileA" (ByVal lpFileName As
      String, lpFindFileData As WIN32_FIND_DATA) As Long
      Private Declare Function FindNextFile Lib "kernel32" Alias "FindNextFileA" (ByVal hFindFile As
      Long, lpFindFileData As WIN32_FIND_DATA) As Long
      Private Declare Function FindClose Lib "kernel32" (ByVal hFindFile As Long) As Long
      Private Declare Function GetLastError Lib "kernel32" () As Long
      Const ERROR_NO_MORE_FILES = 18&


      Const MAX_PATH = 260
      Private Type FILETIME
              dwLowDateTime As Long
              dwHighDateTime As Long
      End Type

      Private Type WIN32_FIND_DATA
         dwFileAttributes As Long
         ftCreationTime As FILETIME
         ftLastAccessTime As FILETIME
         ftLastWriteTime As FILETIME
         nFileSizeHigh As Long
         nFileSizeLow As Long
         dwReserved0 As Long
         dwReserved1 As Long
         cFileName As String * MAX_PATH
         cAlternate As String * 14
      End Type

      ===================================================
      Public Sub FindMyFiles()

         Dim h As Long
         Dim fd As WIN32_FIND_DATA
         Dim High As String
         Dim Low As String
         
         h = FindFirstFileMyPath & "\*.dat", fd)
         High = fd.cFileName
         Low = fd.cFileName
         While GetLastError() <> ERROR_NO_MORE_FILES
            If fd.cFileName > High Then
               High = fd.cFileName
            ElseIf fd.cFileName < Low Then
               Low = fd.cFileName
            End If
            Call FindNextFile(h, fd)
         Wend
             
         Debug.Print "High: " & High
         Debug.Print "Low: " & Low

         Call FindClose(h)


      End Sub
0
 
deightonCommented:
Private Sub Command1_Click()
    Dim sSearch As String
    Dim sPath As String
    Dim iVal As Long
    Dim iMin As Long     'Minimum value
    Dim iMax As Long     'Maximum value
   
    iMin = 99999
   
    sPath = "a:"     'YOUR PATH
   
   
    sSearch = Dir(sPath + "*.dat")
    If sSearch = "" Then
        MsgBox "No matches"
        Exit Sub
    End If
   
    Do
   
        iVal = Val(Left(sSearch, 4))
        If iVal > iMax Then iMax = iVal
        If iVal < iMin Then iMin = iVal
       
        sSearch = Dir

    Loop Until sSearch = ""

   
End Sub

0
 
deightonCommented:
Here I've added a bit to give you the actual full name - not just the number
I think this is pretty efficient


Private Sub Command1_Click()
    Dim sSearch As String
    Dim sPath As String
    Dim iVal As Long
    Dim iMin As Long     'Minimum value
    Dim iMax As Long     'Maximum value
    Dim sMin As String   'name of lowest
    Dim sMax As String  'name of highest
   
    iMin = 99999
   
    sPath = "a:"     'YOUR PATH
   
   
    sSearch = Dir(sPath + "*.dat")
    If sSearch = "" Then
        MsgBox "No matches"
        Exit Sub
    End If
   
    Do
   
        iVal = Val(Left(sSearch, 4))
        If iVal > iMax Then iMax = iVal: sMax = sSearch
        If iVal < iMin Then iMin = iVal: sMin = sSearch
       
        sSearch = Dir

    Loop Until sSearch = ""
   
   
   'view results
   
   MsgBox "maximim = " + Format(iMax)
   MsgBox "minimum = " + Format(iMin)
   MsgBox "maximim = " + sMax
   MsgBox "minimum = " + sMin
   
   
End Sub



0
The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

 
zsiCommented:
tell,

There is a much faster way of dong this.  And with less code, too.

====================================================
In [Declarations]:

Option Explicit
Private Declare Function FindFirstFile Lib "kernel32" Alias "FindFirstFileA" (ByVal lpFileName As String, lpFindFileData As WIN32_FIND_DATA) As Long
Private Declare Function FindNextFile Lib "kernel32" Alias "FindNextFileA" (ByVal hFindFile As Long, lpFindFileData As WIN32_FIND_DATA) As Long
Private Declare Function FindClose Lib "kernel32" (ByVal hFindFile As Long) As Long
Private Declare Function GetLastError Lib "kernel32" () As Long
Const ERROR_NO_MORE_FILES = 18&


Const MAX_PATH = 260
Private Type FILETIME
        dwLowDateTime As Long
        dwHighDateTime As Long
End Type

Private Type WIN32_FIND_DATA
   dwFileAttributes As Long
   ftCreationTime As FILETIME
   ftLastAccessTime As FILETIME
   ftLastWriteTime As FILETIME
   nFileSizeHigh As Long
   nFileSizeLow As Long
   dwReserved0 As Long
   dwReserved1 As Long
   cFileName As String * MAX_PATH
   cAlternate As String * 14
End Type

===================================================
Public Sub FindMyFiles()

   Dim h As Long
   Dim fd As WIN32_FIND_DATA
   Dim High As String
   Dim Low As String
   
   h = FindFirstFileMyPath & "\*.dat", fd)
   High = fd.cFileName
   Low = fd.cFileName
   While GetLastError() <> ERROR_NO_MORE_FILES
      If fd.cFileName > High Then
         High = fd.cFileName
      ElseIf fd.cFileName < Low Then
         Low = fd.cFileName
      End If
      Call FindNextFile(h, fd)
   Wend
     
   Debug.Print "High: " & High
   Debug.Print "Low: " & Low

   Call FindClose(h)


End Sub
0
 
deightonCommented:
Dear Zsi,

Your solution has loads of code and definintely more characters in it.  Also its a Rolls Royce solution where a VW Beetle would have done.

A.Nutter






0
 
zsiCommented:
Yes, but since Tell is asking for a solution with a V-8 as opposed to an air-cooled V-4 that has a difficult time accellerating while going uphill, you need the API.  Tell *did* ask for a solution that would be as fast as possible.

Feel free to run the benchmarks yourself.
0
 
yowkeeCommented:
deighton,
   zsi's method will be much faster than you especially there got a lot files under the directory. :)

   Just want to provide a alternative way , it may not be faster than zsi's, I didn't test its real performance. Just suddenly think of it. Have fun. :)

**Declaration of API under a module:
Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Any) As Long
Public Const LB_DIR = &H18D
Public Const DDL_READWRITE = &H0
Public Const DDL_ARCHIVE = &H20

**Put a Listbox in a Form, set its property "Sorted" to True.

Private Sub Form_Load()

  SendMessage List1.hwnd, LB_DIR, DDL_READWRITE Or
              DDL_ARCHIVE, "*.dat"
  If List1.ListCount <> 0 Then
      MsgBox "Min: " + List1.List(0)
      MsgBox "Max: " + List1.List(List1.ListCount - 1)
  End If
End Sub

   
0
 
zsiCommented:
yowkee,

That method will get very slowed in instances where there are a lot of files.  Especially with the sorted property set to true as it will sort on the insertion of each entry.
0
 
tellAuthor Commented:
Thanks a lot,

zsi's solution is definitely my favourite.
ATTENTION ( for those who use the code later on):
 there is a syntax error in line
            h = FindFirstFileMyPath & "\*.dat", fd)
correct:    h = FindFirstFile(MyPath & "\*.dat", fd)
0
 
deightonCommented:
I accept defeat
0
 
tellAuthor Commented:
Greetings to both, zsi and deighton.
0
All Courses

From novice to tech pro — start learning today.