實例5:用Python批量生成word版邀請函

每到年終時,公司都要舉辦年會,總結當年的得失。還有就是組織個晚會,表演些節目,抽獎......當然,還有,賞大餐一頓。人事部的妹子這時就發愁了,忙碌地進行各種準備不說,還要給供應商,政府部門發邀請函。這個邀請函其實除了受邀者的名字不同外,其它信息完全一樣,純粹的體力活。這種臟累活兒,就交給Python來干吧。

首先,我們需要將所有受邀者的公司名和代表姓名填入一個Excel表格。然後做好邀請函的模板,在需要填字的地方打上小星星「****」,然後就讓Python來玩填字遊戲啦。話不多說,直入主題,代碼走一波......

#1.從Excel文件獲取受邀人單位和名字
from openpyxl import load_workbook
wb=load_workbook(data/name_list.xlsx)
ws=wb[name]
names=[]
for row in range(2,ws.max_row+1):
company=ws["A"+str(row)].value
name=ws["B"+str(row)].value
names.append(" {} {} ".format(company,name))
names
>>[ 供應商1 王波 ,
供應商2 劉海洋 ,
供應商3 少和光 ,
供應商4 真凡巧 ,
供應商5 魯鴻運 ,
政府1 樂清霽 ,
政府2 郎綺琴 ,
政府3 貝芳懿 ,
政府4 哈彥君 ]

我們首先導入openpyxl模塊中的load_workbook模塊。openpyxl是一個可讀取Excel的第三方庫。load_workbook()可打開一個現有的Excel文件(或叫工作簿)。我們使用load_workbook(path)讀取文件,並存在變數wb裡面。我們可以想像變數就是容器,用來儲存各種數據,這裡的wb就是這個容器的名字。wb存儲的是整個工作簿的內容,我們知道一個Excel有幾個工作表「Sheet」,接下來我們需要選取我們所需要的「Sheet」,也就是名字叫"name"的那張表。當然你可以給這個工作表起自己喜歡的名字,在寫代碼的時候把wb[name]中的"name"字樣替換成你的個性化名字即可。

然後定義一個空列表names來存儲受邀人單位和名字信息。隨後我們遍歷工作表,將所有信息提取出來存入列表names。因為工作表第一行是標題,所以我們從第2行開始,最大一行+1結束range(2,ws.max_row+1)。之所以要加1,是因為range(1,5)只能取到「1,2,3,4」四個值,5是取不到的。ws.max_row指工作表的總行數。然後我們開始提取公司名稱,company=ws["A"+str(row)].value,當row取2時,就相當於將工作表中A2(即A列2行單元格的值)單元格的值傳給了company變數。獲取姓名也是類似的操作方式。

然後將公司名稱和姓名排一下版,再加入names列表。" {} {} ".format(company,name)這個格式化字元串函數就完成了這個操作。我們在公司名和姓名之間及前後都加入了一個空格,這樣在最終的邀請函上看起來就是這樣的:「尊敬的 供應商1 王波 先生/女士:」。不留空格的話,就變成這樣了:「尊敬的供應商1王波先生/女士:」,似乎有點不和諧。格式化字元串可以理解為,將format(company,name)括弧中的值依次填入前面的{}。

# 2.批量填字,存為不同的word文件
import docx #導入處理word的庫,無恥地直接使用別人造好的輪子
doc=docx.Document(data/邀請函.docx)
for name in names:
doc.paragraphs[1].runs[2].text=name
doc.save(data/邀請函_{}.docx.format(name))

受邀人信息獲取完成後,我們就可以開始批量生成邀請函了。首先導入處理word的庫,無恥地直接使用別人造好的輪子。建立一個容器doc,來盛裝打開的邀請函,docx.Document(data/邀請函.docx)為固定寫法,括弧內填寫邀請函模板的路徑及文件名。doc可理解為就是這個名為「邀請函」word文件。然後遍歷names列表,將裡面的信息逐個寫入word文件的第二段的第三個run,即doc.paragraphs[1].runs[2].text=name,相當於直接用name的值「 供應商1 王波 」替換掉****。其中的run指的是每一段中的不同的格式,比如一段中有常規的,有加粗的,有斜體的,有不同顏色的字,那麼就有好幾個run。

那我們怎麼知道****是第二段第三個run呢?通過我們製作的「邀請函」模板,我們知道****位於第二段(即doc.paragraphs[1],因為是從0開始計數,所以0表示第一段,1就表示第二段)。請注意word中若有空行,也算一段,比如模板中的"ABC有限公司"開頭的那一段已經算是第四段了。我么將第二段的所有run列印出來,就可以找到****所在的run了。

doc=docx.Document(data/邀請函.docx)
for run in doc.paragraphs[1].runs:
print(run.text)

>>尊敬

****
先生
/
女士

我們可以看到其中有7個runs,雖然「尊敬的」三個字格式是一樣的,但是還是被識別為兩個單獨的run了,可能這個庫主要用來處理英文文檔,拿來搞中文有些水土不服。不管它了,讓它亂識別吧。通過以上的run列印,我們簡單粗暴地數下去,可以知道****在第三個run,即run[2]

然後逐個保存為單個的文件,並在給新的word文件命名時加上受邀人的信息doc.save(data/邀請函_{}.docx.format(name))。得到的結果如下:

為了方便列印,可以使用word自帶的合併功能將所有邀請函合併為一個word文件。打開第一個邀請函word文檔,然後單擊【插入】選項卡下的【對象】菜單中的【文件中的文字】選項,選擇剩餘的所有邀請函word文件,點插入,搞定!

所有源代碼和說明都在Jupyter notebook上完成,所用到的Excel 資料已上傳GitHub, 歡迎Fork或下載到本地隨意玩。。。轉載請註明出處,謝謝。

GitHub鏈接:github.com/weidylan/Off

微信公眾號:Python操作EXCEL高效率工作


推薦閱讀:

TAG:MicrosoftWord | Python | Python入門 |