优秀的编程知识分享平台

网站首页 > 技术文章 正文

告别复制粘贴!Python 一键生成 Excel 月报 / 周报模板

nanyue 2025-09-29 09:05:16 技术文章 1 ℃

每次到了写周报、月报的日子,你是不是也在重复这些机械操作:打开上个月的 Excel 表,复制一份改文件名,手动修改标题里的日期,还要检查格式有没有乱 —— 看似 5 分钟能搞定,可每周每月都来一次,一年下来浪费的时间竟能凑出好几部电影时长。

作为天天跟自动化打交道的 Python 开发者,今天就带大家用 30 行代码搞定 Excel 模板自动生成,从此跟复制粘贴说再见,让周报月报 “一键到位”。

一、先想清楚:自动化生成模板的核心逻辑

其实 Excel 模板自动化的本质很简单,就四步,咱们用 “人话” 拆解下,新手也能懂:

  1. 定 “骨架”:模板的样式是固定的(比如标题位置、表头内容、列宽),要么用现成的 Excel 当基础模板,要么用代码直接 “画” 出骨架;
  2. 算 “动态值”:唯一要变的是日期(比如本月 1 日到 30 日、本周一到周日),用 Python 自动计算,不用手动查日历;
  3. 填 “内容”:把计算好的日期、标题(比如 “2024 年 8 月销售月报”)填到模板对应的位置;
  4. 存 “文件”:自动创建文件夹,按 “年份 + 月份 + 用途” 命名文件(比如 “2024 年 8 月_销售月报.xlsx”),不用再手动建文件夹改名字。

二、工具选对,效率翻倍:为什么用 openpyxl?

做 Excel 自动化的库不少,但适合 “生成模板” 的,首推openpyxl—— 它是 Python 处理 Excel(.xlsx 格式)的 “全能选手”,既能新建表格,又能修改现有表格,还能精确控制格式(字体、对齐、合并单元格),完全满足模板生成的需求。

反观其他库,比如xlwt只支持旧版.xls 格式,pandas更擅长数据处理,格式控制很麻烦,所以openpyxl是最优解。

先别急着写代码,先把工具装好,打开终端输一行命令就行:

bash

pip install openpyxl

这里提醒一句:尽量装 3.0 以上版本,旧版本可能会有中文路径报错的问题,后面会讲怎么避坑。

三、实战:30 行代码生成月报模板

咱们先从月报入手,假设你需要的月报模板包含三个核心元素:大标题(带月份)、日期区间(当月 1 日到月末)、表头(日期 / 产品 / 销量 / 单价 / 销售额)。直接上可运行的代码,每一步都标了注释,跟着做就行:

python

# 导入需要的库
import openpyxl
from openpyxl.styles import Font, Alignment  # 控制字体和对齐
from datetime import datetime  # 处理日期
import calendar  # 计算月末日期
import os  # 处理文件夹和文件路径

# 1. 自动计算当月日期(核心:不用手动改日期)
now = datetime.now()  # 获取当前时间
year = now.year  # 提取年份(比如2024)
month = now.month  # 提取月份(比如8)
# 计算当月1日(格式:2024-08-01)
first_day = datetime(year, month, 1).strftime("%Y-%m-%d")
# 计算当月最后一天(calendar.monthrange返回当月天数,比如31)
last_day = datetime(year, month, calendar.monthrange(year, month)[1]).strftime("%Y-%m-%d")

# 2. 创建Excel工作簿(相当于新建一个Excel文件)
wb = openpyxl.Workbook()
ws = wb.active  # 获取默认工作表
ws.title = "月报"  # 给工作表改名(默认是Sheet)

# 3. 设置大标题(合并单元格+加粗居中)
title = f"{year}年{month}月 销售月报"  # 标题内容(动态生成)
ws.merge_cells("A1:E1")  # 合并A1到E1的单元格(让标题占满一行)
ws["A1"] = title  # 填写标题
ws["A1"].font = Font(size=16, bold=True)  # 字体:16号加粗
ws["A1"].alignment = Alignment(horizontal="center", vertical="center")  # 对齐:水平垂直居中

# 4. 设置日期区间(跟标题一样居中)
ws.merge_cells("A2:E2")  # 合并A2到E2
ws["A2"] = f"日期:{first_day} 至 {last_day}"  # 填写日期区间
ws["A2"].alignment = Alignment(horizontal="center", vertical="center")  # 居中对齐

# 5. 设置表头(日期/产品/销量/单价/销售额)
headers = ["日期", "产品", "销量", "单价", "销售额"]
ws.append(headers)  # 把表头添加到表格(会自动放在第3行)

# 6. 自动调整列宽(避免内容显示不全)
for col in range(1, len(headers)+1):
    # 把列号(1→A,2→B)转成字母,设置宽度为15
    ws.column_dimensions[openpyxl.utils.get_column_letter(col)].width = 15

# 7. 保存文件(自动创建文件夹,避免手动建)
save_folder = r"C:\Users\YourName\Desktop\Excel_Templates\Monthly"  # 保存路径(建议英文)
os.makedirs(save_folder, exist_ok=True)  # 不存在文件夹就创建,存在就跳过
# 文件名:2024年8月_销售月报.xlsx(动态命名)
file_path = os.path.join(save_folder, f"{year}年{month}月_销售月报.xlsx")
wb.save(file_path)  # 保存文件

print(f"月报模板生成完成!路径:{file_path}")  # 提示生成成功

