Vb.net 在数据表的列中指定数据类型

Vb.net 在数据表的列中指定数据类型,vb.net,csv,Vb.net,Csv,我正试图将一个CSV文件从个人本地机器上传到我的程序中,但我遇到了一点障碍。我有一列是数字和文本的混合,如F-23、Pool等。但是,当我上传文件时,它会将该列专门视为十进制列。我是否可以将所有列值设置为字符串类型以避免这种情况?我现在正在使用Oledb将csv上传到数据表中 将csv上载到数据表的代码如下所示 Dim conn As OleDbConnection = New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Sou

我正试图将一个CSV文件从个人本地机器上传到我的程序中,但我遇到了一点障碍。我有一列是数字和文本的混合,如F-23、Pool等。但是,当我上传文件时,它会将该列专门视为十进制列。我是否可以将所有列值设置为字符串类型以避免这种情况?我现在正在使用Oledb将csv上传到数据表中

将csv上载到数据表的代码如下所示

Dim conn As OleDbConnection = New 
OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & 
Path.GetDirectoryName(fullDir) & ";Extended 
Properties=""Text;HDR=Yes;FMT=Delimited(,);IMEX=1"";")
conn.Open()
Dim adp As New OleDbDataAdapter("SELECT * FROM [" & fileName & "]", conn)
adp.Fill(dt)
conn.Close()

使用模式文件帮助,您可以明确定义每个列类型,而不考虑内容。使用模式文件帮助,您可以明确定义每个列类型,而不考虑内容。如果您知道该列是:

让我们在这里使用人事档案的小例子

1/创建一个包含相应列的

CREATE TABLE My_Personnel(
   ID   INT              NOT NULL,
   NAME VARCHAR (50)     NOT NULL,
   AGE  INT              NOT NULL,
   ADDRESS  VARCHAR (1000) ,  
   PRIMARY KEY (ID)
);
然后您将创建一个来存储数据,如下所示:

Public Class Person
    Public Property ID As Integer
    Public Property Name As String
    Public Property Age As Integer
    Public Property Address As String
End Class
然后创建一个函数,用
TextFieldParser
提取数据:

Imports Microsoft.VisualBasic.FileIO.TextFieldParser
提取数据功能:

Public Function ExtractData(ByVal csvData As String) As List(Of Person)
    Dim result As New List(Of Person)
    Dim afile As FileIO.TextFieldParser = New FileIO.TextFieldParser(csvData)
    Dim CurrentRecord As String() ' this array will hold each line of data
    afile.TextFieldType = FileIO.FieldType.Delimited
    afile.Delimiters = New String() {","}
    afile.HasFieldsEnclosedInQuotes = True
    ' parse the actual file
    Do While Not afile.EndOfData
        Try
            Dim tempPerson As New Person
            CurrentRecord = afile.ReadFields
            tempPerson.ID = CurrentRecord(0)
            tempPerson.Name = CurrentRecord(1)
            tempPerson.Age = CurrentRecord(2)
            tempPerson.Address = CurrentRecord(3)
            result.Add(tempPerson)
        Catch ex As FileIO.MalformedLineException
            Stop
        End Try
    Loop
    Return result
End Function
只需呼叫

Dim MyPersonnel As List(Of Person) = ExtractData("C:\test.csv")
在此之后,只需创建一个函数,让MyPersonal中的每个人都将数据插入数据库

只有当您确定您的数据具有固定格式时,此操作才会起作用


在这里,我使用一个类来存储数据,以防您需要修改它或使用它。如果您只需要插入,您可以直接为提取函数中的每一行创建一个插入。如果您知道列是:

让我们在这里使用人事档案的小例子

1/创建一个包含相应列的

CREATE TABLE My_Personnel(
   ID   INT              NOT NULL,
   NAME VARCHAR (50)     NOT NULL,
   AGE  INT              NOT NULL,
   ADDRESS  VARCHAR (1000) ,  
   PRIMARY KEY (ID)
);
然后您将创建一个来存储数据,如下所示:

Public Class Person
    Public Property ID As Integer
    Public Property Name As String
    Public Property Age As Integer
    Public Property Address As String
End Class
然后创建一个函数,用
TextFieldParser
提取数据:

Imports Microsoft.VisualBasic.FileIO.TextFieldParser
提取数据功能:

