【问题标题】:Is there a better way to indicate "null" values in Excel?有没有更好的方法在 Excel 中指示“空”值?
【发布时间】:2011-04-21 01:07:18
【问题描述】:

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

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

  1. 单元格完全空白。
  2. 单元格包含#N/A

不幸的是,这两个都是有问题的:

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

  2. 任何计算结果为#N/A 的公式(由于实际查找错误或由于使用了NA() 函数)被视为空值。这似乎是理想的解决方案,直到我发现必须打开 Excel 工作簿才能使其工作。关闭工作簿后,OLEDB 突然开始将所有 #N/As 视为字符串。这会导致在填充 DataTable 时抛出如下异常:

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

问题:如何在填写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 我都试过了,但没什么区别。

【问题讨论】:

  • 我真的看不到这个问题?您可以修改公式吗?
  • @Cilvic,对不起,你是对的。我加一个。
  • @Cilvic,是的,我绝对可以编辑公式。我需要知道的是什么公式结果将为空。一旦知道这一点,我就可以在需要 null 的任何时候编辑公式以生成该值。
  • @Civic 之后对空值的评估是什么,这使得它们变得必要?是否有生成#N/A 值的现有公式的示例?
  • 您也可以尝试保留空字符串 =IF(A1="","",A1)

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


【解决方案1】:

您遇到了许多非常沮丧的 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(max)/errors #N/A 等)

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

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

编辑: 只是把靴子放进去:) 另外两件事让我很恼火;如果工作表上的第一个字段在前 8 行中为空白并且您无法编辑注册表设置,则整个工作表将返回为空白(许多有趣的对话告诉经理他们是合并单元格的傻瓜!)。此外,如果在 Excel 2007/2010 中,您有一个部门返回一个包含 >255 列/字段的工作表,那么如果您需要非连续导入(例如第 1 列中的键和 255+ 列中的数据),您将遇到巨大的问题

【讨论】:

  • +1,谢谢。我想我已经能够通过在填充 Excel 数据之前将我的数据库的模式导入到DataTable 中来避免整个“使用前 8 行问题猜测数据类型”。但是,这并不能解决 null 问题。我提出了一个使用 com interop 的解决方案,它似乎为我提供了所需的速度和灵活性。到目前为止,它实际上比我的 OLEDB 解决方案更快。最后,我现在坚持使用 Excel,因为它非常适合我所做的工作(我的所有同事都在使用它),但肯定还有改进的余地。
  • 小心.. 使用模式很好,是正确的做法,但从 ACE/Jet 返回的数据/记录集不一定与您定义的模式匹配。
  • 是的...我想我在想的是,通过使用模式,至少会引发异常以指示 Excel 确定的数据类型不正确。也就是说,使用互操作而不是 OLEDB 可以完全避免这个问题。
  • 如果您有一个标准模板正在使用,一个肮脏的解决方法可以在未来提供帮助,那就是创建一个 VBA Workbook_BeforeClose 事件并将数据作为值粘贴到命名/隐藏的导入表中,并替换所有包含#.
猜你喜欢
  • 1970-01-01
  • 2017-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多