Python自动化Excel实战:从3小时到3分钟的蜕变

先说说为什么非要搞自动化。我接手的第一个项目是月度销售报表,3000多行数据,每天要更新,每行有十几个字段,还要做各种汇总。手动操作不仅慢,还容易出错。有一次把“销售额”列的数据类型搞错了,汇总结果差了好几十万,被领导训了一顿。从那以后,我就铁了心用Python。

第一步:选对工具

,0,.08);”
loading=”lazy” wi

dth=”800″ height=”500″>

别急着装xlrd、xlwt这些老古董,现在都2025年了,我推荐用openpyxl搭配pandas。为什么?

  • openpyxl:专门处理.xlsx格式,支持读写、公式、图表,功能全面
  • pandas:数据处理神器,各种清洗、合并、分组操作一行搞定

安装很简单:

bash
pip install openpyxl pandas

`

核心操作:读取与写入

先看一个最基本的例子。假设你有个Excel文件叫销售数据.xlsx,里面有三列:日期、产品名称、销售额。

`python
import pandas as pd

读取Excel文件,指定工作表名

df = pd.read_excel('销售数据.xlsx', sheet_name='Sheet1', engine='openpyxl')

看看数据长啥样

print(df.head())

简单统计:每个产品的总销售额

product_summary = df.groupby('产品名称')['销售额'].sum().reset_index()
print(product_summary)
`

这里为什么要用engine=’openpyxl’?因为pandas默认的引擎对.xlsx支持不太好,遇到复杂格式可能报错。我刚开始没加这个参数,结果一个带着合并单元格的文件直接崩了,心累。

还有个坑:pandas读取Excel时,如果列名有空格或特殊字符,会自动转成下划线。比如“产品名称”变成“产品名称_1”。所以最好在Excel里就把列名规范好,或者读取后用df.columns重命名。

数据清洗:那些反人类的设计

官方文档这段文档不够清晰,什么“inplace=True”“axis=1”,看得头皮发麻。我直接给你总结三个最实用场景。

场景1:处理空值

Excel里那些空白单元格,Python读进来就变成NaN。不处理的话,后续计算全崩。

`python

删除销售额为空的整行

df.dropna(subset=['销售额'], inplace=True)

用0填充所有NaN

df.fillna(0, inplace=True)

或者用均值填充

mean_sales = df['销售额'].mean()
df['销售额'].fillna(mean_sales, inplace=True)
`

我一般用第二种,因为产品销售数据里,空值通常意味着没卖出去,填0比较合理。

场景2:处理数据类型

这个设计真的反人类——Excel里看起来是数字的列,读进来可能变成字符串。比如“销售额”列里有个单元格不小心写成了“1,000”,Python就傻眼了。

`python

去掉逗号并转成数值

df['销售额'] = df['销售额'].astype(str).str.replace(',', '').astype(float)

日期列标准化

df['日期'] = pd.to_datetime(df['日期'], format='%Y-%m-%d')
`

场景3:去重

同一个订单号出现两次,算销售额时就要注意。

`python

按订单号去重,保留第一次出现的记录

df.drop_duplicates(subset=['订单号'], keep='first', inplace=True)

查看重复项

duplicates = df[df.duplicated(subset=['订单号'], keep=False)]
print(f"发现{len(duplicates)}条重复记录")
`

高级操作:报表自动化

另一个坑是生成报表。你以为写个分组汇总就完了?人家要的是带格式、带图表、带超链接的漂亮报表。

下面这段代码,能生成一个按月份和产品分组的销售汇总表,并加上条件格式:

`python
from openpyxl import Workbook
from openpyxl.styles import PatternFill, Font, Alignment
from openpyxl.utils.dataframe import dataframe_to_rows

准备数据:按月汇总

df['月份'] = df['日期'].dt.month
monthly_summary = df.groupby(['月份', '产品名称'])['销售额'].sum().reset_index()

创建Excel工作簿

wb = Workbook()
ws = wb.active
ws.title = "月度销售汇总"

写入数据

for r in dataframe_to_rows(monthly_summary, index=False, header=True):
ws.append(r)

设置格式

header_fill = PatternFill(start_color="FFC000", end_color="FFC000", fill_type="solid")
header_font = Font(bold=True, color="FFFFFF")

for cell in ws[1]:
cell.fill = header_fill
cell.font = header_font
cell.alignment = Alignment(horizontal='center')

自动调整列宽

for column in ws.columns:
max_length = 0
column_letter = column[0].column_letter
for cell in column:
if cell.value:
max_length = max(max_length, len(str(cell.value)))
ws.column_dimensions[column_letter].width = max_length + 2

保存

wb.save('月度销售汇总_自动化.xlsx')
print("报表生成完成!")
`

这个代码里踩过最大的坑是dataframe_to_rows这个函数。第一次用的时候忘了传index=False,结果多了一列索引号,怎么调都调不对,差点怀疑人生。

还有个技巧:如果需要追加数据到已有工作表,用openpyxlload_workbook函数读取现有文件,然后操作ws.append

实战案例:每天自动生成日报

我现在的流程是这样的:每天早上8点,脚本自动读取数据库导出的Excel,做清洗、汇总、生成带图表的新报表,然后发邮件给团队。整个过程不到3分钟。

核心代码片段:

`python
import schedule
import time

def daily_report():
# 1. 读取数据
df = pd.read_excel('今日销售数据.xlsx', engine='openpyxl')

# 2. 清洗
df.dropna(subset=['销售额'], inplace=True)
df['销售额'] = pd.to_numeric(df['销售额'], errors='coerce')

# 3. 汇总
summary = df.groupby('产品类别')['销售额'].sum().sort_values(ascending=False)

# 4. 生成报表(详细代码见上)
generate_report(summary)

# 5. 发送邮件(略)
print(f"日报生成完毕:{time.strftime('%Y-%m-%d %H:%M:%S')}")

每天8点执行

schedule.every().day.at("08:00").do(daily_report)

while True:
schedule.run_pending()
time.sleep(60)
`

这个设计真的反人类?不是,是很实用。但要注意:生产环境别用while True死循环,最好用cron或Windows任务计划。

总结一下,你可以立刻用的三个点

  • 先用pandas读数据:用pd.read_excel(‘文件.xlsx’, engine=’openpyxl’),别用老掉牙的xlrd
  • 清洗三步走:处理空值(fillna/ dropna)、转数据类型(astype/ to_datetime)、去重(drop_duplicates)
  • 生成报表用openpyxl:配合dataframe_to_rows`写入数据,条件格式和自动列宽让报表看起来专业
  • 记住:自动化不是为了炫技,是为了把重复劳动交给机器,让自己有时间去解决更复杂的问题。下次有人问你Python处理Excel,直接把这篇文章甩给他。

    滚动至顶部