Append text to text file if it already exists - vbscript

I have a script which is working, to replace some characters in a fixed width file (starting from row 2 onward).
What want to avoid overwriting the target file if it already exists. Instead, if it exists, to append the rows (from row 2 onwards of the source file) to the end of the target file. I am struggling to find a thread with a proper suggestion. This is the current code:
Dim objFSO
dim objFile
dim thisLine
Set objFSO = CreateObject("Scripting.FileSystemObject")
If (objFSO.FileExists("C:\Users\Dimitar\Desktop\BPSDRC\PAYBOTH.dat")) Then
Set objFile = objFSO.GetFile("C:\Users\Dimitar\Desktop\BPSDRC\PAYBOTH.dat")
Else
WScript.Quit()
End If
If objFile.Size > 0 Then 'make sure the input file is not empty
Set inputFile = objFSO.OpenTextFile("C:\Users\Dimitar\Desktop\BPSDRC\PAYBOTH.dat", 1) 'Replace the filename here
set outputFile = objFSO.CreateTextFile("C:\Users\Dimitar\Desktop\BPSDRC\PAYIMP.dat", TRUE) 'replace it with output filename
' first line - leave it as it is
thisLine = inputFile.ReadLine
newLine = thisLine
outputFile.WriteLine newLine
'all remaining lines - read them and replace the middle part with 18 zeroes
do while not inputFile.AtEndOfStream
thisLine = inputFile.ReadLine ' Read an entire line into a string.
'the zeroes are to fix issue N1 (payment in other amt)
'the CDF are to fix issue N2 (payment in local amt)
newLine = mid(thisLine,1,47) & "000000000000000000" & mid(thisLine,66,121) & "CDF" & mid(thisLine,190)
outputFile.WriteLine newLine
loop
inputFile.Close
outputFile.Close
objFSO.DeleteFile "C:\Users\Dimitar\Desktop\BPSDRC\PAYBOTH.dat"
end if

Open the file for appending
Option Explicit
Const ForReading = 1, ForAppending = 8
Dim inputFileName, outputFileName
inputFileName = "C:\Users\Dimitar\Desktop\BPSDRC\PAYBOTH.dat"
outputFileName = "C:\Users\Dimitar\Desktop\BPSDRC\PAYIMP.dat"
Dim fso
Set fso = CreateObject("Scripting.FileSystemObject")
If Not fso.FileExists( inputFileName ) Then
WScript.Quit
End If
If fso.GetFile( inputFileName ).Size < 1 Then
WScript.Quit
End If
Dim newFile, inputFile, outputFile
newFile = Not fso.FileExists( outputFileName )
Set inputFile = fso.OpenTextFile( inputFileName, ForReading )
Set outputFile = fso.OpenTextFile( outputFileName, ForAppending, True )
Dim lineBuffer
lineBuffer = inputFile.ReadLine()
If newFile Then
outputFile.WriteLine lineBuffer
End If
Do While Not inputFile.AtEndOfStream
lineBuffer = inputFile.ReadLine
lineBuffer = mid(lineBuffer,1,47) & "000000000000000000" & mid(lineBuffer,66,121) & "CDF" & mid(lineBuffer,190)
outputFile.WriteLine lineBuffer
Loop
inputFile.Close
outputFile.Close
fso.DeleteFile inputFileName

Related

Reading script and replacing specific line. vbscript

