在日常工作中,类似合同一样的文档通常都会有固定的模板,如偶尔编辑一两份文档,则可以手动完成。假如同一个模板有一百份或更多文档需要生成呢?如果手工逐个文档的编辑保存,不仅容易出错,还是一项费力不讨好的工作;如果能够根据模板批量生成文档,则会大大提高工作效率,减少出错的几率。本文以一个简单的小例子,简述如何通过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)关。
塞上长城空自许,镜中衰鬓已先斑。
出师一表真名世,千载谁堪伯仲间。