我有一个Excel 2007工作簿,其中包含使用ADO.NET导入DataTable
个对象的数据表。
通过一些实验,我设法找到两种不同的方法来表明ADO.NET应该将一个单元格视为“null”:
#N/A
。不幸的是,这两个都存在问题:
Excel中的大多数数据列都是通过公式生成的,但在Excel中无法生成导致完全空白单元格的公式。只有一个完全空白的单元格才会被视为空(空字符串不起作用)。
任何评估为#N/A
的公式(由于实际查找错误或因使用NA()
函数而导致)将视为null。这似乎是理想的解决方案,直到我发现 Excel工作簿必须打开才能使用。一旦关闭工作簿,OLEDB就会突然开始将所有#N/A
视为字符串。这会导致在填充DataTable时抛出以下异常:
输入字符串的格式不正确。无法存储< #N / A>在值列中。预期的类型是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=0
和IMEX=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种选择:
更改注册表设置TypeGuessRows = 0
将前8行中所有可能的类型变体列为“虚拟数据”(例如备注字段/ nchar(最大)/错误#N / A等)
更正Excel中的所有数据类型异常
不要使用Excel - 非常值得考虑!
修改强> 只是为了启动:)另外两件真让我烦恼的事情是;如果工作表上的第一个字段在前8行中是空白而您无法编辑注册表设置,那么整个工作表将返回为空白(许多有趣的对话告诉管理员他们是合并单元格的傻瓜!)。此外,如果在Excel 2007/2010中您有一个部门返回一个包含> 255列/字段的工作表,那么如果您需要非连续导入(例如col 1中的键和cols 255+中的数据),则会出现大问题。