I'm developing a script that encrypts a users Tacacs-password, and writes this string into another script. My script opens, reads & writes the Tacacs-password into my other script but it doensn't overwrite it.
First run:
strTacacs = "Test1234"
Second run:
strTacacs = "Test1234"strTacacs = "Test1234"
My current script:
'***********Write to auto-logon script************
Const ForReading = 1
Const ForWriting = 2
newline = "strTacacs = " & chr(34) & Tacacs & chr(34)
line = 30
Set objFSO = CreateObject("Scripting.FileSystemObject")
Dim lineCount : lineCount = 0
Dim firstContent : firstContent = ""
Set objFolder = objFSO.GetFolder(objStartFolder)
Set colFiles = objFolder.Files
For Each objFile in colFiles
If LCase(objFSO.GetExtensionName(objFile)) = "vbs" Then
lineCount = 0
firstContent = ""
FileName = objStartFolder & objFile.Name
Set objStream = objFSO.OpenTextFile(strFile, ForReading)
Do Until objStream.AtEndOfStream
lineCount = lineCount + 1
firstContent = firstContent & objStream.ReadLine & vbCrLf
'msgbox(firstContent)
if lineCount = 30 Then
firstContent = firstContent & newline
msgbox(firstContent)
End if
Loop
Set objStream = objFSO.OpenTextFile(FileName, ForWriting)
objStream.WriteLine firstContent
objStream.Close
End If
Next
.
Does anybody know what I'm doing wrong?
I'm new in the world of scripting so your help is greatly appreciated!
Thx!
It looks like you are writing both the original line and the new line when you get to line 30. You should only write newline when lineCount is 30 and write the original line otherwise:
Do Until objStream.AtEndOfStream
lineCount = lineCount + 1
If lineCount = 30 Then
' Replace line with newline
firstContent = firstContent & newline & vbCrLf
Else
' Write original line
firstContent = firstContent & objStream.ReadLine & vbCrLf
End If
Loop
If you know the password in the original file, you could read the whole file content in one shot using ReadAll method:
Set objStream = objFSO.OpenTextFile(strFile, ForReading)
firstContent = objStream.ReadAll
then use Replace to replace the password, and finally write the content back.
You current line-by-line approach is easier if you don't know the password and simply replace a specific line. You could also check if line starts with strTacacs = which gets you away from hardcoding the line number:
Dim sLine
Dim sPasswordLine
sPasswordLine = "strTacas ="
Do Until objStream.AtEndOfStream
' Read line
sLine = objStream.ReadLine
If Left(sLine, Len(sPasswordLine)) = sPasswordLine Then
' Replace line with newline
firstContent = firstContent & newline & vbCrLf
Else
' Write original line
firstContent = firstContent & sLine & vbCrLf
End If
Loop

How to append text from one file to another file after a specific line using VBScript?

I need to insert the contents of a text file into another existing text file after the line with a specific word in it.
Here is my code.
'//OPEN FILE and READ
Set objFileToRead = fso.OpenTextFile(ActiveDocument.Path & "\file.txt", 1)
strFileText = objFileToRead.ReadAll()
objFileToRead.Close
objStartFolder = ActiveDocument.Path
Set objFolder = fso.GetFolder(objStartFolder)
Set colFiles = objFolder.files
For Each objFile In colFiles
If fso.GetExtensionName(objFile.Name) = "opf" Then
filename = objFile.Name
End If
Next
MsgBox filename
'///PASTE
If fso.FileExists(ActiveDocument.Path & "\" & filename) Then
MsgBox filename
Set objFile = fso.OpenTextFile(ActiveDocument.Path & "\" & filename)
Do Until objFile.AtEndOfStream
strLine = objFile.ReadLine
If InStr(strLine, "<manifest>") = 1 Then
MsgBox filename
objFile.WriteLine vbCrLf & strFileText
objFile.Close
End If
Loop
End If
I get a bad file error in the following line
objFile.WriteLine vbCrLf & strFileText
Can anyone please tell me what is wrong and what I have to do?
You can't write to a file that was opened for reading.
Either write the modified content to a temporary file and replace the original file with it afterwards:
p = fso.BuildPathActiveDocument.Path, filename)
Set f1 = fso.OpenTextFile(p)
Set f2 = fso.OpenTextFile(p & ".tmp", 2, True)
Do Until f1.AtEndOfStream
line = f1.ReadLine
f2.WriteLine line
If InStr(line, "<manifest>") = 1 Then f2.WriteLine strFileText
Loop
f1.Close
f2.Close
fso.DeleteFile p, True
fso.GetFile(p & ".tmp").Name = filename
or read the entire content into memory before writing the modified content back to the original file:
p = fso.BuildPathActiveDocument.Path, filename)
txt = Split(fso.OpenTextFile(p).ReadAll, vbNewLine)
Set f = fso.OpenTextFile(p, 2)
For Each line In original
f.WriteLine line
If InStr(line, "<manifest>") = 1 Then f.WriteLine strFileText
Next
f.Close
Note that the latter shouldn't be used for large files, lest your computer come grinding to a halt due to memory exhaustion.

