C#采用ADO.NET读取Excel 03/07 数据不完整的问题
最开始还想是不是Excel里数据格式的问题,或者是数据表的字段类型跟长度的 问题,但一一排除后,还是不得其解。于是搜之,才发现原来是因为在使用ADO.NET读取Excel表格时,OLEDB(Excel 2000-2003一般是是Jet 4.0,Excel 2007是ACE 12.0,即Access Connectivity Engine,ACE也可以用来访问Excel 2000-2003)。会默认扫面Sheet中的前几行来决定数据类型,这个行数是由注册表中
Excel 2000-2003 : HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Jet\\4.0\\Engines\\Excel Excel 2007 :
HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Office\\12.0\\Access Connectivity Engine\\Engines\\Excel
Excel 2010 :
HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Office\\14.0\\Access Connectivity Engine\\Engines\\Excel
中的TypeGuessRows值来控制,默认是8。如果前8行都是数字,那么ADO.NET扫描不会有问题; 如果前8行内的数据类型不一样,ADO.NET会采用一个通配的数据类型来匹配,通常为varchar或unicode varchar。但是如果前8行的数据都比较短小,使得ADO.NET选择匹配了varchar,那么就只能容下255个字符,而实际上却有可能是其它更 大的类型。
为了避免这种情况产生的尴尬,需要在执行Excel读取之前将
TypeGuessRows值设为0,那样Jet就会扫描最多16384行。当然,如果文件太大的话,这里就有效率问题了,不过对于当前所要处理的情况就没有问题。写了个简单的设置函数。
private void modifyTypeGuessRows(bool setDefault) {
int toSetValue = 0; if (setDefault) toSetValue = 8; try {
string Root = \"SOFTWARE\\\\Microsoft\\\\Jet\\\\4.0\\\\Engines\\\\Excel\";
RegistryKey JetRegKey = Registry.LocalMachine.OpenSubKey(Root, true);
JetRegKey.SetValue(\"TypeGuessRows\", Convert.ToString(toSetValue, 16), RegistryValueKind.DWord); JetRegKey.Close();
Root = \"SOFTWARE\\\\Microsoft\\\\Office\\\\12.0\\\\Access Connectivity Engine\\\\Engines\\\\Excel\"; JetRegKey = Registry.LocalMachine.OpenSubKey(Root, true);
JetRegKey.SetValue(\"TypeGuessRows\", Convert.ToString(toSetValue, 16), RegistryValueKind.DWord); JetRegKey.Close();
Root = \"SOFTWARE\\\\Microsoft\\\\Office\\\\14.0\\\\Access Connectivity Engine\\\\Engines\\\\Excel\"; JetRegKey = Registry.LocalMachine.OpenSubKey(Root, true);
JetRegKey.SetValue(\"TypeGuessRows\", Convert.ToString(toSetValue, 16), RegistryValueKind.DWord); JetRegKey.Close(); } catch{} }
批处理bat注册表
@echo off
reg add HKLM\\SOFTWARE\\Microsoft\\Jet\\4.0\\Engines\\Excel /v TypeGuessRows /t REG_DWORD /d 0 /f @echo off
reg add \"HKLM\\SOFTWARE\\Microsoft\\Office\\12.0\\Access Connectivity Engine\\Engines\\Excel\" /v TypeGuessRows /t REG_DWORD /d 0 /f @echo off
reg add \"HKLM\\SOFTWARE\\Microsoft\\Office\\14.0\\Access Connectivity Engine\\Engines\\Excel\" /v TypeGuessRows /t REG_DWORD /d 0 /f
这样只要在读取Excel前设置TypeGuessRows为0,读取完成后将其改回默认值8,就可以解决这一问题了。 注意,网上说采用这个方案一般还要在Excel文件连接字符串中的Extended Properties加入IMEX=1,如 strACEConn = “Provider=Microsoft.ACE.OLEDB.12.0;Data Source=” + xlsFile + “;Extended Properties=\\”Excel 12.0;HDR=NO;IMEX=1\\”;”;
strJetConn = “Provider=Microsoft.Jet.OLEDB.4.0;Data Source=” + xlsFile + “;Extended Properties=\\”Excel 8.0;HDR=NO;IMEX=1\\”;”;
但是我采用这种方法后发现,依然有些文件会发生截断现象。于是将IMEX的值改为2,如
strACEConn = “Provider=Microsoft.ACE.OLEDB.12.0;Data Source=” + xlsFile + “;Extended Properties=\\”Excel 12.0;HDR=NO;IMEX=2\\”;”;
strJetConn = “Provider=Microsoft.Jet.OLEDB.4.0;Data Source=” + xlsFile + “;Extended Properties=\\”Excel 8.0;HDR=NO;IMEX=2\\”;”;
因篇幅问题不能全部显示,请点此查看更多更全内容