Do While Loop not looping inside If-Else statement
-
Monday, August 06, 2012 1:39 PM
I have a program that does miscellaneous stuff, but in this instance it is in relation to looping. Before I modified it recently, it would loop through each file that matched the specified pattern. However, now, it will only execute the Do While loop once and continue on with the program. I don't believe anything was changed in relation to my program syntax, but if someone could point out to me why it isn't looping (and it's only executing once) , I'd greatly appreciate it. All the variables are defined and none are null. In reality, with my current sample data, it should match 5 files. However, it only matches the first file in the list (sorted by name) and does the copy. Thanks for looking!
Dim sFile As String Dim sPath As String Dim sDestPath As String Dim sMMDD As String Dim sMMDDYYYY As String Dim sMMDDminusone As String sFile = Dir(sPath & sMMDD & "????.dat") prevdayfiles = Dir(sPath & sMMDDminusone & "????.dat") Dim copyFileCount As Integer copyFileCount = 0 If sFile = "" Then MessageBox.Show("Error: There are no files to copy. Closing without copying or zipping.") YPollDate.Enabled = True btnCancel.Enabled = True btnCopy.Enabled = True Exit Sub Else Do While sFile <> "" FileCopy(sPath & sFile, sDestPath & sFile) copyFileCount = copyFileCount + 1 Application.DoEvents() sFile = Dir() Loop End If
Justin
All Replies
-
Monday, August 06, 2012 2:13 PMAccording to the code, only one folder is being searched (no subfolders) for files with a .dat extension. Is this what you intend?
Paul ~~~~ Microsoft MVP (Visual Basic)
-
Monday, August 06, 2012 2:16 PM
That is correct. It isn't going to the next file, like the dir() inside the loop (or so I understand it) should make it do. Out of curiosity, I did this:
If sFile = "" Then MessageBox.Show("Error: There are no files to copy. Closing without copying or zipping.") YPollDate.Enabled = True btnCancel.Enabled = True btnCopy.Enabled = True Exit Sub Else Do While sFile <> "" MessageBox.Show("sFile before operation is " & sFile) FileCopy(sPath & sFile, sDestPath & sFile) copyFileCount = copyFileCount + 1 MessageBox.Show("sFile before application.doevents " & sFile) Application.DoEvents() MessageBox.Show("sFile before Dir() is " & sFile) sFile = Dir() MessageBox.Show("sFile after operation is " & sFile) Loop End If
And after the Dir() command it is showing as blank (or null, I suppose) in the message box, which makes no sense as there are 4 more files there matching the pattern in the same folder.
Justin
-
Monday, August 06, 2012 2:36 PMWhat are the file names in that folder that match that pattern?
Paul ~~~~ Microsoft MVP (Visual Basic)
-
Monday, August 06, 2012 2:39 PM
08031245.dat
08032154.dat
08036487.dat
08034547.dat
08035545.datIt only copies the 08031245.dat file, and after the Dir() it shows sFile as nothing (or perhaps "").
Justin
-
Monday, August 06, 2012 2:42 PMUse IO.Directory.GetFiles instead of Dir(). I also suggest removing Application.DoEvents. It's not required as the thread already has a message loop.
Armin
-
Monday, August 06, 2012 2:48 PM
The reason for the application.doevents was because of the volume of files (outside of a test environment) would cause the GUI to report it as "not responding." This seemed to fix the problem, and didn't seem to effect anything at the time. I've also taken that out (thinking much the same thing), but had the same problem present itself.
I'm afraid I'm not familiar with IO.Directory.GetFiles. I see here http://msdn.microsoft.com/en-us/library/system.io.directory.getfiles.aspx that it allows the search parameter to be passed to it, so would I replace my sFile variable's definition? Would it still be a string?
Ex:
Instead of
sFile = Dir(sPath & sMMDD & "????.dat")
It would be
sFile = IO.Directory.GetFiles(sPath, sMMDD & "????.dat")
Correct?
How would I replace the Dir()? Just use IO.Directory.GetFiles()?
Justin
- Edited by Justin Wright Monday, August 06, 2012 2:50 PM
-
Monday, August 06, 2012 2:57 PM
Hi Justin,
IO.Directory.GetFiles returns an array of all files, so it would be...:
Dim Files As String() Files = IO.Directory.GetFiles(sPath, sMMDD & "????.dat") If Files.Length = 0 Then MessageBox.Show("Error: There are no files to copy. Closing without copying or zipping.") YPollDate.Enabled = True btnCancel.Enabled = True btnCopy.Enabled = True Exit Sub Else For Each File In Files Dim SourceFilename, DestFile As String SourceFilename = IO.Path.GetFileName(File) DestFile = IO.Path.Combine(sDestPath, SourceFilename) IO.File.Copy(File, DestFile) Next End IfEDIT: Oh, and you may want to insert "copyFileCount += 1" again. Sorry, I forgot that. Or just take Files.Length as the total number.
Armin
- Edited by Armin Zingler Monday, August 06, 2012 3:05 PM
- Marked As Answer by Justin Wright Monday, August 06, 2012 7:46 PM
-
Monday, August 06, 2012 3:29 PM
_Damien_ I tried yours and it shows:
"A first chance exception of type 'System.IO.IOException' occurred in Microsoft.VisualBasic.dll"
And it shows the sFile = Dir() line as the error in question.
I'm going to rework the loop to Armin's suggestions and I'll post back in a moment when I've tested it. Thanks for all the help so far guys!
Justin
-
Monday, August 06, 2012 3:47 PM
Armin, your solution worked perfectly! I still don't know why Dir() suddenly stopped working, but I don't suppose it matters. If you could help me rewrite one section that I can't figure out, I'll leave all you guys alone and mark this answered. Thanks a bunch for the help so far!
The code I have now looks like the following (just assume the functions/variables are defined):
Dim zipPath As String = "Y:\DAILY\" & sMMDDYYYY & "01.zip" Dim zip As Package = ZipPackage.Open(zipPath, _ IO.FileMode.OpenOrCreate, IO.FileAccess.ReadWrite) sFile = Dir(sPath & sMMDD & "????.dat") Do While sFile <> "" AddToArchive(zip, sPath & sFile) Application.DoEvents() sFile = Dir() Loop zip.Close() 'Close the zip file zipNum = "01" 'Says zip 01 created later on sFile = Dir(sPath & sMMDD & "????.dat") Do While sFile <> "" My.Computer.FileSystem.DeleteFile(sPath & sFile) Application.DoEvents() sFile = Dir() Loop
Justin
-
Monday, August 06, 2012 3:52 PMWell, it's pretty much the same: read all files into an array, then process the array. As it's almost equal to the previous code, I don't post a code example. I'd remove DoEvents and replace My.Computer.FileSystem.DeleteFile by IO.File.Delete.
Armin
-
Monday, August 06, 2012 3:54 PM
I assume it would be something like this:
Dim zipPath As String = "Y:\DAILY\" & sMMDDYYYY & "01.zip" Dim zip As Package = ZipPackage.Open(zipPath, _ IO.FileMode.OpenOrCreate, IO.FileAccess.ReadWrite) sFile = IO.Directory.GetFiles(sPath, sMMDD & "????.dat") For Each File in sFile AddToArchive(zip, sFile) Next zip.Close() 'Close the zip file zipNum = "01" 'Says zip 01 created later on sFile = IO.Directory.GetFiles(sPath, sMMDD & "????.dat") For Each File in sFile Dim SourceFilename, DestFile As String SourceFilename = IO.Path.GetFileName(File) DestFile = IO.Path.Combine(sDestPath, SourceFilename) IO.File.Delete(File) Next
The reason I ask hesitantly is because of the zip function I have is this, and seems to only take in a string:
Public Sub AddToArchive(ByVal zip As Package, _ ByVal fileToAdd As String) 'Usage: 'AddToArchive(zip, "C:\TEMP\Compression\Compress Me3.txt") 'Replace spaces with an underscore (_) Dim uriFileName As String = fileToAdd.Replace(" ", "_") 'A Uri always starts with a forward slash "/" Dim zipUri As String = String.Concat("/", _ IO.Path.GetFileName(uriFileName)) Dim partUri As New Uri(zipUri, UriKind.Relative) Dim contentType As String = _ Net.Mime.MediaTypeNames.Application.Zip 'The PackagePart contains the information: ' Where to extract the file when it's extracted (partUri) ' The type of content stream (MIME type): (contentType) ' The type of compression: (CompressionOption.Normal) Dim pkgPart As PackagePart = zip.CreatePart(partUri, _ contentType, CompressionOption.Normal) 'Read all of the bytes from the file to add to the zip file Dim bites As Byte() = File.ReadAllBytes(fileToAdd) 'Compress and write the bytes to the zip file pkgPart.GetStream().Write(bites, 0, bites.Length) End Sub
Justin
- Edited by Justin Wright Monday, August 06, 2012 4:02 PM
-
Monday, August 06, 2012 4:03 PM
I think that GetFiles does not consider file attributes. The Dir function will only look for files with no attributes set by default. Any chance those other files have attributes set? I tested your code (using Dir, files w/no attributes) and it worked fine for me.
Paul ~~~~ Microsoft MVP (Visual Basic)
-
Monday, August 06, 2012 4:06 PM
_Damien_ I tried yours and it shows:
"A first chance exception of type 'System.IO.IOException' occurred in Microsoft.VisualBasic.dll"
And it shows the sFile = Dir() line as the error in question.
I'm going to rework the loop to Armin's suggestions and I'll post back in a moment when I've tested it. Thanks for all the help so far guys!
Justin
Yea i know sorry for wasting your time i tried to delete my post as quick as i could, i suggest you stick with Armin.
-
Monday, August 06, 2012 4:13 PM
Ok i tried this and it copies the files to TESTDEST
Private Sub Red() Dim sFile As String Dim sPath As String Dim sDestPath As String sPath = "C:\TEST\" sFile = Dir(sPath & "*.txt") 'added star here sDestPath = "C:\TEST\TESTDEST\" Dim copyFileCount As Integer copyFileCount = 0 If sFile = "" Then MessageBox.Show("Error: There are no files to copy. Closing without copying or zipping.") Exit Sub Else Do While sFile <> "" FileCopy(sPath & sFile, sDestPath & sFile) copyFileCount = copyFileCount + 1 Application.DoEvents() sFile = Dir() Loop End If End SubI checked now and it loops through the loop 3 time as i have 3 txt files.
- Edited by _Damien_ Monday, August 06, 2012 4:16 PM
-
Monday, August 06, 2012 4:24 PM
@ Paul The files don't have attributes set. In actuality, all the .dat files are in the test environment are txt files with "Test Test" over and over to make them over a certain file size (handled earlier in the program) and renamed with a .dat extension.
@ Damien That's what is so incredibly weird. That code worked before for me. For some reason, it doesn't now. I have no clue why... but even copy and pasting your code verbatim (with the txt changed to dat and the directories changed) it won't work... I'm honestly baffled. It will only take the first file it finds, do the required operations, and doesn't do any more. If it has 5 files, I'd have to run the sub 5 times for the files to get copied over. Even weirder, though, is that Armin's code worked for that part of the sub.
Justin
- Edited by Justin Wright Monday, August 06, 2012 4:26 PM
-
Monday, August 06, 2012 4:27 PM
The code I have now looks like the following (just assume the functions/variables are defined):
Dim zipPath As String = "Y:\DAILY\" & sMMDDYYYY & "01.zip" Dim zip As Package = ZipPackage.Open(zipPath, _ IO.FileMode.OpenOrCreate, IO.FileAccess.ReadWrite) sFile = Dir(sPath & sMMDD & "????.dat")-->"????*.dat" but im not sure why you use question marks is it part of the file name Do While sFile <> "" AddToArchive(zip, sPath & sFile) Application.DoEvents() sFile = Dir() Loop zip.Close() 'Close the zip file zipNum = "01" 'Says zip 01 created later on sFile = Dir(sPath & sMMDD & "????.dat") Do While sFile <> "" My.Computer.FileSystem.DeleteFile(sPath & sFile) Application.DoEvents() sFile = Dir() Loop
Justin
I think that star makes a difference. Have a look here http://msdn.microsoft.com/en-us/library/dk008ty4%28v=vs.71%29.aspx
- Edited by _Damien_ Monday, August 06, 2012 4:30 PM
-
Monday, August 06, 2012 4:30 PM
I replaced the code:
sFile = Dir(sPath & sMMDD & "????.dat")
With
sFile = Dir(sPath & sMMDD & "*.dat")
I had read somewhere else that the * didn't like to work as a wildcard in some of the things I was doing. I see now that this was an erroneous assumption, but even so, using the * still doesn't allow it to work.
As a caveat, in the example link you posted, it copies ALL the *.dat files. I only want ones matching the pattern, for instance, of 0806*.dat.
Justin
- Edited by Justin Wright Monday, August 06, 2012 4:33 PM
-
Monday, August 06, 2012 4:36 PM
Armins code is better because i think its trial and error free but all i did after my first post which is now deleted is just add the star like this
"*.dat"
But do you need those question marks probably a stupid question but cant you do this rather
sFile = Dir(sPath & sMMDD & "????" & "*.dat")
Good luck.no but then that wouldn't work because that * makes it find first dat file regardless of name and when you put this in the loop
sFile = Dir()
It goes to the next.dat file
yip go with armin
- Edited by _Damien_ Monday, August 06, 2012 4:39 PM
-
Monday, August 06, 2012 4:39 PM
Like I said, the lack of question marks didn't seem to effect anything else (there is just the only doing the loop once problem), so I don't think I need them. However, I also tried what you suggested with both the question marks with the * and received the same result. It's just doing the loop once, then when Dir() is called, it's showing that there's nothing else there to do things with, which isn't the case. It's frustrating, particularly since I could swear the same code worked not a week ago.
EDIT: I'm not sure why it broke in the first place, but it seems as if I'll have to. I'm just having trouble rewriting the loop above for adding the files to an archive and deleting them from the source dir after the copy/zip operations, particularly since it appears (to me) that the function won't like it if I pass it an array instead of a simple string.
Justin
- Edited by Justin Wright Monday, August 06, 2012 4:41 PM
-
Monday, August 06, 2012 4:42 PM
Like I said, the lack of question marks didn't seem to effect anything else (there is just the only doing the loop once problem), so I don't think I need them. However, I also tried what you suggested with both the question marks with the * and received the same result. It's just doing the loop once, then when Dir() is called, it's showing that there's nothing else there to do things with, which isn't the case. It's frustrating, particularly since I could swear the same code worked not a week ago.
Justin
Same with me but then i realized i changed the value of my counter from 1 to 2 lol -
Monday, August 06, 2012 5:05 PM
I think I figured it out. I put your second call to Dir into the code. When you call Dir a second time with new parameters it will be reset. That means subsequent calls to Dir with no parameters will be operating on the last call to Dir that included search parameters. I would suspect that the second call to Dir either returned one or no matches.
You should only process one set of Dir search criteria at a time.
Paul ~~~~ Microsoft MVP (Visual Basic)
- Marked As Answer by Justin Wright Monday, August 06, 2012 7:46 PM
-
Monday, August 06, 2012 5:22 PMModerator
I made a filescanner, maybe you can find something useful in its code.
Paul's Skydrive - FileScan.zip
If you want something you've never had, you need to do something you've never done. If you believe something to be true, then one day you will be called upon to demonstrate that truth.
-
Monday, August 06, 2012 5:35 PM
I think I figured it out. I put your second call to Dir into the code. When you call Dir a second time with new parameters it will be reset. That means subsequent calls to Dir with no parameters will be operating on the last call to Dir that included search parameters. I would suspect that the second call to Dir either returned one or no matches.
You should only process one set of Dir search criteria at a time.
Paul ~~~~ Microsoft MVP (Visual Basic)
This makes complete and total sense, sadly. I can't believe I didn't see it. There is another part of the module that takes the previous day's data using the Dir() search command with parameters as well and attempts to work concurrently with it.
sFile = Dir(sPath & sMMDD & "*.dat") prevdayfiles = Dir(sPath & sMMDDminusone & "*.dat") Dim copyFileCount As Integer copyFileCount = 0 ' After the check for 0 byte and massive download files, it will see if there are any .dat files left over to copy If sFile = "" Then MessageBox.Show("Error: There are no files to copy. Closing without copying or zipping.") YPollDate.Enabled = True btnCancel.Enabled = True btnCopy.Enabled = True Exit Sub Else Do While sFile <> "" FileCopy(sPath & sFile, sDestPath & sFile) copyFileCount = copyFileCount + 1 Application.DoEvents() sFile = Dir() Loop End If ' For previous day .dat file copying and addition to the report total: If CheckBox1.CheckState = 1 Then MessageBox.Show("It's saying the checkbox is checked") 'If true If prevdayfiles = "" Then ' Say nothing and do nothing, but continue with the sub Else Do While prevdayfiles <> "" FileCopy(sPath & prevdayfiles, sDestPath & prevdayfiles) copyFileCount = copyFileCount + 1 Application.DoEvents() prevdayfiles = Dir() Loop End If End If
Other than Armin's code, how could I fix it? Could I call the current day's Dir search function, do all the copying/zipping/deleting, THEN define another variable using Dir() with parameters and do the previous day's stuff? Would that work? Or can you only use for one purpose in a module?
Another thought... could I just do the following:
1) Define Dir() search variable one
2) Do copying stuff for variable one parameters
3) Define Dir() search variable two
4) Do copying stuff for variable two parameters
5) Define Dir() search variable one
6) Do zipping stuff for variable one parameters
7) Do deleting stuff for variable one parameters
8) Define Dir() search variable two
9) Do zipping stuff for variable two parameters
10) Do deleting stuff for variable two parameters
Justin
- Edited by Justin Wright Monday, August 06, 2012 5:38 PM
-
Monday, August 06, 2012 6:27 PM
That sounds about right. As long as you use Dir serially it should work. Like I said, you should only operate on one set of search criteria (folder) at a time.
Dir is somewhat of a legacy function from the VB/VBA/DOS world. When called recursively it can list out a complete directory structure. But when used in this way the results from a directory are returned and preserved in an array or collection, so that Dir can then be called to handle any sub directories in the results.
Paul ~~~~ Microsoft MVP (Visual Basic)
-
Monday, August 06, 2012 7:47 PMThat did it, thank all of you for all of your help!
Justin

