我們在實例5中演示了如何用Python批量生成word版邀請函桥狡。我們是簡單粗暴地找到需要填寫受邀者信息所在位置(即run),然后將這個run直接替換成受邀者的公司名及姓名颅围。因為只有一處需要替換萌焰,所以這個方法行得通,但遇到合同谷浅,一般有十來處需要修改,如果也逐個去找其位置所在的run奶卓,那就反而會降低我們的工作效率一疯,背離辦公自動化的初衷了。實例5可以作為入門python-docx
模塊的練手項目夺姑。
對于合同的批量處理墩邀,我們將使用更聰明的辦法。我們的思路是盏浙,先建立一個word模板眉睹,在合同里面需要變動信息的地方用“【....】”來代替,比如“【合同編號】”等废膘。然后再建一個Excel文檔竹海,將“【合同編號】”等信息作為標(biāo)題,將不同的合同信息放入這個Excel的每一行丐黄。然后用python-docx
去讀取word模板中的所有內(nèi)容斋配,凡是遇到“【....】”的字符,就用Excel中的對應(yīng)標(biāo)題下的信息去進行替換灌闺。Excel中從第二行開始每一行代表一個合同內(nèi)需要填入的信息艰争。
我們建立的模板和合同信息如下圖所示:
這里有幾個注意事項:
- Excel文檔中數(shù)字需要改成文本格式桂对,不然像合同編號20190401在寫入到word時會變成20190401.0甩卓。至于怎么轉(zhuǎn)格式,請參考度娘:http://jingyan.baidu.com/artic
- Excel中的公式需要去除蕉斜,不然填到word中的信息是公式逾柿,而不是值。
- Word模板中的“【....】”和Excel中的標(biāo)題必須一一對應(yīng)蛛勉,且必須是全中文或全英文字符鹿寻,因為
python-docx
會將中英混合的內(nèi)容視為兩個及以上的格式(run),導(dǎo)致在替換的時候無法正確識別诽凌。 - Word模板做好后毡熏,要用
python-docx
讀取一下,看看“【....】”是不是一個獨立的run侣诵,若不是痢法,則需要從Excel標(biāo)題欄中重新復(fù)制狱窘,覆蓋word模板中的“【....】”信息,已保證這一串字符是一個run财搁。
import docx #導(dǎo)入docx庫
doc = Document("data/合同模板.docx") #打開word文件
for para in doc.paragraphs: #讀取word中的每個段落
for run in para.runs: #讀取每個段落中的不同格式(run)
print(run.text)
>>
合同編號:
【合同編號】
【貨物名稱】
采購
合同
甲方
:
【采購方】
乙方
-------省略----------
通過以上程序蘸炸,我們打印顯示了合同里面的所有的格式(其中每一行代表一個格式(run))對應(yīng)的文本(text),我們可以看到“【....】”都是在一行里面的尖奔,這樣就沒問題搭儒。由于word版合同里還有一些是在表格里面的,通過doc.paragraphs
是無法抓取出來的提茁,此時需要用doc.tables
淹禾,表格(tables)里面又包含行(rows),行還包含單元格(cell)茴扁,所以需要讀取所有的表格铃岔,然后讀取所有的行,再讀取單元格峭火,并打印顯示出來毁习。可見 “【....】” 也是在一行里面的卖丸,這樣可保證后續(xù)替換時可查找到纺且,不會導(dǎo)致遺漏。
for table in doc.tables:
for row in table.rows:
for cell in row.cells:
print(cell.text)
>>
甲方(蓋章):【采購方】
法人代表:
或委托代理人:
開戶行: 【開戶行】
賬 號:【賬號】
聯(lián)系人:【聯(lián)系人】
電 話:【電話】
住 所:【住所】
乙方(蓋章):ABC商貿(mào)有限公司
法人代表:
或委托代理人:
開戶行:中國建設(shè)銀行
賬 號:989898989898
聯(lián)系人:張三豐
電 話:999-99999
住 所: 桃花源
Word模板做好后坯苹,“【....】”內(nèi)的信息就不可隨意變動了隆檀,即便我們將“【合同編號】”里面的“遍”字刪掉重新輸入,結(jié)果還是“【合同編號】”粹湃,但此時“【合同編號】”已經(jīng)不是一個格式了恐仑,會變成2個格式。如下示例顯示了這個結(jié)果,“【合同編號】”已經(jīng)不在同一行了为鳄。所以這個格式非常小氣裳仆,不可輕易得罪啊孤钦!此時需要重新去Excel標(biāo)題欄復(fù)制【合同編號】歧斟,再粘貼過去,保存偏形,即可恢復(fù)同一格式(也可以在word中復(fù)制“【合同編號】”静袖,覆蓋粘貼成文本)。
doc = Document("data\合同模板 - 需填入部分格式錯誤.docx") #打開word文件
for para in doc.paragraphs: #讀取word中的每個段落
for run in para.runs: #讀取每個段落中的不同格式(run)
print(run.text)
>>合同編號:
【合同編
號】
【貨物名稱】
采購
合同
甲方
:
【采購方】
此實例雖然是采購合同俊扭,其處理方法適用于所有合同的批量生成队橙,只需要準備好合同的模板,和需要填入合同的信息,剩下的就放心地交給Python吧捐康。合同信息和模板準備好之后仇矾,就可開始批量替換,生成合同了〗庾埽現(xiàn)在跟我出發(fā)贮匕。
import docx
def info_update(doc,old_info, new_info):
'''此函數(shù)用于批量替換合同中需要替換的信息
doc:合同模板
old_info和new_info:原文字和需要替換的新文字
'''
#讀取段落中的所有run,找到需替換的信息進行替換
for para in doc.paragraphs: #
for run in para.runs:
run.text = run.text.replace(old_info, new_info) #替換信息
#讀取表格中的所有單元格花枫,找到需替換的信息進行替換
for table in doc.tables:
for row in table.rows:
for cell in row.cells:
cell.text = cell.text.replace(old_info, new_info) #替換信息
為方便后續(xù)重復(fù)調(diào)用刻盐,以上我們定義了一個函數(shù)info_update()
,它包含三個參數(shù)doc,old_info, new_info
劳翰,分別代表word模板隙疚,原文本,和新文本磕道。逐個讀取word模板中的所有信息,只要遇到原文本行冰,就替換成新文本溺蕉。然后再讀取word中的表格中的信息,也是遇到原文本悼做,就替換成新文本疯特。
from openpyxl import load_workbook #用于讀取Excel中的信息
wb = load_workbook('data/合同信息.xlsx')
ws = wb.active
doc = docx.Document("data/合同模板.docx")
for row in range(2, ws.max_row+1):
for col in range(1, ws.max_column+1):
#調(diào)用上面建立的函數(shù),替換信息
info_update(doc,str(ws.cell(row=1,column=col).value), str(ws.cell(row=row,column=col).value))
doc.save("data/{}合同.docx".format(str(ws.cell(row=row,column=3).value)))
print("{}合同完成".format(str(ws.cell(row=row,column=3).value)))
>>
公司001合同完成
公司002合同完成
公司003合同完成
公司004合同完成
公司005合同完成
公司006合同完成
公司007合同完成
公司008合同完成
公司009合同完成
公司010合同完成
然后使用“openpyxl”庫的“l(fā)oad_workbook”模塊肛走,讀物Excel檔的合同信息漓雅,遍歷每一行,每一列朽色,調(diào)用替換信息的函數(shù)“info_update”完成合同信息替換邻吞,隨后保存。
我們以第一份合同為例葫男,逐個看這些步驟是如何完成的抱冷。因為Excel中第一行是標(biāo)題,合同信息是從第二行開始的梢褐,所以我們行是從2開始row in range(2, ws.max_row+1)
旺遮,最大行加1結(jié)束(因為range函數(shù)是取不到最后一個數(shù)的,此例中最大行是11盈咳,如果不加1耿眉,則只能取到10,這樣最后一份合同就會被漏掉了)鱼响。列也類似鸣剪,不過是從第一列開始的col in range(1, ws.max_column+1)
。
第一份合同對應(yīng)的row值為2,col值為1西傀。原信息是Excel中的標(biāo)題斤寇,對應(yīng)也就是word中的“【....】”部分。次數(shù)原信息先取ws.cell(row=1,column=1).value
拥褂,即如下所示娘锁,為'【合同編號】'。因為Excel表中有一些數(shù)字饺鹃,加上str()是為了轉(zhuǎn)換為字符串莫秆。
新信息為ws.cell(row=2,column=2).value
,如下所示悔详。然后就將word中'【合同編號】'替換為'手機'镊屎,再替換第二列,第三列.....直到替換完所有的列茄螃,于是第一份合同生成完成缝驳,我們使用doc.save
保存。我們給保存的文件名加上公司名稱归苍,以便于區(qū)分用狱,公司名是Excel中第三列的值ws.cell(row=row,column=3).value
。
第一份合同完成后拼弃,回到for循環(huán)夏伊,開始第二份合同的替換和保存,直到搞定所有合同吻氧。最終成果如下:
所有源代碼和說明都在Jupyter notebook上完成溺忧,所用到的Excel 資料已上傳GitHub, 歡迎Fork或下載到本地隨意玩。盯孙。鲁森。轉(zhuǎn)載請注明出處,謝謝振惰。
GitHub鏈接:https://github.com/weidylan/Office_Automation_by_Using_Python
微信公眾號:Python操作Office軟件高效工作