运行这段代码后,去桌面的Excel_Templates/Monthly文件夹里看看,会发现一个带标题、日期、表头的空月报 —— 直接填数据就行,不用再调格式改日期。

四、进阶:周报模板的关键 —— 算准周一和周日

周报和月报的核心区别,在于日期计算:月报是 “当月 1 日到月末”,周报是 “本周一到周日”。这里用datetime的timedelta(时间差)来算,逻辑很简单

Python 里datetime.weekday()会返回 0-6 的数字,0 代表周一,6 代表周日。比如今天是周五(返回 4),减去 4 天就是周一,再加 6 天就是周日。

直接上周报代码,重点看日期计算部分:

python

from datetime import datetime, timedelta  # 多了timedelta算时间差
import openpyxl
from openpyxl.styles import Font, Alignment
import os

# 1. 计算本周日期(关键:算准周一和周日)
today = datetime.now()
weekday = today.weekday()  # 获取今天是周几(0=周一,6=周日)
monday = today - timedelta(days=weekday)  # 今天减N天=周一
sunday = monday + timedelta(days=6)  # 周一加6天=周日
# 格式化为2024-08-26这样的字符串
start_date = monday.strftime("%Y-%m-%d")
end_date = sunday.strftime("%Y-%m-%d")

# 2. 剩下的步骤跟月报类似,改改标题和表头就行
wb = openpyxl.Workbook()
ws = wb.active
ws.title = "周报"

# 标题:2024-08-26 至 2024-09-01 工作周报
title = f"{start_date} 至 {end_date} 工作周报"
ws.merge_cells("A1:D1")  # 周报表头少一列,合并A1到D1
ws["A1"] = title
ws["A1"].font = Font(size=14, bold=True)
ws["A1"].alignment = Alignment(horizontal="center", vertical="center")

# 表头:日期/任务内容/负责人/完成情况(更贴合周报需求)
headers = ["日期", "任务内容", "负责人", "完成情况"]
ws.append(headers)

# 调整列宽(宽一点,任务内容可能很长)
for col in range(1, len(headers)+1):
    ws.column_dimensions[openpyxl.utils.get_column_letter(col)].width = 25

# 保存文件
save_folder = r"C:\Users\YourName\Desktop\Excel_Templates\Weekly"
os.makedirs(save_folder, exist_ok=True)
file_path = os.path.join(save_folder, f"周报_{start_date}_至_{end_date}.xlsx")
wb.save(file_path)

print(f"周报模板生成完成!路径:{file_path}")

这里要避个坑:跨年的周报(比如 12 月 31 日是周日,那周一就是 12 月 25 日;1 月 1 日是周一,周日就是 1 月 7 日),代码里的timedelta会自动处理日期跨年份的情况,不用手动调整,但要注意文件名会显示正确的年份(比如 “周报_2023-12-25_至_2024-01-01.xlsx”)。

五、实战避坑 + 优化:让脚本更稳定

写代码最怕 “跑着跑着报错”,分享 3 个实战中踩过的坑,以及优化方向,让你的脚本更靠谱:

1. 避坑:这 3 个问题最容易踩

  • 中文路径报错:旧版openpyxl处理不了带空格或中文的路径,建议把保存路径改成英文(比如把 “月报” 改成 “Monthly”);
  • 文件占用保存失败:如果生成的 Excel 还开着,再运行脚本会报错,建议加个异常处理,提示关闭文件:

python

try:
    wb.save(file_path)
except PermissionError:
    print("保存失败!请先关闭已打开的Excel文件")
  • 日期计算错误:如果你的周报是 “周日到周六”(不是周一到周日),把weekday = today.weekday()改成weekday = today.isoweekday() - 1isoweekday()返回 1 = 周一,7 = 周日,减 1 后跟之前逻辑一致)。

2. 优化:让脚本更灵活

  • 批量生成:想一次生成一年 12 个月的月报?加个循环就行:

python

for month in range(1, 13):  # 遍历1-12月
    first_day = datetime(2024, month, 1).strftime("%Y-%m-%d")
    # 后面的代码跟月报一样,把month换成循环变量
  • 自定义表头:把表头做成参数,让用户输入,适应不同需求:

python

headers = input("请输入表头(用逗号分隔,比如:日期,产品,销量)").split(",")


  • 格式美化:给表头加个背景色,更醒目:

python

from openpyxl.styles import PatternFill
# 浅紫色背景
fill = PatternFill(start_color="E6E6FA", end_color="E6E6FA", fill_type="solid")
for col in range(1, len(headers)+1):
    ws.cell(row=3, column=col).fill = fill  # 第3行是表头,给每个单元格加背景

六、最后:自动化的意义不止 “省时间”

可能有人会说:“生成个模板而已,用 Excel 的‘另存为’也很快”。但你想想:如果公司有 10 个部门,每个部门的月报表头不一样,手动改 10 次模板要多久?如果要生成过去 5 年的周报模板,手动复制 52*5=260 次,要浪费多少时间?

Python 自动化的核心价值,是把 “重复、机械、易出错” 的工作交给代码,让你把时间花在更有价值的事上 —— 比如分析报表里的数据,而不是跟模板格式较劲。

现在就把上面的代码复制到 PyCharm 或 VS Code 里,改改保存路径,运行试试。如果遇到问题,评论区留言,咱们一起解决~


感谢关注【AI码力】,获取更多Python秘籍!

最近发表
标签列表