Hi there,
Sorry for the delay in getting back to you on this one. I wanted to be able to sit down and think this one through... mostly to do with the data placement. So let's try this one out... A summary of the changes:
-Set to clear Range("B6:F24") at beginning of procedure
-Had to add a row/column counter set in the routine to allow data to be placed in the range down the column first, then across to next column (uses the cells(r,c) object, rather than range("A65536").end(xlup)
-Also added a bailout in case more than 95 matches were found (19x4 cells) so the procedure just exits at this point
-Dropped InStr in favour of some left/right text functions to ensure that file names can deal with single digit days and/or months in the date strings
Option Explicit
Private Sub cmdOkay_Click()
Const MainPath = "\\Disk1\Data\Year"
Dim Prompt As String, FullFilePath As String, _
StartDate As Date, EndDate As Date, x As Date, _
fso As Object, fs As Object, _
FilesToProcess As Integer, i As Integer, Countfiles As Integer, _
wsTarget As Worksheet, _
r As Integer, c As Integer, _
datelength As Long
'Turn off screen updating
Application.ScreenUpdating = False
Set wsTarget = Worksheets("Found")
'Make sure both textboxes have date values assigned
If Not IsDate(tbFromDate.Value) Then
Prompt = "Please enter a valid date in the From field" & vbCrLf
Else
StartDate = tbFromDate.Value
End If
If Not IsDate(tbToDate.Value) Then
Prompt = Prompt & "Please enter a valid date in the To field"
Else
EndDate = tbToDate.Value
End If
'If Prompt is empty, then no problems were detected
If Prompt = "" Then
'Clear out the worksheet
With wsTarget
.Range("B6:F24").Clear
End With
'Initialize C to place data in the first column of the data storage field
'(This is used to start in column B below - cells(r+5,c+1)
c = 1
'Create a file scripting object and set the FullFilePath variable
Set fso = CreateObject("Scripting.FileSystemObject")
'Create a file search object to work with the files inside the loop
Set fs = Application.FileSearch
'Expand userform to show progress bar
Me.Height = 174
'For each date in the range entered, search for matching files
For x = StartDate To EndDate
'Create the path to the files based on the date being examined
FullFilePath = MainPath & Year(x) & "" & Format(x, "mmm") & ""
datelength = Len(Format(x, "d-m-yyyy"))
'Update the progress indicator title, and set progress back to start
With Me
.lblProgDesc.Caption = "Searching for files containing " & Format(x, "dd-mm-yyyy")
.frmProgress.Caption = "0% complete"
.lblProgress.Width = 0
.Repaint
End With
'Check if the file path exists (using file scripting object)
If fso.FolderExists(FullFilePath) Then
Countfiles = 0
'Search for matching files (using file search object)
With fs
'Set the directory to look in
.LookIn = FullFilePath
'Search only Excel workbooks in the directory
.FileType = msoFileTypeExcelWorkbooks
'Execute the search
.Execute
'Count total files to process for progress indicator
FilesToProcess = .FoundFiles.Count
'Search through all files for filenames containing the date being
'evaluated, and create a hyperlink to those files
'(Displays only data after the word "Data" in the file name)
For i = 1 To .FoundFiles.Count
'Evaluate if the file name found matches that searched for
'(InStr returned 11-1-2004 as well as 1-1-2004 so chose left/right combo)
If Left(Right(.FoundFiles(i), _
Len(.FoundFiles(i)) - Len(FullFilePath) - 4), _
datelength) = Format(x, "d-m-yyyy") Then
'Increment the Row and Column counters to place the data
If r < 19 Then
r = r + 1
Else
r = 1
c = c + 1
End If
'If column > 5 then too many matches have been found to fit in the data
'range, so exit procedure
If c > 5 Then GoTo ExitPoint
'Add the hyperlink in the correct row/column
wsTarget.Hyperlinks.Add _
Anchor:=wsTarget.Cells(5 + r, 1 + c), _
Address:=.FoundFiles.Item(i), _
TextToDisplay:=Right(.FoundFiles(i), _
Len(.FoundFiles(i)) - Len(FullFilePath) - 4)
End If
'Count files processed for progress indicator
Countfiles = Countfiles + 1
'Update the progress indicator
Me.frmProgress.Caption = Int(Countfiles / FilesToProcess * 100) & "% complete"
Me.lblProgress.Width = Countfiles / FilesToProcess * (Me.frmProgress.Width - 10)
Me.Repaint
Next i
End With
Else
'If directory does not exist, mark this in the list
wsTarget.Range("A65536").End(xlUp).Offset(1, 0).Value _
= FullFilePath & " does not exist. No data found for " & Format(x, "d-mm-yyyy")
End If
Next x
Else
'If Prompt is not empty, tell the user what info need correcting and return to the
'userform
MsgBox "Sorry, but I need more information!" & vbCrLf & Prompt, _
vbCritical + vbOKOnly, "Please try again!"
End If
ExitPoint:
'Turn screen updating back on, release all objects, and unload the userform
Application.ScreenUpdating = True
Unload Me
End Sub
I tried to document the code fairly well so you can follow what it's doing all the way through. It can be a bit confusing though, as it uses loops within loops... particularly when some variables are set within the first, and not the second vs when they're set in the innermost...
If you have any questions on any of it, just let me know, and I'll see if I can explain better. And, of course, if something doesn't work, or you want to modify it a bit, let me know!
Cheers,