使用Python實(shí)現(xiàn)自動(dòng)編寫(xiě)word文檔
前言
工作中有大量的報(bào)告編寫(xiě)需求,在不停地復(fù)制粘貼之后,突然想到,這種高度重復(fù)的工作有沒(méi)有編程可以實(shí)現(xiàn)的方法呢?經(jīng)過(guò)查找相關(guān)內(nèi)容發(fā)現(xiàn)一個(gè)關(guān)鍵詞叫做RPA(機(jī)器人流程自動(dòng)化,各位去搜索一下這個(gè)關(guān)鍵詞,會(huì)發(fā)現(xiàn)和我想要實(shí)現(xiàn)的需求完全一致,只是這個(gè)詞一般在財(cái)務(wù)金融之類的環(huán)境中提起),那么python可以實(shí)現(xiàn)RPA嗎?繼續(xù)搜索發(fā)現(xiàn)有很多包,這里介紹一下python-docx,一個(gè)用來(lái)生成word文檔的包。官方文檔鏈接python-docx。
安裝python-docx
使用pip就可以安裝了,如果下載速度慢,需要替換為國(guó)內(nèi)鏡像源:
pip install python-docx
python-docx使用
創(chuàng)建word文檔
from docx import Document document = Document() document.save("報(bào)告.docx")
使用Document()就完成了一個(gè)word文檔的創(chuàng)建,我起的變量名叫document,這個(gè)步驟相當(dāng)于在文件夾里鼠標(biāo)右鍵新建了一個(gè)空的word文檔。
document很重要,相當(dāng)于一個(gè)還沒(méi)有裝水的大池子,我們所有插入內(nèi)容的內(nèi)容都要灌進(jìn)這個(gè)池子里,專業(yè)的說(shuō)法document是新建的一個(gè)對(duì)象,所有操作都要使用這個(gè)對(duì)象(document后面一個(gè)點(diǎn),再加上具體要調(diào)用的方法),document操作完之后,最后一步記得調(diào)用save()方法保存文檔,可以是相對(duì)路徑也可以是絕對(duì)路徑,如果使用相對(duì)路徑,程序所在路徑是根目錄。
下面所有的代碼都應(yīng)該放在document = Document()和document.save(“報(bào)告.docx”)之間,就不再重復(fù)給出了。
設(shè)置紙張方向、大小和頁(yè)邊距
熟悉word操作大家肯定知道分節(jié)符,每一節(jié)中頁(yè)眉頁(yè)腳和邊距等都是統(tǒng)一的。新建的document中默認(rèn)有一個(gè)分節(jié)符,想要設(shè)置第一節(jié)的紙張方向和頁(yè)邊距,就要獲取分節(jié)符對(duì)象。下面代碼中section就是獲取到的分節(jié)符對(duì)象,如果有好幾個(gè)分節(jié)符,0代表第一個(gè),依此類推。
import docx.shared from docx.enum.section import WD_ORIENTATION """ 獲取第一個(gè)分節(jié)符 """ section = document.sections[0] """ 設(shè)置橫向 """ section.orientation = WD_ORIENTATION.LANDSCAPE # 設(shè)置頁(yè)面 page_h, page_w = section.page_width, section.page_height # 高度和寬度顛倒一下 # 設(shè)置橫向紙的寬度 section.page_width = page_w # 設(shè)置橫向紙的高度 section.page_height = page_h # 設(shè)置上下左右頁(yè)邊距 section.left_margin = docx.shared.Cm(2) section.right_margin = docx.shared.Cm(2) section.top_margin = docx.shared.Cm(2) section.bottom_margin = docx.shared.Cm(2)
word文檔有橫向和縱向,python-docx設(shè)置橫向的代碼section.orientation = WD_ORIENTATION.LANDSCAPE,如果設(shè)置縱向要改為section.orientation = WD_ORIENTATION.PORTRAIT,默認(rèn)是縱向的,所以一般只有橫向才需要代碼實(shí)現(xiàn)。
如果不設(shè)置紙的高度和寬度,你會(huì)發(fā)現(xiàn)打開(kāi)的word文檔好像還是“縱向”的,實(shí)際在打印的時(shí)候以及查看布局——紙張方向你會(huì)發(fā)現(xiàn)確實(shí)是橫向的,電腦識(shí)別到的word文檔和我們看起來(lái)好像不一致,為了使得觀感和紙張方向統(tǒng)一,我們獲取紙張的高寬,然后高度設(shè)置為寬度,寬度設(shè)置為高度,就可以了。
當(dāng)然,如果你只需要縱向的文檔,那么上面的步驟都不需要。
設(shè)置這一節(jié)內(nèi)容的上下左右頁(yè)邊距,分別設(shè)置section的不同屬性即可,python-docx對(duì)于各種距離單位,默認(rèn)使用的是“磅”,也就是說(shuō)section.left_margin = 2,會(huì)將左邊距設(shè)置為2磅,個(gè)人還是習(xí)慣厘米做單位,不過(guò)這樣的話要通過(guò)docx.shared.Cm()將厘米轉(zhuǎn)換為磅,上面代碼中設(shè)置邊距為2厘米,通過(guò)轉(zhuǎn)換函數(shù)轉(zhuǎn)換為了磅。
如果要添加新的分節(jié)符:
from docx.enum.section import WD_SECTION_START section_new = document.add_section(start_type=WD_SECTION_START.NEW_PAGE)
python-docx的函數(shù)名起的都很好理解,上面的代碼不解釋大家也能明白,調(diào)用document的方法新增了一個(gè)section,類型WD_SECTION_START可以選擇NEW_PAGE下一節(jié),也可以選擇連續(xù)等分節(jié)符。
統(tǒng)一設(shè)置格式
python-docx添加的圖表文字等內(nèi)容都可以在"add"后再修改格式,但是這樣的話文字每次add之后,都要多好幾行代碼去設(shè)置行距、字體、縮進(jìn)等,太繁瑣了,python-docx可以和word一樣設(shè)置樣式,add完文字后,將樣式應(yīng)用到文字上即可??梢孕陆邮?,也可以修改已有樣式。
""" 創(chuàng)建正文樣式 """ from docx.oxml.ns import qn from docx.enum.style import WD_STYLE_TYPE from docx.shared import Pt, Cm style_normal = document.styles.add_style('NORMAL STYLE', WD_STYLE_TYPE.PARAGRAPH) style_normal.base_style = document.styles['Normal'] # 基本樣式 style_normal.font.name = 'Times New Roman' # 英文字體 style_normal.element.rPr.rFonts.set((qn('w:eastAsia')), '宋體') # 中文字體 style_normal.paragraph_format.space_before = Pt(0) # 段前 style_normal.paragraph_format.space_after = Pt(0) # 段后 style_normal.font.size = Pt(14) # 字號(hào) style_normal.paragraph_format.line_spacing = Pt(28) # 行距 style_normal.paragraph_format.first_line_indent = Pt(28) # 首行縮進(jìn)
上面的代碼新建了一個(gè)樣式,我起名叫做NORMAL STYLE,它繼承自基本樣式,然后設(shè)置了自己字體和段前段后,行距縮進(jìn)等,python-docx沒(méi)有“字符”這個(gè)單位,所以我想首行縮進(jìn)兩字符只能自己去算,一個(gè)字14磅,那么首行縮進(jìn)28磅就是兩個(gè)字符啦。
document.styles['Normal'].font.name = 'Times New Roman' # 英文字體 document.styles['Normal'].element.rPr.rFonts.set((qn('w:eastAsia')), '宋體') # 中文字體 document.styles['Normal'].paragraph_format.space_before = Pt(0) document.styles['Normal'].paragraph_format.space_after = Pt(0) document.styles['Normal'].font.size = Pt(14) document.styles['Normal'].paragraph_format.line_spacing = Pt(28) document.styles['Normal'].paragraph_format.first_line_indent = Pt(28)
上面的代碼修改了已有樣式,這里將基本的Normal樣式進(jìn)行了修改,之后代碼所有add的文字格式都會(huì)按照修改后的Normal樣式。
如果新建樣式,在每次add之后都要應(yīng)用一下樣式,如果是修改Normal樣式,那么add之后不需要應(yīng)用樣式,如果修改其他樣式,同樣需要add之后應(yīng)用一下樣式,因?yàn)槟J(rèn)按照Normal的格式顯示。修改Normal樣式雖然不需要每次設(shè)置正文的樣式,但經(jīng)過(guò)作者嘗試發(fā)現(xiàn)了一個(gè)問(wèn)題,如果word文檔中有表格要插入文字的話,無(wú)論怎樣設(shè)置表格中文字的樣式,依然會(huì)被設(shè)置為Normal樣式,好像Normal的優(yōu)先級(jí)很高,不是表格中的文字沒(méi)有這個(gè)問(wèn)題,可以正常應(yīng)用其他樣式,所以word文檔中有表格的話,建議新建樣式,不要采用修改Normal樣式的方法。
word自帶了很多樣式,不過(guò)沒(méi)必要的話不要繼承一些沒(méi)聽(tīng)過(guò)的樣式,比如某個(gè)樣式自帶了下劃線,代碼里怎么設(shè)置也去不掉,會(huì)有這種情況。
插入文本
word文檔有很多段落(paragraph),python-docx也有這個(gè)概念,然后進(jìn)一步的,python-docx的概念中,每個(gè)段落又有很多"run"對(duì)象。
添加一段文字,可以設(shè)置段落整體的行距,首行縮進(jìn)等,給段落中添加一個(gè)run,可以設(shè)置這個(gè)run里文字的格式,這樣就實(shí)現(xiàn)了一段文字中,有不同的字體格式。
paragraph = document.add_paragraph("測(cè)試段落") paragraph.style = "NORMAL STYLE"
添加一段文字很簡(jiǎn)單,添加之后設(shè)置style的屬性,就可以應(yīng)用之前添加的樣式。每次調(diào)用add_paragraph,都相當(dāng)于按了一次回車(chē)鍵,然后才是文字內(nèi)容。上面提到,如果一段文字要設(shè)置不同格式,可以添加多個(gè)run。
paragraph = document.add_paragraph(style="NORMAL STYLE") run = paragraph.add_run("尊敬的") run.font.name = "黑體" run = paragraph.add_run("XX女士/先生") run.font.name = "宋體"
和設(shè)置樣式類似,段落以及run都可以設(shè)置里面的字體大小等屬性進(jìn)行細(xì)節(jié)的格式修改。
插入表格
table = document.add_table(rows=5, cols=5, style='NORMAL STYLE') table.cell(0, 0).text = '測(cè)試' table.rows[1].cells[0].merge(table.rows[1].cells[1])
表格的添加很簡(jiǎn)單,在新建表格時(shí)設(shè)置好行列參數(shù),并且可以設(shè)置表格內(nèi)文字的樣式,前面提到過(guò),如果修改word自帶的Normal樣式的話這里的設(shè)置樣式會(huì)失效。table.cell可以獲取具體幾行幾列的單元格,調(diào)用.text修改內(nèi)容。使用merge可以合并單元格,上面的代碼表示將第2行第1列單元格和第2行第2列單元格合并(python計(jì)數(shù)從0開(kāi)始)。如果有多個(gè)單元格合并,只能一個(gè)一個(gè)進(jìn)行,我一般是寫(xiě)一個(gè)循環(huán)實(shí)現(xiàn)。如果合并單元格對(duì)應(yīng)的原始單元格有多個(gè)填充了文字,那么和excel類似,只會(huì)保留第一個(gè)單元格的內(nèi)容。
插入圖片
添加圖片,同樣簡(jiǎn)單粗暴,add_picture搞定,類似于設(shè)置文字的屬性一樣,我們可以設(shè)置圖片的一些屬性,一般對(duì)圖片設(shè)置主要是設(shè)置大小,我獲取了圖片的高度和寬度(默認(rèn)單位是磅),然后將磅轉(zhuǎn)換為了厘米,把圖片設(shè)置為厘米單位的高度寬度。figurepath大家自己替換為圖片的文件地址即可。
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT run = paragraph.add_run() pic = run.add_picture(figurepath) original_width, original_height = pic.width, pic.height change_ratio = (7/2.54*914400) / original_height scaled_width = int(original_width * change_ratio) scaled_height = int(original_height * change_ratio) # 縮放至7cm pic.width = scaled_width # 縮放 pic.height = scaled_height # 縮放 paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
結(jié)語(yǔ)
python-docx使用十分方便,不過(guò)也需要注意,它主要是用來(lái)按照代碼生成新的word文檔的(雖然也可以讀取已有word文檔,但是功能較弱),如果已有一些word文檔,想要讀取word文檔并在指定位置做修改,要用到更底層的pywin32等包才能實(shí)現(xiàn)需求。python-docx本質(zhì)上是在新建一個(gè)文件,只不過(guò)這個(gè)文件按照word文檔的規(guī)范編排,如果你的電腦沒(méi)有安裝word程序,python-docx生成word文檔依然可以正常執(zhí)行,只是需要換一臺(tái)裝了word的電腦才可以正常打開(kāi)閱讀,而pywin32等包加載已有的word文檔,需要通過(guò)運(yùn)行word程序來(lái)操作,必須要安裝word程序才能實(shí)現(xiàn),本質(zhì)上是程序代替你打開(kāi)word來(lái)操作,好處是這樣可以進(jìn)行的格式編排會(huì)比python-docx更精細(xì),但是代碼會(huì)更加底層和復(fù)雜。
可能還有的人會(huì)問(wèn),python-docx插入文字,圖,表之類的,和word模板豈不是很類似?如果單從python-docx一個(gè)包來(lái)看,實(shí)現(xiàn)的功能會(huì)有點(diǎn)類似,但是python-docx可以與其他工具包配合,將大量數(shù)據(jù)的計(jì)算,繪制圖表與word文檔結(jié)合起來(lái),這樣的強(qiáng)大功能是word模板完全無(wú)法相比的。鼠標(biāo)一點(diǎn),幾十頁(yè)的報(bào)告一鍵生成,這樣的便利性只有各位在實(shí)際工作中用到了才能真正體會(huì)到O(∩_∩)O。
到此這篇關(guān)于使用Python實(shí)現(xiàn)自動(dòng)編寫(xiě)word文檔的文章就介紹到這了,更多相關(guān)Python自動(dòng)編寫(xiě)word內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用Python操作Redis所有數(shù)據(jù)類型的方法
當(dāng)今互聯(lián)網(wǎng)時(shí)代,數(shù)據(jù)處理已經(jīng)成為了一個(gè)非常重要的任務(wù),而Redis作為一款高性能的NoSQL數(shù)據(jù)庫(kù),越來(lái)越受到了廣大開(kāi)發(fā)者的喜愛(ài),本篇博客將介紹如何使用Python操作Redis的所有類型,以及一些高級(jí)用法,需要的朋友可以參考下2023-11-11Python內(nèi)置的HTTP協(xié)議服務(wù)器SimpleHTTPServer使用指南
這篇文章主要介紹了Python內(nèi)置的HTTP協(xié)議服務(wù)器SimpleHTTPServer使用指南,SimpleHTTPServer本身的功能十分簡(jiǎn)單,文中介紹了需要的朋友可以參考下2016-03-03Python3.6筆記之將程序運(yùn)行結(jié)果輸出到文件的方法
下面小編就為大家分享一篇Python3.6筆記之將程序運(yùn)行結(jié)果輸出到文件的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-04-04Python實(shí)現(xiàn)網(wǎng)絡(luò)端口轉(zhuǎn)發(fā)和重定向的方法
這篇文章主要介紹了Python實(shí)現(xiàn)網(wǎng)絡(luò)端口轉(zhuǎn)發(fā)和重定向的方法,結(jié)合實(shí)例形式分析了Python基于threading和socket模塊實(shí)現(xiàn)端口轉(zhuǎn)發(fā)與重定向的具體操作技巧,需要的朋友可以參考下2016-09-09python 并發(fā)編程 多路復(fù)用IO模型詳解
這篇文章主要介紹了python 并發(fā)編程 多路復(fù)用IO模型詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-08-08Python設(shè)計(jì)模式之觀察者模式實(shí)例
這篇文章主要介紹了設(shè)計(jì)模式中的觀察者模式Python實(shí)例,需要的朋友可以參考下2014-04-04