Sign in to follow this  
Followers 0
williamk

Help with While and User Function Statements

8 posts in this topic

Have a script that I just wrote. It works, but I think I messed up on some of my "While" loops and my user Function statement. What this script does is create a file containing a list of numbers that are derived from a directory of files. This list of numbers is looped through a sql statement. Each result of the sql statement is used to rename the original file to it's correct name.

For example in the directory of files is file 1234.tiff. When you run 1234 through the sql statement it tells you that the file should be named 5678.tiff. So the script then renames 1234.tiff to 5678.tiff.

Below is the script. My questions are:

1. At the end of my script there is a message box telling me that the script has reached the end. The loop seems to work fine, all the numbers in cslist2.txt are looped through but I never get to the msgbox. It seems to be exiting somewhere before that, but where and why?

2. My many while statements all work, but think I didn't do them correctly. I know after "While" you are supposed to put an expression, but I wasn't really sure what to put so I just used numbers to name the While statements (Ie my first while statement is "while 1" the second is "while 2", etc). Is that wrong?

3. When using a user Function (in this script I have _checkim()) it seems to want to loop continously. I have run into this in other scripts I've written. Is that normal, or am I just writing them wrong?

Sorry for so many questions. Not asking you to rewrite my script, just to help me learn from my errors. I am code challanged!!! :rolleyes:

include <GUIConstants.au3>
#include <File.au3>
;creates list of files
RunWait(@ComSpec & " /c " & "Dir /B C:\Corrected_Scans\Before >C:\Corrected_Scans\Before\cslist.txt")
_ReplaceStringInFile ("C:\Corrected_Scans\Before\cslist.txt", 'cslist.txt', '')
MsgBox(0, "Please check the file" , "The instrument numbers from the Corrected Scans Before directory have been placed in a text file.  In preparation for use in the checkimage sql script, make sure that the file contains a single column of numbers.  There should be no letters in a instrument number and each instrument number should NOT start with the number zero.  The file will now be opened for checking.  Close notepad when you are through and the script will continue.")
;opens file list and splits it into an array
$file1 = FileOpen("C:\Corrected_Scans\Before\cslist.txt", 0)
If $file1 = -1 Then
    MsgBox(0, "Error", "Unable to open file.")
    Exit
EndIf
$FileArray = StringSplit(FileRead($file1), @CRLF)
;opens output file in the append mode
If fileexists ("C:\Corrected_Scans\cslist2.txt") Then
    FileDelete("C:\Corrected_Scans\cslist2.txt")
    Endif
$file2 = FileOpen("C:\Corrected_Scans\cslist2.txt", 1)
If $file2 = -1 Then
    MsgBox(0, "Error", "Unable to open file.")
    Exit
EndIf
;loops thru each array element looking for .001 and writes those lines to cslist2.txt
For $i = 1 To $FileArray[0]
    If StringMid($FileArray[$i], 9, 4) = ".001" Then
        If StringLeft($FileArray[$i], 1) = "0" Then
            FileWriteLine($file2, StringMid($FileArray[$i], 2, 7))
        Else
            FileWriteLine($file2, StringLeft($FileArray[$i], 8))
        EndIf
    EndIf
Next
FileClose ($file1)
FileClose($file2)
sleep (2000)
;open the cslist2.txt file to check for errors and correct mistakes
ShellExecute("C:\Corrected_Scans\cslist2.txt")
;wait until notepad is closed then continue script
While 1
Sleep(2000)
$state = WinGetState("cslist2.txt - Notepad", "")
If $state = 0 Then _Checkim()
Wend
;Primary function finds and renames files according to sql script
Func _Checkim()
If FileExists("C:\Corrected_Scans\image_check.sql") Then
   FileDelete("C:\Corrected_Scans\image_check.sql")
EndIf
sleep (50)
$file3 = FileOpen("C:\Corrected_Scans\cslist2.txt", 0)
; Check if file opened for reading OK
If $file3 = -1 Then
    MsgBox(0, "Error", "Unable to open file.")
    Exit
EndIf
While 2;This is the beginning of the Main Loop.  Each line in cslist2.txt is run through the sql statement which tells what the files need to be renamed to
    $line = FileReadLine($file3)
    If @error = -1 Then Exit
    filecopy ("C:\sqlreports\originals\image_check.sql" , "C:\Corrected_Scans\image_check.sql", 1)
