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