【问题标题】:Jet.OLEDB.4.0 Truncating String When importing from CSVJet.OLEDB.4.0 从 CSV 导入时截断字符串
【发布时间】:2018-08-13 16:52:52
【问题描述】:

我有一个 Windows 窗体应用程序,它接收 CSV/Excel 文件,让用户将它们导入 SQL DB。

最近,我遇到了一个奇怪的错误,用户上传 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  

【问题讨论】:

  • 那些数据单元格远不及 255 个字符
  • 我撤回了重复投票,但这是我所知道的字符串被截断的唯一情况。您提到 64 位,但您的代码表明使用了 Jet 提供程序。 Jet 仅作为 32 位提供程序存在。 ACE 提供程序可以是 32 位或 64 位,但只安装了一个版本(是的,我看到声称允许安装 32 位和 64 位的黑客)。您是否有机会提供被截断的数据样本?即提供一个可重现的例子。
  • 我更新了它以包含被截断的测试数据。那么他们都需要32位吗?我还尝试将我的程序编译为 32 位应用程序,但没有成功。

标签: vb.net csv datatable oledbdataadapter


【解决方案1】:

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

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

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

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

解决方案一:

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

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

对于喷气机供应商:

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等其他编码,则不会读取该文件,而是使用注册表中的设置。

【讨论】:

  • 哇,谢谢你的回答。如果我不使用它,有什么更好的选择?
  • @AlanPear,对于 CSV,您可以使用 (TextFieldParser Class](msdn.microsoft.com/en-us/library/…)。对于使用 2007+ 文件格式的 Excel 文件,有多种选项:Open XML SDK(这个有学习曲线陡峭),ClosedXML 和各种商业产品。对于较旧的 xls 格式 Excel 文件,您可能需要商业产品。
猜你喜欢
  • 2017-03-24
  • 2021-12-22
  • 2018-07-01
  • 2012-01-26
  • 2015-07-08
  • 1970-01-01
  • 1970-01-01
  • 2015-11-26
  • 1970-01-01
相关资源
最近更新 更多