_ReplaceStringInFile ("C:\Corrected_Scans\image_check.sql", '7503491', ($line))
if fileexists ("C:\Corrected_Scans\Image_Result.txt") Then
    filedelete ("C:\Corrected_Scans\Image_Result.txt")
    Endif
RunWait('osql.exe -U usrname -P password -S DC-1 -d Mydb -h-1 -n -w 24 -i C:\Corrected_Scans\image_check.sql -o C:\Corrected_Scans\Image_Result.txt')
sleep (50)
$file4 = FileOpen("C:\Corrected_Scans\Image_Result.txt", 0);this is a file that shows the return from the Sql statement
If $file4 = -1 Then
    MsgBox(0, "Error", "Unable to open file.")
    Exit
EndIf
    $chars = FileRead($file4)
    If @error = -1 Then ExitLoop
    fileclose ($file4)
    $chars = StringReplace($Chars, @TAB, '')
    $chars = StringReplace($Chars, @LF, '')
    $chars = StringReplace($Chars, ' ', '')
    $chars = StringStripCR ($chars)
    MsgBox(0, "The SQL Result is:", $chars); this shows the sql return after it has been trimmed.
If $chars = "(0rowsaffected)" Then
    msgBox (0, "Error", "The record does not exist and/or there is no image for instrument number", $line)
    endif
If StringLeft ($chars, 8) = "yakimaD0" then
    msgBox (0, "Yakima", "This file is on F:\Yakima")
    $filecopy = stringmid ($chars, 7, 8)
    msgbox (0, "The D0 number is:", $filecopy)
; beginning of file rename section
; Shows the number of matching files in the F:\Yakima Directory.
$search1 = FileFindFirstFile("F:\Yakima\" & $filecopy & ".*")  
; Check if the search was successful
If $search1 = -1 Then
    MsgBox(0, "Error", "No files/directories matched the search pattern in F:\Yakima")
    Exit
EndIf
$i = 0
While 3
    $file5 = FileFindNextFile($search1) 
    If @error Then ExitLoop
    $i = $i+1
WEnd
; Shows the number of matching files in the C:\Corrected Scans Directory.
$search2 = FileFindFirstFile("C:\Corrected_Scans\Before" & $line & ".*")  
; Check if the search was successful
If $search2 = -1 Then
    MsgBox(0, "Error", "No files/directories matched the search pattern for the C:\Corrected_Scans\Before Folder")
    Exit
EndIf
$j = 0
While 4
    $file6 = FileFindNextFile($search2) 
    If @error Then ExitLoop
    $j = $j+1
WEnd
If $i = $j Then
msgbox (0, "Confirm File Rename", "Corrected files for instrument number " & $line & " is " & $j & ". Number of uncorrected files is " & $i)
  filemove ("C:\Corrected_Scans\Before" & $line & ".*", "C:\Corrected_Scans\After\" & $filecopy & ".*", 1)  
Else
    msgbox (0, "Error", "Corrected files for instrument number " & $line & " is " & $j & ". Number of uncorrected files is " & $i & "There is a mismatch between existing files and corrected scan files.  Please correct this error and rerun the script.  Script will now exit")
    exit
endif
; End of file rename section
EndIf
If StringLeft ($chars, 9) = "yakima\CD" then
    msgBox (0, "Bilbo", "This file is archived on Bilbo")
EndIf
wend; End of the Main Loop
fileclose $file3
fileclose $file4
fileclose $file5
msgbox (0, "Success","The main while has exited.  The script is complete")
EndFunc

Share this post


Link to post
Share on other sites



Try tabbing stuff to organize the script. That might also fix the problem.

- gsglive

PS : "#include <GUIConstants.au3>" not "include <GUIConstants.au3>"


- gsglive

Share this post


Link to post
Share on other sites

OK - first about the While-Wend loops: from the help file:

While...WEnd

--------------------------------------------------------------------------------

Loop based on an expression.

While <expression>

statements

...

WEnd

Parameters:

expression If the expression is true the following statements up to the WEnd statement are executed. This loop continues until the expression is false.

Remarks

While...WEnd statements may be nested.

The expression is tested before the loop is executed so the loop will be executed zero or more times.

To create an infinite loop, you can use a non-zero number as the expression.

So - by using numbers as "expresion" you made your loops infinite -> your main loop (While 2) never ends -> your code never reaches the end of the script where that messagebox is located.

What to do?

Add this line at the begining of your script:

AutoItSetOption ("TrayIconDebug", 1)

if your script hangs up - you can see in the windows tray a tooltip about what line is currently executed.

Set the While loops in a proper way (replace the numbers with expressions)

Good Luck


SNMP_UDF ... for SNMPv1 and v2c so far, GetBulk and a new example script

wannabe "Unbeatable" Tic-Tac-Toe

Paper-Scissor-Rock ... try to beat it anyway :)

Share this post


Link to post
Share on other sites

williamk,

I would not use a User Defined Function (UDF) for this script.

While you are learning, you might want to stick to a linear script. (A script that runs from top to bottom without any UDFs.) You can have some loops in the script - just be sure that you know how and when they exit the loop.

Now for the issues with your code.

ShellExecute("C:\Corrected_Scans\cslist2.txt")

;wait until notepad is closed then continue script

While 1

Sleep(2000)

$state = WinGetState("cslist2.txt - Notepad", "")

If $state = 0 Then _Checkim()

WEnd

When you call a UDF, normally the script goes off and runs the UDF and returns to the point that called it. In other words, when this line runs If $state = 0 Then _Checkim() the UDF named "_Checkim" will run and then (had the script not exited during the UDF) the script would have returned to the next line which is WEnd... that would then go thru the While/WEnd loop again, calling "_Checkim" again, returning again - stuck in an infinite loop.

As your code is currently written,

the UDF named "_Checkim" is called once

it gets to While 2

inside that loop a file is read

$line = FileReadLine($file3)

once the end of that file is reached,

the entire script exits via this line:

If @error = -1 Then Exit

So, I've removed the UDF call and replaced it with an ExitLoop.

This lets the script wait until Notepad has been closed before going on.

I also changed the line that I mentioned above that was ending your script

If @error = -1 Then Exit

to

If @error = -1 Then ExitLoop

That should let you get to your "Success" MsgBox. :-)

