日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > python >内容正文

python

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

發(fā)布時(shí)間:2023/12/8 python 51 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python-docx 不改变原文件调整段落行间距的问题 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

?

python-docx模塊是處理word的利器,希望通過(guò)調(diào)用模塊生成預(yù)定格式的文件,word本身自帶的模板使用不太方便,而工作中對(duì)文檔格式要求很高(~~)

借助一個(gè)富文本編輯器,可以將文檔內(nèi)容輸出為word,存在幾類問(wèn)題,

  • 字體大小、字號(hào)、加粗等,這些直接調(diào)用styles即可實(shí)現(xiàn),python-docx對(duì)字體支持還是很完善,

  • 另外一個(gè)問(wèn)題是段落間距問(wèn)題,折騰了一天在抓狂的狀態(tài)下終于解決,原因還是因?yàn)閷?duì)xml原理不熟悉

以下介紹不改變?cè)募姆椒?#xff0c;修改間距為“行”“自動(dòng)”的方法:


1.如果段間距是以“磅”作為單位,那么對(duì)應(yīng)的python中即是Pt單位,通過(guò)以下直接對(duì)讀出的段落進(jìn)行修改:

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"]進(jìn)行類修改,網(wǎng)上資料較多,修改pt值即可實(shí)現(xiàn)段前斷后間距;


2.如果段間距是以“行”作為單位,pydocx模塊內(nèi)置不能識(shí)別該格式,導(dǎo)致失效。

用xml查看會(huì)發(fā)現(xiàn)spacing設(shè)置“1行”的參數(shù)名稱:

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

而源碼文件parfmt.py中class CT_Spacing(BaseOxmlElement)只定義了四種類型:after,before,line,lineRule,雖然在word中看到的段前斷后選1行和選1磅仍然在同一個(gè)框中,但是實(shí)際的數(shù)據(jù)類型已經(jīng)是另外的了。所以要對(duì)pydocx源碼進(jìn)行修改。

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函數(shù)

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

一個(gè)是子函數(shù),一個(gè)是設(shè)置參數(shù),設(shè)置需要調(diào)用子函數(shù),所以都要改。

  • 首先判斷spacing是不是空
  • 接著判斷是否有行參數(shù),如果有則返回行參數(shù)或者修改行參數(shù)
  • 如果行參數(shù)不存在,則按原來(lái)的pt等值進(jìn)行修改

(到這猜測(cè)pydocx為什么沒(méi)聲明這種類型,國(guó)內(nèi)用的word可能是微軟針對(duì)國(guó)內(nèi)word再加工,國(guó)外的統(tǒng)一用pt等度量值,可能沒(méi)行單位,或者就是pydocx有需要優(yōu)化的地方)

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這樣可以試一下讀一個(gè)采用1行間距的值大小

讀出的值應(yīng)該是63500,而一個(gè)1磅的值應(yīng)該是6350,差了10倍。

解決了“行”的問(wèn)題,本來(lái)以為可以愉快玩耍了,但是遇到了下一個(gè)問(wèn)題,“自動(dòng)”


3.行間距為“自動(dòng)”的間距設(shè)置

有些富文本編輯器導(dǎo)出的行間距沿用上一段或者沿用一種style的模板,所以行間距在word中顯示自動(dòng),用上面改行的方法,對(duì)自動(dòng)行雖然讀出值是顯示改了,但是實(shí)際效果并沒(méi)有改,但是不怕,因?yàn)橥ㄟ^(guò)2已經(jīng)大概了解ms的套路。

3.1同樣用xml查看“自動(dòng)”行

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

很明顯,又多了一個(gè)beforeAutospacing類型,而且value值是1,所以推斷它是一種布爾變量。

3.2在parfmt.py的CT_Spacing中再增加兩個(gè)類型,最終:

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的修改

當(dāng)我們要調(diào)整格式的時(shí)候,顯然不希望間距是自動(dòng),所以刪除這種類型最好,但是找了幾分鐘get_or_add_spacing這個(gè)函數(shù)在pydocx中信息較少,只有個(gè)相關(guān)方法的注冊(cè),再繼續(xù)研究又會(huì)陷入另外一個(gè)坑,所以轉(zhuǎn)換一下思路。

既然修改的時(shí)候肯定不是自動(dòng),那么就保留它,而把布爾值設(shè)為0,另外再新增需要的間距值就行。

所以不用管子函數(shù)函數(shù),只用改“設(shè)置”的那個(gè)函數(shù),在設(shè)置間距之前先將“自動(dòng)”賦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

將自動(dòng)強(qiáng)制設(shè)為None.

3.4測(cè)試

將word找個(gè)行調(diào)整為自動(dòng)或者X行,python程序設(shè)為Pt(0),運(yùn)行一下,發(fā)現(xiàn)完美實(shí)現(xiàn)間距為0。

檢查:將word導(dǎo)出為xml,結(jié)果發(fā)現(xiàn),將beforeAutospacing,afterAutospacing兩個(gè)變量設(shè)置為None后,xml實(shí)際刪除了auto的變量類型,最終也實(shí)現(xiàn)了我想要的結(jié)果。


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

還有一個(gè)思路是打開(kāi)原WORD,讀出paragraph列表了之后,用循環(huán)將內(nèi)容復(fù)制到另外一個(gè)word,用add_paragraph來(lái)設(shè)置間距、字體等。但是因?yàn)槲矣袌D有表,段落列表、圖列表和表格列表一次出來(lái)后存在定位問(wèn)題,又需要用xml去定位,坑可能更大,所以又返回來(lái)用修改原文件的方法。

介紹得有點(diǎn)啰嗦,主要說(shuō)明思路,希望有所幫助。

TIPs:notepad等工具修改源碼會(huì)使tab的空格發(fā)生變化而報(bào)錯(cuò),所以還是用pycharm等工具修改源碼較好。

總結(jié)

以上是生活随笔為你收集整理的python-docx 不改变原文件调整段落行间距的问题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。