IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> 用 Python 轻松实现批量多层级嵌套 Excel 转 Word - 十分钟干完一个月的活 -> 正文阅读

[Python知识库]用 Python 轻松实现批量多层级嵌套 Excel 转 Word - 十分钟干完一个月的活

相关文件

想学Python的小伙伴可以关注小编的公众号【Python日志】
有很多的资源可以白嫖的哈,不定时会更新一下Python的小知识的哈!!

前言

把 Excel 转换成 Word 格式的文档大家肯定都干过吧?是不是十分的枯燥无味而且浪费时间?
你可能在想:用 Excel 、Word 转换器啊!是啊,对于普通的 Excel 文档来说,这可能是个好方法。但是,如果是一个数据很多并且存在着很多人为设定的查看规则呢?普通的转换器碰上这种高度定制化的 Excel 就显得无能为力了。

项目描述

用文字表述不清,各位看图吧。

编辑
在这里插入图片描述
在这里插入图片描述

看懂要怎么看这张表了嘛……
整张表分三个 Sheet ,每个 Sheet 下存储一种数据。而这三个 Sheet 中的数据是相互关联的。例如,第一张图里的设备编号是引用的第二张图里的设备,第一张图里每一个检测对象都属于 A 列的大类别编号所对应的大类别……
不仅如此,整张表还有层级关系。对于 Sheet 1,有着三级或更多的层级嵌套。别说机器了,就是人也不能一下子明白这张表咋看。
这还不够,转换出来的 Word 还有四种不同的形式,虽然有两份是大同小异的,但剩下的可都不太一样。
然而,这表的数据量还大到离谱 —— 转换出来的 Word 文档最少也得一百页,多的甚至上千页。这要是人干,恐怕肝是要爆啊……

开发历程

读取 Excel

既然接下了这个活,那肯定得干啊。先看看怎么用 Python 读写 Excel 吧。
一开始以为 openpyxl 就可以解决问题,但仔细一看这是 Excel 2003 的工作簿…… 没办法,只能转用 xlrd 和 xlwt 。
读取的过程还是比较愉快的,但期间我还是掉了不少头发……
首先,是怎么设计这个存储结构。因为最终的文档是以大类别作为一级标题的,且嵌套等级太多,我构思了好久才搞出来这个读取器。
最终,我把读取出来的数据转换为 JSON 文件,方便后续生成器进行二次读取。

生成 Word

现在最困难的事情到了。我在网上搜索了一圈后,发现了 python-docx 这个 Word 操作库。
幸运的是,python-docx 支持 Word 内表格的各种操作,没有必要再自己鼓捣了。
在看完不那么好懂的英文文档后,我一气呵成,做出了生成器的第一个版本。
我兴奋的运行了起来,在跑了一个小时之后,我发现了事情的不对劲:为啥跑这么久啊喂!
果断加上进度条再次运行,结果:
在这里插入图片描述
好家伙七个小时还让不让人活啦!不行,必须优化!

多进程

根据我爬虫的思路,一旦什么东西跑的太慢,那就用多进程 / 多线程优化!
研究库的底层实现
在有了多进程的失败过后,我又查看了一遍日志。而这次,我发现了一个很重要的信息!
每次执行一开始的时候,速度是非常快的,但是越往后,速度就越慢。而且变慢的速度是飞速的。
这就让我想起了指数爆炸。难道有一个深层递归在暗中执行?
我翻遍了官方文档,没有发现一句有关性能的提示。我决定深入看看 python-docx 的底层实现。
在 table.py 中找到 Table 类很容易,于是我就挨个函数地看源代码。这一看不要紧,关键是很多我认为是 O(1) 的方法,实际实现其实是 O(n) 的!怪不得慢。
但是那也不应该这么慢呀。继续往下看,一切都是那么的正常,直到我看到了 _cells 函数。

@property
def _cells(self):
    """
    A sequence of |_Cell| objects, one for each cell of the layout grid.
    If the table contains a span, one or more |_Cell| object references
    are repeated.
    """
    col_count = self._column_count

    cells = []
    for tc in self._tbl.iter_tcs():
        for grid_span_idx in range(tc.grid_span):
            if tc.vMerge == ST_Merge.CONTINUE:
                cells.append(cells[-col_count])
            elif grid_span_idx > 0:
                cells.append(cells[-1])
            else:
                cells.append(_Cell(tc, self))
    return cells

不想多说啥了,找到原因了。这个如此频繁使用的函数,复杂度竟然是 O(n^2) 的!小规模数据还不要紧,数据量一大,几万几万的数据写到表格里,_cells 函数的遍历次数也越来越多,执行时间也越来越长。
一个 8000 行的表格数据,写入到 Word 里可能变成 10000 行左右。这意味着什么?这意味着这段代码将会遍历整个表格!10 * 10000 的数据可能看起来没有那么可怕,但运行次数一多了,时间耗费就会非常大。
其实库的开发者这样做也是为了保证 merged cells 的正确性。但是,就是太耗时了……
知道了问题的源头,我就去 GitHub 上寻找答案。最终,我在 python-docx 的官方仓库中找到了 这个 Issue 。Issue 中有人说,一个 150 * 8 的表格需要 60 秒来创建。看来找对地方了。幸运的是,Issue 的发起者给出了一个 可行的解决方案 。但是,这个临时方案并不支持有合并单元格需求的表格。
很明显,我这个表格用不了这个方案。但是,既然有了一个样例,我可以照猫画虎嘛!
于是,我加上了我自己做的临时缓存。一开始的效果还不错,速度保持在每秒处理 5 行左右。但是跑了半个小时之后,速度又开始急速下降:每 5 秒处理一行。

这说明什么?

  1. 我的缓存方案有效
  2. 它还不够有效
  3. 我需要更有效的方案

继续优化

仔细思考一下就能知道,如果我们不能减少执行这个循环的次数,那就缩小循环范围呀!缩小循环范围,就是让我们的表格变小呀!
实现方式很简单,就是每隔一会就切断当前表格,建立一个新的。
但是,因为生成的表格中有很多合并的单元格,所以很难直接分开。最终,在实现难度和速度的综合考量下,我选择了在每个合并长度最大的单元格合并完成时拆分表格。
再次运行程序,哇!简直神速!原来跑一天不完的程序,现在只需要十分钟就可跑完!
最终,我得到了一个大小高达 674 KB 的 Word 文件(页数太多电脑短时间加载不完了)!
在这里插入图片描述

Victory!

UI 界面

总不能给用户用命令行吧……
我用 Flask 快速搭建了一个 API ,并部署到了云平台上可供前端调用。
前端方面我使用了 React + Next.js + Mantine 的技术架构,简单做了一个前端 UI 。
在这里插入图片描述

于是,这个项目的搭建就到此告一段落了。

想学Python的小伙伴可以关注小编的公众号【Python日志】

有很多的资源可以白嫖的哈,不定时会更新一下Python的小知识的哈!!

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2022-02-22 20:32:43  更:2022-02-22 20:33:50 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 23:32:40-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码