数据处理之xlsx文件探秘(简单解析)

数据处理之xlsx文件探秘(简单解析)

二月 15, 2020

最近在对xlsx文件中的许多数据进行分析处理,其中一个很棘手的问题是读取出xlsx表格中的文字颜色,按照文字颜色不同进行句子的划分。

但是在python中的各种xlsx库均不支持读取单个单元格中的文字样式,只能读出当前单元格的样式。

便只能自己查文档,从底层进行分析来提取文字样式了,成功之后记录一下历程供以后参阅。

1.python库试错

对于这个问题先要找一下有没有相关的工具可以用,毕竟重复造轮子太浪费时间了,python处理xlsx的库找到了以下几个:

(1)xlwt/xlrd

这个库中xlwt是用来进行 excel 文件的存储,而xlrd是进行 excel 文件的保存,各种功能都比较基础,提供简单的数据处理功能,增删改查等,并不适应目前的需求,而且由于以前并不是用于处理xlsx文件的,比较旧,所以放弃。

(2)openpyxl

这个库目前可以很好的处理xlsx文件,并且综合了xlwtxlrd的功能,可以进行xlsx文件的读写操作,在提供xlsx文件增删改查功能的基础上还具有单元格样式查看以及其它的一些功能。

但是样式查看仅限于单元格的样式,对于单元格中文字的样式只能读取到开头文字的样式,对于其余文字的样式束手无策。虽然很好用,但只能放弃。

(3)xlwings

这个python库应该是处理xlsx功能最全的库了,大佬们总结的优点如下:

1.语法接近 VBA

2.可以用 Python 代码取代 VBA 编写宏

3.在 windows 可以用 Python 编写 Excel 用户自定义函数

4.全功能支持 Numpy Pandas matplotlib 等科学计算库

5.支持 Windows 和 MacOS

6.支持 Py2.7 Py3.3+

也就说 office 能干的事,这货都能干,但为啥这货这么强大,这是有原因的,强大的原因是因为这货就是打开微软的office来处理文件的,它不仅继承了 VB 的功能,还继承了 VB 奇慢无比的速度,甚至更慢,想想 excel 的打开速度就知道了。

xlwings库打开xlsx文件的具体流程就是打开 office ,载入xlsx文件,执行功能,关闭 office ,要是中间你忘了写 quit ,能给你分分钟开一堆 Excel 表格,而且其中要更改设置使 Excel 表格的界面不给你弹出来,如果不设置的后果就是程序在执行过程中会不停的给你弹出窗口,而且不仅你要在开始设置不弹出来,还要在结束后给它改回去,不然就会出现打开 Excel 表格时没有界面的捉急事情。

同样的如果你在执行中间有 bug 程序中断了你还要手动给设置回去,设置回去后还要记得打开任务管理器把后台开的 Excel 表格给关掉,不关下次继续给你报错,甚至有的时候还会出现文件半天不知道为什么就打不开了的灵异事件。

这种反人类的东西果断扔掉,是真的玩不来。

至此找工具的历程结束,实在找不到合适的库来进行操作。

2.xlsx结构试错

通过查询以及以前的隐写经历知道xlsx是可以解析成zip文件的,那么目前我们的目标就是从里面的xml文件中找到我们需要的信息来进行分析

通过对压缩包中文件的排查,确定了我们需要的相关信息就在xl文件夹下的sharedStrings.xml之中,于是使用xml包对其中的xml文件进行处理。

xml文件中每个<si>即为一个单元格也就是一个cell,每个<si>中的<r>即为当前单元格的一种文字样式,首先的思路是通过读取每个<r>中的内容来进行数据的分割。

当然里面我是无法区分哪一个数据是哪一列的啊,毕竟里面的东西都是混在一块的,这个问题嘛,我把除了我要处理的那一列之外的所有数据全删了2333333,我实在是太粗暴了(〃ノωノ)。

但是在处理过程中还是有问题了,因为需求是分割不同颜色的句子,有的<r>标签出现分割只是因为字号,粗细等样式不一致才出现的,这样会导致分割出现问题,于是进一步更正思路为读取<r>中的颜色样式来进行对比后再进行分割。

