In a text file consisting of thousands of records, each having greater than 20 lines of data, I need to count the 14th line after the start of every record if that 14th line is blank. The line is either blank or contains a date.
The start of every record is the same: "1 Start of new record"
Scenario:
1 Start of new record
2 some data
3 "
4 "
5 "
6 "
7 "
8 "
9 "
10 "
11 "
12 "
13 "
14
...
1 Start of new record
...
8 "
9 "
10 "
...
14 10/19/2019
...
In this simple scenario, the result should be 1. I have code that copies line 1 of every record into a second file.
The result obviously being:
1 Start of new record
1 Start of new record
...
Here is the code I have:
Const ForReading = 1
Dim words(1)
Dim msg
words(0) = "1 Start of New Record"
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set inFile = objFSO.OpenTextFile("c:\Temp\altest.txt", ForReading)
Set outFile = objFSO.OpenTextFile("c:\Temp\altest_output.txt", 8, True)
Do Until inFile.AtEndOfStream
strSearchString = inFile.ReadLine
For i = 0 To UBound(words)-1
If InStr(strSearchString,words(i)) Then
msg = msg&strSearchString&vbcrlf
End If
next
Loop
inFile.Close
outfile.WriteLine msg
WScript.Echo "Done!"
This seems like a good start, but again, I need to count the 14th line after the start of every record if that 14th line is blank.
Any help is greatly appreciated.
-Alel
Hardly elegant but something like this should get you on your way. This doesn't use SkipLine, it just marks the next line of interest:
Option Explicit 'force explicit variable declaration, this is just good practice
Const ForReading = 1
Dim strContent
Dim Offset : Offset = 14 'define the 14th 'line'
Dim StartLine
Dim NewRecordMarker : NewRecordMarker = "1 Start of new record" 'just use a string to match
Dim objFSO, inFile, outFile
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set inFile = objFSO.OpenTextFile("e:\Temp\altest.txt", ForReading)
Set outFile = objFSO.OpenTextFile("e:\Temp\altest_output.txt", 8, True)
'notice we're only reading forward
'that means we can set the next LineOfInterest without having to worry about
'exceeding AtEndOfStream like we would if we'd use SkipLine
'this is just simpler.
'this obviously falls apart when the line of interest is NOT the 14th line
Do Until inFile.AtEndOfStream
Dim LineOfInterest
strContent = inFile.ReadLine 'inFile.Line will at 2 at this point because we just read it
If strContent = NewRecordMarker Then 'found a new record, we want to look 14 lines from here
LineOfInterest = inFile.line - 1 + Offset ' -1 or we'll overshoot our target
End If
If inFile.Line = LineOfInterest Then 'this is the line we want to inspect
outFile.WriteLine strContent 'just write out entire value, no checking for date here
End If
Loop
inFile.Close
outFile.Close
WScript.Echo "Done!"
Related
I would like to read a specific line in a .txt file in a vb 6.0 program. My intrest is where a particular line where a certain text appears. I am trying to apply this code which I got from another project.
Dim strLine As String
Open "E:\Projects\VB\Ubunifu\MyList.txt" For Input As #1
Line Input #1, strLine ' read one line at a time vs entire file
lblCurrent.Caption = strLine
Line Input #1, strLine
lblO.Caption = strLine
Close #1
however this doesnt seem to be working it says "input past end of file"
You can try this:
Private Sub Form_Load()
Text1.MultiLine = True
Open "E:\Projects\VB\Ubunifu\MyList.txt" For Input As #1
Text1.Text = Input$(LOF(1), #1)
lblCurrent.Caption = udf_ReadLine(Text1.Text, 1) ' read line #1
lblCurrent_i.Caption = udf_ReadLine(Text1.Text, 2) ' read line #2
Close #1
End Sub
Private Function udf_ReadLine(ByVal sDataText As String, ByVal nLineNum As Long) As String
Dim sText As String, nI As Long, nJ As Long, sTemp As String
On Error GoTo ErrHandler
sText = ""
nI = 1
nJ = 1
sTemp = ""
While (nI <= Len(sDataText))
Select Case Mid(sDataText, nI, 1)
Case vbCr
If (nJ = nLineNum) Then
sText = sTemp
End If
Case vbLf
nJ = nJ + 1
sTemp = ""
Case Else
sTemp = sTemp & Mid(sDataText, nI, 1)
End Select
nI = nI + 1
Wend
If (nJ = nLineNum) Then
sText = sTemp
End If
udf_ReadLine = sText
Exit Function
ErrHandler:
udf_ReadLine = ""
End Function
I just added a function to read line from a string, and you can keep using the LOF function as you wish, also all of the concept from your original code.
First, if you had searched for your error you would have found the cause, https://msdn.microsoft.com/en-us/library/aa232640(v=vs.60).aspx.
Second, you need to do something to ensure there is anything in the file to read. https://msdn.microsoft.com/en-us/library/aa262732(v=vs.60).aspx
Finally, use a loop to read lines from the file. It appears you want the first line displayed in one label and the second line displayed in another. The code below reads one line at a time from the file, decides if it is reading an odd line number (first line) or even line number (second line) and displays the line in the label. After each line is read it looks for "a certain text" whatever that may be, and if found it exits the loop and closes the file.
Open "E:\Projects\VB\Ubunifu\MyList.txt" For Input As #1
Do While EOF(1) = False
Line Input #1, strLine ' read one line at a time vs entire file
lngLineNum = lngLineNum + 1 'Am I reading an odd or even line number
If lngLineNum Mod 2 <> 0 Then
lblCurrent.Caption = strLine
Else
lblO.Caption = strLine
End If
If InStr(1, strLine, "a cetain text", vbTextCompare) > 0 Then
Exit Do
End If
Loop
Close #1
Note that I did not check that strLine contained anything before calling InStr. If it is empty the InStr function will cause an error. You should add some defensive coding. At the very least an error handler.
I have 180 lines in a text file and want to read every 20 lines (1-20, 21-40...)
Here is my current code:
Const ForReading = 1
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objTextFile = objFSO.OpenTextFile("C:\Bess_Automation\EditFiles\TSTVLD1.txt", ForReading)
'Reading the count of lines
objTextFile.ReadAll
strLinecount=objTextFile.Line
msgbox strLinecount
strnumoftimes=Round((strLinecount/20),0)
msgbox strnumoftimes
Here's how I'd approach the problem. This code sets the number of lines to be read at a time initially then opens the file for reading and sets up an array. While we're not finished reading the file, we add a line from it to myArray.
When we hit a multiple of 20 lines read, we report that and do whatever we need to with those 20 lines (in my case, I've just echoed them to the screen, separated by semicolons).
Then we reset the array to be empty again and repeat until all the file has been read, then output the final batch of lines (as otherwise they'd be ignored since we only do anything with batches of 20 in the example).
Option Explicit
Const LINES_TO_READ = 20
Dim iLines, iTotalLines
Dim oFso : Set oFso = CreateObject("Scripting.FileSystemObject")
Dim oFile : Set oFile = oFso.OpenTextFile("C:\temp\mytextfile.txt", 1)
Dim myArray()
ReDim myArray(0)
iLines = 0
iTotalLines = 0
While Not oFile.AtEndOfStream
myArray(UBound(myArray)) = oFile.ReadLine
iLines = iLines + 1
ReDim Preserve myArray(UBound(myArray)+1)
If iLines Mod LINES_TO_READ = 0 Then
WScript.Echo iLines & " read now."
' do anything you like with the elements of myArray here before we reset it to empty
WScript.Echo Join(myArray, ";")
' reset array to be totally empty again
ReDim myArray(0)
End If
Wend
WScript.Echo "Final Lines: " & Join(myArray, ";")
WScript.Echo "Total lines in file: " & iLines
I am creating a guy script read files in a folder, (Scripting.FileSystemObject), but I would like to relate a indice inpubox type int to determine which file in the folder I'll write on the screen.
Ex: indice = inputbox "" ← 4 grab the indice file in the folder 4 and esquever your name on the screen.
I wonder if this is possible because already tried in many ways and even by matrix, but without result.
This and my code. I do not know but where to go!
Dim sFO, NovaPasta, Folder,File, Indice
Dim inpast(4)
'Setup
Set sFO = CreateObject("Scripting.FileSystemObject")
Set Folder = sFo.GetFolder("C:\Users\502526523\Documents\Control")
NovaPasta = "Control"
'Development
If Not sFO.FolderExists (NovaPasta) = True Then
sFO.CreateFolder (NovaPasta)
Wscript.Sleep 900
WScript.Echo "Pasta Criada"
Else
WScript.Echo "Pasta Existente "
End If
' Line Verificas a quantidade de inpastas dentro da pasta, se > 5
' deleta os exedentes com data mais antiga
For Each file In folder.Files
If Folder.Files.Count > 5 And (DateDiff("d", file.DateLastModified, Now) > 7) Then
WScript.Echo (file.Name & vbLf)
WScript.Echo ("Total files :" & Folder.Files.Count)
File.Delete
End If
Next
For Each file In folder.Files
inpast(0) = (file.Name)
inpast(1) = (file.Name)
inpast(2) = (file.Name)
inpast(3) = (file.Name)
inpast(4) = (file.Name)
Indice = Inputbox ("Digite o valor do Indice de 0...30")
Select Case Indice
Case 0
WScript.Echo inpast(0)
Case 1
WScript.Echo inpast(1)
Case 2
WScript.Echo inpast(2)
Case 3
WScript.Echo inpast(3)
Case 4
WScript.Echo inpast(4)
End Select
Next
Still not sure if I understand your question correctly. You mean you have a list of filenames and you want to display the filename corresponding to the number the user entered via an InputBox? If that's what you want you should change your second For Each loop like this:
i = 0
For Each file In folder.Files
inpast(i) = file.Name
i = i + 1
Next
Indice = InputBox("Digite o valor do Indice de 0...30")
WScript.Echo inpast(CInt(Indice))
Note, however, that the condition in your first For Each loop does not guarantee you'll only ever have 5 files left after the loop. If for some reason the folder contains more than 5 files that were modified within the past 7 days the second loop would fail with a "subscript out of range" error.
There are several ways you could handle this:
Dynamically resize the inpast array so it can hold more than 5 items.
Sort the files in the folder by last modification date (e.g. like this) and delete everything except the 5 most recent files.
Cut off the second For Each loop after the 5th iteration (Exit For).
Note also, that you should sanitize your input. (What happens when users enter text, an invalid number, or press "Cancel"?)
Set fso = CreateObject("Scripting.FileSystemObject")
Dirname = InputBox("Enter Dir name")
'Searchterm = Inputbox("Enter search term")
ProcessFolder DirName
Sub ProcessFolder(FolderPath)
' On Error Resume Next
Set fldr = fso.GetFolder(FolderPath)
msgbox fls.count
Msgbox fls.item("computerlist.txt")
End Sub
To do the 7th
Set Fls = fldr.files
For Each thing in Fls
Count = Count + 1
If count = 7 then msgbox Thing.Name & " " & Thing.DateLastModified
Next
I have a file in which I am able to find the keyword using vbscript but further I need to keep copying next 3-4 lines down it, until I find another occurrence of similar pattern of keyword.
I have written something like this - ( I am newbee for assume I am dumb )
Set fso = CreateObject("Scripting.FileSystemObject")
Set inFile = fso.OpenTextFile("FileName", 1)
Set outFile = fso.OpenTextFile("FileName", 8, True)
outFile.WriteLine("This is some sample data.")
strAnswer = InputBox("Please enter a value:", _
"Enter Value")
Do until inFile.AtEndOfStream
line = inFile.ReadLine
If InStr(line, strAnswer) Then
outFile.WriteLine line ' Copy the line and write to output file
serNum = Left(line, 7)
'If Not ((line = inFile.ReadLine())
'take first 3 char and find the next occurance of it
'copy all lines until that line
WScript.Echo "Found"
End If
Loop
outfile.Close
Set fSO = Nothing
Any suggestion is appreciable.
You could use a sub-loop to continue writing until the serial number is found again.
Do until inFile.AtEndOfStream
line = inFile.ReadLine
If InStr(line, strAnswer) Then
outFile.WriteLine line ' Copy the line and write to output file
serNum = Left(line, 7)
' Continue writing until EOF or serial number is found...
Do While Not inFile.AtEndOfStream
line = inFile.ReadLine
If InStr(line, serNum) = 0 Then outFile.WriteLine line
Loop
End If
Loop
Use the state of the variable serNum to decide what you need to do with the current line:
Do until inFile.AtEndOfStream
line = inFile.ReadLine
If Not IsEmpty(serNum) And InStr(line, serNum) > 0 Then WScript.Quit
If IsEmpty(serNum) And InStr(line, strAnswer) > 0 Then serNum = Left(line, 7)
If Not IsEmpty(serNum) Then outFile.WriteLine line
Loop
The first condition checks if you have found the second match and then quits.
The second condition checks if you have found the first match and then initializes serNum.
The third condition causes all lines from the first match to the line before the second match to be written to the output file.
I have two .csv files: inputfile.csv and mainfile.csv
I need to write a script that:
1- will read one by one all the records in inputfile.csv
2- then find if there is a match in the mainfile.csv
3- if there is a match then do nothing and read the next record from inputfile.csv
4- else if there is not a match in the mainfile.csv write that record from the inputfile.csv to the mainfile.csv
This solution uses Scripting.Dictionary to record each line in mainfile.csv. Then, to see if a line in inputfile.csv is new, all it takes is to see if that line exists in the dictionary. For example:
mainfile.csv
exists,one
exists,two
exists,three
exists,four
exists,five
inputfile.csv
exists,two
new,one
exists,four
new,two
new,three
mainfile.csv (after running the program)
exists,one
exists,two
exists,three
exists,four
exists,five
new,one
new,two
new,three
Here's the code:
Option Explicit
Const ForReading = 1, ForWriting = 4, ForAppending = 8
Dim oFso : Set oFso = CreateObject("Scripting.FileSystemObject")
Dim oDict : Set oDict = CreateObject("Scripting.Dictionary")
'
' Read the contents of 'mainfile.csv'. Add each line to a dictionary
' to allow for a quick lookup.
'
Dim oFileMain : Set oFileMain = oFso.OpenTextFile("mainfile.csv", ForReading)
Dim sLine
While Not oFileMain.AtEndOfStream
sLine = oFileMain.ReadLine()
oDict.Add sLine, True
Wend
oFileMain.Close
Set oFileMain = Nothing
'
' Re-open 'mainfile.csv' in append mode.
'
Set oFileMain = oFso.OpenTextFile("mainfile.csv", ForAppending)
'
' Read the contents of 'inputfile.csv'. Write a line to 'mainfile.csv'
' only if that line does not exist in the dictionary.
'
Dim oFileInput : Set oFileInput = oFso.OpenTextFile("inputfile.csv", ForReading)
While Not oFileInput.AtEndOfStream
sLine = oFileInput.ReadLine()
If Not oDict.Exists(sLine) Then ' not a duplicate!
WScript.Echo "Found new line: [" & sLine & "]"
oFileMain.WriteLine sLine
End If
Wend
oFileInput.Close
Set oFileInput = Nothing
'
' Wrap it up.
'
oFileMain.Close
Set oFileMain = Nothing
Set oDict = Nothing
Set oFso = Nothing
' End
Here is my best attempt at doing it in python, not knowing the structure of the files:
with open("mainfile.csv", "r") as main:
records = [x.strip() for x in main.readlines()]
with open("inputfile.csv", "r") as input:
inputs = [x.strip() for x in input.readlines()]
for input in inputs:
if input not in records:
records.append(input)
with open("mainfile.csv", "w") as main:
for record in records:
main.write(record + "\n")
So for the following files you start with this:
inputfile.csv:
A quick brown fix
Two turtle doves
Feather boa
mainfile.csv:
Some other stuff
Two turtle doves
Friends in low places
Feather boa
Another Fairly boring thing
After you run the script mainfile.csv looks like this:
Some other stuff
Two turtle doves
Friends in low places
Feather boa
Another Fairly boring thing
A quick brown fix