Reputation: 57
I'm trying to import a CSV file into a DataGridView but I'm running in some issues when I try to import multiline text.
What I'm trying to import is this:
ID;RW;Name;Description;Def;Unit;Min;Max
0;R;REG_INFO;"state of the
machine";0;ms;0;0xFFFF
1;R/W;REG_NUMBER;current number;0;days;0;65,535
This is what it should like when imported:
What I've implemented till now:
Private Sub btnOpen_Click(sender As Object, e As EventArgs) Handles btnOpen.Click
Using ofd As OpenFileDialog = New OpenFileDialog() With {.Filter = "Text file|*.csv"}
If ofd.ShowDialog() = DialogResult.OK Then
Dim lines As List(Of String) = File.ReadAllLines(ofd.FileName).ToList()
Dim list As List(Of Register) = New List(Of Register)
For i As Integer = 1 To lines.Count - 1
Dim data As String() = lines(i).Split(";")
list.Add(New Register() With {
.ID = data(0),
.RW = data(1),
.Name = data(2),
.Description = data(3),
.Def = data(4),
.Unit = data(5),
.Min = data(6),
.Max = data(7)
})
Next
DataGridView1.DataSource = list
End If
End Using
End Sub
But I run in some problems with multiline text when I try to load the CSV, as "state of the machine" in the example.
Upvotes: 1
Views: 1001
Reputation: 32248
An example, using the TextFieldParser class.
(This class is available in .Net 5)
The TextFieldParser object provides methods and properties for parsing structured text files. Parsing a text file with the TextFieldParser is similar to iterating over a text file, while using the ReadFields method to extract fields of text is similar to splitting the strings
TextFieldType = FieldType.Delimited
C
in CSV
), so you need to pass the delimiter symbol(s) to the SetDelimiters() method.Imports Microsoft.VisualBasic.FileIO
Public Class RegisterParser
Private m_FilePath As String = String.Empty
Private m_delimiters As String() = Nothing
Public Sub New(sourceFile As String, delimiters As String())
m_FilePath = sourceFile
m_delimiters = delimiters
End Sub
Public Function ReadData() As List(Of Register)
Dim result As New List(Of Register)
Using tfp As New TextFieldParser(m_FilePath)
tfp.TextFieldType = FieldType.Delimited
tfp.SetDelimiters(m_delimiters)
tfp.ReadFields()
Try
While Not tfp.EndOfData
result.Add(New Register(tfp.ReadFields()))
End While
Catch fnfEx As FileNotFoundException
MessageBox.Show($"File not found: {fnfEx.Message}")
Catch exIDX As IndexOutOfRangeException
MessageBox.Show($"Invalid Data format: {exIDX.Message}")
Catch exIO As MalformedLineException
MessageBox.Show($"Invalid Data format at line {exIO.Message}")
End Try
End Using
Return result
End Function
End Class
Pass the path of the CSV file and the set of delimiters to use (here, just ;
).
The ReadData()
method returns a List(Of Register)
objects, to assign to the DataGridView.DataSource
.
DefaultCellStyle.WrapMode is set to True
, so multiline text can actually wrap in the Cell (otherwise it would be clipped).
After that, call AutoResizeRows(), so the wrapped text can be seen.
Dim csvPath = [The CSV Path]
Dim csvParser = New RegisterParser(csvPath, {";"})
DataGridView1.DataSource = csvParser.ReadData()
DataGridView1.Columns("Description").DefaultCellStyle.WrapMode = DataGridViewTriState.True
DataGridView1.AutoResizeRows()
Register
class:
Added a constructor that accepts an array of strings. You could change it to Object()
, then add a converter to the class to parse and convert the values to another Type.
Public Class Register
Public Sub New(ParamArray values As String())
ID = values(0)
RW = values(1)
Name = values(2)
Description = values(3)
Def = values(4)
Unit = values(5)
Min = values(6)
Max = values(7)
End Sub
Public Property ID As String
Public Property RW As String
Public Property Name As String
Public Property Description As String
Public Property Def As String
Public Property Unit As String
Public Property Min As String
Public Property Max As String
End Class
Upvotes: 2