Replace a specific string with the filename?

How to replace a specific string with the filename? Example: I have several files with different names (like: Test.asp, Constant.asp, Letter.asp, etc.) within a subfolder that contain the text "ABC123". I would like to replace the "ABC123" in each file with the filename.
Below is the code I have that finds string and replaces it with a specific string but it doesn't do the job that I listed above.
Option Explicit
Dim objFilesystem, objFolder, objFiles, objFile, tFile, objShell, objLogFile,objFSO, objStartFolder, colFiles
Dim SubFolder, FileText, bolWriteLog, strLogName, strLogPath, strCount, strCount2, strOldText, strNewText, strEXT
bolWriteLog = True
Const ForReading = 1
Const ForWriting = 2
Const TriStateUseDefault = -2
Set objFilesystem = WScript.CreateObject("Scripting.FileSystemObject")
Set objShell = CreateObject("WScript.Shell")
strLogName = "log.txt"
strLogPath = "C:\" & strLogName
strCount = 0
strCount2 = 0
strOldText = "ABC123"
strNewText = ""
strEXT = "asp"
'Initialize log file
If bolWriteLog Then
On Error Resume Next
Set objLogFile = objFileSystem.OpenTextFile(strLogPath, 2, True)
WriteLog "############### Start Log ##################"
If Not Err.Number = 0 Then
MsgBox "There was a problem opening the log file for writing." & Chr(10) & _
"Please check whether """ & strLogPath & """ is a valid file and can be openend for writing." & _
Chr(10) & Chr(10) & "If you're not sure what to do, please contact your support person.", vbCritical, "Script Error"
WScript.Quit
End If
On Error Goto 0
End If
Set objFSO = CreateObject("Scripting.FileSystemObject")
objStartFolder = "D:\MyFolder"
Set objFolder = objFSO.GetFolder(objStartFolder)
WScript.Echo objFolder.Path
Set colFiles = objFolder.Files
For Each objFile In colFiles
'WScript.Echo objFile.Name
' Now we have an exception for all files that can not be opened in text modus: all extensions such as "exe" should be listed upfront.
ReplaceText(objFile)
Next
ShowSubfolders objFSO.GetFolder(objStartFolder)
Sub ReplaceText(objFile)
If InStr(1, strEXT, Right(LCase(objFile.Name), 3)) = 0 Or objFile.Size = 0 Then
Else
strCount = strCount + 1
WriteLog("Opening " & objFile.Name)
Set tFile = objFile.OpenAsTextStream(ForReading, TriStateUseDefault)
FileText = tFile.ReadAll
tFile.Close
If InStr(FileText, strOldText) Then
WriteLog("Replacing " & strOldText & " with " & strNewText & ".")
FileText = Replace(FileText, strOldText, strNewText)
WriteLog("Text replaced")
Else
WriteLog(strOldText & " was not found in the file.")
strCount2 = strCount2 + 1
End If
Set tFile = objFile.OpenAsTextStream(ForWriting, TriStateUseDefault)
tFile.Write FileText
tFile.Close
FileText = ""
strCount = 0
strCount2 = 0
End If
End Sub
Sub ShowSubFolders(Folder)
For Each Subfolder in Folder.SubFolders
'WScript.Echo Subfolder.Path
Set objFolder = objFSO.GetFolder(Subfolder.Path)
Set colFiles = objFolder.Files
For Each objFile in colFiles
'WScript.Echo objFile.Name
ReplaceText(objFile)
Next
ShowSubFolders Subfolder
Next
End Sub
WriteLog "############### EndLog ##################"
WScript.Echo "Script Complete"
objShell.Run "C:\" & strLogName
'Clear environment and exit
On Error Resume Next
Set tFile = Nothing
Set objFile = Nothing
Set objFiles = Nothing
Set objFolder = Nothing
Set objLogFile = Nothing
Set objFilesystem = Nothing
Set objShell = Nothing
WScript.Quit
'Subs and functions ********** DO NOT EDIT ***************
Sub WriteLog(sEntry)
If bolWriteLog Then objLogFile.WriteLine(Now() & ": Log: " & sEntry)
End Sub
I can give you a one line Ruby solution, should be not too difficult to translate that in Python but somewhat more extensive in VbScript I am afraid. First a generic search and replace version.
ARGV[0..-3].each{|f| File.write(f, File.read(f).gsub(ARGV[-2],ARGV[-1]))}
Save it in a script, eg replace.rb
You start in on the command line (here cmd.exe) with
replace.rb *.txt <string_to_replace> <replacement>
broken down so that I can explain what's happening but still executable
# ARGV is an array of the arguments passed to the script.
ARGV[0..-3].each do |f| # enumerate the arguments of this script from the first to the last (-1) minus 2
File.write(f, # open the argument (= filename) for writing
File.read(f) # open the argument (= filename) for reading
.gsub(ARGV[-2],ARGV[-1])) # and replace all occurances of the beforelast with the last argument (string)
end
And finally your request to replace ABC123 with the filename.
Of course tested and working
ARGV[0..-1].each{|f| File.write(f, File.read(f).gsub('ABC123', f))}
Contents of one of my testfiles (1.txt) after executing
test phrase
1.txt
EDIT
I see you want subfolder recursion on a fixed folder, no problem
Dir['**/*'].each{|f| File.write(f, File.read(f).gsub('ABC123', f)) unless File.directory?(f) }

Read text and match all dates in text file otherwise write value to error.txt file

The below .TXT file is read into a VBS FileSystemObject. I am trying to search for all dates that match otherwise I need to put them in a "error.txt" file. However, when I run my code below it is always placing the matches in the error.txt file and not skipping the matching dates.
Why are the dates not matching?
INPUT:
"LIRRR 1M",.412900,02/08/2016
"LIRRR 3M",.222700,02/08/2016
"LIRRR 6M",.333200,02/08/2016
"LIRRR12M",1.1333300,02/08/2016
"FEDFRRRR",.333000,02/08/2016
"CCC 1YR",.550330,02/08/2016
"5YRCMT",1.2503300,02/08/2016
"10YRCMT",1.860000,02/08/2016
Here is the code that I have written:
On error resume next
Const ForReading = 1
Dim strSearchFor
Dim MyDate, MyWeekDay
MyDate = Date ' Assign a date.
MyWeekDay = Weekday(MyDate)
If MyWeekDay = 2 then
strSearchFor =Right("0" & DatePart("m",Date), 2)&"/"&Right("0" & DatePart("d",Date-3), 2)&"/"&DatePart("yyyy",Date)
Else
strSearchFor =Right("0" & DatePart("m",Date), 2)&"/"&Right("0" & DatePart("d",Date-1), 2)&"/"&DatePart("yyyy",Date)
End If
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objTextFile = objFSO.OpenTextFile("C:\Users\Desktop\index.txt", ForReading)
do until objTextFile.AtEndOfStream
strLine = objTextFile.ReadLine()
If InStr(strLine, strSearchFor) <> 0 then
Set objFile = objFSO.CreateTextFile("C:\Users\Desktop\pass.txt")
objFile.Write "date is match"& vbCrLf
Else
Set objFile = objFSO.CreateTextFile("C:\Users\Desktop\error.txt")
objFile.Write "date is not match"& vbCrLf
End If
loop
objTextFile.Close
Why not use RegEx to get the portion of the string that appears to be the date and use the IsDate Function to validate it?
Option Explicit
Dim arrLines,i
arrLines = ReadFile("./input.txt","byline")
For i=LBound(arrLines) to UBound(arrLines)
wscript.echo FormatOutput(arrLines(i))
Next
'*********************************************
Function FormatOutput(s)
Dim re, match
Set re = New RegExp
re.Pattern = "[\d]+[\/-][\d]+[\/-][\d]+"
re.Global = True
For Each match In re.Execute(s)
if IsDate(match.value) then
FormatOutput = CDate(match.value)
Exit For
end if
Next
Set re = Nothing
End Function
'*********************************************
Function ReadFile(path,mode)
Const ForReading = 1
Dim objFSO,objFile,i,strLine
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile(path,ForReading)
If mode = "byline" then
Dim arrFileLines()
i = 0
Do Until objFile.AtEndOfStream
Redim Preserve arrFileLines(i)
strLine = objFile.ReadLine
strLine = Trim(strLine)
If Len(strLine) > 0 Then
arrFileLines(i) = strLine
i = i + 1
ReadFile = arrFileLines
End If
Loop
objFile.Close
End If
If mode = "all" then
ReadFile = objFile.ReadAll
objFile.Close
End If
End Function
'*****************************************************************

How to correct VBscript runtime error: input past end of file

I'm getting the following error for this code. Please could you advise where it is wrong? Line 71 is "urls2 = objInputFile.ReadAll".
Line 71
Character 1
Error: Input past end of file
Code: 800A003E
Source: Microsoft VBScript runtime error.
inputfile = "C:\Evernote.html"
outputfolder = "c:\"
msgbox("launched. press ok to continue")
'create urls1.txt
Set objFileSystem = CreateObject("Scripting.fileSystemObject")
Set objOutputFile = objFileSystem.CreateTextFile(outputfolder & "urls1.txt", TRUE)
'read inputfile (evernote exported html)
Set objFileSystem = CreateObject("Scripting.fileSystemObject")
Set objInputFile = objFileSystem.OpenTextFile(inputfile, 1)
html = objInputFile.ReadAll
objInputFile.Close
'split html var
html = Split(html, "<tr><td><b>Source:</b></td><td><a href=""")
'loop through html array and clean up the results so you get just the urls
'and write them to urls1.txt
For i = 1 To UBound(html)
checkA = InStr(html(i), """")
if checkA > 1 then
html(i) = Split(html(i), """")
urls = html(i)(0)
objOutputFile.WriteLine(urls)
end if
Next
'remove duplicates
'create urls2.txt
Set objFileSystem = CreateObject("Scripting.fileSystemObject")
Set objOutputFile = objFileSystem.CreateTextFile(outputfolder & "urls2.txt", TRUE)
'read urls1.txt and remove duplicates and write results to urls2.txt
Set objFS = CreateObject("Scripting.FileSystemObject")
strFile = outputfolder & "urls1.txt"
Set objFile = objFS.OpenTextFile(strFile)
Set d = CreateObject("Scripting.Dictionary")
Do Until objFile.AtEndOfStream
strLine = objFile.ReadLine
If Not InStr(strLine,"--------") >0 Then
If Not d.Exists(strLine) Then
d.Add strLine , 0
End If
End If
Loop
x=d.Items
For Each strKey In d.keys
objOutputFile.WriteLine(strKey)
Next
'sort alphabetically
'read urls2.txt and sort everything alphabetically
'read urls2.txt
Set objFileSystem = CreateObject("Scripting.fileSystemObject")
Set objInputFile = objFileSystem.OpenTextFile(outputfolder & "urls2.txt", 1)
urls2 = objInputFile.ReadAll
objInputFile.Close
'split each line into array
urls2 = Split(urls2, VBCrLf)
'sort urls2 array by alphabet with bubble sort method
For i = (UBound(urls2) - 1) to 0 Step -1
For j= 0 to i
If UCase(urls2(j)) > UCase(urls2(j+1)) Then
strHolder = urls2(j+1)
urls2(j+1) = urls2(j)
urls2(j) = strHolder
End If
Next
Next
'write the sorted version of urls2.txt in urlsfinal.txt
'create urlsfinal.txt
Set objFileSystem = CreateObject("Scripting.fileSystemObject")
Set objOutputFile = objFileSystem.CreateTextFile(outputfolder & "urlsfinal.txt", TRUE)
'write all sorted vars from urls2 array to urlsfinal.txt
For i = 0 to UBound(urls2)
objOutputFile.WriteLine(urls2(i))
next
msgbox("all done")
The problem is your source file urls2.txt is empty. The reason for this is you are not closing your files after you write to them. You need to add this after you have finished writing out to urls1.txt and urls2.txt.
objOutputFile.Close
Also, you don't need to continually recreate the instance of objFileSystem every time you access the files. You can instantiate it once at the top.
Be sure to be a good memory citizen and destroy all objects you set in your code.
Set objFileSystem = Nothing

Resources