Python自动化办公-玩转报表

Python七号

共 10473字,需浏览 21分钟

 ·

2021-08-16 10:27

你很可能也看到过公众号文章下方的广告,是关于 Python 自动化生成报表的,我自己就经常看到,说的是一个人因为报表做不出来,愁眉苦脸,做不出来就要被辞职了,这时一个高手拿过电脑,一顿操作猛如虎,一份精美的报表很快就生成了,被帮助的人写满一脸的崇拜...

其实不用崇拜,很简单,今天,我来告诉你方法。

这里说做报表,不用 excel,不用专业的报表平台,就是纯 html 生成一些漂亮的可视化报表,甚至可以交互,这样的报表你可以发 html 邮件给老板,老板不需要下载,不需要登陆专业的报表平台,打开邮件就可以直接看到,还可以点击来交互,非常方便,如果你这样做,那离升职加薪不会太远👍。

废话不多说,现在就告诉你方法。咱们以目标为导向,技术不技术的不重要,实现了就好。

1、选择一个报表模版

首先你要生成什么样的报表,这里有个网站可以供你选择,就是大名鼎鼎的 ECharts 库,https://echarts.apache.org/zh/index.html

点击所有示例,可以看到很多样例图片:

选择一个你想用的,比如,我们选择「柱状图」->「基础柱状图」

点击「下载示例」,就可以下载一个 html 文件,用浏览器打开就是这个柱状图。

现在用个编辑器打开这个 html 文件,修改其中的数据,我们就可以生成一个属于自己的报表

然后保存,这样一个报表就生成了,如果简陋一点的话,你直接把这个 html 作为邮件的附件发给老板,老板双击这个 html 文件就可以在浏览器上看到,不过这并不是完美的,万一老板的电脑没有浏览器呢。

完美的解决方案是将这些报表显示在邮件的正文。

2、用 Python 发送 html 邮件

这个 前文最简单的方式发送邮件 小节 "发送多彩的 html 邮件" 有有具体的方法和代码,这里就不重复说了。

3、使用 Jinja2 来渲染 html

第 1 步中的替换是手工操作的,假如数据量比较大,或者要批量生成报表,可能就没那么方便,这不,我们有万能的 Python 嘛。

如果用过 Django,你就知道 Jinja2 的模版大法,简单来讲,Jinja2 将一个文件中的标识替换成你需要的内容。这里我们用的正是这一点。

比如 html 文件中的有这么一段:

option = {
    xAxis: {
        type'category',
        data: ['张三''李四''王五''赵六']
    },
    yAxis: {
        type'value'
    },
    series: [{
        data: [12020015080],
        type'bar'
    }]
};

我们希望替换其中两处的 data,就可以先这样写


option = {
    xAxis: {
        type'category',
        data: {{ data1 }}
    },
    yAxis: {
        type'value'
    },
    series: [{
        data: {{ data2 }},
        type'bar'
    }]
};

然后借助 Jinja2 可以很方便的替换:

from templater import DefaultTemplater

if __name__ == "__main__":

    templater = DefaultTemplater("bar-simple.html""bar-simple-templeted.html")
    data1 = ['张三1''李四2''王五3''赵六4']
    data2 = [312032003150980]
    tags = {
        "data1": data1,
        "data2": data2,
    }
    templater.render(tags)

打开 bar-simple-templeted.html 发现已经被替换掉了,在批量制作报表时,是不是很方便?

这里用到了 DefaultTemplater,其实现代码如下 (templater.py):

# templater.py
from dataclasses import dataclass
from typing import Dict
from jinja2 import Template


@dataclass
class DefaultTemplater(object):
    """ Allow to inject data in a jinja2 templated file and write the result to specified destination """

    source: str
    destination: str

    def render(self, data: Dict) -> None:
        """ Write template from source filled with data to destination
        Args:
        data: the data to inject in the template
        """

        self.load_template()
        filled_template = self.replace(data)
        self.write_filled_template(filled_template)

    def load_template(self) -> None:
        """ Load template from source
        """

        with open(self.source, "r"as f:
            self.template = f.read()

    def replace(self, values: Dict) -> str:
        """ Replace tag in template with values
        Args:
        values: dict with key: tag to search in template, value: value to replace the tag
        """

        template = Template(self.template)
        templated = template.render(**values)
        return templated

    def write_filled_template(self, content: str):
        """Write the result of the template and injected value to destination
        Args:
        content: what to write
        """

        with open(self.destination, "w"as f:
            f.write(content)

比如说一些更酷炫的:

其 html 代码如下(与 echarts 上下载的略有调整):

<!DOCTYPE html>
<html style="height: 100%">
    <head>
        <meta charset="utf-8">
    </head>
    <body style="height: 100%; margin: 0">
        <div id="container" style="height: 100%"></div>

        <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts@5/dist/echarts.min.js"></script>     

        <script type="text/javascript">
var dom = document.getElementById("container");
var myChart = echarts.init(dom);
var app = {};

var option;



var data_list = [
       [12345],
       [84323],
       [596103],
       [97476],
       [54329]
]

option = {
    xAxis: {
        max'dataMax',
    },
    yAxis: {
        type'category',
        data: ['A''B''C''D''E'],
        inversetrue,
        animationDuration300,
        animationDurationUpdate300,
        max4 // only the largest 3 bars will be displayed
    },
    series: [{
        realtimeSorttrue,
        name'X',
        type'bar',
        data: data_list[0],
        label: {
            showtrue,
            position'right',
            valueAnimationtrue
        }
    }],
    legend: {
        showtrue
    },
    animationDuration0,
    animationDurationUpdate3000,
    animationEasing'linear',
    animationEasingUpdate'linear'
};

var index = 1;

function run ({
    var data = option.series[0].data;
    if(index >= data_list.length){
        return;
    }
    for (var i = 0; i < data.length; ++i) {
        data[i] = data_list[index][i];
    }
    index++;
    myChart.setOption(option);
}


setInterval(function ({
    run();
}, 3000);

if (option && typeof option === 'object') {
    myChart.setOption(option);
}

        
</script>
    </body>
</html>

你只需要修改 data_list 和 yAxis 的分类就可以实现自己想要的动态报表。

最好懂一点 javascript 的语法,这样可以改一改数据的结构,更方便的生成自己想要的报表。

最后的话

要生成报表,其实并不需要太精通技术,从网上下载个模版,自己改下数据和分类,就可以制作一个 html 报表,然后将 html 作为邮件正文发送出去,也可以转成图片、pdf 发送,具体场景就看自己需求了。如果要批量制作很多同类报表,可以借助 Jinja2 的模版大法,批量替换报表中的数据,更高效的完成。

如果你也在学习 Python,不妨关注一下我,每天学习一个 Python 技巧。

推荐阅读:

Python自动化办公-玩转图表

有问题?留言讨论


浏览 21
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报