从Excel导入到数据集时,为列值插入NULL

我正在导入excel数据到我的应用程序中的数据表,并面临一些特定列值的问题。

excel表单列CustomerUniqID中的某些单元格显示angular落中带有绿色标记的警告。

该号码格式化为文本或在撇号之前。

从Excel工作表填充数据集时,这些单元格值不会导入并显示空白值。

Dim query As String = "SELECT CINT(CustomerUniqID),[Status] FROM [Sheet1$]" Dim conn As New OleDbConnection(conStr) If conn.State = ConnectionState.Closed Then conn.Open() End If Dim cmd As New OleDbCommand(query, conn) Dim da As New OleDbDataAdapter(cmd) Dim ds As New DataSet() da.Fill(ds) 

我的连接string是

 <add name ="Excel07ConString" connectionString="Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties='Excel 12.0;HDR=YES;IMEX=2'"/> 

CustomerUniqID列包含数字,我无法导入这些单元格的值。 这个怎么做 ?

唯一能让它失败的方法就是在原文中所描述的是,如果转义/文本单元比我最初testing的更低。 OleDB不会使用Schema.ini与Excel文件,因为这将允许一个非常干净和简单的解决scheme,唉…

使用的示例数据:

 Country Capital Population Rank France Paris 2.25 7 Canada Toronto 2.5 6 Egypt Cairo 10.2 9 ... 

