OleDbConnection仅在Excel中打开工作簿时查找单元格值

时间:2014-09-12 19:19:24

标签: c# excel ssis oledb

我有一个程序(实际上是SSIS脚本任务,但我不认为这很重要)创建了与Excel工作簿的OLE DB连接,并读取每个工作表中的单元格值,将它们存储在SQL Server中表

每个工作表都有几个行部分,每个部分用于单独的产品。每个产品部分的前两行是四分之一行和一年。这是一个屏幕截图:

enter image description here

我使用 OleDbDataReader 和"选择*"命令将每个工作表中的数据读入DataTable。我有一个名为" YearQuarter"在我的SQL数据库中,我存储了年份行值和前一个季度行值的串联,并在两个字符串之间加了一个连字符:

enter image description here

我的代码是这样的:

  OleDbConnection oleExcelConnection = new OleDbConnection(
        "Provider=Microsoft.ACE.OLEDB.12.0;" +
        "Data Source=" + strWkbkFilePath + ";" +
        "Mode=Read;" +
        "Extended Properties=\"Excel 8.0;HDR=No;IMEX=1\"");

   oleExcelConnection.Open();

   DataTable dtCurrSheet = new DataTable();

   // Name of table is in strLoadTblNm.

    OleDbCommand oleExcelCommand;
    OleDbDataReader oleExcelReader;

    oleExcelCommand = excel_conn.CreateCommand();
    oleExcelCommand.CommandText = "Select * From [" + strLoadTblNm + "]";
    oleExcelCommand.CommandType = CommandType.Text;
    oleExcelReader = oleExcelCommand.ExecuteReader();

    // Load worksheet into data table
    dtSheet.Load(oleExcelReader);

    oleExcelReader.Close();

查看输出数据,我注意到我的结果不一致。某些行的YearQuarter列值只包含Year行值,而其他行则具有两行的单元格值。例如,我有" 2009年 - 年终"只有" 2010",没有" - 1st Qtr。"附加到它。

这是因为数据集可视化器显示的那个四分之一单元格值永远不会加载到数据读取器中:

enter image description here

另请注意,在数据集中,缺少Quarter单元格值的列还有其他数字值缺少其格式(无逗号)。

如果我将文件保存为.csv,则会保留所有单元格值。

然而,我注意到它并不一致。有时我会运行我的包,同一行现在将具有完整的值。所以,在上面的例子中,我得到了" 2010年 - 第一个Qtr。"

我终于意识到,只有当我在程序运行的同时在Excel中打开工作簿 时,才按预期工作

为什么会有所作为?可能是Excel中执行的工作簿中有一个宏,但是只有通过OLE DB连接才能访问工作簿时?它是否已在Excel中执行然后会影响OLE DB获取的数据吗?如果是这样的话,我该如何解决这个问题呢?电子表格提供给我。所以我无法修改它们。

2 个答案:

答案 0 :(得分:2)

我认为您在Excel尝试应用的自动格式化问题上遇到了问题。使用OLEDB连接,我无法看到如何打开表单来解决您的问题(显然非常奇怪)。

尝试将IMEX = 1添加到您的连接选项,将整个工作表视为文本,以查看这是否是您的问题。从OLEDB connection does not read data from excel sheet拉出来自外部网站的另一篇优秀帖子:Tips for reading Excel spreadsheets using ADO.NET

此外,您还要从Excel工作表中提取数据并将其写入另一个Excel工作表...相同的工作簿?根据你的情况,我还有一些想法。

答案 1 :(得分:1)

这个错误原来是一个“功能”,它应该带有一个很大的警示标志。

This article(谢谢,@ vb4all)解释说“ADO.NET扫描前8行数据,并根据它,猜测每列的数据类型。然后尝试将该列中的所有数据强制转换为该数据类型,强制失败时返回NULL !“

换句话说,它将工作表视为关系表,其中给定列中的所有值都是相同类型。当然,工作表数据不受此限制的约束。

可以通过在连接字符串选项中设置 IMEX = 1 然后修改这些注册表设置来解决此问题:

HKEY_LOCAL_MACHINE /软件/微软/喷射/ 4.0 /发动机/ Excel中/ ImportMixedTypes

HKEY_LOCAL_MACHINE /软件/微软/喷射/ 4.0 /发动机/ Excel中/典型值

(注意:注册表项因32位与64位而异。例如,对于64位,第一个是HKEY_LOCAL_MACHINE \ SOFTWARE \ Wow6432Node \ Microsoft \ Jet \ 4.0 \ Engines \ Jet 4.0)。

我认为这是一个非常冒险的设计,会引起很容易被忽视的数据传输错误。