python模擬office郵件合并生成成績單

計算思維中識別日常生活中的模式,識別日常生活中的模式是一項具有普遍需求的技能,無論是復盤找規(guī)律總結(jié)方法論,信息化建設(shè)中總結(jié)標準流程,建設(shè)線上流程;發(fā)現(xiàn)生活中的重復性工作等.

需求

在word中有一項很強大的功能:郵件合并,可以方便的生成請柬,工資條,信封等,避免了簡單低效的重復操作,這個屬于word中比較實用的功能,計算機二級MS Office高級應用中也會用到.但是郵件合并只能從excel中抽取數(shù)據(jù),批量生成word,如果有一部分有規(guī)律的word,郵件合并就沒有辦法了.

我們可以用python讀取excel數(shù)據(jù),并批量生成word,下面我們就講解如何實現(xiàn).

數(shù)據(jù)轉(zhuǎn)換

會把excel中的成績數(shù)據(jù),根據(jù)上圖中間的模板,生成每個學生的成績單,而完成上述任務只需要不到20行代碼:


18行代碼

用字符串模擬批量生成

實際上,請柬,信封,作業(yè)本封面都是有一個固定的模板,然后填寫必要的信息.模板應用非常廣泛,office辦公軟件中就存在巨大的模板,我們平時也會下載各種模板,模板會為我們節(jié)約大量時間提高效率;在現(xiàn)在的web開發(fā)中,前端頁面大多是用模板生成的,比如flask框架的jinjia2模板.

單個同學的例子

比如,我們要發(fā)獎狀

student = '張三'
template = "恭喜{}同學成為三好學生"
print(template.format(student))

程序運行結(jié)果如下:

D:\寫作>C:/Users/xpro/AppData/Local/Programs/Python/Python37-32/python.exe d:/寫作/01email.py
恭喜張三同學成為三好學生

我們把template變量看做是獎狀,name變量代表的是獲獎的同學張三,最后輸出了獲獎信息,恭喜張三同學成為三好學生.

python中一切皆對象, 字符串也是對象, format是字符串對象的一個方法,作用是把參數(shù)填充到字符串中用大括號標記的地方,比如"恭喜{}同學成為三好學生".format("張三"), 就是把用format方法把學生姓名張三填充到模板字符串"恭喜{}同學成為三好學生"中的大括號, 字符串"恭喜{}同學成為三好學生"張三為參數(shù)調(diào)用format方法之后,就會變成了恭喜張三同學成為三號學生.

不熟悉format函數(shù)使用的話,可以識別下列二維碼:

format函數(shù)

這是一個非常簡單的例子,但是卻是python實現(xiàn)郵件合并的原型,當我們根據(jù)數(shù)據(jù)和模板批量生成文件的時候,需要的不外乎大量的姓名列表,一個模板,然后輸出,只不過細節(jié)可能會更多一些.假設(shè)我們有一個列表,列表里有很多姓名(可以來自excel或者數(shù)據(jù)庫或者csv文件),然后循環(huán)執(zhí)行生成模板的代碼就好了,距離如下:

students = ['張三', '李四', '王五', '趙六'] # 數(shù)據(jù)源
template = "恭喜{}同學成為三好學生" # 模板
for student in students: # 循環(huán)
    print(template.format(student)) # 根據(jù)模板生成文件

運行結(jié)果如下:

D:\寫作>C:/Users/xpro/AppData/Local/Programs/Python/Python37-32/python.exe d:/寫作/01email.py
恭喜張三同學成為三好學生
恭喜李四同學成為三好學生
恭喜王五同學成為三好學生
恭喜趙六同學成為三好學生

在這個例子里,我們簡單地打印字符串,代替需要批量生成的文件,比如生成的word,ppt或者生成圖片,但是跟把大象放冰箱,總共分幾步一樣,一共分為,準備數(shù)據(jù)源,準備模板,根據(jù)數(shù)據(jù)和模板批量生成三個步驟:

  • 準備數(shù)據(jù)源
  • 準備模板
  • 根據(jù)數(shù)據(jù)和模板批量生成