;creates list of files
RunWait(@ComSpec & " /c " & "Dir /B C:\Corrected_Scans\Before >C:\Corrected_Scans\Before\cslist.txt")
_ReplaceStringInFile("C:\Corrected_Scans\Before\cslist.txt", 'cslist.txt', '')
MsgBox(0, "Please check the file", "The instrument numbers from the Corrected Scans Before directory have been placed in a text file.  In preparation for use in the checkimage sql script, make sure that the file contains a single column of numbers.  There should be no letters in a instrument number and each instrument number should NOT start with the number zero.  The file will now be opened for checking.  Close notepad when you are through and the script will continue.")
;opens file list and splits it into an array
$file1 = FileOpen("C:\Corrected_Scans\Before\cslist.txt", 0)
If $file1 = -1 Then
    MsgBox(0, "Error", "Unable to open file.")
    Exit
EndIf
$FileArray = StringSplit(FileRead($file1), @CRLF)
;opens output file in the append mode
If FileExists("C:\Corrected_Scans\cslist2.txt") Then
    FileDelete("C:\Corrected_Scans\cslist2.txt")
EndIf
$file2 = FileOpen("C:\Corrected_Scans\cslist2.txt", 1)
If $file2 = -1 Then
    MsgBox(0, "Error", "Unable to open file.")
    Exit
EndIf
;loops thru each array element looking for .001 and writes those lines to cslist2.txt
For $i = 1 To $FileArray[0]
    If StringMid($FileArray[$i], 9, 4) = ".001" Then
        If StringLeft($FileArray[$i], 1) = "0" Then
            FileWriteLine($file2, StringMid($FileArray[$i], 2, 7))
        Else
            FileWriteLine($file2, StringLeft($FileArray[$i], 8))
        EndIf
    EndIf
Next
FileClose($file1)
FileClose($file2)
Sleep(2000)
;open the cslist2.txt file to check for errors and correct mistakes
ShellExecute("C:\Corrected_Scans\cslist2.txt")
;wait until notepad is closed then continue script
While 1
    Sleep(2000)
    $state = WinGetState("cslist2.txt - Notepad", "")
    If $state = 0 Then ExitLoop
