python-docx模块是处理word的利器,希望通过调用模块生成预定格式的文件,word本身自带的模板使用不太方便,而工作中对文档格式要求很高(~~)

借助一个富文本编辑器,可以将文档内容输出为word,存在几类问题,

  • 字体大小、字号、加粗等,这些直接调用styles即可实现,python-docx对字体支持还是很完善,

  • 另外一个问题是段落间距问题,折腾了一天在抓狂的状态下终于解决,原因还是因为对xml原理不熟悉

以下介绍不改变原文件的方法,修改间距为“行”“自动”的方法:


1.如果段间距是以“磅”作为单位,那么对应的python中即是Pt单位,通过以下直接对读出的段落进行修改:

pars=doc1.paragraphs
for par in pars:if par.style.name=="Heading 1":par.paragraph_format.space_before = Pt(0)par.paragraph_format.space_after =Pt(0)

也可以使用doc.styles["Heading 1"]进行类修改,网上资料较多,修改pt值即可实现段前断后间距;


2.如果段间距是以“行”作为单位,pydocx模块内置不能识别该格式,导致失效。

用xml查看会发现spacing设置“1行”的参数名称:

<w:spacing w:beforeLines="100" w:afterLines="100"/>

而源码文件parfmt.py中class CT_Spacing(BaseOxmlElement)只定义了四种类型:after,before,line,lineRule,虽然在word中看到的段前断后选1行和选1磅仍然在同一个框中,但是实际的数据类型已经是另外的了。所以要对pydocx源码进行修改。

2.1在oxml/text/parfmt.py的CT_Spacing新增两种类型:afterLines和beforeLines

class CT_Spacing(BaseOxmlElement):"""``<w:spacing>`` element, specifying paragraph spacing attributes such asspace before and line spacing."""after = OptionalAttribute('w:after', ST_TwipsMeasure)before = OptionalAttribute('w:before', ST_TwipsMeasure)line = OptionalAttribute('w:line', ST_SignedTwipsMeasure)lineRule = OptionalAttribute('w:lineRule', WD_LINE_SPACING)afterLines = OptionalAttribute('w:afterLines', ST_TwipsMeasure)beforeLines = OptionalAttribute('w:beforeLines', ST_TwipsMeasure)

2.2在parfmt.py修改spacing_after和spacing_before函数

    def spacing_after(self):"""The value of `w:spacing/@w:after` or |None| if not present."""spacing = self.spacingif spacing is None:return Noneif spacing.afterLines is not None:return spacing.afterLinesif spacing.after is not None:return spacing.after@spacing_after.setterdef spacing_after(self, value):if value is None and self.spacing is None:returnif self.spacing.afterLines is not None:self.get_or_add_spacing().afterLines = valuereturnif self.spacing.after is not None:self.get_or_add_spacing().after = valuereturn@property

一个是子函数,一个是设置参数,设置需要调用子函数,所以都要改。

  • 首先判断spacing是不是空
  • 接着判断是否有行参数,如果有则返回行参数或者修改行参数
  • 如果行参数不存在,则按原来的pt等值进行修改

(到这猜测pydocx为什么没声明这种类型,国内用的word可能是微软针对国内word再加工,国外的统一用pt等度量值,可能没行单位,或者就是pydocx有需要优化的地方)

spacing_before也用同样道理修改:

    def spacing_before(self):"""The value of `w:spacing/@w:before` or |None| if not present."""spacing = self.spacingif spacing is None:return Noneif spacing.beforeLines is not None:return spacing.beforeLinesif spacing.before is not None:return spacing.before#return spacing.before@spacing_before.setterdef spacing_before(self, value):if value is None and self.spacing is None:returnif self.spacing.beforeLines is not None:self.get_or_add_spacing().beforeLines = valuereturnif self.spacing.before is not None:self.get_or_add_spacing().before = value@property

2.3这样可以试一下读一个采用1行间距的值大小

读出的值应该是63500,而一个1磅的值应该是6350,差了10倍。

解决了“行”的问题,本来以为可以愉快玩耍了,但是遇到了下一个问题,“自动”


3.行间距为“自动”的间距设置

