ado和odbc读取excel总结

来源:互联网 发布:知乎如何盈利 编辑:程序博客网 时间:2024/06/05 02:06

      因为项目需要,最近在做一个读取excel的工具,最开始是把excel转成tab分割的txt文本,然后当做文本文件来读取,然后有人嫌转换太麻烦,要求直接读excel,没办法,整!

      我只尝试了ado和com两种方式,过程中也遇到很多的问题,所以决定总结下供需要的人参考。这里不详细说明读取的方法,这些在msdn都能查到,只说说在调用过程中我碰到的一些麻烦事。

      因为读取的表格过多,我没有采用绑定表格的方式,只是采用最简单的前滚(forwardonly)的方式读出来即可。

1 excel驱动

      因为我的电脑上刚好装了2003和2007两个版本的excel,所以我两种都尝试了。

      2007驱动的优点就是它能识别excel表格中设置的单元格格式,如果没有设置单元格格式,驱动就根据该列所填的数据来判断,如果设置了,就根据实际设置的格式来读取。

      而excel97-2003貌似不行哦(这点我只尝试了数值和字符两种类型,所以不太确定),不管我是否在某列设置单元格格式,驱动都是按照自己的判断来读取的。比如某列我设置单元格格式为字符,可是前8列填的是数值,驱动读出来以后还是会认为这一列是数值,并且后面的字符都会因为不是数值读不出来。


2 表格中的数据类型

在详细说下数据类型的问题,如果没有定义单元格格式的话,excel默认的单元格格式是常规,这时excel的驱动扫描表格中每列的前8个数据来猜测该列的数据类型,扫描的数据行数可以自行在windows的注册表中更改:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Jet\4.0\Engines\Excel

更改TypeGuessRow这个参数。

如果TypeGuessRow的值为默认值8,毕竟不是每台电脑都能随便让你改注册表的,就有可能会出现问题,如果某列的前8行都没有数据呢?或者某一列实际是字符,可是前8行刚好需要以数字的形式表现字符,可是驱动就会把该列当做数值类型,如果后面再出现字符数据,驱动不能识别,就会认为该单元格为空。这点让我查了好久,明明有数据,为什么读不出来呢???

我的解决办法是把整个表的单元格格式偷设置成字符型,这样填表的人就不需要区分填的是字符还是数字,然后把读出来的字符数据转换成自己需要的类型。(仅用于2007驱动)


还有对于数字和字符混合的列,使用odbc也需要指定单元格格式,否则就会读错。而使用ado只需要在open的操作里加上IMEX=1

“Provider=Microsoft.Jet.OLEDB.4.0;Data Source=tableName;Extended Properties=\"Excel 8.0;HDR=Yes;IMEX=1\"”

这样驱动就会把混合的单元格都通通当做字符串处理


3 超过255的字符串截断

使用odbc的函数

void GetFieldValue( short nIndex, CStringA& strValue )

来读取excel,读取字符串的最大长度是256,超过的就会被截断。

因为CRecordSet 用来存储表头的结构 CODBCFieldInfo的成员m_nPrecision表示该列的精度,貌似它假定字符串都是在256以内的。不过还好这个数据我们是可以修改的,通过下面的方式:

rset.m_rgODBCFieldInfos[index].m_nPrecision = 1024;

rset是一个CRecordSet对象,index是需要修改长度的列。

修改了以后再读,发现还是被截断,再找原因,发现这个也和odbc扫描每列的前8行来判断数据类型和数据大小有关,如果前8行的字符长度都在256以内,驱动就认为该列字符的最大长度为256,即使后面有超过256的也只读取256个。

这个也可以通过修改前面说的注册表的TypeGuessRow这个参数来解决。可是因为我这个工具的使用对象不只我一个,我不能跑去人家每台电脑上修改注册表,所以放弃了。

如果是绑定的从CRecordSet继承表,可以参考下面的办法:

 http://support.microsoft.com/kb/125727/zh-cn

可是因为我要读取的表格很多,所以也没有绑定

我采取了一个很烂的办法,就是把表格的第一行用来占位,把长度可能超过255的列的第一行都填一个超大字符串进去,然后驱动就能扫描到我这列是需要超大空间的了,哇哈哈~~然后在读取数据的时候,第一行给忽略掉


而使用ado来读超过256的单元格时,超过256后面的部分不是被截断,而是变成了乱码,即使把excel该列第一行的数据改成超过256的字符都不行,还没有找到破的方法


参考:

http://hi.baidu.com/sky_lixf/item/8ca62a07b5894e17acdc70a8

http://sharedderrick.blogspot.tw/2012/02/excel-null-typeguessrows-imex.html