有没有更好的方法在Excel中指示“null”值?

时间:2011-04-21 01:07:19

标签: c# excel ado.net excel-2007 oledb

我有一个Excel 2007工作簿,其中包含使用ADO.NET导入DataTable个对象的数据表。

通过一些实验,我设法找到两种不同的方法来表明ADO.NET应该将一个单元格视为“null”:

  1. 牢房完全空白。
  2. 该单元格包含#N/A
  3. 不幸的是,这两个都存在问题:

    1. Excel中的大多数数据列都是通过公式生成的,但在Excel中无法生成导致完全空白单元格的公式。只有一个完全空白的单元格才会被视为空(空字符串不起作用)。

    2. 任何评估为#N/A的公式(由于实际查找错误或因使用NA()函数而导致)视为null。这似乎是理想的解决方案,直到我发现 Excel工作簿必须打开才能使用。一旦关闭工作簿,OLEDB就会突然开始将所有#N/A视为字符串。这会导致在填充DataTable时抛出以下异常:

        

      输入字符串的格式不正确。无法存储< #N / A>在值列中。预期的类型是Int32。

    3. 问题:当我填写DataTable时,如何通过Excel公式指示空值而不必须打开工作簿?或者,即使工作簿已关闭,还可以将#N/A值视为null?

      如果重要,我的连接字符串是使用以下方法构建的:

      var builder = new OleDbConnectionStringBuilder
      {
          Provider = "Microsoft.ACE.OLEDB.12.0",
          DataSource = _workbookPath
      };
      builder.Add("Extended Properties", "Excel 12.0 Xml;HDR=Yes;IMEX=0");
      return builder.ConnectionString;
      

      _workbookPath是工作簿的完整路径。)

      我已经尝试了IMEX=0IMEX=1,但没有区别。

1 个答案:

答案 0 :(得分:6)

你正在遇到许多非常沮丧的Excel用户正在经历的问题。遗憾的是Excel作为一种公司工具很普遍,看起来非常强大,不幸的是因为每个单元格/列/行都有一个变体数据类型,这使得它成为处理MySQL,SQL Server,R,RapidMiner,SPSS等其他工具的噩梦。列表继续。 Excel 2007/2010似乎得不到很好的支持,当考虑32/64位版本时更是如此,这在当今时代是一个可耻的。

主要问题是,当ACE / Jet访问Excel中的每个字段时,他们使用注册表设置“TypeGuessRows”来确定用于评估数据类型的行数。 “要扫描的行”的默认值为8行。注册表设置'TypeGuessRows'可以指定从一(1)到十六(16)行的整数值,或者您可以指定零(0)来扫描所有现有行。如果您无法更改注册表设置(例如在90%的办公环境中),那么生活很困难,因为要猜测的行数限制在前8行。

例如,没有注册表更改 如果#N / A的第一次出现在前8行内,则IMEX = 1将错误返回为字符串“#N / A”。如果IMEX = 0,则#N / A将返回'Null'。

如果第一次出现#N / A超出前8行,则IMEX = 0& IMEX = 1都返回'Null'(假设所需的数据类型是数字)。

随着注册表更改(TypeGuessRows = 0),那么一切都应该没问题。

也许有4种选择:

  1. 更改注册表设置TypeGuessRows = 0

  2. 将前8行中所有可能的类型变体列为“虚拟数据”(例如备注字段/ nchar(最大)/错误#N / A等)

  3. 更正Excel中的所有数据类型异常

  4. 不要使用Excel - 非常值得考虑!

  5. 修改 只是为了启动:)另外两件真让我烦恼的事情是;如果工作表上的第一个字段在前8行中是空白而您无法编辑注册表设置,那么整个工作表将返回为空白(许多有趣的对话告诉管理员他们是合并单元格的傻瓜!)。此外,如果在Excel 2007/2010中您有一个部门返回一个包含> 255列/字段的工作表,那么如果您需要非连续导入(例如col 1中的键和cols 255+中的数据),则会出现大问题。