Public Function ExtractData(ByVal csvData As String) As List(Of Person)
    Dim result As New List(Of Person)
    Dim afile As FileIO.TextFieldParser = New FileIO.TextFieldParser(csvData)
    Dim CurrentRecord As String() ' this array will hold each line of data
    afile.TextFieldType = FileIO.FieldType.Delimited
    afile.Delimiters = New String() {","}
    afile.HasFieldsEnclosedInQuotes = True
    ' parse the actual file
    Do While Not afile.EndOfData
        Try
            Dim tempPerson As New Person
            CurrentRecord = afile.ReadFields
            tempPerson.ID = CurrentRecord(0)
            tempPerson.Name = CurrentRecord(1)
            tempPerson.Age = CurrentRecord(2)
            tempPerson.Address = CurrentRecord(3)
            result.Add(tempPerson)
        Catch ex As FileIO.MalformedLineException
            Stop
        End Try
    Loop
    Return result
End Function
只需呼叫

Dim MyPersonnel As List(Of Person) = ExtractData("C:\test.csv")
在此之后,只需创建一个函数,让MyPersonal中的每个人都将数据插入数据库

只有当您确定您的数据具有固定格式时,此操作才会起作用


在这里,我使用一个类来存储数据,以防您需要修改它或使用它,如果您只需要插入,您可以直接为提取函数中的每一行创建一个插入

,因此,正如Mederic和Colster前面提到的,我可以简单地使用模式文件来更改特定CSV文件上读取值的方式。因此,为了做到这一点,我知道在任何上传过程中列都将保持不变,所以我创建了一个模式,并将列设置为各自的值

Dim strSchema() As String = {"[" & ofdOpenExcelSheet.SafeFileName & "]", "ColNameHeader=True", "Format=CSVDelimited", "Col1=A Text", "Col2=B Text", "Col3=C Text", "Col4=D Text", "Col5=E Integer", "Col6=""F Space"" Decimal", "Col7=""G Space"" Decimal"}
Using outFile As New StreamWriter(Path.GetDirectoryName(fullDir) & Convert.ToString("\Schema.ini"))
    For Each line As String In strSchema
        outFile.WriteLine(line)
    Next
End Using
Dim conn As OleDbConnection = New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & Path.GetDirectoryName(fullDir) & ";Extended Properties=""Text;HDR=Yes;FMT=Delimited;MaxScanRows=0;IMEX=1"";")
conn.Open()
Dim adp As New OleDbDataAdapter("SELECT * FROM [" & fileName & "]", conn)
adp.Fill(dt)
conn.Close()
' Remove schema since we don't need it.
My.Computer.FileSystem.DeleteFile(Path.GetDirectoryName(fullDir) & Convert.ToString("\Schema.ini"))

因此,正如Mederic和Colster前面提到的,我可以简单地使用模式文件来更改在特定CSV文件上读取值的方式。因此,为了做到这一点,我知道在任何上传过程中列都将保持不变,所以我创建了一个模式,并将列设置为各自的值

Dim strSchema() As String = {"[" & ofdOpenExcelSheet.SafeFileName & "]", "ColNameHeader=True", "Format=CSVDelimited", "Col1=A Text", "Col2=B Text", "Col3=C Text", "Col4=D Text", "Col5=E Integer", "Col6=""F Space"" Decimal", "Col7=""G Space"" Decimal"}
Using outFile As New StreamWriter(Path.GetDirectoryName(fullDir) & Convert.ToString("\Schema.ini"))
    For Each line As String In strSchema
        outFile.WriteLine(line)
    Next
End Using
Dim conn As OleDbConnection = New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & Path.GetDirectoryName(fullDir) & ";Extended Properties=""Text;HDR=Yes;FMT=Delimited;MaxScanRows=0;IMEX=1"";")
conn.Open()
Dim adp As New OleDbDataAdapter("SELECT * FROM [" & fileName & "]", conn)
adp.Fill(dt)
conn.Close()
' Remove schema since we don't need it.
My.Computer.FileSystem.DeleteFile(Path.GetDirectoryName(fullDir) & Convert.ToString("\Schema.ini"))

这是我一直在使用的函数,通过在for循环中插入if,您可以根据需要灵活使用:-