是不是很簡單.

虛擬數(shù)據(jù)

對于python不是很熟悉的老師,可以跳過虛擬數(shù)據(jù)這部分.
每次用列表生成示例數(shù)據(jù)是很麻煩的,我們結(jié)束一個庫來幫我們生成虛擬的姓名數(shù)據(jù),我們要用到一個叫做faker的python第三方庫,安裝方式是

pip install faker

用faker庫生成姓名

虛擬姓名

Python 3.7.2 (tags/v3.7.2:9a3ffc0492, Dec 23 2018, 23:09:28) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from faker import Faker
>>> fake = Faker('zh_CN') # 指定local所屬地區(qū)中國
>>> fake.name()
'蘇紅霞'
>>> fake.name()
'董雷'
>>>

在交互式命令行中,我們可以很容易的看到,faker庫會幫我們生成虛擬的姓名,但是符合我們中國人的姓名習慣的.

生成虛擬地址

>>> fake.address()
'江西省合山縣東麗劉街k座 806555'
>>> fake.address()
'重慶市柳縣沙灣吳街P座 708245'
>>>

改寫生成獎狀的程序如下

from faker import Faker 

fake = Faker('zh_CN')

template = "恭喜{}同學成為三好學生" # 模板
for i in range(5):
    student = fake.name()
    print(template.format(student))

因為可以用faker庫生成姓名,所以不再需要姓名列表,你可以理解為我們的數(shù)據(jù)源從students列表變成了faker庫,運行結(jié)果如下

D:\寫作>python 01email.py
恭喜楊林同學成為三好學生
恭喜王成同學成為三好學生
恭喜劉瑞同學成為三好學生
恭喜王玉同學成為三好學生
恭喜郭欣同學成為三好學生

這里我用了python命令執(zhí)行了01email.py文件,這里需要注意的是faker庫每次調(diào)用生成的數(shù)據(jù)不通,我第二次運行結(jié)果如下:

D:\寫作>python 01email.py
恭喜林峰同學成為三好學生
恭喜鮑瑩同學成為三好學生
恭喜祁婷同學成為三好學生
恭喜惠雪梅同學成為三好學生
恭喜盧秀芳同學成為三好學生

讀取excel數(shù)據(jù)

成績表

讀取并處理excel數(shù)據(jù),最好用的就是numpy庫了,不過numpy不如xlrd庫直觀,我們先用xlrd來寫示例程序.這次的數(shù)據(jù)源是excel,是一個有姓名,語數(shù)英成績的excel表,當前目錄下的data.xlsx文件,數(shù)據(jù)在excel文件的Sheet1工作表中.

import xlrd

# 用xlrd模塊的open_workbook方法打開excel文件
# 類似于我們在wps,office的打開操作
# 參數(shù)是文件的路徑,字符串前面的r表示路徑
xls = xlrd.open_workbook(r'data.xlsx')
# 通過工作表的名字Sheet1獲取工作表1
sheet1 = xls.sheet_by_name('Sheet1')

# 第一行第一列是姓名表頭
# 但是python中是從0開始計數(shù)
# student的值是姓名
student = sheet1.cell_value(0, 0)
print(student)
# 運行結(jié)果是: 姓名

運行結(jié)果如下

D:\寫作>python 01email.py
姓名

獲取工作表Sheet1
圖解

第一個學生張三是第2行第1列的數(shù)據(jù),讀取方法如下

import xlrd

# 用xlrd模塊的open_workbook方法打開excel文件
# 類似于我們在wps,office的打開操作
# 參數(shù)是文件的路徑,字符串前面的r表示路徑
xls = xlrd.open_workbook(r'data.xlsx')
# 通過工作表的名字Sheet1獲取工作表1
sheet1 = xls.sheet_by_name('Sheet1')

