New Column/Row Data for CSV - vb.net

I have a CSV file where I need to add new columns namely app_modulname, app_module.status, app_module.increment, app_module.success. This could easily be done with this lines of codes below.
Dim csvData = File.ReadLines(filename).Select(Function(line, index)
If(index = 0,
line + ",app_module.name,app_module.status,app_module.increment,app_module.success",
line + "," + moduleName & ",inactive," & index & ",")
)
File.WriteAllLines(savePath, csvData)
For the app_module.increment column, the row data are just increment numbers. The problem is that the code above is reading the line breaks. And, I use index as the increment number. is there other way to get the index of row?

I started with the following text file:
One,"First record",Primary
Two,"Second
record",Secondary
Three,"Third record",Tertiary
I executed this code:
Dim lines As New List(Of String)
Dim lineNumber = 1
Using parser As New TextFieldParser("TextFile1.txt") With {.Delimiters = {","}}
Do Until parser.EndOfData
Dim fields = parser.ReadFields()
'Add quotes around the column that may be multiline.
fields(1) = $"""{fields(1)}"""
lines.Add(String.Join(",", fields) & "," & lineNumber)
lineNumber += 1
Loop
End Using
File.WriteAllLines("TextFile1.txt", lines)
I ended up with this text file:
One,"First record",Primary,1
Two,"Second
record",Secondary,2
Three,"Third record",Tertiary,3

Related

What is the simplest way to get the second item of each row in a string file

I have a String file with 8 items (separated by commas) in each row, e.g., CA,23456,aName,aType,anotherName,aWord,secondword,number. I want to create a new string of items consisting of the 2nd item (an Integer) of each row of the original file. I know there are many ways to do this but someone out there knows how to do it with very few lines of code, which is what I am looking for. I prefer not to use a parser.
The way to show what I have tried is to look at the code below.
Dim sn2 As String = ""
Dim sn2S As String = ""
Using readFile As New StreamReader(newFile1)
Do While readFile.Peek() <> -1
sn2S = readFile.ReadLine(1)
sn2 = sn2 & sn2S & ","
Loop
End Using
The code returns the second character of each row not the second item. What I hope to get is a string that looks like: 123,1345,4325,3321,3456,3211 etc. Where each number is the second item in each row of the original file.
You could split it up by cells
Dim row As String = "CA,23456,aName,aType,anotherName,aWord,secondword,number"
Dim cells() As String = row.Split(",")
Dim cellValue As String = cells(1)
But in your case, I would just do a search and Substring by the index of the delimiter.
Dim startPosition As Integer = row.IndexOf(",") + 1
Dim endPosition As Integer = row.IndexOf(",", startPosition)
Dim cellValue As String = row.Substring(startPosition, endPosition - startPosition)
If you have the whole file in memory, there could be some regex that could do the job with one pass.
As for this line
sn2 = sn2 & sn2S & ","
You might want to check at doing a join or using stringbuilder.
You could try
Dim sn2 As String = ""
Dim sn2S(7) As String = ""
Using readFile As New StreamReader(newFile1)
Do While readFile.Peek() <> -1
Array.Clear(sn25,0,sn25.Length)
sn2S = readFile.ReadLine(1).Split(",")
sn2 = sn2 & sn2S(1) & ","
Loop
End Using
In one line
Dim sn2 = String.Join(",", File.ReadAllLines(newFile1).Select(Function(s) s.Split(","c)(1)))
From the inside-out:
File.ReadAllLines(newFile1) splits the file into lines and results in a string array holding those lines, which is fed into...
...Select(Function(s) s.Split(","c)(1)) which operates on each line by splitting the line by comma s.Split(","c) and then indexing the resulting array (1) to return the second (zero-based) element. This is fed into...
String.Join(",", ... ) which takes those second elements and joins then together with comma.

VB - Sorting Alphabetically From a CSV File

