Reset index of File object for reading several time - vba

Now, I am writing a VBA program. In my program, firstly I need to count all line from a file. I need line count because of creating array for line in file. So, I used this code. It is OK.
'Open file
Set file = fsObject.OpenTextFile(filePath, ForReading)
'Read all line
file.ReadAll
'Get line count
lineCount = file.line
'Close file
file.Close
After getting line count, I want to subtract 2 from it for header and footer(the blank line). I don't know which word will be header. I only know row that they are first row and last row(the blank row).
'Remove header and blank line from line count
lineCount = lineCount - 2
And then, I wanna read that file line by line which are only useful for me and store all line in array. The problem is at that, when reading line by line, It is need to re-open file. Only after re-open, I can read line by line.
Because, "ReadAll" method is readed all line and the index of file object is shown "AtEndOfFile". So, I must re-open it. Please check my code.
'If line count is greater than 0, read again file to get data
If lineCount > 0 Then
'Re-define array size
ReDim lineList(lineCount) As String
'Here I opend it, I don't wanna open. I just want to set index of file object.
'Re-open file
Set file = fsObject.OpenTextFile(filePath, ForReading)
'Read file until end
Do Until file.AtEndOfStream
'If current line is not first line(header) or last line(blank line)
If line <> 0 And line <= lineCount Then
'Store line into array
lineList(index) = file.ReadLine
'Increase array index
index = index + 1
Else
file.ReadLine
End If
'Increase line index
line = line + 1
Loop
End If
But, I want another way. I don't wanna re-open file. I want to reset the index to the first line of file object. So, I don't need to re-open it.
I already search about it in internet. But, I didn't found any suggestions for that. Please help me. Thanks.

My approach is slightly different than your current approach, I would use the Binary read to read the file and save it in a temporary string, then use Split function to put them in an Array.
This method has one drawback as in the if the length (number of characters) of the file is greater than the size of a String variable then we might have issues but other than that. This is quite different approach.
Public Sub ReadFileData(filePath As String, Optional separatorStr As String = ";#;")
'******************************************************************************
' Opens a large TXT File, reads the data until EOF on the Source,
' then stores them in an Array
' Arguments:
' ``````````
' 1. The Source File Path - "C:\Users\SO\FileName.Txt" (or) D:\Data.txt
' 2. (Optional) Separator - The separator, you wish to use. Defauls to ';#;'
'*******************************************************************************
Dim strIn As String, tmpStr As String, lineCtr As Long
Dim tmpArr() As String
Open filePath For Input As #1
Do While Not EOF(1)
'Read one line at a time.
Line Input #1, strIn
tmpStr = tmpStr & Trim(strIn) & separatorStr
lineCtr = lineCtr + 1
Loop
Close #1
tmpArr = Split(tmpStr, separatorStr)
Debug.Print "Number of Elements in the Arrays is - " & UBound(tmpArr)
Debug.Print "Number of Lines Read is - " & lineCtr
End Sub

Related

Trying to close textfile after line is read

Im trying to output the data from the second line of my textfile to a datagridview but when doing so it is also outputting every line after the the second line. This is what I have tried. Thanks
Dim lines = IO.File.ReadAllLines(OrderID & ".txt")
For index = 1 To lines.Length - 1
Dim cells = lines(index).Split(","c)
dgvOutput.Rows.Add(cells)
FileClose()
It's outputting every line after the second line, because that's what you're telling it to do when you iterate through the array of strings returns from ReadAllLines.
IO.File.ReadAllLines does not leave an output stream open. The file is closed. What it does do, is return a zero-based (by default) array of the contents of the file, with line breaks being the delimiter for the split.
To just get the contents of the second line, using ReadAllLines, this is what you need:
Dim lines = IO.File.ReadAllLines(OrderID & ".txt")
If lines.length >= 2 Then
Dim cells = lines(1).Split(","c)
dgvOutput.Rows.Add(cells)
End If
Now, that does have the overhead of reading the entire file in. If you open the file using a reader object, then you only need to read the first and second lines of the file to get that second line.
That would be something like this:
Dim reader as StreamReader = My.Computer.FileSystem.OpenTextFileReader(OrderId & ".txt")
Dim a as String
' This reads the first line, which we throw away
reader.ReadLine()
a = reader.ReadLine()
reader.Close()
Dim cells = a.Split(","c)
dgvOutput.Rows.Add(cells)
You would need to test your explicit circumstances to determine which is better for what you're trying to do.
Your loop is executed over all lines skipping just the first line.
While I cannot see what happen in the FileClose call it seems to not have any sense because ReadAllLines has already closed the file.
You can get the second line of your file with a single line of code
Dim line as String = File.ReadLines(OrderID & ".txt").Skip(1).Take(1).FirstOrDefault()
' this check is required to avoid problems with files containing 0 or 1 line
if line IsNot Nothing Then
Dim cells = line.Split(","c)
dgvOutput.Rows.Add(cells)
End If
Notice that I have replaced the ReadAllLines with ReadLines. This is better because using this method you don't read all lines when you need only the second one (if it exists). More info at ReadLines vs ReadAllLines
Dim lines = IO.File.ReadAllLines(OrderID & ".txt")
Dim SecondLine = lines(1)
File.ReadAllLines opens and closes the file for you so there is not need to add code to close it.

