Jet.OLEDB.4.0截断字符串从CSV导入时

时间:2018-03-05 22:27:28

标签: vb.net csv datatable oledbdataadapter

我有一个带有CSV / Excel文件的Windows窗体应用程序,允许用户将它们导入SQL DB。

最近,我遇到了一个奇怪的错误,用户上传了一个CSV文件,它会截断一列中的文字。

这是源文件:

Source File

以下是我的应用中的DatagridView,在将数据转换为数据表后显示相同的数据:

After Conversion

请注意,某些值完全为空,并以红色突出显示,而其他值似乎被截断。 但是,这只发生在CSV文件中,而不是excel。这让我相信这可能是一个驱动问题。

以下是将平面文件数据转换为数据表的代码:

Private Function ConvertCSVToDataTable(ByVal path As String) As DataTable
    Using con As OleDb.OleDbConnection = New OleDb.OleDbConnection()
        Try
            If System.IO.Path.GetExtension(path) = ".csv" Then
                con.ConnectionString = String.Format("Provider={0};Data Source={1};Extended Properties=""Text;HDR=YES;FMT=Delimited""", "Microsoft.Jet.OLEDB.4.0", IO.Path.GetDirectoryName(path))
                Using cmd As OleDb.OleDbCommand = New OleDb.OleDbCommand("SELECT * FROM [" & IO.Path.GetFileName(path) & "]", con)
                    Using da As OleDb.OleDbDataAdapter = New OleDb.OleDbDataAdapter(cmd)
                        con.Open()
                        da.Fill(dt)
                        con.Close()
                    End Using
                End Using
            ElseIf System.IO.Path.GetExtension(path) = ".xlsx" Then
                con.ConnectionString = String.Format("Provider={0};Data Source={1};Extended Properties=""Excel 12.0 Xml;HDR=Yes;IMEX=1""", "Microsoft.ACE.OLEDB.12.0", path)
                con.Open()
                Dim dbSchema As DataTable = con.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, Nothing)
                Dim firstSheetname As String = dbSchema.Rows(0)("TABLE_NAME").ToString
                Using cmd As OleDb.OleDbCommand = New OleDb.OleDbCommand("SELECT * FROM [" & firstSheetname & "]", con)
                    Using da As OleDb.OleDbDataAdapter = New OleDb.OleDbDataAdapter(cmd)
                        'con.Open()
                        da.Fill(dt)
                        con.Close()
                    End Using
                End Using
            End If

        Catch ex As Exception
            MessageBox.Show(ex.ToString(), "Conversion Error", MessageBoxButtons.OK, MessageBoxIcon.Asterisk)
        Finally
            If con IsNot Nothing AndAlso con.State = ConnectionState.Open Then
                con.Close()
            End If
        End Try
    End Using
    Return dt
End Function

有什么想法导致这个? 我还应该注意,我的一些用户只能导入CSV而不能导入Excel。我想出具有32位Access驱动程序的用户可以导入excel文件,而64位用户则无法导入。我让他们在这里下载驱动程序:

https://www.microsoft.com/en-us/download/details.aspx?id=23734

现在这些用户可以导入Excel,但是它们仍然存在被截断的字符串的问题。这让我相信它可能仍然是一个驱动问题。

测试数据:

Sales Order #  
US00123  
US00123  
US00123  
SG0000123 
SG0000123 
S00123
S00123
S00123
S00123  
S00123  

1 个答案:

答案 0 :(得分:1)

我能够重现您的问题。

问题是由于某种原因,Jet提供程序使用的文本文件驱动程序将“S00123”解释/解析为数值。我必须使用MaxScanRows = 0和ImportMixedTypes =“Majority Type”配置注册表。

我不知道为什么会发生这种情况,但我只是将其归因于另一种使用记录不佳的技术的乐趣。似乎任何以“S”开头,后跟数字的字段都被解释为数字。

如果你坚持使用这种技术来完成一个有更好选择的任务,那么你必须忍受它的许多缺点和怪癖。

解决方案1:

配置要导入的提供程序,并将注册表值ImportMixedTypes设置为“Text”。现在,如果您进行此更改以允许您的程序工作,您还将负责打破任何其他依赖于现有配置的代码。

64位操作系统上注册表值的位置。

对于Jet Provider:

Computer\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Jet\4.0\Engines\Text

Computer\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Jet\4.0\Engines\Excel

对于ACE提供商:

Computer\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Office\12.0\Access Connectivity Engine\Engines\Text

Computer\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Office\12.0\Access Connectivity Engine\Engines\Excel

解决方案2:

使用[Schema.ini]文件https://docs.microsoft.com/en-us/sql/odbc/microsoft/schema-ini-file-text-file-driver)定义如何使用定义的列解释文本文件。

这是使用此技术的首选方法。请注意,文件的编码非常重要;它必须位于.Net编码System.Text.Encoding.ASCIISystem.Text.Encoding.Unicode中。如果您使用其他编码,例如UTF-8,则不会读取该文件,并且将使用注册表中的设置。