有些富文本编辑器导出的行间距沿用上一段或者沿用一种style的模板,所以行间距在word中显示自动,用上面改行的方法,对自动行虽然读出值是显示改了,但是实际效果并没有改,但是不怕,因为通过2已经大概了解ms的套路。

3.1同样用xml查看“自动”行

<w:spacing w:before="100" w:beforeAutospacing="1" w:after="100" w:afterAutospacing="1"/>

很明显,又多了一个beforeAutospacing类型,而且value值是1,所以推断它是一种布尔变量。

3.2在parfmt.py的CT_Spacing中再增加两个类型,最终:

class CT_Spacing(BaseOxmlElement):"""``<w:spacing>`` element, specifying paragraph spacing attributes such asspace before and line spacing."""after = OptionalAttribute('w:after', ST_TwipsMeasure)before = OptionalAttribute('w:before', ST_TwipsMeasure)line = OptionalAttribute('w:line', ST_SignedTwipsMeasure)lineRule = OptionalAttribute('w:lineRule', WD_LINE_SPACING)afterLines = OptionalAttribute('w:afterLines', ST_TwipsMeasure)beforeLines = OptionalAttribute('w:beforeLines', ST_TwipsMeasure)beforeAutospacing=OptionalAttribute('w:beforeAutospacing', ST_TwipsMeasure)afterAutospacing = OptionalAttribute('w:afterAutospacing', ST_TwipsMeasure)

3.3spacing_after和spacing_before的修改

当我们要调整格式的时候,显然不希望间距是自动,所以删除这种类型最好,但是找了几分钟get_or_add_spacing这个函数在pydocx中信息较少,只有个相关方法的注册,再继续研究又会陷入另外一个坑,所以转换一下思路。

既然修改的时候肯定不是自动,那么就保留它,而把布尔值设为0,另外再新增需要的间距值就行。

所以不用管子函数函数,只用改“设置”的那个函数,在设置间距之前先将“自动”赋0,所以after和before的修改如下:

    def spacing_after(self, value):if value is None and self.spacing is None:returnself.spacing.beforeAutospacing=Noneself.spacing.afterAutospacing = Noneif self.spacing.afterLines is not None:self.get_or_add_spacing().afterLines = valuereturnif self.spacing.after is not None:self.get_or_add_spacing().after = valuereturn@property
    def spacing_before(self, value):if value is None and self.spacing is None:returnself.spacing.beforeAutospacing=Noneself.spacing.afterAutospacing = Noneif self.spacing.beforeLines is not None:self.get_or_add_spacing().beforeLines = valuereturnif self.spacing.before is not None:self.get_or_add_spacing().before = value@property

将自动强制设为None.

3.4测试

将word找个行调整为自动或者X行,python程序设为Pt(0),运行一下,发现完美实现间距为0。

检查:将word导出为xml,结果发现,将beforeAutospacing,afterAutospacing两个变量设置为None后,xml实际删除了auto的变量类型,最终也实现了我想要的结果。


终于又可以愉快的玩耍了。

还有一个思路是打开原WORD,读出paragraph列表了之后,用循环将内容复制到另外一个word,用add_paragraph来设置间距、字体等。但是因为我有图有表,段落列表、图列表和表格列表一次出来后存在定位问题,又需要用xml去定位,坑可能更大,所以又返回来用修改原文件的方法。

介绍得有点啰嗦,主要说明思路,希望有所帮助。

TIPs:notepad等工具修改源码会使tab的空格发生变化而报错,所以还是用pycharm等工具修改源码较好。

