Do While Loop not looping inside If-Else statement

Answered Do While Loop not looping inside If-Else statement

  • Monday, August 06, 2012 1:39 PM
     
      Has Code

    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 PM
     
     
    According 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
     
      Has Code

    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 PM
     
     
    What 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.dat

    It only copies the 08031245.dat file, and after the Dir() it shows sFile as nothing (or perhaps "").


    Justin

  • Monday, August 06, 2012 2:42 PM
     
     
    Use 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


  • Monday, August 06, 2012 2:57 PM
     
     Answered Has Code

    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 If
    EDIT: Oh, and you may want to insert "copyFileCount += 1" again. Sorry, I forgot that. Or just take Files.Length as the total number.
     


    Armin




  • 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
     
      Has Code

    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 PM
     
     
    Well, 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
     
      Has Code

    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


  • 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
     
      Has Code

    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 Sub

     I 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



  • Monday, August 06, 2012 4:27 PM
     
      Has Code

    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




  • Monday, August 06, 2012 4:36 PM
     
      Has Code

    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


  • 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
     
     Answered

    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 PM
    Moderator
     
     

    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
     
      Has Code

    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


  • 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 PM
     
     
    That did it, thank all of you for all of your help!

    Justin