Reading and writing lines to and from a file

I am writing a simple console application using Microsoft Visual Basic 2010 express. I am trying to make a "newfile1.txt" file in which will be write something heading and than lets say 10 rows with three words in each row.
After that, I would like to read from file, and write to the "newfile2" file only the second word from file "newfile1.txt"
Than I would like to read from this file every line, and store lets and store only the second word from newfile1.txt
I try to use following code but I don't know how to specify several things (see bellow code)
Module Module1
Sub Main()
Dim i As Integer
FileOpen(1, "C:\Users\Namba\Documents\ANALYZA MD\newFile1.txt", OpenMode.Append, OpenAccess.ReadWrite, OpenShare.Default)
FileOpen(2, "C:\Users\Namba\Documents\ANALYZA MD\newFile2.txt", OpenMode.Append, OpenAccess.ReadWrite, OpenShare.Default)
WriteLine(1, "Heading of the file1")
For i = 1 To 10 Step 1
WriteLine(1, "Word 1" & "Word 2" & "Word 3")
Next
FileClose(1)
WriteLine(2, "Heading of the file2")
Dim filereader As System.IO.StreamReader
filereader = My.Computer.FileSystem.OpenTextFileReader("C:\Users\Namba\Documents\ANALYZA MD\newFile1.txt")
Dim stringReader As String
For i = 1 To 10 Step 1
stringReader = filereader.ReadLine()
WriteLine(2, stringReader)
Next
End Sub
End Module
So I have several questions:
Is it possible via ReadLine store words lets say in to the array or each word to the different string variable?
Is there simpler form how to open file and read each word, eventual define that the first word will be store in to the string var1, the second in to the var2 and so on, and similar if we have a file with numbers so that I would like to read from this file and store each number in to the some variable.
I can do this in fortran easy, via READ() WRITE() in very simple way
OPEN(UNIT=11, FILE="newfile1.txt)
READ(UNIT=11) x, y, z
OPEN(UNIT=12, FILE="newfile2.txt)
WRITE(UNIT=12,*) y
So this will read from one file the first 3 word(or number if the x, y, z is declare as number) from the first line and write in to the second file just second word (or number).
So I wonder if there is something very similar also in visual basic?
In general, if your files aren't large then it is faster (with respect to code writing) and easier to just read the contents of the file into memory and then manipulate it as needed.
Hopefully these examples will be of some help.
' Read entire contents of file1.txt into an array.
Dim file1 As String() = System.IO.File.ReadAllLines("C:\file1.txt")
' Now extract the 2nd word from each line (assuming all lines have at least 2 words).
Dim secondWords As New List(Of String)
For Each line In file1
' Break apart the string by spaces and take the second index (word).
secondWords.Add(line.Split(" ")(1))
Next
' Write the contents to a new file.
' This new file will have 1 word per line.
System.IO.File.WriteAllLines("C:\file2.txt", secondWords.ToArray())
If you are looking to examine each word, the code can become something like this:
' Read entire contents of file1.txt into an array.
Dim file1 As String() = System.IO.File.ReadAllLines("C:\file1.txt")
' Process each line.
For Each line In file1
' Process each word within the line.
For Each word In line.Split(" ")
' Do something with the word.
Console.WriteLine(word)
Next
' Or process by word index.
Dim words As String() = line.Split(" ")
For i As Integer = 0 To words.Length - 1
Console.WriteLine(String.Format("Word {0} is {1}", i + 1, words(i)))
Next
Console.WriteLine("Moving to a new line.")
Next

Error: Object Required: 'example'

Hey I have this do until loop that takes a text file made into a string ("strnotapprovedData") and then calls this function that runs a command to delete the share. I keep getting the error object required: "xxxx". How do I fix this is the problem the function the loop statement or the string.
Function:
Function DeleteThisShare(Value)
DeleteThisShare = "net share " & Share & " \DELETE"
Set objShell = CreateObject("Wscript.Shell")
Msgbox AddQuotes(DeleteThisShare)
objShell.Run DeleteThisShare
End Function
Loop Statement:
Do Until strnotapprovedData.AtEndOfStream
Dim objShare : objShare = Split(strnotapprovedData,vbCrLf)
notapprovedShares = objShare
DeleteThisShare(notapprovedShares)
Loop
String:
Dim notapprovedList, notapprovedShares
Set notapprovedList = objFSo.OpenTextFile ("C:\Users\abro\Shares_Not_Approved.txt")
Dim strnotapprovedFile, strnotapprovedData
strnotapprovedFile = ("C:\Users\abro\Shares_Not_Approved.txt")
strnotapprovedData = objFSO.OpenTextFile(strnotapprovedFile,ForReading).ReadAll
Reply to Chris Nielsen
Well I added this and the same problem still occurs
strnotapprovedData = objFSO.OpenTextFile(strnotapprovedFile,ForReading).ReadAll
Do Until objnotapprovedLines.AtEndOfStream
objnotapprovedLines = Split(Trim(strnotapprovedData),vbCrLf)
DeleteThisShare(objnotapprovedLines)
Loop
strnotapprovedData is set to a string as a result of the ReadAll method of the file system object. Since it is a string and not a stream, it will not have an AtEndOfStream property. Instead, you should split it on line breaks and loop over the resulting array.
Response to edit:
Your code does not show where objnotapprovedLines is being defined or initialized. From your usage, I presume it starts life as a stream, but I have no way to know that. However, on the first line after your DO, you overwrite it to be an array. Arrays do not have an AtEndOfStream property, so that would certainly cause the error, even if nothing else has.
Here is some untested code to try:
' Define a new variable called "notApprovedLines"
' VBScript is loosely-typed, so this could be anything at this point.
Dim notApprovedLines
' Read the contents of the file into the "notApprovedLines" variable.
' This assumes that you have a variable named "strnotapprovedFile" that
' contains the path to the file, as your example code indicates. At the
' end of this, the "notApprovedLines" variable contains the entire contents
' of the file as one giant string.
notApprovedLines = objFSO.OpenTextFile(strnotapprovedFile, ForReading).ReadAll
' Split the contents of the file into an array, so we can deal with one line at
' a time. After this, "notApprovedLines" will be an array of strings, with each
' entry representing one line of the original file.
notApprovedLines = Split(notApprovedLines, vbCrLf)
' Loop over those lines
Dim x, k, line
' This sets the upper boundary of the loop.
k = uBound(notApprovedLines)
' In VBScript, arrays start at zero. The "x" is our counter variable. Its
' value will be incremented with each iteration of the loop, so we hit the
' entries one at a time.
For x = 0 To k
' Trim whitespace away from each line. After this executes, the "line"
' variable will contain a single line from the file, as a string, without
' and leading or trailing whitespace.
line = Trim(notApprovedLines(x))
' We don't want to process blank lines, if any exist. This test lets us
' skip those. Any line that contained only whitespace would also be
' skipped here, since it's length would be zero after trimming away the
' whitespace.
If Len(line) > 0 Then
' This executes your function. I have not really proofed it very
' closely. Let's hope it works! =)
DeleteThisShare(line)
End If
Next

Reading CSV file with Streamreader getting (index of ouf range exception) on empty or wrong formated rules how to avoid

Oke so i read an CSV file with streamreader and get the exception index out of range when it reads an empty line or when the line is not in the correct format.
is there an solution that when you get this error you go to the next line of the csv file
The best approach is to avoid parsing CSV manually at all and use one of the available CSV-readers instead. For example this fast CSV-reader.
Instead of reacting on exceptions i would skip empty lines in the first place.
Instead of a StreamReader you could also use File.ReadLines with Linq:
Dim lines = From line In File.ReadLines(path)
Where line.Length <> 0
' now you can enumerate all not-empty lines '
For Each line In lines
' ... '
Next
If you insist on a Streamreader:
Using sr = New StreamReader(path)
While Not sr.EndOfStream
Dim line = sr.ReadLine()
If Not String.IsNullOrEmpty(line) Then
' ... '
End If
End While
End Using

Delete line in TXT file but keep everything else

Hey all i am trying to figure out a way to delete something inside a text file but keep everything around it.
An example of this would be:
SDfmifgn349234024jn4tnge0b04tnEFGm34tmn34t0egonkerglnk
318erg4nergpERGhmboergn4t34tmg054
fg94t34tskmsdglnEGgjr894ERG94mrg34tSDFS$45352ty
GGreerkg0gm4m505556g0fdg6555fbd105f1g
And say i wanted to delete the 318erg4nergpERGhmboergn4t34tmg054 and therefore it would turn out to be saved as:
SDfmifgn349234024jn4tnge0b04tnEFGm34tmn34t0egonkerglnk
fg94t34tskmsdglnEGgjr894ERG94mrg34tSDFS$45352ty
GGreerkg0gm4m505556g0fdg6555fbd105f1g
But i am unable to find out how to go about doing that!
I've tried this code below that i found:
Dim dir As New DirectoryInfo(defaultNetworkDrive)
For Each file As FileInfo In dir.GetFiles()
If file.Extension = ".txt" Then
Dim ioFile As New StreamReader(defaultNetworkDrive & file.Name)
Dim ioLine As String ' Going to hold one line at a time
Dim ioLines As String ' Going to hold whole file
ioLine = ioFile.ReadLine
ioLines = ioLine
While Not ioLine = ""
ioLine = ioFile.ReadLine
ioLines = ioLines & vbCrLf & ioLine
End While
MsgBox(ioLines) 'SHOWS all the lines in the TXT file
If InStr(1, ioLines, encryptedText, vbTextCompare) <> 0 Then
MsgBox("True")
Else
MsgBox("False")
End If
'Dim sw As StreamWriter = file.CreateText("input.txt")
'sw.Write(ioLines)
'sw.Close()
ioFile.Close()
End If
Next
I do find it and its TRUE but i am not sure how to go about just deleting that line then saving it!
Any help would be great! :o)
David
You have to rewrite the file. Use StreamWriter to create a temporary file. Read one line at a time and write it to the output file. Skip the write if you don't want the line. Clean up by renaming the original, renaming the temporary then deleting the renamed original.
Use something better than a text file, like a dbase, if this is too slow.
You need to check for the string to exclude inside the loop where you read the lines:
While Not ioLine = ""
ioLine = ioFile.ReadLine
If ioLine <> "318erg4nergpERGhmboergn4t34tmg054" then
ioLines = ioLines & vbCrLf & ioLine
End
End While
If ioLines.StartsWith(encryptedText) Then
MsgBox("True")
Else
MsgBox("False")
End If
You are checking if the 'file' (ioLines) starts with the encrypted text, not the line (ioLine). I suspect that's why it isn't finding it.
I'm not sure if you are intending it, but I think adding the vbCrLf to ioLines will cause an empty line between each line. So your file output would be
LINE
[empty line]
LINE
[empty line]
...
To save the file without that line, you would need to write the lines you want to save to a new file.
Read line from file
If not excluded line
write line
Something like that (obviously off the top of my head) :)
Hmm, maybe I found the answer.
You are connecting all lines together:
ioLines = ioLines & vbCrLf & ioLine
Later you are trying to find the search string, but only at the start of the combined line!
ioLines.StartsWith(encryptedText)
This would only find the encryptedText if it be appear on the very first line of the file.
In your example the relevant string is somewhere in the middle of the iolines string.
So you should try to use
ioLines.Contains(encryptedText)
instead.
Edit:
You could try to do the following (just a though, I haven't tested it)
Dim fileLines as List(Of String)
fileLines = new List(Of String)(File.ReadAllLines(yourFileNameHere))
For i as Integer = fileLines.Count To 0 Step -1
If fileLines(i).Contains(encryptedText) Then
fileLines(i).RemoveAt(i)
End If
Next
File.WriteAllLines(yourFileNameHere, fileLines.ToArray)
HTH