zoukankan      html  css  js  c++  java
  • Python办公自动化之批量生成文档

    在日常工作中,类似合同一样的文档通常都会有固定的模板,如偶尔编辑一两份文档,则可以手动完成。假如同一个模板有一百份或更多文档需要生成呢?如果手工逐个文档的编辑保存,不仅容易出错,还是一项费力不讨好的工作;如果能够根据模板批量生成文档,则会大大提高工作效率,减少出错的几率。本文以一个简单的小例子,简述如何通过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')
    View Code

    示例截图

    批量文档生成后,截图如下所示:

     合同文档内文,如下所示:

     以上就是批量生成文档的全部内容,可以看出,生成后的文档,格式与模板保持一致。

    备注

    书愤五首·其一

    【作者】陆游 【朝代】宋

    早岁那知世事艰,中原北望气如山。

    楼船夜雪瓜洲渡,铁马秋风大散(sǎn)关。

    塞上长城空自许,镜中衰鬓已先斑。

    出师一表真名世,千载谁堪伯仲间。


    作者:Alan.hsiang
    出处:http://www.cnblogs.com/hsiang/
    本文版权归作者和博客园共有,写文不易,支持原创,欢迎转载【点赞】,转载请保留此段声明,且在文章页面明显位置给出原文连接,谢谢。

  • 相关阅读:
    Go语言学习资源
    优秀编程学习网站
    我对架构的理解
    【转】TCP协议中的三次握手和四次挥手(图解)
    【转】asp.net c# 网上搜集面试题目大全(附答案)
    spring framework 4 源码阅读
    浮点类型
    把二元查找树转变成排序的双向链表
    用模板写快速排序-链表
    用模板写快速排序-数组
  • 原文地址:https://www.cnblogs.com/hsiang/p/15041676.html
Copyright © 2011-2022 走看看