# 第一行第一列是姓名表頭
# 但是python中是從0開始計數(shù)
# student的值是姓名
# cell_value方法獲取單元格的值
# 第一個參數(shù)代表行序號,第二個參數(shù)代表列序號
student = sheet1.cell_value(1, 0)
print(student)
# 運行結(jié)果是: 姓名

運行結(jié)果

D:\寫作>python 01email.py
張三

當我們知道了如何讀取姓名,也就知道了如何讀取語數(shù)英的成績分別是

chinese = sheet1.cell_value(1, 1)
math = sheet1.cell_value(1, 2)
english = sheet1.cell_value(1, 3)

接下來我們輸出張三同學的成績單:

import xlrd

# 讀取數(shù)據(jù)源
xls = xlrd.open_workbook(r'data.xlsx')
sheet1 = xls.sheet_by_name('Sheet1')

# 模板
template = "{}同學的成績?nèi)缦?語文{},數(shù)學{},英語{}"

student = sheet1.cell_value(1, 0)
chinese = sheet1.cell_value(1, 1)
math = sheet1.cell_value(1, 2)
english = sheet1.cell_value(1, 3)

# 根據(jù)模板輸出信息
print(template.format(student, chinese, math, english))

運行結(jié)果如下:

D:\寫作>python 01email.py
張三同學的成績?nèi)缦?語文89.0,數(shù)學100.0,英語100.0

接下來我們只需要用循環(huán)讀取數(shù)據(jù)就可以了,有個問題,excel中有多少行數(shù)據(jù)呢?可以用工作表的nrows獲取行數(shù),需要注意的是excel的第一行不是數(shù)據(jù)而是表頭,循環(huán)的時候需要跳過.

import xlrd

# 讀取數(shù)據(jù)源
xls = xlrd.open_workbook(r'data.xlsx')
sheet1 = xls.sheet_by_name('Sheet1')

# 模板
template = "{}同學的成績?nèi)缦?語文{},數(shù)學{},英語{}"

rows = sheet1.nrows # 表格行數(shù)

for i in range(1, rows): # 跳過表頭一行
    student = sheet1.cell_value(i, 0) # 第i行代表第i行數(shù)據(jù)
    chinese = sheet1.cell_value(i, 1)
    math = sheet1.cell_value(i, 2)
    english = sheet1.cell_value(i, 3)
    # 根據(jù)模板輸出信息
    print(template.format(student, chinese, math, english))

運行結(jié)果如下:

D:\寫作>python 01email.py
張三同學的成績?nèi)缦?語文89.0,數(shù)學100.0,英語100.0
李四同學的成績?nèi)缦?語文92.0,數(shù)學99.0,英語98100.0
王五同學的成績?nèi)缦?語文95.0,數(shù)學97.0,英語88.0
趙六同學的成績?nèi)缦?語文98.0,數(shù)學98.0,英語78.0

word模板

docxtpl庫簡單案例
pip install docxtpl

解決了數(shù)據(jù)源的問題,我們來研究如何生成word,實際上我們在郵件合并的時候,就是要有一個word模板,然后根據(jù)word模板插入相關(guān)的域,就是可以用郵件合并生成數(shù)據(jù)了,實際上這里也許要一個word模板,word模板如下

要生成word模板,需要用到一個第三方庫,python強大的原因之一,就是有各種第三方庫可以滿足我們的需求.

word模板
import xlrd
from docxtpl import DocxTemplate

# 讀取數(shù)據(jù)源,打開word
xls = xlrd.open_workbook(r'data.xlsx')
sheet1 = xls.sheet_by_name('Sheet1')

rows = sheet1.nrows # 表格行數(shù)
# 讀取數(shù)據(jù)并生成文件
for i in range(1, rows): # 跳過表頭一行
    student = sheet1.cell_value(i, 0) # 第i行代表第i行數(shù)據(jù)
    chinese = sheet1.cell_value(i, 1)
    math = sheet1.cell_value(i, 2)
    english = sheet1.cell_value(i, 3)
    # 根據(jù)模板輸出信息
    # 打開一個模板
    doc = DocxTemplate(r"score.docx")
    data = {} #  構(gòu)造填充模板需要的數(shù)據(jù)
    data['student'] = student
    data['chinese'] = chinese
    data['math'] = math
    data['english'] = english
    doc.render(data) # 填充數(shù)據(jù)data到模板
    doc.save("{}.docx".format(student)) # 根據(jù)模板為每個學生生成成績單

程序運行后,會在當前目錄下生成以學生名字命名的word文件,如下圖:


運行結(jié)果1

生成的結(jié)果2

可以看到跟之前字符串的例子是類似的,數(shù)據(jù)自動的填充到了word模板之中.

字典

注意之前我們渲染字符串的時候,通過向字符串的format方法,傳遞變量,就可以完成字符串的填充.而渲染模板則要復雜的多,首先我們用python中的字典保存了需要填充到模板中的變量,

字典保存數(shù)據(jù)

這個跟JavaScript中的json數(shù)據(jù)格式有些類似的.python中字典的鍵值可以字符串,然后冒號后面是對應的鍵的值,比如student鍵的值是趙六,然后這些值會通過doc對象的render方法填充到word模板:
模板

word模板的寫法是,用兩個大括號包裹變量,習慣上變量兩邊有個空格,如{{ student }},data字典中student鍵值對應的值會被doc對象的render方法填充到{{ student }},也就是word模板中,更加詳細的關(guān)系如下圖
數(shù)據(jù)轉(zhuǎn)換

包括注釋和空行在內(nèi)不到30行代碼,就可以很輕松的生成成績單了.當然代碼是可以更加精簡的,但是會更難以理解.


18行代碼

docx-mailmerge庫

python有豐富的第三方庫,實際上早已經(jīng)有人想到用python模擬郵件合并,并專門寫了一個庫docx-mailmerge,但是這個庫需要用戶熟悉郵件合并,并有插入域的操作,不如直接在word里用jinja2的語法生成模板來的方便.所以不予采用.但是這個方法不需要理解字典這種數(shù)據(jù)結(jié)構(gòu).

小結(jié)

通過不到30行代碼,哪怕是成千上萬條數(shù)據(jù),也可以方便的用python生成成績報告了.

擴展

其實python讀取word/excel/ppt和生成word/excel/ppt都是很容易的,而且根據(jù)成績生成圖表也是很容的,所以往成績單插入折線圖/雷達圖也是很容易的,也可以讀取別的word中的內(nèi)容插入到成績單,或者讀取excel的數(shù)據(jù),批量插入到ppt中.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

  • python學習筆記 聲明:學習筆記主要是根據(jù)廖雪峰官方網(wǎng)站python學習學習的,另外根據(jù)自己平時的積累進行修正...
    renyangfar閱讀 3,237評論 0 10
  • 當年的上天梯三姐妹,可是南湖水大壩邊上一道靚麗的風景,我陪襯著也靚麗一下。而今時光飛逝,轉(zhuǎn)眼二十載,今日喜相聚,大...
    DAN524閱讀 290評論 0 0
  • 昨晚睡不著時我又在看《流星花園》的搞笑片段,恍恍惚惚我感覺我又回到了大一暑假,那時我在觀內(nèi)外學手繪,二姐剛失戀又每...
    Hazel馬閱讀 245評論 0 0
  • 自古逢秋悲長空,登臨石南大不同。 斜陽草樹霧嵐輕,尋常巷陌禪意濃。 地振高崗挽盧弓,門朝清溪護蒼龍。 魚池山月來相...
    朱二哥的一些事一些情閱讀 230評論 0 6

友情鏈接更多精彩內(nèi)容