Appearance
6.1 自动化日报生成器
在企业日常运营中,定期生成和发送各类报告是一项常见但繁琐的工作。特别是日报这类高频次的报告,如果能够实现自动化,将大大提高工作效率。本节将介绍如何使用Python构建一个完整的自动化日报生成器,实现从数据收集、报告生成到邮件发送的全流程自动化。
需求分析
一个典型的自动化日报生成流程通常包括以下步骤:
- 数据收集与处理:从Excel表格中读取原始数据,进行必要的清洗和计算
- 报告生成:将处理后的数据生成为格式化的Word文档报告
- 邮件发送:将生成的报告作为附件,发送给指定收件人
技术选型
我们将使用以下Python库来实现各个环节:
- pandas:用于Excel数据读取和处理
- python-docx:用于生成Word文档报告
- matplotlib/seaborn:用于生成数据可视化图表
- smtplib/email:用于发送邮件
代码实现
第一步:读取和处理Excel数据
python
import pandas as pd
import numpy as np
from datetime import datetime, timedelta
def read_and_process_data(excel_path):
"""读取并处理Excel数据"""
# 读取Excel文件
df = pd.read_excel(excel_path)
# 数据清洗
df = df.dropna(subset=['日期', '销售额']) # 删除关键字段为空的行
# 数据转换
df['日期'] = pd.to_datetime(df['日期'])
df['销售额'] = df['销售额'].astype(float)
# 按日期筛选最近一天的数据
latest_date = df['日期'].max()
today_data = df[df['日期'] == latest_date]
# 计算关键指标
total_sales = today_data['销售额'].sum()
avg_sales = today_data['销售额'].mean()
max_sales = today_data['销售额'].max()
max_sales_product = today_data.loc[today_data['销售额'].idxmax()]['产品名称']
# 按产品类别统计
category_sales = today_data.groupby('产品类别')['销售额'].sum().reset_index()
# 计算环比数据(与前一天相比)
yesterday = latest_date - timedelta(days=1)
yesterday_data = df[df['日期'] == yesterday]
yesterday_sales = yesterday_data['销售额'].sum() if not yesterday_data.empty else 0
sales_growth = ((total_sales - yesterday_sales) / yesterday_sales * 100) if yesterday_sales > 0 else 0
# 返回处理后的数据
return {
'report_date': latest_date.strftime('%Y年%m月%d日'),
'total_sales': total_sales,
'avg_sales': avg_sales,
'max_sales': max_sales,
'max_sales_product': max_sales_product,
'sales_growth': sales_growth,
'category_sales': category_sales,
'daily_data': today_data
}
第二步:生成数据可视化图表
python
import matplotlib.pyplot as plt
import seaborn as sns
import os
def generate_charts(data, output_folder):
"""生成数据可视化图表"""
# 确保输出文件夹存在
os.makedirs(output_folder, exist_ok=True)
# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
# 图1:产品类别销售额饼图
plt.figure(figsize=(8, 6))
plt.pie(data['category_sales']['销售额'],
labels=data['category_sales']['产品类别'],
autopct='%1.1f%%', startangle=90)
plt.title(f"{data['report_date']}销售额类别分布")
plt.tight_layout()
pie_chart_path = os.path.join(output_folder, 'category_sales_pie.png')
plt.savefig(pie_chart_path)
plt.close()
# 图2:产品销售额条形图(Top 5)
top_products = data['daily_data'].nlargest(5, '销售额')
plt.figure(figsize=(10, 6))
sns.barplot(x='销售额', y='产品名称', data=top_products)
plt.title(f"{data['report_date']}销售额Top5产品")
plt.tight_layout()
bar_chart_path = os.path.join(output_folder, 'top_products_bar.png')
plt.savefig(bar_chart_path)
plt.close()
return {
'pie_chart_path': pie_chart_path,
'bar_chart_path': bar_chart_path
}
第三步:生成Word报告
python
from docx import Document
from docx.shared import Inches, Pt, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.enum.style import WD_STYLE_TYPE
def generate_report(data, charts, output_path):
"""生成Word格式的日报"""
doc = Document()
# 设置文档样式
styles = doc.styles
style = styles.add_style('CustomHeading1', WD_STYLE_TYPE.PARAGRAPH)
style.font.size = Pt(18)
style.font.bold = True
style.font.color.rgb = RGBColor(0, 0, 128) # 深蓝色
# 添加标题
title = doc.add_paragraph(f"销售日报 - {data['report_date']}")
title.alignment = WD_ALIGN_PARAGRAPH.CENTER
title.style = 'CustomHeading1'
# 添加摘要部分
doc.add_heading('一、销售概况', level=1)
summary = doc.add_paragraph()
summary.add_run(f"报告日期:{data['report_date']}\n").bold = True
summary.add_run(f"总销售额:{data['total_sales']:.2f} 元\n")
summary.add_run(f"平均单品销售额:{data['avg_sales']:.2f} 元\n")
summary.add_run(f"销售额最高产品:{data['max_sales_product']} ({data['max_sales']:.2f} 元)\n")
# 添加环比分析
doc.add_heading('二、环比分析', level=1)
growth = doc.add_paragraph()
if data['sales_growth'] > 0:
growth.add_run(f"销售额较前日增长:{data['sales_growth']:.2f}%\n").bold = True
else:
growth.add_run(f"销售额较前日下降:{abs(data['sales_growth']):.2f}%\n").bold = True
# 添加图表
doc.add_heading('三、销售分布', level=1)
doc.add_paragraph('3.1 产品类别销售分布')
doc.add_picture(charts['pie_chart_path'], width=Inches(5))
doc.add_paragraph('3.2 销售额Top5产品')
doc.add_picture(charts['bar_chart_path'], width=Inches(6))
# 添加详细数据表格
doc.add_heading('四、销售明细', level=1)
table = doc.add_table(rows=1, cols=4)
table.style = 'Table Grid'
# 设置表头
header_cells = table.rows[0].cells
header_cells[0].text = '产品名称'
header_cells[1].text = '产品类别'
header_cells[2].text = '销售数量'
header_cells[3].text = '销售额'
# 添加数据行
for _, row in data['daily_data'].iterrows():
cells = table.add_row().cells
cells[0].text = row['产品名称']
cells[1].text = row['产品类别']
cells[2].text = str(row['销售数量'])
cells[3].text = f"{row['销售额']:.2f}"
# 保存文档
doc.save(output_path)
return output_path
第四步:发送邮件
python
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
import os
def send_email(report_path, recipients, sender_email, sender_password, smtp_server, smtp_port):
"""发送邮件"""
# 创建邮件对象
msg = MIMEMultipart()
msg['From'] = sender_email
msg['To'] = ', '.join(recipients)
# 获取当前日期作为邮件主题
report_date = os.path.basename(report_path).split('.')[0].split('_')[-1]
msg['Subject'] = f"销售日报 - {report_date}"
# 邮件正文
body = f"""
尊敬的团队成员:
附件是{report_date}的销售日报,请查收。
主要内容包括:
1. 销售概况
2. 环比分析
3. 销售分布图表
4. 销售明细数据
如有疑问,请回复此邮件。
此致
销售分析团队
"""
msg.attach(MIMEText(body, 'plain'))
# 添加附件
with open(report_path, 'rb') as file:
attachment = MIMEApplication(file.read(), _subtype="docx")
attachment.add_header('Content-Disposition', 'attachment', filename=os.path.basename(report_path))
msg.attach(attachment)
# 发送邮件
try:
server = smtplib.SMTP(smtp_server, smtp_port)
server.starttls() # 启用TLS加密
server.login(sender_email, sender_password)
server.send_message(msg)
server.quit()
print(f"邮件已成功发送至{len(recipients)}位收件人")
return True
except Exception as e:
print(f"发送邮件时出错: {e}")
return False
第五步:整合所有功能
python
def generate_daily_report(excel_path, output_folder, report_filename, email_config=None):
"""生成并发送日报的主函数"""
# 确保输出文件夹存在
os.makedirs(output_folder, exist_ok=True)
# 步骤1:读取和处理数据
print("正在读取和处理Excel数据...")
data = read_and_process_data(excel_path)
# 步骤2:生成图表
print("正在生成数据可视化图表...")
charts_folder = os.path.join(output_folder, 'charts')
charts = generate_charts(data, charts_folder)
# 步骤3:生成Word报告
print("正在生成Word报告...")
report_path = os.path.join(output_folder, report_filename)
generate_report(data, charts, report_path)
print(f"报告已生成: {report_path}")
# 步骤4:发送邮件(如果提供了邮件配置)
if email_config:
print("正在发送邮件...")
send_email(
report_path,
email_config['recipients'],
email_config['sender_email'],
email_config['sender_password'],
email_config['smtp_server'],
email_config['smtp_port']
)
return report_path
# 使用示例
if __name__ == "__main__":
# 配置参数
excel_path = "sales_data.xlsx"
output_folder = "reports"
report_date = datetime.now().strftime("%Y%m%d")
report_filename = f"销售日报_{report_date}.docx"
# 邮件配置
email_config = {
'recipients': ['team1@example.com', 'team2@example.com'],
'sender_email': 'reports@company.com',
'sender_password': 'your_password', # 建议使用环境变量存储密码
'smtp_server': 'smtp.company.com',
'smtp_port': 587
}
# 生成并发送日报
generate_daily_report(excel_path, output_folder, report_filename, email_config)
实际应用场景
1. 销售团队日报
销售团队可以使用此工具自动生成每日销售报告,包括销售额、订单数、客户转化率等关键指标,帮助团队及时了解销售情况并做出决策。
2. 运营数据日报
网站或APP运营团队可以自动生成包含用户活跃度、新增用户、页面访问量等数据的日报,监控产品运营状况。
3. 财务日报
财务部门可以自动生成包含收入、支出、利润等财务指标的日报,帮助管理层掌握公司财务状况。
4. 生产线监控报告
制造业可以自动生成包含生产效率、质量指标、设备运行状态等数据的日报,及时发现并解决生产问题。
进阶优化
1. 定时任务调度
使用schedule
库或系统的cron任务实现定时自动执行:
python
import schedule
import time
def job():
print("开始生成每日报告...")
generate_daily_report(excel_path, output_folder, report_filename, email_config)
print("报告生成完成!")
# 设置每天早上9点执行
schedule.every().day.at("09:00").do(job)
while True:
schedule.run_pending()
time.sleep(60) # 每分钟检查一次是否有待执行的任务
2. 数据源扩展
除了从Excel读取数据,还可以扩展为从数据库、API或其他数据源获取数据:
python
def get_data_from_database():
"""从数据库获取销售数据"""
import sqlite3
conn = sqlite3.connect('sales.db')
query = """SELECT date, product_name, category, quantity, amount
FROM sales WHERE date = date('now', '-1 day')"""
df = pd.read_sql_query(query, conn)
conn.close()
return df
def get_data_from_api():
"""从API获取销售数据"""
import requests
response = requests.get('https://api.company.com/sales/daily',
headers={'Authorization': 'Bearer YOUR_API_KEY'})
data = response.json()
df = pd.DataFrame(data['sales'])
return df
3. 报告模板化
使用Word模板进一步简化报告生成过程:
python
from docxtpl import DocxTemplate
def generate_report_from_template(data, charts, template_path, output_path):
"""使用模板生成Word报告"""
doc = DocxTemplate(template_path)
# 准备模板变量
context = {
'report_date': data['report_date'],
'total_sales': f"{data['total_sales']:.2f}",
'avg_sales': f"{data['avg_sales']:.2f}",
'max_sales_product': data['max_sales_product'],
'max_sales': f"{data['max_sales']:.2f}",
'sales_growth': f"{data['sales_growth']:.2f}"
}
# 渲染模板并保存
doc.render(context)
doc.save(output_path)
# 在保存后添加图片(需要使用python-docx)
doc_with_images = Document(output_path)
for paragraph in doc_with_images.paragraphs:
if '{{pie_chart}}' in paragraph.text:
paragraph.text = ''
run = paragraph.add_run()
run.add_picture(charts['pie_chart_path'], width=Inches(5))
elif '{{bar_chart}}' in paragraph.text:
paragraph.text = ''
run = paragraph.add_run()
run.add_picture(charts['bar_chart_path'], width=Inches(6))
doc_with_images.save(output_path)
return output_path
4. 多格式报告支持
除了Word格式,还可以支持生成PDF、HTML或Markdown格式的报告:
python
def convert_word_to_pdf(word_path, pdf_path):
"""将Word文档转换为PDF"""
from docx2pdf import convert
convert(word_path, pdf_path)
return pdf_path
def generate_html_report(data, charts):
"""生成HTML格式的报告"""
import jinja2
# 加载HTML模板
template_loader = jinja2.FileSystemLoader(searchpath="./templates")
template_env = jinja2.Environment(loader=template_loader)
template = template_env.get_template("report_template.html")
# 准备模板变量
context = {
'report_date': data['report_date'],
'total_sales': f"{data['total_sales']:.2f}",
'avg_sales': f"{data['avg_sales']:.2f}",
'max_sales_product': data['max_sales_product'],
'max_sales': f"{data['max_sales']:.2f}",
'sales_growth': f"{data['sales_growth']:.2f}",
'pie_chart': charts['pie_chart_path'],
'bar_chart': charts['bar_chart_path']
}
# 渲染HTML
html_content = template.render(context)
# 保存HTML文件
html_path = f"reports/销售日报_{data['report_date']}.html"
with open(html_path, 'w', encoding='utf-8') as f:
f.write(html_content)
return html_path
小结
通过本节的学习,我们实现了一个功能完整的自动化日报生成器,它能够:
- 从Excel表格中读取和处理数据
- 生成数据可视化图表
- 创建格式化的Word报告
- 通过邮件发送报告
- 支持定时执行和多种数据源
这个自动化工具可以为企业节省大量人力和时间成本,提高工作效率,同时保证报告的一致性和准确性。通过进一步的扩展和定制,它可以适应各种不同的业务场景和需求。
在实际应用中,你可以根据自己的需求调整报告的内容和格式,添加更多的数据分析和可视化,或者集成到更大的自动化工作流程中。