但是仍旧出现了问题,因为有的句段是没有颜色属性的,经过排查发现没有颜色属性的句段颜色是按照文件设置的默认颜色来进行填充的,也就是Excel表格中自动的颜色,一般默认为黑色。这里应该是读取一下默认颜色,然后在给没有颜色样式的<r>标签进行标记颜色样式,由于文件比较统一,暂时先默认黑色,还有一种情况是颜色信息中theme = 1这个,这种是根据xlsx里面预设颜色来进行设定的,预设中第一个theme的颜色为黑色,所以将该颜色也认定为黑色。

这里颜色分布的问题在写了一堆if判断之后搞定了,但是另一个问题出现了,这里的标签顺序是不一致的,研究了一下这里面的顺序是按照修改顺序来进行排序的,于是直接使用openpyxl将所有cell里无关紧要的信息改了一下。

但是神奇的事情出现了,虽然改了数据,但是个别数据的顺序并没有变,因为更新的数据会放到文件底部,那些个别数据就像大海中的礁石一样岿然不动的被推到了最前面,这就把人整懵了。

无奈之下,那咱也别试了,直接看xlsx文档研究数据结构,整体框架搞明白了什么就都好说了,这里是我从微软的文档里面扣出来的表格数据和xml文件对应图


这是一张很厉害的图。详细标明了各个xml文件之间是如何联系的

这下一目了然了,既然取巧取不了,那就刚正面,面对疾风吧,骚年!

3.xlsx文件结构解析

在这里面主要涉及到了xl文件夹下的多个xml文件,多个xml文件拼接成了完整的excle表格,就是图里面没有标出来对应的xml文件蛤,我解释一下这些东西吧。

这些缝合怪分别为: sharedStrings.xml,styles.xml,workbook.xmlworksheets中包含的以每个sheet名称命名的xml,预设样式theme文件夹下设定的xml文件

sharedStrings.xml

其主要用来记录数据,表格中的数据都在这个里面,当一个cell中的数据存在不同的样式时这里面还会存储样式信息,但是记住这里面并不包含cell的样式信息,如果里面有数据采取的样式是cell的样式这里面并不会出现这段数据的样式,所以遇到没有样式信息的数据那就别在这里面找了,去styles.xml找吧。

这里我举个栗子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<si>
<r>
<t>我是cell样式</t>
</r>
<r>
<rPr>
<sz val="18"/>
<color theme="3" tint="0.4"/>
<rFont val="宋体"/><charset val="134"/>
<scheme val="minor"/>
</rPr>
<t>我变了样式</t>
</r>
<r>
<rPr>
<sz val="10"/>
<color theme="3" tint="0.6"/>
<rFont val="宋体"/>
<charset val="134"/>
<scheme val="minor"/>
</rPr>
<t>我也有自己的个性样式</t>
</r>
</si>

这里展示的是一个cell的结构,这个一个<si>就是一个cell,一个<r>就是一种样式,第一个<r>标签中除了装有数据内容的<t>标签以外就什么都没有了,这种情况就是这些字使用的样式为cell的样式

剩下的两个<r>标签代表了其中的字使用的自定义样式,在<rPr>标签中表明了其所拥有的样式,我一开始就是在读这里面的颜色样式来进行比对,这些就是同一个cell中不同样式文字的展现逻辑。

这也是为什么把所有cell的样式都改过之后仍然会有数据的顺序不会被改变,因为这些数据采用的是cell的样式,并没有在sharedStrings.xml中更改,所以就算更改了数据样式,其在xml文件中的顺序也不会改变。

ps:最近发现有的时候并不会出现sharedStrings.xml,数据存在了sheet文件夹里面的xml中了,猜测有可能是当文件只有一个sheet的时候并不会出现sharedSing.xml,毕竟sharedString有共享字符串的意思,这个只是猜测吧,毕竟没有sharedStrings.xml的表就最近见到了一次,太忙了并没有研究。

style.xml

顾名思义,这里面存储的就是样式信息了,在excle里面有很多用来节省空间的结构和搜寻时间的结构和算法,非常多的东西是公共的,应该有使用哈希表进行搜索,格式刷的功能也许就是这么来的,直接更改style对应的文本位置就可以实现格式刷的功能了。

这里面最重要的问题就是如何保证style和文本的链接