WEnd

;finds and renames files according to sql script
If FileExists("C:\Corrected_Scans\image_check.sql") Then
    FileDelete("C:\Corrected_Scans\image_check.sql")
EndIf
Sleep(50)
$file3 = FileOpen("C:\Corrected_Scans\cslist2.txt", 0)
; Check if file opened for reading OK
If $file3 = -1 Then
    MsgBox(0, "Error", "Unable to open file.")
    Exit
EndIf
While 1;This is the beginning of the Main Loop.  Each line in cslist2.txt is run through the sql statement which tells what the files need to be renamed to
    $line = FileReadLine($file3)
    If @error = -1 Then ExitLoop
    FileCopy("C:\sqlreports\originals\image_check.sql", "C:\Corrected_Scans\image_check.sql", 1)
    _ReplaceStringInFile("C:\Corrected_Scans\image_check.sql", '7503491', ($line))
    If FileExists("C:\Corrected_Scans\Image_Result.txt") Then
        FileDelete("C:\Corrected_Scans\Image_Result.txt")
    EndIf
    RunWait('osql.exe -U usrname -P password -S DC-1 -d Mydb -h-1 -n -w 24 -i C:\Corrected_Scans\image_check.sql -o C:\Corrected_Scans\Image_Result.txt')
    Sleep(50)
    $file4 = FileOpen("C:\Corrected_Scans\Image_Result.txt", 0);this is a file that shows the return from the Sql statement
    If $file4 = -1 Then
        MsgBox(0, "Error", "Unable to open file.")
        Exit
    EndIf
    $chars = FileRead($file4)
    If @error = -1 Then ExitLoop
    FileClose($file4)
    $chars = StringReplace($chars, @TAB, '')
    $chars = StringReplace($chars, @LF, '')
    $chars = StringReplace($chars, ' ', '')
    $chars = StringStripCR($chars)
    MsgBox(0, "The SQL Result is:", $chars); this shows the sql return after it has been trimmed.
    If $chars = "(0rowsaffected)" Then
        MsgBox(0, "Error", "The record does not exist and/or there is no image for instrument number", $line)
    EndIf
    If StringLeft($chars, 8) = "yakimaD0" Then
        MsgBox(0, "Yakima", "This file is on F:\Yakima")
        $filecopy = StringMid($chars, 7, 8)
        MsgBox(0, "The D0 number is:", $filecopy)
        ; beginning of file rename section
        ; Shows the number of matching files in the F:\Yakima Directory.
        $search1 = FileFindFirstFile("F:\Yakima\" & $filecopy & ".*")
        ; Check if the search was successful
        If $search1 = -1 Then
            MsgBox(0, "Error", "No files/directories matched the search pattern in F:\Yakima")
            Exit
        EndIf
        $i = 0
        While 1
            $file5 = FileFindNextFile($search1)
            If @error Then ExitLoop
            $i = $i + 1
        WEnd
        ; Shows the number of matching files in the C:\Corrected Scans Directory.
        $search2 = FileFindFirstFile("C:\Corrected_Scans\Before" & $line & ".*")
        ; Check if the search was successful
        If $search2 = -1 Then
            MsgBox(0, "Error", "No files/directories matched the search pattern for the C:\Corrected_Scans\Before Folder")
            Exit
        EndIf
        $j = 0
        While 1
            $file6 = FileFindNextFile($search2)
            If @error Then ExitLoop
            $j = $j + 1
        WEnd
        If $i = $j Then
            MsgBox(0, "Confirm File Rename", "Corrected files for instrument number " & $line & " is " & $j & ". Number of uncorrected files is " & $i)
            FileMove("C:\Corrected_Scans\Before" & $line & ".*", "C:\Corrected_Scans\After\" & $filecopy & ".*", 1)
        Else
            MsgBox(0, "Error", "Corrected files for instrument number " & $line & " is " & $j & ". Number of uncorrected files is " & $i & "There is a mismatch between existing files and corrected scan files.  Please correct this error and rerun the script.  Script will now exit")
            Exit
        EndIf
        ; End of file rename section
    EndIf
    If StringLeft($chars, 9) = "yakima\CD" Then
        MsgBox(0, "Bilbo", "This file is archived on Bilbo")
    EndIf
WEnd; End of the Main Loop
fileclose $file3
fileclose $file4
fileclose $file5
MsgBox(0, "Success", "The main while has exited.  The script is complete")

[size="1"][font="Arial"].[u].[/u][/font][/size]

Share this post


Link to post
Share on other sites

[i hate it when the forum Rich Text Format (RTF) editor goes crazy like it did for me in that last post. I'll try some more ramblings in this fresh post.]

williamk,

If you are using the RTF editor, then you might have a square icon with a blue background and a white triangle (part of the AutoIt icon). Press that icon and then paste/post your AutoIt code between those forum code tags. That way, your code should (and I do mean should) post in pretty colors for us to read. :-)

In my last post, I changed as little of your code as I could so that you could recognize most of it. Now for the one thing that I would change in the code in my last post.

This could change:

;wait until notepad is closed then continue script
While 1
    Sleep(2000)
    $state = WinGetState("cslist2.txt - Notepad", "")
    If $state = 0 Then ExitLoop
WEnd

Back to the comment that I made in my last post about UDFs... If you write a linear script and you find that you copy and paste blocks of code over and over, then you should consider making that block of code a UDF. Then "call" that UDF over and over in the main body of your code.

Caveat: I have no formal training as a programmer. Others in the forum may offer different/better advice on the topic of UDFs.

...enjoy AutoIt and this forum community... :-)


[size="1"][font="Arial"].[u].[/u][/font][/size]

Share this post


Link to post
Share on other sites

[i hate it when the forum Rich Text Format (RTF) editor goes crazy like it did for me in that last post. I'll try some more ramblings in this fresh post.]

williamk,

If you are using the RTF editor, then you might have a square icon with a blue background and a white triangle (part of the AutoIt icon). Press that icon and then paste/post your AutoIt code between those forum code tags. That way, your code should (and I do mean should) post in pretty colors for us to read. :-)

In my last post, I changed as little of your code as I could so that you could recognize most of it. Now for the one thing that I would change in the code in my last post.

This could change:

;wait until notepad is closed then continue script
While 1
    Sleep(2000)
    $state = WinGetState("cslist2.txt - Notepad", "")
    If $state = 0 Then ExitLoop
WEnd

Back to the comment that I made in my last post about UDFs... If you write a linear script and you find that you copy and paste blocks of code over and over, then you should consider making that block of code a UDF. Then "call" that UDF over and over in the main body of your code.

Caveat: I have no formal training as a programmer. Others in the forum may offer different/better advice on the topic of UDFs.

...enjoy AutoIt and this forum community... :-)

