Jump to content

AmbiguousJoe

Members
  • Posts

    13
  • Joined

  • Last visited

AmbiguousJoe's Achievements

Seeker

Seeker (1/7)

0

Reputation

  1. Yes, I could, but that defeats the purpose of what I was trying to point out: The script fails to exit when it reaches the end. A user only needs to launch the file once, but they may re-open the file 3-5 times throughout the day. Each time they run it, more and more memory is used up that doesn't get released. The reason for this launcher is so that I can constantly update a Microsoft Access file and push updates, without requiring users to grab a new file themselves. Whenever the person runs the launcher they will automatically get the most up-to-date version of the file. I can post the full code for the launcher, but I figured it's irrelevent if the same problem can be demonstrated with a single line of code.
  2. I created a Launcher script for work, which checks a network drive for the newest version of a Microsoft Access front end file, updates the user's copy if they have an older version, and then launches the newest version. However, each time it's run, new tasks keep showing up in the Task Manager that don't get closed. I've tracked down the problem to the ShellExecute function. ShellExecute("U:\My Documents\Access DB\Test.accdb") I created a script with a single line of code (above) and ran it 10 times. 2 out of 10 times (2nd run and 10th run), the script opened the Test.accdb file and stopped running, as intended. The other 8 times, the Test.accdb file was opened, but the script kept running indefinitely. It just fails to stop running, and doesn't appear to be doing anything. I can add extra lines of code after Shellexecute, like ConsoleWrite("Am I still running?") and it will run that code, but the script will still fail to exit afterwards.. Does anyone know what the problem is, or how I can avoid it?
  3. hannes08: FileWriteToLine doesn't use file handles, but I assume you are suggesting the same method as water. water: You're correct: the $sBackupFile variable is a filename selected in an earlier part of the script. I write to specific lines so that I don't have to delete and re-create backup files every time the script runs. A single file is used and updated, which matches the format of the excel file (so I can just copy and paste it in). That being said, that's not a good reason to use a less efficient function under these circumstances. czardas: I write to file every single time because some rows can take several minutes to complete (based on the actions performed on that row). Saving after every 10 entries or so might solve the problem I first described, but it could mean that I lose around 45 minutes of progress if I stopped the script during a set of slower actions. I replaced FileWriteToLine() with $FileHandle = FileOpen($sBackupFile, 1) FileWriteLine($FileHandle, $sLineOutput) FileClose($FileHandle)I let the script run through about 10,000 rows and it didn't have any problems writing to the file. Thanks for your help guys.
  4. I created the following function to back-up rows from a 2D-array as my script runs through the data. I write to an Excel file at the end, so this provided a way for me to terminate the script early, without losing all my progress. It's works fine until my script starts writing to the file multiple times per second. My text files become corrupted. What should be a 125-500kb file with tab-delimited data, turns into an 80-123mb file with several thousand lines of nothing but blank characters/spaces. Func _BackupArray($nRow) ;Receives the row number that will be backed up. ConsoleWrite("Function: BackupArray"&@CRLF) Local $nCol = 0 ;column counter Local $sLineOutput = $aExcelList[$nRow][0] ;Collects the first array cell into a string While($nCol <= $nTotalExcelCols-1) ;cycles through columns to collect Array data. $sLineOutput = $sLineOutput&@TAB&$aExcelList[$nRow][$nCol] ;Adds each array's cell to the line, TAB delimited. $nCol = $nCol+1 ;Increases the column counter WEnd _FileWriteToLine($sBackupFile, $nRow+1, $sLineOutput,1) ;Sends the string to the backup file EndFunc ;==>BackupArray I suspect that the the problem is that _FileWriteToLine is a slow or inefficient way to accomplish a backup, but perhaps someone more knowledgable could help me out. When there are several seconds between calling this function, I don't have any problems; it's only when the function starts getting called several times per second.
  5. Hmm, that would solve scenario 1, but not scenario 2 (unless I'm thinking of it in the wrong way). I like the thinking behind that solution though, and may use it elsewhere in my script. -Preventing SetState from occuring if the field switch is set to 1- Scenario 1: The switch for field 1 triggers the first time the user hits the character limit, preventing future auto-jumps while editing information in the first field. Scenario 2: The user types something in the field that is the same character limit (or copies & pastes into the field). The user clicks the end of the field and attempts to type, but nothing happens since the field is already at the limit. The user would prefer auto-jump in this case, since they're already at the end of the field. I'm trying to mimic a system that coworkers in my department are already used to. With the software they use, if they hit the character limit, and their caret is in the middle of a field, it prevents auto-jumping to the next field. However, if they click at the end of a field that's already reached the character limit, attempting to type something will automatically jump to the next field. It's one of the few things they like about their current software. Being able to obtain the caret position would also allow me to jump-back a field if they press backspace on the first character position of a field.
  6. So I'm building a data entry screen and I want the caret (aka: insertion point or cursor) to automatically jump to the next field when the character limit is reached. However, it needs to be a bit smarter than that. I have two extra scenarios that I need to handle. Scenario 1: Lets say I reach my character limit for the first field (12) and continue typing, but then I notice I mistyped something in the first field. I delete the typo, and then begin to correct it. This new word happens to be longer than the previous word, so I hit the character limit while in the center of the field. At this point, the caret stops typing in the middle of the first field and jumps to the next field. The extra letters wind up overwriting the second field, and now all the information is a mess (both fields are incorrect). You can see this by running the code below and typing "Typing across multiple fields." In the first field, highlight the the word "Typing" and start typing "Testing across multiple fields." -Instead of automatically jumping, I would prefer one of two things to happen: either nothing happens when you continue typing, or the rest of the text in the same field starts being overwritten. Scenario 2: I type something that happens to be the exact length of the character limit (12) ie: "it's strange". I change fields to enter information elsewhere in the form. Later I decide to come back to add more to the first field. I click on the first field, and start typing ", nothing types". Because the caret is already at the character limit, nothing triggers and nothing gets typed. I would like the the caret to automatically jump to the next field and start typing in that field if this occurs. In either situation, it seems I need to know the caret position in order to code for these possibilities. At the least, I need to test if it's at the end of the field's character limit. The overwrite code would be a bit more tricky, but may still need to get the caret's position, so it can start replacing text. I tried using WinGetCaretPos(), but that gives the X & Y coordinates of the caret, which will change based on the length of the characters being typed. There are several other functions which use the caret positions, but don't provide a way to find it. The code I'm using was posted by Siao in thread: #include Global $input_limit = 12 $gui = GUICreate("InputBox autofocus demo", 350, 100) $in1 = GUICtrlCreateInput("", 40, 20, 80, 20) GUICtrlSetLimit(-1, $input_limit) $in2 = GUICtrlCreateInput("", 140, 20, 80, 20) GUICtrlSetLimit(-1, $input_limit) $in3 = GUICtrlCreateInput("", 240, 20, 80, 20) GUICtrlSetLimit(-1, $input_limit) $btn = GUICtrlCreateButton("OK", 100, 60, 50, 25) GUIRegisterMsg(0x0111, "On_WM_COMMAND") GUISetState() While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE Exit Case $btn $str = GUICtrlRead($in1) & " " & GUICtrlRead($in2) & " " & GUICtrlRead($in3) MsgBox(0, "You have entered", $str) EndSwitch WEnd Func On_WM_COMMAND($hWnd, $Msg, $wParam, $lParam) $nNotifyCode = BitShift($wParam, 16) $nID = BitAnd($wParam, 0x0000FFFF) Switch $nNotifyCode Case 0x400 ;$EN_UPDATE If StringLen(GUICtrlRead($nID)) = $input_limit Then GUICtrlSetState($nID+1, $GUI_FOCUS) EndSwitch EndFunc
  7. In order to deal with error message popus in my own script, I first had to find out when they were occuring and the window title of these messages. My script had a navigation function that opened different pages depending on where I told it to go, this was the easiest place for my pop-up checking to be placed, as it was used in nearly every function call. Here's the code I added to deal with a fatal exception window: If WinExists("P/J Fatal") Then ;If the fatal exception window is open WinKill("P/J Fatal") ;Closes the fatal exception window. WinWaitClose("P/J Fatal", "", 5) ;waits up to 5 seconds for the window to close. EndIf For more specific popups, I put similar code after any action that could result in the popup being opened. In these cases, the popup should appear within a second or two of the action being taken. However, sometimes they wouldn't open, so I needed a way to handle these windows if they opened. WinWaitActive("Portal/J", "", 3) ;Waits 3 seconds to see if the Portal/J window appears If WinExists("Portal/J") <> 0 Then ;If the Portal/J window exists Send("{ENTER}") ;Sends the Enter key, which will close the menu by selecting the default "Continue" button. WinWaitClose("Portal/J", "", 10) ;Waits up to 10 seconds for the window to close. EndIf If the window popped up, it would be closed and the script would continue running usually within a second. If the popup didn't appear, no more than 3 seconds would be wasted waiting for a window that may not ever appear. There may be more efficient ways of handling popus, but these methods are the ones that worked for me.
  8. So I increased the length of time required before a timeout error occurs, as well as adding some re-try code, which will search for the entry a second time. This bug hasn't popped up in a while, until yesterday. In addition to the extra reporting in my error function, I have the code take a screenshot so I can see what's displayed on the screen when the error occurs. I'm absolutely dumbfounded by the results: -The error reporting is correct. The timeout occurs on the entry that it says it occured on. The screenshot backs this up: Row 638 reports a timeout and the screenshot shows a loading screen with the information from row 638. -Even though the timeout occured, all the information for that entry was updated, as if there weren't any problems.. -My console shows that upon timeout of Row 638, the function was exited, and the next entry in the list begins the search process (intended). The console shows that the next entry (639) was searched for, updated, and every step ran without any problems. -Row 639 (the entry after the error), which reported no errors and appears to have run just fine, has not been altered whatsoever... it's as if there was a timeout on that entry. -The final result is that Row 638 is reported as a timeout even though it's been updated. Row 639 has not been updated, but it's reported that everything was run successfully. My first thought was that the timed out entry was eventually loaded while the script attempted to load Row 639. This would cause the the script to enter information from row 639 into the entry from row 638... but no, all the information from Row 638 was entered correctly. At this point, I'm clueless. This scripts runs thousands of entries each night, and I'm unable to monitor what's happening exactly at the moment of timeout, other than the single screenshot taken when an error occurs. This particular bug is frustating because its reporting that an entry was updated correctly, when nothing was actually changed. Incorrect data in the db is not a good thing. Anyone have any ideas? I don't expect anyone to debug my code for me, just trying to understand where my logic went wrong. Here's the code from my search function. The error is sent within this code: ;Populates the search fields on the TIMC010 panel and searches for the document ;$nMode variable: 0 = First time the function has been called 1 = Function called recursively, indicating a timeout on the first attempt. Func _PopulatePassportSearch($nRow, $nMode = 0) ;Receives a row number so that Passport data can be populated ConsoleWrite("Function: PopulatePassportSearch"&@CRLF) Local $nLoopCount = 0 WinActivate("TIM") ;Activates the Passport window. WinMove("TIM", "",1659,229,900,730) ;Resizes the Passport window in case it was previously opened or resized. Sleep(250) ;Sleeps for 0.25 seconds _PopulateRequiredFields($nRow) ;Fills out Search info into the appropriate fields. MouseClick("left",2330,355, 1) ;Clicks the Execute button, which begins the seach. ;Loops until the search is completed. The search is complete when the "TIMCO1W" window is loaded, or the color of the status field changes. While(PixelGetColor(1785,365) <> 13353643 Or WinExists("TIMC01W") = 1) If $nLoopCount >= 4 Then ;If the search loop has been running for 2 seconds or more. if PixelGetColor(1690, 288) = 0 Then ;Check if there's a No Document Found message ConsoleWrite("Document was not found, skipping this document."&@CRLF) _AddErrorCode($nRow, "DIDFNF") Return 1 ;Breaks out of function and notifies other functions of error. EndIf If $nLoopCount >= 20 Then ;If the loop has run 20 or more times (10 seconds) and the document has not been found ConsoleWrite("Document took too long to load, taking appropriate action."&@CRLF) If $nMode = 0 Then ;If this is the first time the function has been run, attempt a second try. ConsoleWrite("DID not found on first attempt. Re-starting function after 5 seconds."&@CRLF) Sleep(5000) ;Sleeps for 5 seconds before attempting a second try. $nErrorCheck = _PopulatePassportSearch($nRow, 1) ;Checks for errors on the 2nd attempt. The results will be returned to the calling function. Return $nErrorCheck ;Exits out of this function so the next steps are not duplicated. ElseIf $nMode = 1 Then ;If a second call resulted in a timeout. ConsoleWrite("DID was not found after a second attempt. Marking as a timed out entry."&@CRLF) _AddErrorCode($nRow, "DIDTO", 2) ;Logs the timeout error. The 2 indicates that this entry can be re-tried at the end of the script. Return 1 ;Returns an error, which will be returned by the original call in the next statement. EndIf EndIf EndIf Sleep(500) ;Sleeps for 0.5 seconds If WinExists("TIMC01W") = 1 Then ;If the DID Selection page is opened (search completed) MouseClick("left",1680,395, 2) ;Double-clicks on the first entry. WinWaitActive("TIMC010","",60) ;Waits up to 60 seconds for the info page to load. This is verified in the next function. EndIf If WinExists("TIMC010") = 0 Then ;If the search window gets closed, or is navigated away from, call recursively. $nErrorCheck = _PopulatePassportSearch($nRow) ;Function calls itself, restarting all search steps. Return $nErrorCheck ;prevents looping continuously after a page has been lost due to lag/closing EndIf $nLoopCount = $nLoopCount + 1 ;Tracks the number of times the loop has been run WEnd ;End of the search wait loop. EndFunc ;==>PopulatePassportSearch The bug only occurs on time-out errors, and only occasionally. I realize the problem may be somewhere outside of the Search function, and outside of the error reporting function, but I honestly wouldn't know where to look: After the search function is called, either the information for that row is entered, or the next entry in the list is searched for.
  9. I'm wondering if I can exit from a calling(parent) function (as in, exit from the current function and the one that called it), like you can exit a parent Loop with the "ExitLoop 2" command. If not, I'd like to know if there is a more efficient way of exiting a function without adding several "if, then, return" statements in my code. I'm using _IELoadWait($oIE) and WinWaitActive() commands throughout my code. I've had to add timeouts to all of these commands because I found that they were causing my code to hang indefinitely whenever something unexpected occured. In several of these cases, a timeout means I need to exit the function (so that my script isn't trying to click buttons that don't exist) and then proceed to the next process. Do I have to add the following code to every single Wait command in order to achieve this? If IELoadWait($oIE, 0, 30000) > 0 Then Return EndIf I know it's only an extra 2-3 lines, but when I've got several of these checks in a function, the code becomes less readable and means I'm typing the same thing over and over. I wanted to create a seperate function that would be able to handle the check and automatically break out of the function, but I quickly realized that the Return command would only break out of that function, then go right back and continue running the parent function. I tried the Exit command, but that just exited the entire script.
  10. I use Excel 2007, however, I managed to isolate the problem a bit more. It seems I broke it when adding some code to another function (which is usually the case). Along with your code to Write Excel files quickly, I found the following code somewhere on these forums in order to read Excel files very quickly. However, I added a loop in the ReadExcelFile function to handle cells which had over 256 characters (which otherwise get converted to "###" using this method). ;Opens Excel Project File and creates an array for it. Func _ReadExcelFile() Local $oExcel = _ExcelBookOpen($sExcelProjectFile) Global $aDistCodes = ReadSheet($oExcel, "DistCodes") ;Creates an array of Distribution Codes. Global $nTotalDistCodes = $nTotalRows Global $nTotalDistTypes = $nTotalCols Global $aExcelList = ReadSheet($oExcel, "Passport Information") ;Creates an array of Update information. Global $nTotalExcelRows = $nTotalRows Global $nTotalExcelCols = $nTotalCols ;This code prevents cells that are over 256 characters from showing up as all pound symbols. ;Cycles through all the data rows of the Excel Spreadsheet For $nCount = 0 To $nTotalExcelRows - 1 ;Cycles through all delimiter columns of the Excel spreadsheet. Earlier cols should be under 256 characters. For $nLoopCount = 10 To $nTotalExcelCols - 1 ;If a cell is populated by all pound symbols (assumed if starts with 3 of them) If StringLeft($aExcelList[$nCount][$nLoopCount], 3) = "###" Then ;Updates the Array value with the correct spreadsheet value. $aExcelList[$nCount][$nLoopCount] = _ExcelReadCell($oExcel, $nCount+1, $nLoopCount+1) EndIf Next Next ConsoleWrite("There are "&$nTotalExcelRows&" rows, and "&$nTotalExcelCols&" columns in the Project file."&@CRLF) _ExcelBookClose($oExcel) EndFunc ;==>ReadExcelFile Func ReadSheet($excel, $sheet) ;Used by the new Excel read-in function Return String2DSplit(ExcelSheetToClip($excel, $sheet)) EndFunc ;==>ReadSheet Func String2DSplit($string, $rowDelimiter = @CRLF, $columnDelimiter = " ") ;Used by the new Excel read-in function $lines = StringSplit(StringStripWS($string, 3), $rowDelimiter, 1) $columnsNum = _StringCount($lines[1], $columnDelimiter) + 1 Global $nTotalRows = $lines[0] Global $nTotalCols = $columnsNum Dim $result[$lines[0]][$columnsNum] = [[0]] For $i = 1 To $lines[0] $columns = StringSplit($lines[$i], $columnDelimiter) For $j = 1 To $columns[0] $result[$i - 1][$j - 1] = $columns[$j] Next Next Return $result EndFunc ;==>String2DSplit Func _StringCount($string, $substring) ;Used by the new Excel read-in function Local $i, $count = 0 For $i = 1 To StringLen($string) If StringMid($string, $i, StringLen($substring)) = $substring Then $count = $count + 1 Next Return $count EndFunc ;==>_StringCount Func ExcelSheetToClip($excel, $sheet) ;Used by the new Excel read-in function _ExcelSheetActivate($excel, $sheet) ClipPut("") Send("^{HOME}^a^c") Do Sleep(100) Until ClipGet() Return ClipGet() EndFunc ;==>ExcelSheetToClip The error is only occuring when a cell contains more than 256 characters, but runs fine if I remove the code I added. My guess is that it doesn't play well with the _ExcelReadCell function, but I only started scripting a few months ago, so I've made a fair share of mistakes. At this point, I can at least create a trigger variable that will let me know when this situation occurs, allowing me to skip the update Excel function and prevent the script from just stopping completely. It doesn't solve the problem, but it will keep the script running til I can find a better solution. I appreciate your help. I'd like to find out why the script is failing so I can avoid future conflicts.
  11. Hey Water, I've been using the code you posted to quickly update my Excel Sheets (It's dropped my Excel times from 6+ minutes to 5 seconds). It's worked fine for all my data up until now. My script is now crashing whenever it hits my excel update function with a large array. The array is 580 rows, 20 columns. If I run it on my smaller projects, under 100 rows, it completes just fine. I checked the help files and couldn't find anything that helped me with the UBound and .transpose commands. Is there any way to catch the following error so my script doesn't stop when it hits it? -=Console's output=- Function: UpdateExcelFile U:My DocumentsScriptsPPNavigator8.au3 (2351) : ==> The requested action with this object has failed.: $aOverViewTransposed = $oExcel.transpose($aExcelList) $aOverViewTransposed = $oExcel.transpose($aExcelList)^ ERROR Func _UpdateExcelFile() ConsoleWrite("Function: UpdateExcelFile"&@CRLF) Local $oExcel = _ExcelBookOpen($sExcelTemplateFile) _ExcelSheetActivate($oExcel,"Passport Information") Sleep($nLagTimer) ;Copy data to Excel. $aOverViewTransposed = $oExcel.transpose($aExcelList) $oExcel.Range("A1:A1").Resize(UBound($aExcelList,1),UBound($aExcelList,2)) = $aOverViewTransposed _ExcelBookSaveAs($oExcel, $sExcelCompletionFile, "xls", 0, 1) Sleep($nLagTimer) _ExcelBookClose($oExcel, 0) EndFunc ;==>UpdateExcelFile
  12. I added the code you suggested, and put similar reporting on my Document Search function and the other functions that call it. Hopefully this will help track down the problem. I haven't been looking for the problem esclusively in that AddErrorCode function. I searched through the functions that were being called. All the functions receive the $nRow variable to update and pull information from the array, but the only code that modifies the variable is the loop. I'll post more information if anything turns up. I wanted to throw the question out there and see if anyone knew of any issues with large arrays. I suspect the problem is either in the Document Search function, or due to a memory issue. IT has these computers locked down so that I can't even check the speed/memory, but I've had memory issues while running programs even without a script running through thousands of entries.
  13. I've been trying to nail down a bug that my script has with logging time-out errors. The company I work for uses a system called Passport to search for and access image files. Each image has a Document ID, Title, and a bunch of meta data so that the image can be searched for. Sometimes we get a request to modify the title or meta data of 1000+ images, so I wrote a script to cycle through and update each of the requested images. Here's a little background on what the script does. -An excel file that contains the image's ID and meta data is read in using _ExcelReadSheetToArray() -It opens and logs into Passport. -A loop begins, reading the first row of the array. -It searches for the Document ID. -If the search times out (search page is inactive for over 10 seconds), it logs a timeout error. If the Document ID was not found, it logs a File Not Found error. The errors are simply a code that I enter into the last column of the array. -It navigates through Passport's windows to reach the data entry screen. -It updates the image data by submitting the info from the array. -The array's status column, for the current row, is marked "COMPLETE" -The first loop is now complete and the next row is read. This loop continues til the last row has been updated. -A new Excel file is created using _ExcelWriteSheetFromArray() so that any errors can be viewed. The problem comes in when logging time-out errors. Sometimes the error code is entered into the correct line, sometimes it's entered 1 row early. My Excel file will say that Row 620 (as an example) timed out. So, I search for it manually, and it turns out 620 was updated just fine, but line 621 hasn't been updated (So 621 was the row that actually timed out). Again, this doesn't happen all the time. Sometimes it says line 150 timed out, and when I search for it, 150 hasn't been updated, and the surrounding rows were updated as expected. From what I've seen, it's only the time-out errors that have this issue, the File Not Found errors have been recorded correctly. Every time a function is called, I ConsoleWrite() the function name, I also ConsoleWrite() the current row each loop so I can see a log of all the actions my script has taken. Here's what just plain confuses me. According to that log, it will say that Row 620 ran the function to search for the Document ID, called the AddErrorCode function, and then moved on to row 621. Row 621 shows that all the update functions were called and everything ran smoothly... Everything in my log suggests that Row 620 had a time-out error, but manually checking shows that 621 had the timeout. Last night I ran 1,500 rows. 6 of them reported time-out errors: the second and last errors were accurate, but the other 4 all displayed the error on the previous row. So, can anyone take a guess as to what's happening here or how to fix it? My code isn't 1 row off because that would mean all the data would be 1 row off, but the initial and completed Excel files match. I also have nothing in my code that says "$nRow - 1". Is this possibly a memory issue from handling 1000+ rows with 18 columns each? Because this is a time-out issue, which doesn't happen that often, I haven't witnessed what's actually happening when it times out. Here's the code I use to log my errors: Func _AddErrorCode($nRow, $sErrorCode) ConsoleWrite("Function: AddErrorCode"&@CRLF) ;Sets the the status column to "*ERROR*" $aExcelList[$nRow][1] = "*ERROR*" ;If there is nothing in the Error column, add the new code. If $aExcelList[$nRow][17] = "" Then $aExcelList[$nRow][17] = $sErrorCode ;Else, there is already an entry in the box. Else ;Searches if this Error Code is already logged. If not, it adds the code. Prevents the same code from being added multiple times. If StringInStr($aExcelList[$nRow][17],$sErrorCode) = 0 Then ;Updates the error column by adding a comma and the new column $aExcelList[$nRow][17] = $aExcelList[$nRow][17]&","&$sErrorCode EndIf EndFunc
×
×
  • Create New...