我們在實例5中演示了如何用Python批量生成word版邀請函。我們是簡單粗暴地找到需要填寫受邀者信息所在位置(即run),然后將這個run直接替換成受邀者的公司名及姓名。因為只有一處需要替換,所以這個方法行得通,但遇到合同,一般有十來處需要修改,如果也逐個去找其位置所在的run,那就反而會降低我們的工作效率,背離辦公自動化的初衷了。實例5可以作為入門python-docx 模塊的練手項目。 對于合同的批量處理,我們將使用更聰明的辦法。我們的思路是,先建立一個word模板,在合同里面需要變動信息的地方用“【....】”來代替,比如“【合同編號】”等。然后再建一個Excel文檔,將“【合同編號】”等信息作為標題,將不同的合同信息放入這個Excel的每一行。然后用python-docx 去讀取word模板中的所有內(nèi)容,凡是遇到“【....】”的字符,就用Excel中的對應(yīng)標題下的信息去進行替換。Excel中從第二行開始每一行代表一個合同內(nèi)需要填入的信息。
我們建立的模板和合同信息如下圖所示:

這里有幾個注意事項:
Excel文檔中數(shù)字需要改成文本格式,不然像合同編號20190401在寫入到word時會變成20190401.0。至于怎么轉(zhuǎn)格式,請參考度娘:jingyan.baidu.com/artic Excel中的公式需要去除,不然填到word中的信息是公式,而不是值。 Word模板中的“【....】”和Excel中的標題必須一一對應(yīng),且必須是全中文或全英文字符,因為python-docx 會將中英混合的內(nèi)容視為兩個及以上的格式(run),導致在替換的時候無法正確識別。 Word模板做好后,要用python-docx 讀取一下,看看“【....】”是不是一個獨立的run,若不是,則需要從Excel標題欄中重新復制,覆蓋word模板中的“【....】”信息,已保證這一串字符是一個run。
import docx #導入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ù)替換時可查找到,不會導致遺漏。 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標題欄復制【合同編號】,再粘貼過去,保存,即可恢復同一格式(也可以在word中復制“【合同編號】”,覆蓋粘貼成文本)。 doc = Document('data\合同模板 - 需填入部分格式錯誤.docx') #打開word文件 for para in doc.paragraphs: #讀取word中的每個段落 for run in para.runs: #讀取每個段落中的不同格式(run) print(run.text) >>合同編號: 【合同編 號】 【貨物名稱】 采購 合同 甲方 : 【采購方】
此實例雖然是采購合同,其處理方法適用于所有合同的批量生成,只需要準備好合同的模板,和需要填入合同的信息,剩下的就放心地交給Python吧。合同信息和模板準備好之后,就可開始批量替換,生成合同了?,F(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ù)重復調(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中第一行是標題,合同信息是從第二行開始的,所以我們行是從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中的標題,對應(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
|