07版Excel采用Xml打包的形式展现给世人,从此我们很方便地解析excel文件了
任意一款解压工具都可以解压开一个xlsx扩展名文件,如:
WinRAR.exe x a.xls a\
这样就把excel文件"a.xls"解压成了一个a的文件夹
在xl文件夹下是这个excel文件的信息
其中
workbook.xml 是工作簿中工作表的信息
sheets节点下的sheet节点代表每一个工作表
sharedStrings.xml是excel表格中的字符串
worksheets文件夹中详细记述了每个sheet页的情况
项目中用到其他部门吐出的excel文件,这文件很大,动不动几百M的样子,ms excel可能都打不开,其中有一个Sheet页中有几百万甚至上千万行的数据,项目中已经在用的几个C++ excel组件都搞不定,那个其他部门的项目已经结项也不可能改成csv文件输出,这个难题甩给了我(作为所谓的项目版本MDE的我,必须解决这个问题,相关的功能都上了,目前灰度发布,给一个版本迭代时间两个月无论如何都得搞定),当时听说阿里有个“去IOE”,我就走上了自研excel文件解析的不归路。
老早就听说了03版以后的Excel文件乃至整个office文件都遵循OpenXML协议,大体意思就是文件格式开放了,不再是二进制文件了,各位老兄可以自己解析了,只要遵循固定的规则,都能相互打开。
毕竟心里有数,之前搞过详细调研,十多天就搞完,并封装成接口,完全遵循项目里既有的excel组件的随机存取接口规则,即类似string getCell(int row,int column)的get系列接口。
主要提供两个接口,bool load(string filePath)和get系列接口:
load:将excel文件使用7z解压到临时目录下,解析worksheets.xml,看有几个Sheet页,然后每个Sheet页创建一个文件夹,然后解析每个Sheet页的xml文件,这xml文件根据表格的大小而变化,需求方给的一个demo数据,500M的Excel只有一个Sheet页,其Sheet1.xml有3G之大;于是不能用xml的dom方式解析了,可以使用sax方式,调查了一下,sax很麻烦(这是借口)会导致代码不好读,全是一大堆回调,不好查错,自己写一套顺序读取文本文件的方式:内存中申请一段缓冲区,我定的是2M(为什么是2M,不知道啊,可能是我的吉利数字是2吧),有一个光标(即当前处理到什么位置了),将缓冲区的内容进行正则提取,然后光标移动,重复操作,当缓冲区内剩余的数据比较少了,则尾部的数据挪到缓冲区头部,光标移动至头,并将缓冲区充满,继续提取。提取出来的全是单元格的信息,有类型和数据,如果是字符串,字符串在共享字符串xml文件中;文件中本来就是按行顺序存放的,行中又是按列顺序存放的,所以当行数达到一定程度(10000行),就将当前所有行的数据序列化成一个文件,存放到Sheet页的文件夹中,依次类推,解析完后就可以调用get系列接口了
get系列:当前有一个被激活的Sheet对象,同时内存中只存放一定行的数据(10000行),当前要获取的行号是否在内存中,不在的话加载当前行所在的那10000行数据
下个月,改造业务代码,貌似那个月打了一个月酱油,简单讲头文件替换,类名改一下,项目中的excel组件叫MyExcel,我给我的自研Excel库起名为MyBigExcel,就这么简单,业务代码中类名稍加替换就OK了。后来我的自研库还活了奖,貌似100块大洋。
写到这里吧,纪念一下第一次写博文,文采略显尴尬,诸位看客别介意。