rajeevsing15 Posted August 14, 2017 Share Posted August 14, 2017 Hi All, I am working on creating a script which can find a text from "Replace.txt" [Find anything which is before (|) and replace it with whatever after (|)] in multiple txlf files. I have tried my best based on my experience but I couldn't get through. Can someone please help? I am attaching my script here, with sample files. Can someone please help out modifying this to meet my requirements? Thanks In Advance Rajeev Replace.txt Find_Replace.au3 File_to_change.txlf Link to comment Share on other sites More sharing options...
Moderators JLogan3o13 Posted August 14, 2017 Moderators Share Posted August 14, 2017 Moved to the appropriate forum "Profanity is the last vestige of the feeble mind. For the man who cannot express himself forcibly through intellect must do so through shock and awe" - Spencer W. Kimball How to get your question answered on this forum! Link to comment Share on other sites More sharing options...
rajeevsing15 Posted August 14, 2017 Author Share Posted August 14, 2017 Thanks Link to comment Share on other sites More sharing options...
Neutro Posted August 14, 2017 Share Posted August 14, 2017 Hi @rajeevsing15 This is how you could try to do it: 1°) use _FileReadToArray() to read the file replace.txt 2°) use _ArrayColInsert() to add a column to the array containin the replace.txt file lines 3°) use StringSplit() to split each line of replace.txt in two using "|" as a delimiter character and store the 2 result substrings in the 2 columns of the array. This way the first column of the array contains the text to look for and the second column contains the text to replace to. 4°) Use FileRead() to read the .txlf file and find the text stored in the first column of the array. If found, use StringReplace() to replace the found text by the text stored in the 2nd column of the array. 5°) Save the modified file using FileWrite() rajeevsing15 1 Identify active network connections and change DNS server - Easily export Windows network settings Clean temporary files from Windows users profiles directories - List Active Directory Groups members Export content of an Outlook mailbox to a PST file - File patch manager - IRC chat connect example Thanks again for your help Water! Link to comment Share on other sites More sharing options...
rajeevsing15 Posted August 16, 2017 Author Share Posted August 16, 2017 (edited) Thanks @Neutrofor replying. THese are very clean instructions and I tried to implement but didn't get any success. Maybe I am doing something wrong. Can you please look through my code below and point out? expandcollapse popup#include <Array.au3> #include <File.au3> #include <GUIConstants.au3> #include <GUIConstantsEx.au3> Global $inputFile $Form1 = GUICreate("Searching\Replacing SKUs", 510, 250, 256, 115,-1,BitOR($WS_EX_TOPMOST,$WS_EX_ACCEPTFILES)) ;$MergeInputBrowse = GUICtrlCreateButton("Browse", 15, 20, 40, 20) $MergeInputPath = GUICtrlCreateInput('Paste path to xls files or click on "Browse..." to find it', 60, 20, 360, 20) GUICtrlSetState($MergeInputPath, $GUI_DROPACCEPTED) $MergeInputBrowsetxlf = GUICtrlCreateButton("Browse", 15, 60, 40, 20) $MergeInputPathTxlf = GUICtrlCreateInput('Paste path to TXLF files or click on "Browse..." to find it', 60, 60, 360, 20) GUICtrlSetState($MergeInputPathTxlf, $GUI_DROPACCEPTED) $Merge = GUICtrlCreateButton("Start!", 430, 20, 60, 20) $MergeProgress = GUICtrlCreateProgress(15,140, 480, 20) $MergeNotification = GUICtrlCreateInput("Ready to serve, my lord.", 15, 110, 480, 20,$ES_READONLY) $MergeProgress2 = GUICtrlCreateProgress(15,210, 480, 20) $MergeNotification2 = GUICtrlCreateInput("Ready to serve, my lord.", 15, 180, 480, 20,$ES_READONLY) GUICtrlCreateTabItem(""); The end of the tabs, this is needed to separate the last tab from other common elements of the GUI. GUISetState(@SW_SHOW) While 1 $nMsg = GUIGetMsg() Select Case $nMsg = $MergeInputPath; updates the variable with the path entered in this, by pasting or by using the Browse. Global $inputFile = GUICtrlRead($MergeInputPath) EndSelect $nMsgtxlf = GUIGetMsg() Select Case $nMsgtxlf = $MergeInputBrowsetxlf $WorkingPath = FileSelectFolder("Select folder","") GUICtrlSetData($MergeInputPathTxlf,$WorkingPath) Case $nMsgtxlf = $MergeInputPathTxlf; updates the variable with the path entered in this, by pasting or by using the Browse. $WorkingPath = GUICtrlRead($MergeInputPathTxlf) Case $nMsgtxlf = $Merge FileChangeDir($WorkingPath) $PathsArraytxlf=_FileListToArrayRec($WorkingPath,"*.txlf",1,1) For $i = 1 to Ubound($PathsArraytxlf)-1 GUICtrlSetData($MergeNotification, "Working on file " & $i & "/" & UBound($PathsArraytxlf)-1 & " : " & $PathsArraytxlf[$i]) GUICtrlSetData($MergeProgress,($i)/(UBound($PathsArraytxlf)-1)*100) Replacer($PathsArraytxlf[$i]) _ReduceMemory() Next MsgBox(0,"","Finished",0,$Form1) Case $nMsgtxlf = $GUI_EVENT_CLOSE Exit Case $nMsgtxlf = $GUI_EVENT_DROPPED ; If the value of @GUI_DropId is $idLabel, then set the label of the dragged file. If @GUI_DropId = $MergeInputPathTxlf Then GUICtrlSetData($MergeInputPathTxlf, @GUI_DragFile) $WorkingPath = GUICtrlRead($MergeInputPathTxlf) EndIf EndSelect WEnd Func Replacer($nMsgtxlf); This one opens files in the path, one by one and makes the replacements. ;Reading TXLF files $iH = FileOpen(@WorkingDir&"\"&$nMsgtxlf,16384) $inContent = FileRead($iH) Local $readStrings ;Reading TXT file _FileReadToArray($inputFile, $readStrings) _ArrayColInsert($readStrings,1) $seperatedText = StringSplit("$readStrings", "|") Global $outContent $oH = StringReplace($inContent,"$seperatedText[0]","$seperatedText[1]") FileWrite($outContent,$oH) FileClose($outContent) EndFunc Func _ReduceMemory($i_PID = -1); function to reduce the RAM memory used by processes called from the script. If $i_PID <> -1 Then Local $ai_Handle = DllCall("kernel32.dll", 'int', 'OpenProcess', 'int', 0x1f0fff, 'int', False, 'int', $i_PID) $ai_Return = DllCall("psapi.dll", 'int', 'EmptyWorkingSet', 'long', $ai_Handle[0]) DllCall('kernel32.dll', 'int', 'CloseHandle', 'int', $ai_Handle[0]) Else $ai_Return = DllCall("psapi.dll", 'int', 'EmptyWorkingSet', 'long', -1) EndIf Return $ai_Return[0] EndFunc ;==>_ReduceMemory Edited August 17, 2017 by rajeevsing15 Made a small change Link to comment Share on other sites More sharing options...
mikell Posted August 16, 2017 Share Posted August 16, 2017 (edited) Basically I would do it like this #include <Array.au3> #include <File.au3> ; this should be done only once Local $array _FileReadToArray("Replace.txt", $array, 1, "|") _ArrayDisplay($array) ; you could loop here (eventually) Local $file = "File_to_change.txlf", $content = FileRead($file) For $i = 1 to $array[0][0] If StringInStr($content, $array[$i][0]) Then _ReplaceStringInFile($file, $array[$i][0], $array[$i][1]) ExitLoop EndIf Next Edit FileOpen not needed because it is done internally by both FileRead (for reading) and _ReplaceStringInFile (for writing) Edited August 16, 2017 by mikell Link to comment Share on other sites More sharing options...
rajeevsing15 Posted August 16, 2017 Author Share Posted August 16, 2017 Thanks, @mikell for the reply. I tried using this script but it only replaces one instance in a file. My requirement is, to replace all the occurrence of IDs in the first column of Array with IDs after (|) in Replace.txt Also, I have to run this on tons of txlf files. I am very new to AutoIt and I am still learning. I Really appreciate your help here Link to comment Share on other sites More sharing options...
mikell Posted August 16, 2017 Share Posted August 16, 2017 Strange... the default flag in _ReplaceStringInFile is 1 : 1 - all occurrences are replaced (default) I tried with the files you provided in post #1 . In the .txlf file, there are 2 occurences of the first ID and both were replaced Apparently, in the .txlf file there are several occurences of only one ID from Replace.txt, reason why I used Exitloop to make the script faster Are your examples files representative ? Link to comment Share on other sites More sharing options...
Neutro Posted August 16, 2017 Share Posted August 16, 2017 @rajeevsing15 Just so you know, when you post in the forum you can use the "< >" button in the editor to post code So please edit your previous post and put your code this way so we can read it better So this is the code that you posted that actually matters to doing what you want (the other is just GUI / file handling which i didn't check): ;Reading TXLF files $iH = FileOpen(@WorkingDir&"\"&$nMsgtxlf,16384) $inContent = FileRead($iH) Local $readStrings ;Reading TXT file _FileReadToArray($inputFile, $readStrings) _ArrayColInsert($readStrings,1) $seperatedText = StringSplit("$readStrings", "|") Global $outContent $oH = StringReplace($inContent,"$seperatedText[0]","$seperatedText[1]") FileWrite($outContent,$oH) FileClose($outContent) Your first error is here: $seperatedText = StringSplit("$readStrings", "|") You put $readStrings between quotes " " but $readStrings is a variable. If you put the variable name between quotes, it's taken into account as a string named "$separatedText" and no variable used. So the correct thing here is: $seperatedText = StringSplit($readStrings, "|") Second error is here: $seperatedText = StringSplit($readStrings, "|") I understand the logic you used here. You thought, "hey, let's use stringsplit on the whole array at once!" But it doesn't work this way I suggest you read this article about arrays to understand your mistake: https://www.autoitscript.com/wiki/Arrays And this is not just specific to autoIT. Most programming languages work this way with arrays. This is the correct version: for $i = 1 to $readStrings[0][0] step 1 $seperatedText = StringSplit($readStrings[$i][0], "|", 1) $readStrings[$i][0] = $seperatedText[1] $readStrings[$i][1] = $seperatedText[2] Next _ArrayDisplay($readStrings) Once you understand how this works you can also correct the next part of the script Identify active network connections and change DNS server - Easily export Windows network settings Clean temporary files from Windows users profiles directories - List Active Directory Groups members Export content of an Outlook mailbox to a PST file - File patch manager - IRC chat connect example Thanks again for your help Water! Link to comment Share on other sites More sharing options...
kylomas Posted August 16, 2017 Share Posted August 16, 2017 Rajeevsing15, Did you try mikells code after removing the "exitloop"? If i understand your task that should work. All that is left is to feed your files in an outer loop. You may want to back up the files first. Kylomas Forum Rules Procedure for posting code "I like pigs. Dogs look up to us. Cats look down on us. Pigs treat us as equals." - Sir Winston Churchill Link to comment Share on other sites More sharing options...
mikell Posted August 16, 2017 Share Posted August 16, 2017 kylomas, You're right. My bad, I didn't pay attention enough to the whole content of the file. It should work if the Exitloop is removed indeed Link to comment Share on other sites More sharing options...
rajeevsing15 Posted August 17, 2017 Author Share Posted August 17, 2017 thanks, @mikell and @Neutro for the help and suggestions. I helped a lot in understanding the Array I am all set with my script until I decided to take the "Replace.txt" with variable and then pass this file to the array but when I did so, I have got a very strange error and I keep on getting the same error even if I had done lots of modification. Can you please look into the error I am getting and let me know which part is not right in below script. I have attached "Replace.txt" and sample files in zip (In case you would like to test)Error: For $i 1 to $array[0][0] ^ Error: Subscript used on non-accessible variable Code: expandcollapse popup#include <FileConstants.au3> #include <MsgBoxConstants.au3> #include <File.au3> #include <Array.au3> #include <Constants.au3> #include <GUIConstants.au3> #include <GUIConstantsEx.au3> #include <MsgBoxConstants.au3> #include <WindowsConstants.au3> #include <EditConstants.au3> $path1 = "" $path2 = "" $path3 = "" Global $array Global $i Global $Temp $Form1 = GUICreate('Searching\Replacing SKUs in TXLF', 420, 150, -1, -1, -1, BitOR($WS_EX_TOPMOST, $WS_EX_ACCEPTFILES)) ; will create a dialog box ;$browse2 = GUICtrlCreateButton("Browse...", 10, 20, 70, 20) ; will display a button Global $idFile2 = GUICtrlCreateInput('Drag and Drop TXT file with SKU', 90, 20, 320, 20) GUICtrlSetState($idFile2, $GUI_DROPACCEPTED) Global $browse3 = GUICtrlCreateButton("Browse...", 10, 60, 70, 20) ; will display a button Global $idPath3 = GUICtrlCreateInput('Paste path to "TXLF" files or click on "Browse..." to find it', 90, 60, 320, 20) ; will display a section to paste the path where files to be renamed should be $MaxlenButton = GUICtrlCreateButton("Submit", 140, 90, 120, 40) ;Local $text3 = GUICtrlCreateLabel("Maxlen to be set in all cells:", 10, 80, 140, 20) ;_FileReadToArray("Replace.txt", $array, 1, "|") GUISetState(@SW_SHOW) ; will display a dialog box Local $idMsg ; Loop until the user exits. While 1 MsgBox(1, "Test", $idFile2) Switch GUIGetMsg() Case $browse3 $path3 = FileSelectFolder("Select folder", "") & "\" ; Displays a window to select a folder and adds "\" to the path selected. GUICtrlSetData($idPath3, $path3) ; Updates the value of the $idPath variable (assigned to the section to paste the path) with the previously selected path. FileChangeDir($path3) ; Changes the working directory to the previously selected path. Case $idPath3 $path3 = GUICtrlRead($idPath3) ; Reads the written content in the section assigned to paste the path. FileChangeDir($path3) ; Changes the working directory to the previously selected path. Case $GUI_EVENT_CLOSE ; closes the dialog box (including Constants required). Exit Case $MaxlenButton $TermsList = GUICtrlRead($idPath3) If $path3 = "" Then ; If no path is provided, error message will appear. MsgBox(0, "Error", "Error: Please select path to files including \ at the end") ContinueLoop EndIf If $path3 = "\" Then ; If browse button is clicked but no folder is selected, it will automatically generate "\" and if submitted, error message will appear. MsgBox(0, "Error", "Error: Please select path to files including \ at the end") ContinueLoop EndIf _Maxlen() ; will run _FileQA function EndSwitch WEnd Func _Maxlen() _FileReadToArray($idFile2, $array, 1, "|") _ArrayDisplay($array) ProgressOn("Replacing SKUs...", "Working on it...", "", 500, 10, 16) $TxmlFiles = _FileListToArrayRec($path3, "*.txlf", 1, 1, 1, 2) _ArrayDelete($TxmlFiles, 0) ;$FileNumberQA = 0 $FileID = 0 $filearray = UBound($TxmlFiles) For $Txml In $TxmlFiles $FileID += 1 $Progress = $FileID / $filearray * 100 ProgressSet($Progress, $FileID & " out of " & $filearray & " files checked...") $content = FileRead($Txml) For $i = 1 to $array[0][0] If StringInStr($content, $array[$i][0]) Then _ReplaceStringInFile($Txml, $array[$i][0], $array[$i][1]) ;ExitLoop EndIf Next Next ProgressOff() MsgBox(0, 'Done', 'SKU Replaced') EndFunc ;==>_Maxlen MsgBox(0 + 64, 'Complete', 'Process complete') Func _ReduceMemory($i_PID = -1) ; function to reduce the RAM memory used by processes called from the script. If $i_PID <> -1 Then Local $ai_Handle = DllCall("kernel32.dll", 'int', 'OpenProcess', 'int', 0x1f0fff, 'int', False, 'int', $i_PID) $ai_Return = DllCall("psapi.dll", 'int', 'EmptyWorkingSet', 'long', $ai_Handle[0]) DllCall('kernel32.dll', 'int', 'CloseHandle', 'int', $ai_Handle[0]) Else $ai_Return = DllCall("psapi.dll", 'int', 'EmptyWorkingSet', 'long', -1) EndIf Return $ai_Return[0] EndFunc ;==>_ReduceMemory Test_Files.zip Replace.txt Link to comment Share on other sites More sharing options...
mikell Posted August 17, 2017 Share Posted August 17, 2017 I didn't test but I noticed a probable typo ; $idFile2 is the IdD of the input Global $idFile2 = GUICtrlCreateInput ; and here... Func _Maxlen() _FileReadToArray($idFile2, $array, 1, "|") ; you probably meant _FileReadToArray(GUICtrlRead($idFile2), $array, 1, "|") Link to comment Share on other sites More sharing options...
Neutro Posted August 17, 2017 Share Posted August 17, 2017 @rajeevsing15 The problem is that you're trying to do too much things at once and then everything fails You're trying to use a GUI, work with multiple files while you can't even do it for 1 file without a GUI! When you get dressed up you dont try to put all your clothes at once, you put your pants then your shirt ect... You need to do the same here So for now focus on replacing the text ONLY in the example file you posted in your first message. Once you get it right, you can work on using a GUI, then when this is working you can add working with multiple files So start from here: #include <Array.au3> #include <File.au3> ;Reading TXLF file $iH = FileOpen(@WorkingDir & "\File_to_change.txlf") $inContent = FileRead($iH) ;Reading TXT file Local $readStrings _FileReadToArray(@ScriptDir & "\Replace.txt", $readStrings) _ArrayColInsert($readStrings, 1) For $i = 1 To $readStrings[0][0] Step 1 $seperatedText = StringSplit($readStrings[$i][0], "|", 1) $readStrings[$i][0] = $seperatedText[1] $readStrings[$i][1] = $seperatedText[2] Next _ArrayDisplay($readStrings) And try from there to figure out the code to replace the text inside $inContent with the text contained in the array $readStrings Identify active network connections and change DNS server - Easily export Windows network settings Clean temporary files from Windows users profiles directories - List Active Directory Groups members Export content of an Outlook mailbox to a PST file - File patch manager - IRC chat connect example Thanks again for your help Water! Link to comment Share on other sites More sharing options...
rajeevsing15 Posted August 17, 2017 Author Share Posted August 17, 2017 3 hours ago, mikell said: I didn't test but I noticed a probable typo ; $idFile2 is the IdD of the input Global $idFile2 = GUICtrlCreateInput ; and here... Func _Maxlen() _FileReadToArray($idFile2, $array, 1, "|") ; you probably meant _FileReadToArray(GUICtrlRead($idFile2), $array, 1, "|") Thanks @mikell I worked. You are awesome Link to comment Share on other sites More sharing options...
rajeevsing15 Posted August 17, 2017 Author Share Posted August 17, 2017 25 minutes ago, Neutro said: @rajeevsing15 The problem is that you're trying to do too much things at once and then everything fails You're trying to use a GUI, work with multiple files while you can't even do it for 1 file without a GUI! When you get dressed up you dont try to put all your clothes at once, you put your pants then your shirt ect... You need to do the same here So for now focus on replacing the text ONLY in the example file you posted in your first message. Once you get it right, you can work on using a GUI, then when this is working you can add working with multiple files So start from here: #include <Array.au3> #include <File.au3> ;Reading TXLF file $iH = FileOpen(@WorkingDir & "\File_to_change.txlf") $inContent = FileRead($iH) ;Reading TXT file Local $readStrings _FileReadToArray(@ScriptDir & "\Replace.txt", $readStrings) _ArrayColInsert($readStrings, 1) For $i = 1 To $readStrings[0][0] Step 1 $seperatedText = StringSplit($readStrings[$i][0], "|", 1) $readStrings[$i][0] = $seperatedText[1] $readStrings[$i][1] = $seperatedText[2] Next _ArrayDisplay($readStrings) And try from there to figure out the code to replace the text inside $inContent with the text contained in the array $readStrings Thanks For the suggestion brother. Link to comment Share on other sites More sharing options...
mikell Posted August 17, 2017 Share Posted August 17, 2017 @rajeevsing15 Glad I could help About details : the little changes below are absolutely not essential but they make your code flow nicely like a clear stream Func _Maxlen() _FileReadToArray($idFile2, $array, 1, "|") ; _ArrayDisplay($array) ProgressOn("Replacing SKUs...", "Working on it...", "", 500, 10, 16) Local $TxmlFiles = _FileListToArrayRec($path3, "*.txlf", 1, 1, 1, 2) $filearray = $TxmlFiles[0] For $n = 1 to $filearray $Progress = $n / $filearray * 100 ProgressSet($Progress, $n & " out of " & $filearray & " files checked...") $content = FileRead($TxmlFiles[$n]) For $i = 1 to $array[0][0] If StringInStr($content, $array[$i][0]) Then _ReplaceStringInFile($TxmlFiles[$n], $array[$i][0], $array[$i][1]) EndIf Next Next ProgressOff() MsgBox(0, 'Done', 'SKU Replaced') EndFunc ;==>_Maxlen Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now