Plato, you are awesome!!! Yeah, that fixed my issues. Makes total sense. Also explains a problem I was having with another little script I wrote. So calling a UDF is basically the same as a GOTO statement. You have no formal training in programming either aye? Well then, there's hope for me yet.

Off topic, but are you a Plato fan? I minored in Philosophy and like his writings as well.

Share this post


Link to post
Share on other sites

OK - first about the While-Wend loops: from the help file:

So - by using numbers as "expresion" you made your loops infinite -> your main loop (While 2) never ends -> your code never reaches the end of the script where that messagebox is located.

What to do?

Add this line at the begining of your script:

AutoItSetOption ("TrayIconDebug", 1)

if your script hangs up - you can see in the windows tray a tooltip about what line is currently executed.

Set the While loops in a proper way (replace the numbers with expressions)

Good Luck

Thanks much. Yes, I did read the Online documentation for the While function. Guess, I just didn't quite get the infinite loop part. Good to know about the TrayIconDebug, that should help now and in the future. I appreciate your input.

Share this post


Link to post
Share on other sites

...Off topic, but are you a Plato fan? I minored in Philosophy and like his writings as well.

I know little of Plato's writings. The moniker came about from a office jest, "Let Plato do it."

I wanted platowashere (in the Kilroy fashion), but alas, it was taken in the Yahoo domain/groups where I first started reading/posting about AutoIt version 2.

-MSP-


[size="1"][font="Arial"].[u].[/u][/font][/size]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0