python-docx 不改变原文件调整段落行间距的问题相关推荐

  1. Python—docx 批量处理 docx2pdf 文件

    使用Python3.X 批量将文件夹中的所有docx文档转为PDF 代码示例: 以下处理的.docx文件由这篇文章代码产生:https://blog.csdn.net/wsp_1138886114/a ...

  2. Word 调整段落行间距无效怎么办

    遇到设置完行间距但依然无效情况怎么办?例如想要文本的行间距是1.0,但红框设置无法生效,红框下方两行文字为正常1.0间距 问题出在段落间距上,需要到布局选项卡进行修改 布局--间距--段前或段后

  3. python-docx库_用 python 来操作 docx, xlsx 格式文件(二)(使用 docx 库操作 docx 格式文件...

    docx 库 文章结构: 一.docx 基本用,创建 docx 文件并添加数据 二.深入理解文本格式(format),并设置所格式属性(attribute) 三.深入理解样式(styles),以及如何 ...

  4. python docx 复制_99%的人都不知道的Python整理文件方法,效率提升100倍

    现在人们经常要去下载或者接收一些文件. 比如说同事传来的文档,自己建立的文件,想看的电影等等,那大家都会怎么处理这些文件呢? 科研工作者.学生们可能需要阅读大量的文献,我们也需要阅读很多的电子书等等, ...

  5. python分割文件为小文件_Python实现将一个大文件按段落分隔为多个小文件的简单操作方法...

    本文实例讲述了Python实现将一个大文件按段落分隔为多个小文件的简单操作方法.分享给大家供大家参考,具体如下: 今天帮同学处理一点语料.语料文件有点大,并且是以连续两个换行符作为段落标志,他想把它按 ...

  6. python docx 合并文档 图片_Python检查Word文件中包含特定关键字的所有页码

    推荐教材:<Python程序设计基础与应用>(ISBN:9787111606178),董付国,机械工业出版社图书详情:配套资源:用书教师可以联系董老师获取教学大纲.课件.源码.教案.考试系 ...

  7. python docx 批量修改docx文件内容和选择位置添加内容

    #-*- encoding:utf_8 -*- from docx import Document from docx.shared import Inches from log import log ...

  8. python压缩文件为zip-python 压缩文件为zip后删除原文件

    压缩.log 文件为zip后删除原文件 需要注意:本人作为小白,该脚本需要和.log在一起,后面有时间需要改正. #!/usr/local/python/bin/python #-*-coding=u ...

  9. python读取docx文件出错_Python:读取 .doc、.docx 两种 Word 文件简述及“Word 未能引发事件”错误...

    Python 中可以读取 word 文件的库有 python-docx 和 pywin32. 优点 缺点 python-docx 跨平台 只能处理 .docx 格式,不能处理.doc格式 pywin3 ...

最新文章

  1. MySQL中定义fk语句_MySQL基础篇/第3篇:MySQL基本操作语句.md · qwqoo/MySQL-Review - Gitee.com...
  2. 小程序-wepy学习
  3. JSR 303 - Bean Validation 介绍及最佳实践
  4. 人人都可以做深度学习应用:入门篇
  5. linux运维新手参观机房后的心得体会
  6. 多个asp.net程序共用Session(sso程序的外设接口)
  7. Spring 3整合Quartz 2实现定时任务三:动态暂停 恢复 修改和删除任务
  8. 为什么属龙的有二婚命_76年属龙的二婚在什么时候,76属龙女人婚姻命运怎么样...
  9. linux计划任务30秒,Linux 计划任务(at batch crontab anacron)
  10. 再论句子中单词的逆序输出
  11. ubuntu linux 1604 编译安装tesseract-ocr 4.0
  12. myeclipse下加VSS版本控制插件
  13. 北大青鸟 ASP.NET视频教程批量下载
  14. vscode编程字体设置与修改
  15. 睿智的目标检测7——yolo3详解及其预测代码复现
  16. 5元的小乌龟吃什么_小乌龟吃什么最好?
  17. watch蜂窝开通服务器中断,原因找到了!Apple Watch Series 3为何无法连接蜂窝网络...
  18. c++实验总结_史上最全场景文字检测资源合集(70篇重要论文 + 15个开源代码 + 176个实验结果 + 1305个统计信息)...
  19. JavaScript JS 如何定义多行文本
  20. 基于罗格里德矩阵的坐标转换7参数求取

热门文章

  1. 办公技巧整合(不定时更新)
  2. Live Messenger ,Gmail ,Orkut ,Wallop
  3. [Markdown] 如何隐藏某些内容
  4. 一个人,向南走了一公里,然后向东走1公里,然后向北走一公里
  5. CF 732F Tourist Reform——v-SCC+dfs
  6. 当输入 https://www.baidu.com 时,返回页面的过程中发生了什么?
  7. 绘画工具商城小程序开发,释放绘画市场消费潜力
  8. 【算法】布赖恩·克尼根算法——天才算法求二进制中1的个数
  9. CAD基础+常用快捷(一)
  10. 【001】Cortex-R5体系结构概述