Search for file in an Array of Directories

IndigoMontoya

Member
Joined
Oct 3, 2012
Messages
17
Programming Experience
Beginner
I have 3 files which are ALWAYS named 1) DailyInventory, 2) WeeklyInventory, 3) MonthlyInventory (this could grow to 4 or 5 in the future, so room for growth would be great) that could be potentially saved in a few variations of directories. A few examples would be C:\Files\File\Daily\ or it could be C:\Files\File\Daily\DailyFiles\ or it could be C:\Files\File\DailyFile\ just to name a few. I am wanting to be able to push a button on a Windows Form, and have VB.Net code, pick the first file name from the array, then scan thro the directories where the file could be saved, when the file is found open it (I will then run a VBA macro to update the #'s), save it, then continue onto the next filename, and cycle back thro the directory array.
 
There are various ways that you could approach this but here's how I would do it:
Dim folderPaths As String() 'Create an array and populate with folder paths
Dim fileNames As String() 'Create an array and populate with file names

'Create an array of DirectoryInfo objects from the array of folder paths.
Dim folders As DirectoryInfo() = Array.Convert(folderPaths, Function(path) New DirectoryInfo(path))

'Get a file list for each folder.
Dim fileLists As FileInfo()() = Array.Convert(folders, Function(folder) folder.GetFiles())

'Search for each file in turn.
For Each fileName In fileNames
    'Search through each folder in turn.
    For Each fileList In fileLists
        'Get the matching FileInfo if there is one.
        Dim fileMatch As FileInfo = fileList.FirstOrDefault(Function(fi) fi.Name = fileName)

        'Check whether a match was found.
        If fileMatch IsNot Nothing Then
            'Get the full path of the matching file.
            Dim filePath As String = fileMatch.FullName

            'Use the file path as appropriate.
        End If
    Next
Next
I don't really know what opening the file means in your particular scenario but you can add in whatever code is appropriate inside that If block.
 
I had to add:
imports System.IO

and now it is highlighting Array.Convert in blue and saying
Convert is not a member of system.Array

Do I need to import something else?
 
Last edited:
Now I am getting a warning that folderPath and filenames is used before it is assigned a value. I don't think that will cause a problem, but want to confirm that, please.
 
Now I am getting a warning that folderPath and filenames is used before it is assigned a value. I don't think that will cause a problem, but want to confirm that, please.

It will cause a problem because they need to contain the folder paths and file names. That's why I put the comments next to them to tell you to:
Create an array and populate with folder paths
and:
Create an array and populate with file names
You can't search a list of folders for a list of files if you don't have a list of folders or a list of files.
 
Oh how silly me! I now have the line:
VB.NET:
Function(fi) fi.Name = fileName

And fileName is underlined in green saying,
'Using the iteration variable in a lambda expression may have unexpected results. Instead, create a local variable within the loop and assign it to the value of the iteration variable

I copied and pasted code, so I don't think I keypunched anything incorrectly ....


EDIT ----
Another snare that I hit is it will highlight this piece:
VB.NET:
Array.ConvertAll(folders, Function(folder) folder.GetFiles())

And display a DirectoryNotFound Exception was unhandled.

Some of these directories may not exist, if the do not, I need the code to continue cycling until it finds the valid directory.
 
Last edited:
VB.NET:
Function(fi) fi.Name = fileName

And fileName is underlined in green saying,
'Using the iteration variable in a lambda expression may have unexpected results. Instead, create a local variable within the loop and assign it to the value of the iteration variable
That's actually not an issue in this case but if you want to get rid of the warning then you can do as it says, i.e. declare a local variable inside the loop, assign the loop iteration variable to that local variable and then use the local variable in the lambda expression in place of the loop iteration variable.

The reason that this is flagged is that lambda expressions are not necessarily executed immediately. If this one is not executed before the loop progresses to the next iteration then you would get unexpected results because the loop iteration variable will have a different value from when the lambda expression was created. By using a local variable you fix the value passed to the lambda expression so it will be the same when the expression is executed even if the loop iteration variable has changed. In this case the lambda expression is always executed immediately, so no issue can arise. It's probably good to get in the habit of not using loop counters and iteration variables in lambda expressions though, so that you don't do it accidentally in a case where it does make a difference.
VB.NET:
Function(fi) fi.Name = fileName

And fileName is underlined in green saying,
'Using the iteration variable in a lambda expression may have unexpected results. Instead, create a local variable within the loop and assign it to the value of the iteration variable

I copied and pasted code, so I don't think I keypunched anything incorrectly ....


EDIT ----
Another snare that I hit is it will highlight this piece:
VB.NET:
Array.ConvertAll(folders, Function(folder) folder.GetFiles())

And display a DirectoryNotFound Exception was unhandled.

Some of these directories may not exist, if the do not, I need the code to continue cycling until it finds the valid directory.
You account for that by changing this line:
Dim folders As DirectoryInfo() = Array.Convert(folderPaths, Function(path) New DirectoryInfo(path))
to this:
Dim folders As DirectoryInfo() = Array.Convert(folderPaths.Where(Function(path) Directory.Exists(path)).ToArray(), Function(path) New DirectoryInfo(path))
or this:
Dim folders As DirectoryInfo() = folderPaths.Where(Function(path) Directory.Exists(path)).Select(Function(path) New DirectoryInfo(path)).ToArray()
 
In my If statement I added these lines of code:
VB.NET:
MxgBox("File was located")
Excel.Application = New Excel.Application
Excel.Application.Visible = True
Excel.Application.Workbooks.Open(fileName)

I get the prompt that the file was found, but when it goes to actually open the workbook, it tells me that the workbook can not be found? How can I have it actually open the file?
 
Last edited:
Here is the block...
For Each fileName in fileNames
    For Each fileList in fileLists
        Dim fileMatch As FileInfo = fileList.firstordefault(Function(fi) fi.Name = fileName)

        If fileMatch IsNot Nothing Then
            Dim filePath As String = fileMatch.FullName

            MsgBox("File was located")
            Excel.Application = New Excel.Application
            Excel.Application.Visible = True
            Excel.Application.Workbooks.Open(fileName)
        End If
    Next
Next
 
Last edited by a moderator:
It frustrates me when people don't actually look at the data that their code is using. Have you looked at the values of 'fileName' and 'filePath' in your code? What did I say earlier?
VB.NET:
            'Get the [B][U]full path[/U][/B] of the matching file.
            Dim [B][U]filePath[/U][/B] As String = fileMatch.FullName
 
            'Use the [B][U]file path[/U][/B] as appropriate.
Look at your code now:
VB.NET:
            Dim [B][U]filePath[/U][/B] As String = fileMatch.FullName
 
            MsgBox("File was located")
            Excel.Application = New Excel.Application
            Excel.Application.Visible = True
            Excel.Application.Workbooks.Open([B][U]fileName[/U][/B])
Did you not wonder what that 'filePath' variable was for? I wouldn't have suggested declaring it it if wasn't going to be used.
 
Sincerest sorries! I now see where my error was. I should have done it like
VB.NET:
Excel.Application.Workbooks.Open(filePath)

Thank you for your patience with working with me!!! And thank you again for this marvelous code :) :) :)
 
Back
Top