I don't know a lot about the subject of sorting but here goes: I am trying to sort a music library (comma seperated in a csv file. Some examples):
1,Sweet Home Alabame,Lynyrd Skynyrd,4:40,Classic Rock
2,Misirlou,Dick Dale,2:16,Surf Rock
I need to sort them alphabetically (by title of track) but I don't know two things: 1. Why my current technique isn't working:
Dim array() As String = {}
sr = New StreamReader("library.csv")
counter = 1
Do Until sr.EndOfStream
array(counter) = sr.ReadLine()
counter += 1
Loop
System.Array.Sort(Of String)(array)
Dim value As String
For Each value In array
Console.WriteLine(value)
Next
Console.ReadLine()
I don't know if this is the best way of sorting. I then need to display them as well. I can do this without sorting, but can't figure out how to do it with sorting.
Help please (from people who, unlike me, know what they're doing).
Right now you're putting all fields in one long string of text (each row).
In order to sort by a particular field, you'll need to build a matrix of rows and columns. For example, a DataTable.
Here's a class that should do the trick for you:
https://www.codeproject.com/Articles/11698/A-Portable-and-Efficient-Generic-Parser-for-Flat-F
Here's the sample usage code from the article, translated to VB:
Public Class CsvImporter
Public Sub Import()
Dim dsResult As DataSet
' Using an XML Config file.
Using parser As New GenericParserAdapter("MyData.txt")
parser.Load("MyData.xml")
dsResult = parser.GetDataSet()
End Using
' Or... programmatically setting up the parser for TSV.
Dim strID As String, strName As String, strStatus As String
Using parser As New GenericParser()
parser.SetDataSource("MyData.txt")
parser.ColumnDelimiter = vbTab.ToCharArray()
parser.FirstRowHasHeader = True
parser.SkipStartingDataRows = 10
parser.MaxBufferSize = 4096
parser.MaxRows = 500
parser.TextQualifier = """"c
While parser.Read()
strID = parser("ID")
strName = parser("Name")
' Your code here ...
strStatus = parser("Status")
End While
End Using
' Or... programmatically setting up the parser for Fixed-width.
Using parser As New GenericParser()
parser.SetDataSource("MyData.txt")
parser.ColumnWidths = New Integer(3) {10, 10, 10, 10}
parser.SkipStartingDataRows = 10
parser.MaxRows = 500
While parser.Read()
strID = parser("ID")
strName = parser("Name")
' Your code here ...
strStatus = parser("Status")
End While
End Using
End Sub
End Class
There's also this from here, demonstrating DataTable usage:
Dim csv = "Name, Age" & vbCr & vbLf & "Ronnie, 30" & vbCr & vbLf & "Mark, 40" & vbCr & vbLf & "Ace, 50"
Dim reader As TextReader = New StringReader(csv)
Dim table = New DataTable()
Using it = reader.ReadCsvWithHeader().GetEnumerator()
If Not it.MoveNext() Then
Return
End If
For Each k As var In it.Current.Keys
table.Columns.Add(k)
Next
Do
Dim row = table.NewRow()
For Each k As var In it.Current.Keys
row(k) = it.Current(k)
Next
table.Rows.Add(row)
Loop While it.MoveNext()
End Using
And this Q&A illustrates how to sort the DataTable by a given column.

Replacing string at certain index of Split

Using streamreader to read line by line of a text file. When I get to a certain line (i.e., 123|abc|99999||ded||789), I want to replace ONLY the first empty area with text.
So far, I've been toying with
If sLine.Split("|")(3) = "" Then
'This is where I'm stuck, I want to replace that index with mmm
End If
I want the output to look like this: 123|abc|99999|mmm|ded||789
Considering you already have code determining if the "mmm" string needs to be added or not, you could use the following:
Dim index As Integer = sLine.IndexOf("||")
sLine = sLine.Insert(index + 1, "mmm")
You could split the string, modify the array and rejoin it to recreate the string:
Dim sLine = "123|abc|99999||ded||789"
Dim parts = sLine.Split("|")
If parts(3) = "" Then
parts(3) = "mmm"
sLine = String.Join("|", parts)
End If
I gather that if you find one or more empty elements, you want to replace the first empty element with data and leave the rest blank. You can accomplish this by splitting on the pipe to get an array of strings, iterate through the array and replace the first empty element you come across and exit the loop, and then rejoin your array.
Sub Main()
Dim data As String = "123||abc|99999||ded||789"
Dim parts = data.Split("|")
For index = 0 To parts.Length - 1
If String.IsNullOrEmpty(parts(index)) Then
parts(index) = "mmm"
Exit For
End If
Next
data = String.Join("|", parts)
Console.WriteLine(data)
End Sub
Results:
123|mmm|abc|99999||ded||789

Extract characters from a long string and reformat the output to CSV by using keywords with VB.net

I am new to VB.Net 2008. I have a task to resolve, it is regading extracting characters from a long string to the console, the extracted text shall be reformatted and saved into a CSV file. The string comes out of a database.
It looks something like: UNH+RAM6957+ORDERS:D:96A:UN:EGC103'BGM+38G::ZEW+REQEST6957+9'DTM+Z05:0:805'DTM+137:20100930154
The values are seperated by '.
I can query the database and display the string on the console, but now I need to extract the
Keyword 'ORDERS' for example, and lets say it's following 5 Characters. So the output should look like: ORDERS:D:96A then I need to extract the keyword 'BGM' and its following five characters so the output should look like: BGM+38G:
After extracting all the keywords, the result should be comma seperated and look like:
ORDERS:D:96A,BGM+38G: it should be saved into a CSV file automatically.
I tried already:
'Lookup for containing KeyWords
Dim FoundPosition1 = p_EDI.Contains("ORDERS")
Console.WriteLine(FoundPosition1)
Which gives the starting position of the Keyword.
I tried to trim the whole thing around the keyword "DTM". The EDI variable holds the entire string from the Database:
Dim FoundPosition2 = EDI
FoundPosition2 = Trim(Mid(EDI, InStr(EDI, "DTM")))
Console.WriteLine(FoundPosition2)
Can someone help please?
Thank you in advance!
To illustrate the steps involved:
' Find the position where ORDERS is in the string.'
Dim foundPosition = EDI.IndexOf("ORDERS")
' Start at that position and extract ORDERS + 5 characters = 11 characters in total.'
Dim ordersData = EDI.SubString(foundPosition, 11)
' Find the position where BGM is in the string.'
Dim foundPosition2 = EDI.IndexOf("BGM")
' Start at that position and extract BGM + 5 characters = 8 characters in total.'
Dim bgmData = EDI.SubString(foundPosition2, 8)
' Construct the CVS data.'
Dim cvsData = ordersData & "," & bgmData
I don't have my IDE here, but something like this will work:
dim EDI as string = "UNH+RAM6957+ORDERS:D:96A:UN:EGC103'BGM+38G::ZEW+REQEST6957+9'DTM+Z05:0:805'DTM+137:20100930154"
dim result as string = KeywordPlus(EDI, "ORDER", 5) + "," _
+ KeywordPlus(EDI, "BGM", 5)
function KeywordPlus(s as string, keyword as string, length as integer) as string
dim index as integer = s.IndexOf(keyword)
if index = -1 then return ""
return s.substring(index, keyword.length + length)
end function
for the interrested people among us, I have put the code together, and created
a CSV file out of it. Maybe it can be helpful to others...
If EDI.Contains("LOC") Then
Dim foundPosition1 = EDI.IndexOf("LOC")
' Start at that position and extract ORDERS + 5 characters = 11 characters in total.'
Dim locData = EDI.Substring(foundPosition1, 11)
'Console.WriteLine(locData)
Dim FoundPosition2 = EDI.IndexOf("QTY")
Dim qtyData = EDI.Substring(FoundPosition2, 11)
'Console.WriteLine(qtyData)
' Construct the CSV data.
Dim csvData = locData & "," & qtyData
'Console.WriteLine(csvData)
' Creating the CSV File.
Dim csvFile As String = My.Application.Info.DirectoryPath & "\Test.csv"
Dim outFile As IO.StreamWriter = My.Computer.FileSystem.OpenTextFileWriter(csvFile, True)
outFile.WriteLine(csvData)
outFile.Close()
Console.WriteLine(My.Computer.FileSystem.ReadAllText(csvFile))
End IF
Have fun!

Textbox Hell - Delete 3 Lines, Skip 1, Repeat

I have a textbox that reads like so:
Line 1
Line 2
Line 3
**Line 4**
Line 1
Line 2
Line 3
**Line 4**
(repeats...)
How can I use VB to loop through the textbox, deleting Lines 1, 2, and 3, skipping the fourth, and repeat? Or, rather, record every fourth line into a new textarea?
I'd probably get the contents, split on the newline character to create an array of strings (one string per line), then loop through the array outputting only the ones i wanted.
If this is VB6 then bear in mind that the variable length String type is a reference type meaning that operations will involve taking a deep copy i.e. concatenation is expensive.
Dim lines() As String
lines = VBA.Split(TextBox1.Text, vbCrLf)
Dim counter As Long
For counter = 3 To UBound(lines) Step 4
lines(counter) = Chr$(22)
Next
TextBox1.Text = _
Replace$( _
Replace$( _
VBA.Join(lines, vbCrLf), _
vbCrLf & Chr$(22), vbNullString), _
Chr$(22) & vbCrLf, vbNullString, 1)
This is code for the previous answer.
Private Function EveryFourthLine(ByVal input As String) As String
Dim newtxt As String = ""
Dim oldtxt As String() = input.Split(vbCrLf)
For i As Integer = 1 To oldtxt.Count
If i Mod 4 = 0 Then
newtxt = newtxt & oldtxt(i - 1)
If i <> oldtxt.Count Then
'add a vbcrlf to all but the last line
newtxt = newtxt & vbCrLf
End If
End If
Next
Return newtxt
End Function
If this is VB.Net and you are using a Textbox - you don't need to split anything yourself. You can just access the .Lines property. You'll get back an array of strings
You certainly can loop through the rows, like others have shown; but another approach is to use LINQ to do that work for you.
txtBox1.Lines = (From curLine In txtBox1.Lines _
Where Array.IndexOf(txtBox1.Lines, curLine) Mod 4 = 3).ToArray
What you are saying here is that you want the Lines in the textbox to be equal to all of the lines that are already in the text box - as long as the index of that particular line, divided by 4 has a remainder of three.
That sounds complicated when you type it out like that, but really, all it's going to do is give you every fourth line, and set that back into the textbox.