C#读取Excel技术概览 (2)

简介:

5、自定义SDK,使用xmlReader文件流式处理

  第四章节中,总是感觉用别人的工具要受制于人。既然我 们知道了Excel的存储方式,问题便转换成从xml中取出数据,然后放入内存得到我们想要的东西,更重要的是,官方的sdk对xml的读取采用的 Document的方式,对于大文件xml执行速度必然降低,同时对 内存,数据量都有限制,若有几十亿,好几百T的数据,这种处理方式就很难发挥作用了,所以我们决定自己做一个sdk出来,只是将原来读取xml的方式,改 为用xmlReader的方式来读取,采用文件流的方式进行处理。

  就不需要将整个的xml文件树完全的读进去,而是按照流的方式进行处理,按照节点一个一个的读取,速度就会更进一步,并且不受数据量以及内存的限制。

   网上关于这样的处理的文章较多,大概整理了一下,但是都不全面,在处理的时候还会遇到很多的问题,网上给的代码也只是一个思路,碰到bug,还需要 自己去更多了解Excel到xml的转换过程到底是怎么样的,而本文将站在巨人的肩膀上,告诉你,应该注意的细节。首先还是转载下前人的文档,然后在对文 档中的问题,进行介绍,注意这些问题是必须要注意的,不然会耗费你大量的时间却找不到自己想要的结果!

 

5.1 Open XML 文件的结构

 

  最近开发的一个网页查询的项目 中,客户提供的数据是多个 Excel 2007 文件,这些文件都很大,有的有十几万行(注意:Excel 2003 文件不能超过 65,536 行)。这些 Excel 2007 文件需要定期批量转换为网页程序可以读取的专用二进制格式文件。我们知道,Microsoft Office System 2007 引入了一个新的文件格式:Office Open XML 格式。她是基于 XML 和 ZIP 归档技术创建的,可以使用任何平台的能够处理 XML 或者 ZIP 文件的工具来访问并且修改文档内容。所以我们就可以使用 Microsoft .NET Framework 2.0 的强大 XML 类库来读取 Excel 2007 文件并转换为网页程序所需的专用二进制格式文件。当然,也可以使用 System.IO.Packaging 名称空间中的类库,但是她位于 .NET Framework 3.0 SDK (WinFX) 的 WindowsBase.dll 中。微软网站上有几篇很有用的文章:“Office (2007) Open XML 文件格式简介”和“如何操作 Office Open XML 格式文档”。下面,就来看看 Excel 2007 (及以上版本) 的Open XML 文件的结构吧。

   

 

                                  解压后的文件

上图是一个名为test_file.xlsx 的 Excel 2013 文件。该文件其实是一个 zip 文件。为了分析其结构,我们现在把她解压到D:\最近下载\_Major\TEST_SETS\XLS文件解析\test_file 目录下。第一个重要的文件是 xl/workbook.xml,如下图所示:

 

该 文件中的每个“<sheet>”元素都代表 Excel 2013 文件中的一个工作表,工作表的名称就是其“name”属性的值,在上图中是“好人”和“坏人”。然后根据“<sheet>”元素“r:id” 属性的值(如上图中的“rId1”)到 xl/_rels/workbook.xml.rels 文件中寻找相应工作表数据实际存放的 xml 文件,如下图所示:

从图中可以看中,第一个工作表“好人”的数据实际存放在 worksheets/sheet1.xml 文件中,该文件的内容如下图所示:

上 图中的“<dimension>”元素的“ref”属性的值(“B4:C6”)表示该工作表的范围。

“<sheetData>”元素表示工作的数据,其子元素“<row>”表示工作表中的一行,“<row>”的子元素“<c>”表示该行中的单元格

如果“<c>”元素有“t”属性的话,“<c>”元素的子元素 “<v>”的值就是各工作表共享的字符串的索引。否则的话,“<v>”元素的值就是该单元格的值。

各工作表共享的字符串存放在 xl/sharedStrings.xml 文件中,如下图所示:

上图中,“<sst>”元素的子元素“<si>”就代表了共享的字符串,其值就是“<si>”元素的子元素“<t>”的值。

5.2 测试程序

下面就看看我们的测试程序吧:

源程序的整体结构如下图所示: