在日常工作中,類似合同一樣的文檔通常都會有固定的模板,如偶爾編輯一兩份文檔,則可以手動完成。假如同一個模板有一百份或更多文檔需要生成呢?如果手工逐個文檔的編輯保存,不僅容易出錯,還是一項費力不討好的工作;如果能夠根據模板批量生成文檔,則會大大提高工作效率,減少出錯的幾率。本文以一個簡單的小例子,簡述如何通過Python批量生成文檔,僅供學習分享使用,如有不足之處,還請指正。
涉及知識點
- xlrd模塊,用於Excel文檔的讀取,其中xldate_as_tuple,主要用於Excel讀取時的日期格式處理。
- python-docx 模塊,用於word文檔的相關操作。
場景介紹
現有一份簡化的合同模板,其中紅色箭頭所指的地方,均是需要替換的地方,如下所示:
同時有21名員工入職,需要簽署這份合同,如下所示:
本文的功能就是根據模板文檔,為21名員工,分別生成合同文檔。
核心代碼
1. 讀取數據
讀取Excel的數據,並返回數據列表,將此功能封裝成單獨的函數,如下所示:
1 def read_data(filename: str = None): 2 """ 3 讀取Excel文件內容 4 :param fileName: 5 :return: 6 """ 7 datas = [] 8 work_book = xlrd.open_workbook(filename=filename) 9 sheet = work_book.sheet_by_index(0) 10 for i in range(1, sheet.nrows): 11 # 日期格式轉換 12 birthday = xldate_as_tuple(sheet.cell_value(i, 6), 0) 13 birthday2 = '%(year)d-%(month)d-%(day)d' % {'year': birthday[0], 'month': birthday[1], 'day': birthday[2]} 14 bpdate = xldate_as_tuple(sheet.cell_value(i, 15), 0) 15 bpdate2 = '%(year)d-%(month)d-%(day)d' % {'year': bpdate[0], 'month': bpdate[1], 'day': bpdate[2]} 16 data = { 17 'bpCompanyName': sheet.cell_value(i, 0), 18 'bpAddress': sheet.cell_value(i, 1), 19 'bpBoss': sheet.cell_value(i, 2), 20 'bpManager': sheet.cell_value(i, 3), 21 'bpWorker': sheet.cell_value(i, 4), 22 'bpSex': sheet.cell_value(i, 5), 23 'bpBirthday': birthday2, 24 'bpHomeAddress': sheet.cell_value(i, 7), 25 'bpId': sheet.cell_value(i, 8), 26 'bpBeginYear': int(sheet.cell_value(i, 9)), # 整數格式處理 27 'bpBeginMonth': int(sheet.cell_value(i, 10)), # 整數格式處理 28 'bpBeginDay': int(sheet.cell_value(i, 11)), # 整數格式處理 29 'bpEndYear': int(sheet.cell_value(i, 12)), # 整數格式處理 30 'bpEndMonth': int(sheet.cell_value(i, 13)), # 整數格式處理 31 'bpEndDay': int(sheet.cell_value(i, 14)), # 整數格式處理 32 'bpDate': bpdate2, 33 'bpSigner': sheet.cell_value(i, 16) 34 } 35 datas.append(data) 36 return datas
2. 單個合同文檔生成
Excel的每一行代表一名員工,生成一份合同文檔【遍歷每一個段落,以及每一個段落的文本,逐個替換文本中的變量內容,且保持原有的格式不變】,如下所示:
1 def write_docx(data, template): 2 """ 3 生成文檔 4 :param data: 5 :return: 6 """ 7 8 doc = Document(docx=template) 9 paragraphs = doc.paragraphs 10 for paragraph in paragraphs: 11 for run in paragraph.runs: 12 for key in data.keys(): 13 run_text = run.text.replace(key, str(data[key])) 14 run.text = run_text 15 doc.save('合同/%s合同.docx' % data['bpWorker'])
3. 批量文檔生成
遍歷所有的員工信息,逐一生成文檔,如下所示:
1 def batch_write_docx(datas, template): 2 """ 3 批量操作 4 :param datas: 5 :return: 6 """ 7 for data in datas: 8 write_docx(data, template)
4. 綜合運用
將以上方法依次調用,就可以生成全部文檔,如下所示:
1 excel_file = '合同數據.xls' 2 template = '合同模板.docx' 3 datas = read_data(excel_file) 4 # print(datas) 5 batch_write_docx(datas, template) 6 print('done')
5. 示例完整代碼

1 import xlrd 2 from xlrd import xldate_as_tuple 3 from docx import Document 4 5 6 def read_data(filename: str = None): 7 """ 8 讀取Excel文件內容 9 :param fileName: 10 :return: 11 """ 12 datas = [] 13 work_book = xlrd.open_workbook(filename=filename) 14 sheet = work_book.sheet_by_index(0) 15 for i in range(1, sheet.nrows): 16 # 日期格式轉換 17 birthday = xldate_as_tuple(sheet.cell_value(i, 6), 0) 18 birthday2 = '%(year)d-%(month)d-%(day)d' % {'year': birthday[0], 'month': birthday[1], 'day': birthday[2]} 19 bpdate = xldate_as_tuple(sheet.cell_value(i, 15), 0) 20 bpdate2 = '%(year)d-%(month)d-%(day)d' % {'year': bpdate[0], 'month': bpdate[1], 'day': bpdate[2]} 21 data = { 22 'bpCompanyName': sheet.cell_value(i, 0), 23 'bpAddress': sheet.cell_value(i, 1), 24 'bpBoss': sheet.cell_value(i, 2), 25 'bpManager': sheet.cell_value(i, 3), 26 'bpWorker': sheet.cell_value(i, 4), 27 'bpSex': sheet.cell_value(i, 5), 28 'bpBirthday': birthday2, 29 'bpHomeAddress': sheet.cell_value(i, 7), 30 'bpId': sheet.cell_value(i, 8), 31 'bpBeginYear': int(sheet.cell_value(i, 9)), # 整數格式處理 32 'bpBeginMonth': int(sheet.cell_value(i, 10)), # 整數格式處理 33 'bpBeginDay': int(sheet.cell_value(i, 11)), # 整數格式處理 34 'bpEndYear': int(sheet.cell_value(i, 12)), # 整數格式處理 35 'bpEndMonth': int(sheet.cell_value(i, 13)), # 整數格式處理 36 'bpEndDay': int(sheet.cell_value(i, 14)), # 整數格式處理 37 'bpDate': bpdate2, 38 'bpSigner': sheet.cell_value(i, 16) 39 } 40 datas.append(data) 41 return datas 42 43 44 def write_docx(data, template): 45 """ 46 生成文檔 47 :param data: 48 :return: 49 """ 50 51 doc = Document(docx=template) 52 paragraphs = doc.paragraphs 53 for paragraph in paragraphs: 54 for run in paragraph.runs: 55 for key in data.keys(): 56 run_text = run.text.replace(key, str(data[key])) 57 run.text = run_text 58 doc.save('合同/%s合同.docx' % data['bpWorker']) 59 60 61 def batch_write_docx(datas, template): 62 """ 63 批量操作 64 :param datas: 65 :return: 66 """ 67 for data in datas: 68 write_docx(data, template) 69 70 71 excel_file = '合同數據.xls' 72 template = '合同模板.docx' 73 datas = read_data(excel_file) 74 # print(datas) 75 batch_write_docx(datas, template) 76 print('done')
示例截圖
批量文檔生成后,截圖如下所示:
合同文檔內文,如下所示:
以上就是批量生成文檔的全部內容,可以看出,生成后的文檔,格式與模板保持一致。
備注
書憤五首·其一
【作者】陸游
早歲那知世事艱,中原北望氣如山。
樓船夜雪瓜洲渡,鐵馬秋風大散(sǎn)關。
塞上長城空自許,鏡中衰鬢已先斑。
出師一表真名世,千載誰堪伯仲間。