Public Function convert_csv_to_data_table(ByVal File As String, ByVal separator As String)
    Dim dt As New System.Data.DataTable
    Dim firstLine As Boolean = True
    If IO.File.Exists(File) Then
        Using sr As New StreamReader(File)
            While Not sr.EndOfStream
                If firstLine Then
                    firstLine = False
                    Dim cols = sr.ReadLine.Split(separator)
'down here change the cols types (they are all set as string at the moment)
'however you can change by using if's, eg. if col = "field name" then dt.Columns.Add(New DataColumn(col, GetType(DECIMAL))).
                    For Each col In cols
                        dt.Columns.Add(New DataColumn(col, GetType(String)))
                    Next
                Else
                    Dim data() As String = sr.ReadLine.Split(separator)
                    dt.Rows.Add(data.ToArray)
                End If
            End While
        End Using
    End If
    Return dt
End Function

这是我一直在使用的函数,通过在for循环中插入if,您可以根据需要灵活使用:-

Public Function convert_csv_to_data_table(ByVal File As String, ByVal separator As String)
    Dim dt As New System.Data.DataTable
    Dim firstLine As Boolean = True
    If IO.File.Exists(File) Then
        Using sr As New StreamReader(File)
            While Not sr.EndOfStream
                If firstLine Then
                    firstLine = False
                    Dim cols = sr.ReadLine.Split(separator)
'down here change the cols types (they are all set as string at the moment)
'however you can change by using if's, eg. if col = "field name" then dt.Columns.Add(New DataColumn(col, GetType(DECIMAL))).
                    For Each col In cols
                        dt.Columns.Add(New DataColumn(col, GetType(String)))
                    Next
                Else
                    Dim data() As String = sr.ReadLine.Split(separator)
                    dt.Rows.Add(data.ToArray)
                End If
            End While
        End Using
    End If
    Return dt
End Function


请您展示一个代码示例,如“是”-仅以文本形式读取文件。您可以在我的编辑中看到,我在Oledb扩展属性中没有这样做吗?啊,是的,您是。您不应该同时需要Properties=”“Text和IMEX=1。您应该只需要Properties=”“Text。话虽如此,不久前我就遇到了这个问题。如果文件是在EXCEL中更新/创建的,而不是在记事本或其他东西中,则会发生这种情况。我的解决办法是不使用Excel作为编辑器。这很公平。然而,这个CSV文件来自一个名为Revu的应用程序,它只是将选定的值导出为CSV文件。我最初尝试不使用IMEX=1,但正在阅读和搜索,人们发现它有帮助,尽管它没有。请您展示一个代码示例,如“是”中所述-仅以文本形式读取文件。您可以在我的编辑中看到,我在我的Oledb扩展属性中没有这样做吗?啊,是的。您不应该同时需要Properties=”“Text和IMEX=1。您应该只需要Properties=”“Text。话虽如此,不久前我就遇到了这个问题。如果文件是在EXCEL中更新/创建的,而不是在记事本或其他东西中,则会发生这种情况。我的解决办法是不使用Excel作为编辑器。这很公平。然而,这个CSV文件来自一个名为Revu的应用程序,它只是将选定的值导出为CSV文件。我最初尝试不使用IMEX=1,但在阅读和搜索时,人们发现它有帮助,尽管它没有。是的,我只是在阅读这个。由于我的CSV文件将被命名为各种各样的文件,我是否可以使用一个好的“一网打尽”的模式,或者我必须以编程方式动态创建一个模式?如果是后者,你有没有偶然的例子?请在提交答案之前检查一下,如果这只是一个建议,请使用评论。是的,我刚才在读这个。由于我的CSV文件将被命名为各种各样的文件,我是否可以使用一个好的“一网打尽”的模式,或者我必须以编程方式动态创建一个模式?如果是后者,你是否有任何偶然的例子?请在提交答案前检查,如果只是一个建议,请使用评论汉克作为例子!但我在这里使用了完全不同的方法,因为我现在不打算在数据库级别上操作,而只是在数据集中操作。我将在这里发布我的解决方案。您可以在dataset中执行相同的操作,创建相应的列,然后将数据加载到其中。数据集和数据库的工作原理相似。顺便说一下,这是一个很好的答案,所以我将把它标记为正确的。然而,我的朋友是这样的