以前我对Word/Excel这类文件的结构很感兴趣,一直想了解它是如何存贮数据的,但苦于找不到相关的资料,而且听说它的文件结构也相当复杂,我等无法理解,因此这种想法也一直是个悬念而已. 随着时代发展, 这些二进制格式的文档由于生成和提取信息都很困难, 影响到了Office在网络时代的数据再利用, Office在2007版之后引进了docx和xlsx等新一代基于XML格式的文档之后,慢慢的这些格式也被用户接受了.原来的版本也日趋老去,微软也在网上开始公开这些过去的二进制的文件结构了. 感兴趣的朋友可以访问 Office文件格式规范 Office文件格式规范 链接2 了解Excel二进制文件格式 了解Word二进制文件格式 因为二进制文件格式使用了大量的结构记录,数据的读取与指针记录大小位置偏移等关系密切,一旦某处代码有错,二进制数据很容易越界,影响前后部分的读写, 生成的文件很容易出错.因此对这类文档的读写要求很高的精确性,实现起来不容易.
在新一代的文档格式中,本质上大部分都是文本形式的XML文档,而且各个部分是按一定规则分离存储的,一个部件损坏不会导致全部数据失效,文件的强壮程度好了很多.比如在Excel的XLSX格式中, 整个文档是一个压缩包,里面包括了多个部分.有的存贮数值,有的存贮样式,有的存贮查询表,有的存贮共享字串.各自有一定的独立性.比如本文中要实现的条件格式,它在文档中和表格的数据就是分开存贮的. 单元格数据在
本文涉及的文件在此,由于本博客系统的代码排版很丑, 有兴趣的可以看以下位置的PDF或PNG图片:
链接:https://pan.baidu.com/s/1Zhs42hD_RJhLza3Rky9EZg
提取码:hiu8
我们先来看看Excel的XLSX文件的结构,这里举例的文件使用上一博客中生成的sampledata.xlsx, 为了便于查看结构,将后缀xlsx改为zip再查看:
在xl目录下的workbook.xml存放的是指向表单的引用,大概内容如下:
...
...
...
用三个不同的r:id属性代表了三个不同名字的表单. 同一目录下, 还有一个styles.xml里放的是样式的规定,这个后面再讲.
我们转到worksheets目录下看:
有三个XML文件,sheet1.xml到sheet3.xml对应三个工作表.其中sheet1.xml存放了我们导入的数据. 为了例于理解条件格式,我把这个文件中相关性不大的部分省略了,留下了部分导入的数据以及生成好的条件格式的部分.,并增加了一些注释. 数据导入的部分,其格式前一博客说过这里不再重复.重点讲条件格式的描述.
...
...
...
...
...
...
前面的博客中将xml数据转化为excel文件时,我用了"硬编码"的方式处理异常数据的显示.比如,先判断一下酸度数值是不是大于50,如果大于50则将数值的格式用rPr元素来指定(这种也称为直接样式化),指定了某个单元格的数值显示为红色.
这种转化判断的逻辑要写在XSL的语法中, 实现起来不太灵活,. 既然Excel已经提供了条件格式这样便利的工具,我们何不直接用它来处理呢? 因此,我将转换数据的XSL进行精简, 去除了导入时对数值的逻辑判断(减少了一大堆冗长的xsl:choose/ xsl:when xsl:otherwise),再生成一个条件格式部分,让Excel载入后自己根据条件格式设定异常值的显示效果.
以下为了突出条件格式的生成, 精简了之前展示过的数据导入的内容.
...
...
...
...
...
...
最后还剩下一个dxfId是什么东西没有说. 是这样的: Excel中为了减少存贮各种格式设置的空间占用, 建立了一套套样式的全集, 每个样式在对应的集合中都有编号. 用到了哪一项,就用一个属性存贮一下这个索引值. 需要用的时候就按索引找来使用即可. 这些样式都存在压缩包的目录xl下style.xml文件中. 与这个相关的部分我掏出来加上注释如下:
看到这些,你就可以知道(Excel也是),条件格式指定为dxfId=2,就该用上面第3项的字体样式和填充样色来突出显示了.
如果需要研究这些规范,可以查阅SpreadsheetML的schema(以下压缩包中的sml.xsd)
链接:https://pan.baidu.com/s/1nHAfAFx8RBxcN-dY1pfpfw
提取码:sche