在 DataGridView 的引号中导入带有逗号和多行文本的 CSV 文件

Import CSV file with comma and multiline text in quotes in a DataGridView

我正在尝试将 CSV 文件导入到 DataGridView 中,但在尝试导入多行文本时我运行遇到了一些问题。

我要导入的是:

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

导入后应该是这样的:

到目前为止我实现了什么:

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

但是我 运行 在尝试加载 CSV 时遇到多行文本的一些问题,例如示例中的“机器状态”。

一个例子,使用TextFieldParser class.
(此 class 在 .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

  • 您的数据源是定界(非固定长度)结构,header/fields 值由符号分隔,因此您可以指定 TextFieldType = FieldType.Delimited
  • 分隔符不是逗号(CSV中的C),所以您需要将分隔符传递给SetDelimiters()方法。
  • 调用 ReadFields() 将每一行提取为字符串数组,代表字段的值(=> 此处不执行任何转换,所有值都作为字符串返回。在中创建您自己的类型转换器以防万一。)

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

传递 CSV 文件的路径和要使用的分隔符集(此处仅 ;)。
ReadData()方法returns一个List(Of Register)对象,赋值给DataGridView.DataSource.

DefaultCellStyle.WrapMode 设置为 True,因此多行文本实际上可以在单元格中换行(否则会被剪裁)。
之后,调用AutoResizeRows(),这样就可以看到换行的文字了。

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:

添加了一个接受字符串数组的构造函数。您可以将其更改为 Object(),然后将转换器添加到 class 以解析并将值转换为另一种类型。

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