docxtpl

基于docxtpl的自动化报告生成(基于word模板)

在阅读这篇文章之前,可以去看我以前写过相似的自动化报告生成文章
ps:以前在新浪博客写,然后各种被删贴后换过来这边了

  • 基于python-docx文本生成word文档 (http://blog.sina.com.cn/s/blog_1473990d60102x4fr.html)
  • 基于tushare文本生成word文档(http://blog.sina.com.cn/s/blog_1473990d60102x4fs.html)
  • 自动化接口文档生成(http://blog.sina.com.cn/s/blog_1473990d60102yhr3.html)

特别感谢

  • https://blog.csdn.net/u012117917/article/details/41604711 CSS 颜色代码大全 CSS颜色对照表
  • https://blog.csdn.net/sunchengquan/article/details/80369304 python批量操作word文档实战
  • https://blog.csdn.net/zhang__ao/article/details/80745873 echarts标题(title)配置
    以上三篇文章。此文是基于以上三篇文章的实施文章。

此文分3部分

  1. 模板设置
  2. 图片生成
  3. 数据/图片插入模板中生成word文件

模板设置

docxtpl_第1张图片
这里,文档中的{{qe}},{{mie}}等都是作为指代参数参数使用,需要跟代码中的指代参数保持一致。
表示方法a为具体的某个指代
表示方法b为表格数据指代
表格的数据格式为

[{'city': '广东省', 'mie': 13885, 'toimie': '5476.71', 'qie': 18158, 'toiqie': '15736.47'},
 {'city': '浙江省', 'mie': 2350, 'toimie': '2861.79', 'qie': 1059, 'toiqie': '859.79'}]

图片生成

此处我是先用pyecharts生成html,再对html图片进行截图。
采用方法:http://pyecharts.org/#/zh-cn/render_images
中的snapshot_selenium,使用 Chrome 浏览器。具体的配置方法可以参考我以前写的

  • 高新技术企业认定工作网(页面截图) (http://blog.sina.com.cn/s/blog_1473990d60102xaf0.html)
    这里不再多说
    相关代码如下
# ************************************画图*****************************************
    from pyecharts.charts import Bar,Grid,Pie
    from pyecharts import options as opts

    # 方形图
    subtitle = ''
    title = '图1.1:***********投资前10省分布'
    path_html = './picture/1.小册子-总体情况.html'
    path_png = "./picture/1.小册子-总体情况.png"
    draw_data = table_1[:10].sort_values(['toimie'], ascending=True)
    x_lable = draw_data['city'].to_list()
    y_data_1 = [format('%.2f'%i) for i in draw_data['toimie'].to_list()]
    y_data_2 = [format('%.2f'%i) for i in draw_data['toiqie'].to_list()]
    init_opts = opts.InitOpts(width="480px", height="360px")
    plt = (
        Bar(init_opts=init_opts)
            .set_global_opts(title_opts=opts.TitleOpts(title=title, # 标题
                                                       # subtitle = subtitle, # 副标题
                                                       pos_left='center',pos_top='bottom', # 标题位置
                                                       title_textstyle_opts = {
                                                           'fontSize':10.5
                                                       }
                                                       ),
                             yaxis_opts=opts.AxisOpts( # Y轴设置

                             ),
                             xaxis_opts=opts.AxisOpts(   # X轴设置
                                # type_="category"     # 行坐标类型
                             ),
                             legend_opts=opts.LegendOpts(type_='scroll',    # 图例
                                                         orient='vertical',  # 图例列表的布局朝向
                                                         pos_left="center", pos_top='center'   # 图例位置
                                                         ),
                             tooltip_opts=opts.TooltipOpts(trigger='axis'),
                             toolbox_opts=opts.ToolboxOpts(),  # 工具栏
                             # datazoom_opts=opts.DataZoomOpts(),  # 缩放功能

                             )
            .set_series_opts(label_opts=opts.LabelOpts(# is_show=False,       # 是否显示数值
                                                       position="right" ,     # 设置字体对齐
                                                       ))
        #     .extend_axis(           # 双轴
        #     yaxis=opts.AxisOpts()
        # )
            .add_xaxis(x_lable
                       )
            .add_yaxis('****投资总额(亿元)', y_data_1,label_opts=opts.LabelOpts(position='right', # 标签文字位置
                                                                        font_weight='bolder',    # 标签字体
                                                                        # color='#FFC8B4'
                                                                        ),
                                                    # color='#FFC8B4'

                       )
            .add_yaxis('对****投资总额(亿元)', y_data_2,label_opts=opts.LabelOpts(position='right',font_weight='bolder'))
            .reversal_axis()  # 转轴
    )
    grid = Grid(init_opts=init_opts)
    grid.add(plt, grid_opts=opts.GridOpts(pos_top='5'))  # 仅使用pos_top修改相对顶部的位置
    grid.render(path_html)


    # 玫瑰图
    subtitle = '图1.2:**********互投行业明细'
    title = '外圈:***投资总额  内圈:对****投资总额'
    path_html_1 = './picture/1.小册子-总体情况_1.html'
    path_png_1 = "./picture/1.小册子-总体情况_1.png"
    code_num = len(table_2['code'].to_list())
    # code_num = 10
    draw_data = \
        [[table_2['code'].to_list()[i],format('%.2f'%table_2['toimie'].to_list()[i])]
         for i in range(code_num) ]
    draw_data_1 = \
        [[table_2['code'].to_list()[i],format('%.2f'%table_2['toiqie'].to_list()[i])]
         for i in range(code_num)]
    init_opts_pie = opts.InitOpts(width="640px", height="480px")
    plt = (
        Pie(init_opts=init_opts_pie)
            .set_global_opts(title_opts=opts.TitleOpts(title=title,  # 标题
                                                       subtitle = subtitle, # 副标题
                                                       pos_left='center', pos_bottom='0',  # 标题位置
                                                       title_textstyle_opts={              # 主标题
                                                           'fontSize': 16.5,               # 字体大小
                                                           "fontWeight": "bolder",         # 字体:加粗
                                                           "color": "#444444"              # 字体颜色
                                                       },
                                                       subtitle_textstyle_opts={           # 负标题
                                                           'fontSize': 16.5,
                                                            "fontWeight": "bolder",
                                                            "color": "#000000"
                                                       }
                                                       ),
                             yaxis_opts=opts.AxisOpts(  # Y轴设置

                             ),
                             xaxis_opts=opts.AxisOpts(  # X轴设置
                                 # type_="category"     # 行坐标类型
                             ),
                             legend_opts=opts.LegendOpts(type_='scroll',  # 图例
                                                         orient='vertical',  # 图例列表的布局朝向
                                                         pos_left="left", pos_top='center'  # 图例位置
                                                         ),
                             tooltip_opts=opts.TooltipOpts(trigger='axis'),
                             toolbox_opts=opts.ToolboxOpts(),  # 工具栏
                             # datazoom_opts=opts.DataZoomOpts(),  # 缩放功能

                             )
            .set_series_opts(label_opts=opts.LabelOpts(# is_show=False,       # 是否显示数值
            position="right",  # 设置字体对齐
        ))
            .add(
            "对****投资总额",
            draw_data_1,
            radius=["15%", "30%"],
            # center=["25%", "50%"],    # 中心点位置
            # rosetype="radius",
            label_opts=opts.LabelOpts(is_show=True,formatter="{b}: {c}",font_weight='bolder',),
        )
            .add(
            "****投资总额",
            draw_data,
            radius=["65%", "80%"],
            # center=["75%", "50%"],
            # rosetype="area",
            label_opts=opts.LabelOpts(is_show=True,formatter="{b}: {c}",font_weight='bolder',),
        )
    )
    grid_1 = Grid(init_opts=init_opts_pie)
    grid_1.add(plt, grid_opts=opts.GridOpts(pos_top='5'))  # 仅使用pos_top修改相对顶部的位置
    grid_1.render(path_html_1)


    # html转图片
    from pyecharts.render import make_snapshot
    from snapshot_selenium import snapshot
    make_snapshot(snapshot, grid.render(path_html), path_png,delay=2,pixel_ratio=2)
    make_snapshot(snapshot, grid_1.render(path_html_1), path_png_1,delay=2,pixel_ratio=2)

数据/图片插入模板中生成word文件

这里是将生成好的数据与图片插入到word中,使用的是jinja2,docxtpl,docx这3个包
代码如下

    import jinja2
    from jinja2.utils import Markup
    from docxtpl import DocxTemplate
    from docxtpl import InlineImage
    from docx.shared import Mm, Inches, Pt

    tpl=DocxTemplate(r'./source/from/1.小册子-总体情况.docx')


        # 20191129针对缺失值修改为 '-' 显示
    table_1 = \
         [{'city': row.city,
           'mie':'-' if format('%.0f' %row.mie) == 'nan' else format('%.0f' %row.mie),
           'toimie': '-' if format('%.2f' % row.toimie) == 'nan' else format('%.2f' % row.toimie),
           'qie': '-' if format('%.0f' % row.qie) == 'nan' else format('%.0f' % row.qie),
           'toiqie': '-' if format('%.2f' % row.toiqie) == 'nan' else format('%.2f' % row.toiqie)}
          for index, row in table_1.iterrows()]
     table_2 = \
         [{'code': row.code,
           'mie': '-' if format('%.0f' % row.mie) == 'nan' else format('%.0f' % row.mie),
           'toimie': '-' if format('%.2f' % row.toimie) == 'nan' else format('%.2f' % row.toimie),
           'qie': '-' if format('%.0f' % row.qie) == 'nan' else format('%.0f' % row.qie),
           'toiqie': '-' if format('%.2f' % row.toiqie) == 'nan' else format('%.2f' % row.toiqie), }
          for index, row in table_2.iterrows()]

    context={
        'year':year,
        'quarter':quarter,
        'qe':qe,
        'mie':mie,
        'toimie':toimie,
        'me':me,
        'qie':qie,
        'toiqie':toiqie,
        'pic_1': InlineImage(tpl, path_png,width=Mm(125)),
        'pic_2': InlineImage(tpl, path_png_1, width=Mm(100)),
        'table_1':table_1,
        'table_2': table_2
              }
    jinja_env = jinja2.Environment(autoescape=True)
    tpl.render(context,jinja_env)
    tpl.save(r'./result/1.小册子-*****总体情况.docx')

效果图
docxtpl_第2张图片
docxtpl_第3张图片

你可能感兴趣的:(Z类分类_python包的使用)