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

Jet.OLEDB.4.0 Truncating String When importing from CSV

我有一个 windows 表单应用程序,它接收 CSV/Excel 个文件,允许用户将它们导入 SQL 数据库。

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

这是源文件:

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

请注意,有些值完全空白并以红色突出显示,而其他值似乎被截断了。 然而,这只发生在 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  

我已经能够重现您的问题。

问题是由于某种原因,Jet 提供程序使用的文本文件驱动程序的数值为 interpreting/parsing "S00123"。我必须使用 MaxScanRows=0 和 ImportMixedTypes="Majority Type".

配置注册表

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

如果您坚持使用此技术来完成一项有更好选择的任务,那么您将不得不忍受它的许多缺点和怪癖。

解决方案 1:

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

注册表值在 64 位上的位置 OS。

对于 Jet 提供商:

Computer\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Jet.0\Engines\Text

Computer\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Jet.0\Engines\Excel

对于 ACE 提供商:

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

Computer\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Office.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,将不会读取该文件并使用注册表中的设置。