VB.NET - Replace column value in text file that is space delimited - vb.net

I am trying to run a vb.net script from SSIS to perform the following in a space delimited text;
Loop through all files in directory (I've already coded this using .GetFiles)
Within each text file loop through each line within the file
Replace/Insert a value in the line
Save the file
I'm struggling to come up with a method to replace/insert a value. I do not believe this is possible with ReadLines and my searches haven't turned up any solutions for my situation. All of the solutions I'm finding recommend using .split, but since this file is text delimited and column sizes vary, .split and .replace will not work.
Any ideas? Here is an example of a line from the text file and where I want to insert the value;
WMS0104 N00011 800171548-1 20190221 OVPRC <INSERT VALUE HERE> PRINTER13 000000000000000000000000000000010000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000 2019022108511300 00000000000000 00000000000000001

Got it
Dim BeforeWH_ID, ExistingWH_ID, AfterWH_ID, DesiredWH_ID, NewLineRecord As String
DesiredWH_ID = "034 "
Dim lines() As String = IO.File.ReadAllLines(ExportFilePath)
'Loop through each line in the array
For i As Integer = 0 To lines.Length - 1
'Fill line variables
BeforeWH_ID = Mid(lines(i), 1, 215)
ExistingWH_ID = Mid(lines(i), 215, 32)
AfterWH_ID = Mid(lines(i), 247, 377)
NewLineRecord = BeforeWH_ID & DesiredWH_ID & AfterWH_ID
'Compare WH_ID
If ExistingWH_ID <> DesiredWH_ID Then
'Replace the line in the array
lines(i) = NewLineRecord
Else
'Keep the line in the array
lines(i) = lines(i)
End If
'Reset Variables
BeforeWH_ID = Nothing
ExistingWH_ID = Nothing
AfterWH_ID = Nothing
NewLineRecord = Nothing
Next
'Overrite existing file with line array
IO.File.WriteAllLines(ExportFilePath, lines)

Related

Gettint text from lastline in richtextbox

I want to copy the last line of a rich textbox.
I am avoiding Dim lastLine As String = RichTextBox1.Lines(RichTextBox1.Lines.Length - 1)as
it's not working properly, as It works just if there are atleast 2 lines in it.
I'm trying with MsgBox(RichTextBox1.Lines(UBound(richtextbox1.Lines))) but the problem is that even if the richtextbox has just 1 line of text but the cursor is in the second empty line, it will give back "" as I think the software is reading the empty 2nd line.
There is a solution to that?
Thanks
This will get the last non-empty line:
RichTextBox1.Lines.Where(Function(line) line <> String.Empty).Last()
There are some potential issues with that. If there's no text at all or if there are multiple lines but they are all empty, that will throw an exception. To allow for that, you can call LastOrDefault instead, in which case it would return Nothing.
If you only want to exclude the last empty line, e.g. if you have some text followed by a line break and then another line break then you want to get the first of those two empty lines, then you can't really do it in one line:
Dim lines = RichTextBox1.Lines
Dim upperBound = lines.GetUpperBound(0)
Dim lastLine = lines(upperBound)
If lastLine = String.Empty Then
If upperBound > 0 Then
lastLine = lines(upperBound - 1)
Else
lastLine = Nothing
End If
End If
'Use lastLine here.

Converting .txt file directly into an array with custom delimiter

I am converting a .txt file directly into an array in excel VBA. The default delimiter is a "," (comma) and I need to change it to "vblf". I am having trouble figuring out how to do that with the code I have today.
Please help
Const strFileName As String = [file]
Dim CONFIGTXT(1 To 13000) As String
Dim intFileNum As Integer
Dim intCount As Integer
Dim strRecordData As String
intFileNum = FreeFile
intCount = 1
Open strFileName For Input As #intFileNum
Do Until EOF(intFileNum) Or intCount > 13000
Input #intFileNum, strRecordData
CONFIGTXT(intCount) = strRecordData
intCount = intCount + 1
Loop
Close #intFileNum
Range("Q2:Q" & UBound(CONFIGTXT) + 1) = WorksheetFunction.Transpose(CONFIGTXT)
Change
Input #intFileNum, strRecordData
to
Line Input #intFileNum, strRecordData
Input is intended to read in data that is comma-delimited, one variable at a time. For example, if you had data of
12345,789
and used the statement
Input #intFileNum var1, var2
then var1 would be given the value 12345 and var2 would be given the value 789.
Line Input is intended to read a line at a time, delimited by the new line character (normally CR/LF).
Note: If your data has information separated by line feeds, this will NOT separate those portions into separate entries in the array. So if your data contains
xxx/xxx/xxx
where the / is actually a line feed, that entire record will be placed into one cell in the final output.

How to Read first x characters of each line of a text file

HI have a Program that loops through a text file and reads the lines.
Using r As StreamReader = New StreamReader("C:\test.txt")
Dim lineCount = File.ReadAllLines("C:\test.txt").Length
MsgBox(lineCount)
For x = 1 to linecount
line = r.ReadLine
msgbox (line)
next
How can I read the Left most 15 characters of each line of the text file, ignoring the other characters in each line. Lastly, if there are spaces in the first 15 characters, i'd like to remove them.
Calling ReadAllLines to discover how many lines are there to drive a for..loop is wrong and a waste of resources (Essentially you are reading all the file content two times). In particular consider that a StreamReader has a method that tells you if you have reached the end of file
So everything could be changed to a simpler
Dim clippedLines = new List(Of String)()
Dim line As String
Using r As StreamReader = New StreamReader("C:\test.txt")
While r.Peek() >= 0
line = r.ReadLine
Dim temp = if(line.Length > 15, line.Substring(0,15), line)
clippedLines.Add(temp.Trim().Replace(" "c, ""))
End While
End Using
This will remove all the spaces from the line AFTER taking the first 15 char (and thus the result could be a string shorter than 15 chars) If you want a line of 15 char after the space removing operation, then
While r.Peek() >= 0
line = r.ReadLine.Trim().Replace(" "c, "")
Dim temp = if(line.Length > 15, line.Substring(0,15), line)
clippedLines.Add(temp)
End While

How to insert a text into text file using VBA

I want to insert a string at a particular position in text file of "utf-8" format.
let say the content in the file is "12367890"
now i want to insert "45" after "3" i.e at position 3,
now the content in the file becomes "1234567890"
I wrote some piece of but it is not working
dim str as string
Dim binaryObj As Object
str = "12367890"
Set binaryObj = CreateObject("adodb.stream")
binaryObj.Open
binaryObj.Charset = "UTF-8"
binaryObj.Type = 2
h = 0
For h = 0 To length
jpByte = Mid(jpString, h + 1, 1)
binaryObj.WriteText jpByte
Next
binaryObj.WriteText ChrW(0)
binaryObj.Position = 6
binaryObj.WriteText "4"
binaryObj.Position = 7
binaryObj.WriteText "5"
binaryObj.SaveToFile "D:\A4\Message_tool\withBom.bin", adSaveCreateOverWrite
Instead of inserting 4 and 5, these are gettin replaced with 6 & 7.
output = "12345890"
As you may have guessed, "WriteText" overwrites the text at that position, rather than inserting. Instead, write everything up until the new character insertion point (after the "3"), write the "4" and "5", then output the rest.
You may find it easier to read the file into a string, then manipulate the string with the built-in string functions, then output to the file, instead of manipulating text files.
You can create a temp file with the modified text and replace this existing file. Here is a proof of concept.
Public Sub TextFileModify()
Dim fso As New FileSystemObject
Dim text As String, line As String, temp As String
Dim path As String, fs As TextStream, fs2 As TextStream
'First create a text file with original content
path = fso.BuildPath(fso.GetSpecialFolder(2), "textfile.txt")
Set fs = fso.CreateTextFile(path, True)
fs.WriteLine "12367890"
fs.WriteLine "other stuff"
fs.Close
'Now open the file to replace a line of text
temp = fso.BuildPath(fso.GetSpecialFolder(2), fso.GetTempName())
Set fs = fso.OpenTextFile(path, ForReading)
Set fs2 = fso.CreateTextFile(temp)
While Not fs.AtEndOfStream
If fs.line = 1 Then
line = fs.ReadLine
fs2.WriteLine Left(line, 3) & "45" & Mid(line, 4)
Else
fs2.WriteLine fs.ReadLine
End If
Wend
fs.Close
fs2.Close
'New delete old file and replace with new file
fso.DeleteFile path
fso.MoveFile temp, path
' textfile.txt now contains "1234567890" in the first line and the rest of the file is identical
End Sub
Notes:
You have to add a reference to the Microsoft Scripting Runtime (per. Example here)
fso.GetSpecialFolder(2) returns the path to your temp folder.
fso.GetTempName() returns a filename like radA5FC8.tmp

Start reading massive text file from the end

I would ask if you could give me some alternatives in my problems.
basically I'm reading a .txt log file averaging to 8 million lines. Around 600megs of pure raw txt file.
I'm currently using streamreader to do 2 passes on those 8 million lines doing sorting and filtering important parts in the log file, but to do so, My computer is taking ~50sec to do 1 complete run.
One way that I can optimize this is to make the first pass to start reading at the end because the most important data is located approximately at the final 200k line(s) . Unfortunately, I searched and streamreader can't do this. Any ideas to do this?
Some general restriction
# of lines varies
size of file varies
location of important data varies but approx at the final 200k line
Here's the loop code for the first pass of the log file just to give you an idea
Do Until sr.EndOfStream = True 'Read whole File
Dim streambuff As String = sr.ReadLine 'Array to Store CombatLogNames
Dim CombatLogNames() As String
Dim searcher As String
If streambuff.Contains("CombatLogNames flags:0x1") Then 'Keyword to Filter CombatLogNames Packets in the .txt
Dim check As String = streambuff 'Duplicate of the Line being read
Dim index1 As Char = check.Substring(check.IndexOf("(") + 1) '
Dim index2 As Char = check.Substring(check.IndexOf("(") + 2) 'Used to bypass the first CombatLogNames packet that contain only 1 entry
If (check.IndexOf("(") <> -1 And index1 <> "" And index2 <> " ") Then 'Stricter Filters for CombatLogNames
Dim endCLN As Integer = 0 'Signifies the end of CombatLogNames Packet
Dim x As Integer = 0 'Counter for array
While (endCLN = 0 And streambuff <> "---- CNETMsg_Tick") 'Loops until the end keyword for CombatLogNames is seen
streambuff = sr.ReadLine 'Reads a new line to flush out "CombatLogNames flags:0x1" which is unneeded
If ((streambuff.Contains("---- CNETMsg_Tick") = True) Or (streambuff.Contains("ResponseKeys flags:0x0 ") = True)) Then
endCLN = 1 'Value change to determine end of CombatLogName packet
Else
ReDim Preserve CombatLogNames(x) 'Resizes the array while preserving the values
searcher = streambuff.Trim.Remove(streambuff.IndexOf("(") - 5).Remove(0, _
streambuff.Trim.Remove(streambuff.IndexOf("(")).IndexOf("'")) 'Additional filtering to get only valuable data
CombatLogNames(x) = search(searcher)
x += 1 '+1 to Array counter
End If
End While
Else
'MsgBox("Something went wrong, Flame the coder of this program!!") 'Bug Testing code that is disabled
End If
Else
End If
If (sr.EndOfStream = True) Then
ReDim GlobalArr(CombatLogNames.Length - 1) 'Resizing the Global array to prime it for copying data
Array.Copy(CombatLogNames, GlobalArr, CombatLogNames.Length) 'Just copying the array to make it global
End If
Loop
You CAN set the BaseStream to the desired reading position, you just cant set it to a specfic LINE (because counting lines requires to read the complete file)
Using sw As New StreamWriter("foo.txt", False, System.Text.Encoding.ASCII)
For i = 1 To 100
sw.WriteLine("the quick brown fox jumps ovr the lazy dog")
Next
End Using
Using sr As New StreamReader("foo.txt", System.Text.Encoding.ASCII)
sr.BaseStream.Seek(-100, SeekOrigin.End)
Dim garbage = sr.ReadLine ' can not use, because very likely not a COMPLETE line
While Not sr.EndOfStream
Dim line = sr.ReadLine
Console.WriteLine(line)
End While
End Using
For any later read attempt on the same file, you could simply save the final position (of the basestream) and on the next read to advance to that position before you start reading lines.
What worked for me was skipping first 4M lines (just a simple if counter > 4M surrounding everything inside the loop), and then adding background workers that did the filtering, and if important added the line to an array, while main thread continued reading the lines. This saved about third of the time at the end of a day.