它实际上使用了16行,最后3个“Rank”项目被转义为文本(例如'2 )。 这些都显示在Excel中的绿色警告标志。

由于OleDB不读取/使用模式,它决定了前N行(在我的registry中定义为8)的每列的数据types。 当转义的单元格不匹配时,它将返回一个DBNull值。 尝试通过SQL( CIntVal )转换列失败,因为在应用转换之前OleDB已经确定数据不匹配。

在某些情况下,我会两次阅读表格。 首先将适当的数据types的“好”列放到一个DataTable ; 然后再次获取“脏”列作为文本和手动转换数据。 这在数据集中有其他数字列的情况下非常有用,您不希望它们转换为文本/string。

对于发布的案例,如果实际上只涉及2列,则应该可以使用一个以文本forms读入的表格; 并添加一个数字列来接收转换的值。 而不是从一个表转换到另一个表,从一列转换到另一个。 (只要问,如果你想要一个例子,但它只是以下的一个子集)。

无论哪种情况,“技巧”都是使用不同的连接string来迫使OleDB以文本forms读取数据。 显然这两个HDR=NoIMEX=1是至less需要我的configuration:

 Dim TextConStr = "Provider=Microsoft.ACE.OLEDB.12.0; Data Source=C:\Temp\capitals.xls;Extended Properties='Excel 8.0;HDR=NO;IMEX=1';" 

这个例子/文本代码使用2表格方法来validation其他数字( Population )没有转换,只是Rank

 ' ConStr to allow OleDB to guess the datatypes Dim TypedConStr = "Provider=Microsoft.ACE.OLEDB.12.0; Data Source=C:\Temp\capitals.xls;Extended Properties='Excel 8.0;HDR=Yes;IMEX=2';" ' ConStr to force OleDB to read it all as Text Dim TextConStr = "Provider=Microsoft.ACE.OLEDB.12.0; Data Source=C:\Temp\capitals.xls;Extended Properties='Excel 8.0;HDR=NO;IMEX=1';" ' get the typed columns into a DT - skip Rank as dirty column Dim SQL = "SELECT Country, Capital, Population FROM [Capitals$]" Using con As New OleDbConnection(TypedConStr), da As New OleDbDataAdapter(SQL, con) dsPop.Tables.Add("Pop") da.Fill(dsPop.Tables("Pop")) End Using ' create a new temp DT containing just the naughty column ' use the generic F/Field index in the SQL (we told Ole there was no header) SQL = "SELECT F4 As RankText FROM [Capitals$]" ' create connection forcing the contents to text: Using con As New OleDbConnection(TextConStr), da As New OleDbDataAdapter(SQL, con) dsPop.Tables.Add("RankText") da.Fill(dsPop.Tables("RankText")) End Using ' remove the header row dsPop.Tables("RankText").Rows.RemoveAt(0) 'create a new INT col in Dt(0) dsPop.Tables("Pop").Columns.Add("Rank", GetType(Int32)) ' convert Tbl(1) text to Int and store in Tbl(0) For n As Integer = 0 To dsPop.Tables(1).Rows.Count - 1 dsPop.Tables("Pop").Rows(n).Item("Rank") = Convert.ToInt32(dsPop.Tables("RankText").Rows(n).Item(0).ToString) Next 'optional: remove the [RankText] tbl since we are done with it dgv.DataSource = dsPop.Tables("Pop") ' report the datatype of the last row rank: tbDataType.Text = dsPop.Tables("Pop").Rows(14).Item("Rank").GetType.ToString 

在即时窗口中,报告的types如预期的那样:

 ? dspop.Tables("Pop").Rows(0).Item(2) ' (population - paris) 2.25 {Double} ? dspop.Tables("RankText").Rows(0).Item(0) ' temp table text "7" {String} ? dspop.Tables("Pop").Rows(0).Item(3) ' converted, merged value 7 {Integer} 

对我来说,OleDB自动将'3 "3"转换为"3" 。 换句话说,当它转换为文本时,省略了前导的刻度/撇号。 由于Excel版本和OleDB.ACE和OleDb.Jet的组合可能会有很多可能性,所以我们可能需要一个回退转换器(在我意外地向Excel中添加了反向标记后,我写了这个转换器,可能对某人有用) :

 Private Function GetNumericValue(s As String) As Integer ' ToDo add exception handling If Char.IsDigit(s(0)) Then Return Convert.ToInt32(s) Else Return Convert.ToInt32( New String(s.ToCharArray(1, s.Length - 1)) ) End If End Function 

它只会检查一个非数字的第一个字符,否则它可能会将"1234 Main Street Suite 56"转换为123456 ,这可能是不可取的。 结果:

在这里输入图像描述
俄罗斯,日本和葡萄牙是把Rank数据作为文本转义出来的行。

资源:

  • Excel连接string
  • Excel值返回为NULL使用DAO
  • IMEX条目MSDN msg板
  • ConnectionStrings.com条目关于IMEX

我熟悉你所说的这个错误,“数字被格式化为文本或在撇号之前”。 有一个应用程序,我用我的工作,将所有的数据存储为文本值,当我导出到Excel每个数字字段发生这种情况。 它与数据的基础types有关。 如果你input一个数字(例如123)到一个单元格(或者甚至是一个数据库)中并不重要。 重要的是它被解释为的types。 所以123 <>“123”(这是一个string)。 问题很可能是您要加载数据的数据库具有数字types的字段(例如int),但导入数据的程序不会将其识别为数字,而是文本值; 因此正在抛出NULLS来弥补。

但是,在某些情况下,这是好的,例如,这些数字中的任何一个都是否为前导零? 如果是这样,您将想要将它们存储为文本值以保留前导零。 如果没有,解决方法是(在Excel 2010中)转到数据选项卡=>文本到列,然后运行向导以获取正确的数据types。 这基本上parsing的价值观。 如果其他所有内容都正确加载,看起来问题不在于您的连接。 这应该可以直接在Excel中修复。

我以前遇到过这个问题,唯一的办法可以解决这个问题,就是将单元格转换为数字,而不是格式化的菜单! 我做了像下面的图像

在这里输入图像说明

请看这个链接 ,希望它有帮助

你的问题是数据访问excel。 喷气发动机通过前8个(或类似的)行解释列数据。 所以,如果前8个单元格(不包括标题)是数字,则喷气引擎将为该列假设一个数字types。 每个跟数据types不匹配的单元格都是NULL

你可以在这里find更多的信息: 我需要一个解决Excel猜数据types的问题

该问题可能是由于您试图将非数值转换为整数值。 对于expression式,如果我们使用下面的expression式:= CInt(“ABC”),我们会得到报告中的#Error值。

请参考下面的自定义代码来解决这个问题:

 Public Function Conv(ByVal A as String) Dim B as string Dim C as Integer If isnumeric(A) Then C=CInt(A) Return C else B=CStr(A) Return B End If End Function