Workbook globals里就记录了整个Workbook公用的东西,比如格式,字符串常量,文档保护等。worksheets,workbook globals都是存储在Workbook Stream里,可以把它们看做是substream。各个substream按一定顺序出现在Workbook Stream里,如下图所示:
图中所示,Globals Substream是必须的,而且至少保护一个Sheet Substream。那么这些Substream是如何区分开的,如何知道一个Substream从文件的哪个位置开始,哪里结束呢?这得从BIFF8描述信息所采用的格式来说。这里说的"信息",包含很多,比如格式信息,位置信息,文本信息,图片信息,宏代码信息,等等。这么多信息要记录,BIFF8是采用Record的方式来记录的。一个Record描述一个信息。因此有很多种Record。因此Record Type肯定是Record数据结构的组成部分。Record是不定长的,种类非常多,各个种类的内容格式千差万别。但是基本遵循如下的结构:
结构包含两部分,Record Header和Record Data。Record Header部分的前2字节是Record Type,然后是2字节描述Record Data的长度。文档给出了几乎所有的Record Type,针对每种Record,描述了Record Data里各字节的含义。Substream的开始和结束,就是采用BOF和EOF这两个Record Type。也就是说在Workbook Stream是Record序列,一个Record接着一个Record,有些BOF的record表示接下来要描述一个Substream了。因此处理程序可以一个Record一个Record的读取,先检查读入的Record的Type,如果不认识,那么就不处理Record data部分,如果认识就解析Record data部分的含义。Excel的版本是不断升级的,补丁是不断更新的,新的版本,新的build就可能有新的Record Type。因此旧版本的Excel打开高版本的xls文件,有些Record就无法识别,但是不影响基本数据的读取。FastExcel就是根据这个原理,只处理一些和文本内容相关的必需的Record Type,像格式之类的Record就不处理了,因此就Fast了。
当一个Cell的内容为字符串常量时,BIFF8一般把这个字符串常量用SST这种Record记录在Global Substream,然后在Sheet Substream里使用LabelSST这种Record引用这个字符串。LabelSST这种Record的Record Data部分就包含了行号,列号,字符串索引号(index)等信息。查看文档,可知LabelSST类型的Record Header的Identifier是00FD(hex),size是10,Record data结构如下图所示:
FastExcel的项目主页也说了它们只实现了如下的Parser来处理一些Record,仅仅是针对文本内容,BIFF8的Record类型可是几百个。这里的BOFParser就是处理BOF类型的Record,LabelSSTParser处理LabelSST类型的Record。
* BOFParser
* EOFParser
* BoundSheetParser
* SSTParser
* IndexParser
* DimensionParser
* RowParser
* LabelSSTParser
* RKParser
* MulRKParser
* LabelParser
* BoolerrParser
* XFParser
* FormatParser
* DateModeParser
* StyleParser
* MulBlankParser
* NumberParser
* RStringParser
BIFF8里多字节数据,比如4字节整数,2字节整数,Unicode都是采用Little-Endian的存储方式。
以上内容,转载自:
没有评论:
发表评论