从聊天到执行:用Python自动化Excel,告别重复劳动
豆包能告诉你"怎么处理Excel",但只有代码能帮你"把Excel处理完"。
一、聊天工具 vs 执行工具:一字之差,效率之别
想象一下这个场景:
你手里有 30 份销售数据表,格式不统一、空值横飞、日期格式从 "2024/3/1" 到 "Mar 1, 2024" 应有尽有。你需要把它们合并成一张干净的汇总表,再按区域分组算出每季度的销售额。
你打开豆包,问:"怎么用 Python 处理 Excel 数据清洗?"
豆包会给你一个完美的答案——pandas 的 read_excel()、fillna()、groupby()……条理清晰、解释到位。但你拿到答案后,仍然要手动打开编辑器、复制代码、调试、再调试。
这就是"聊天工具"的本质:它把信息喂到你嘴边,但执行的那一步,永远在你手里断掉。
而 OpenClaw 这类 Agent 平台做的是另一件事:你把需求丢给它,它直接生成脚本、执行脚本、把结果文件放到你桌面上。从意图到结果,中间零摩擦。
本文不是来吹工具的。我想做的是:给你一段能直接跑起来的代码,让你体会一下"执行"比"知道"爽在哪里。
二、实战:30份Excel的自动化清洗流水线
2.1 需求拆解
我们面对的真实需求通常长这样:
- 批量读取:一个文件夹里有 N 个
.xlsx,结构相似但不完全相同 - 数据清洗:处理缺失值、统一格式、去重、修正异常值
- 简单分析:按区域/时间分组聚合,算总和、均值、增长率
- 自动导出:生成一张干净的新 Excel,带格式、带汇总表
下面这段代码,一步不落。
2.2 完整代码
import pandas as pd
import os
from glob import glob
from openpyxl import Workbook
from openpyxl.styles import Font, PatternFill, Alignment
from openpyxl.utils.dataframe import dataframe_to_rows
# ========== 1. 批量读取 ==========
DATA_DIR = "./sales_data"
files = glob(os.path.join(DATA_DIR, "*.xlsx"))
dfs = []
for f in files:
df = pd.read_excel(f)
df["来源文件"] = os.path.basename(f) # 标记来源,方便追溯
dfs.append(df)
raw_df = pd.concat(dfs, ignore_index=True)
print(f"合并完成:共 {len(raw_df)} 行,来自 {len(files)} 个文件")
# ========== 2. 数据清洗 ==========
clean_df = raw_df.copy()
# 2.1 统一列名(兼容大小写/空格差异)
clean_df.columns = [c.strip().lower().replace(" ", "_") for c in clean_df.columns]
# 2.2 处理缺失值
# 销售金额缺失 → 标记为0并记录
clean_df["sales_amount"] = clean_df["sales_amount"].fillna(0)
# 区域缺失 → 标记为"未知",后续人工复核
clean_df["region"] = clean_df["region"].fillna("未知")
# 日期缺失 → 尝试从文件名推断,否则丢弃
clean_df = clean_df.dropna(subset=["date"])
# 2.3 统一日期格式
clean_df["date"] = pd.to_datetime(clean_df["date"], errors="coerce")
clean_df = clean_df.dropna(subset=["date"]) # 无法解析的日期丢弃
# 2.4 去重(同一区域、同日期、同客户且金额相同视为重复)
clean_df = clean_df.drop_duplicates(
subset=["region", "date", "customer_id", "sales_amount"],
keep="first"
)
# 2.5 异常值修正(销售金额不可能为负数)
clean_df["sales_amount"] = clean_df["sales_amount"].clip(lower=0)
print(f"清洗后:{len(clean_df)} 行,去重 {len(raw_df) - len(clean_df)} 行")
# ========== 3. 简单分析 ==========
# 3.1 按区域汇总
clean_df["year_quarter"] = clean_df["date"].dt.to_period("Q").astype(str)
region_summary = clean_df.groupby(["region", "year_quarter"]).agg({
"sales_amount": ["sum", "mean", "count"],
"customer_id": "nunique"
}).reset_index()
region_summary.columns = ["区域", "季度", "销售额合计", "平均客单价", "订单数", "独立客户数"]
# 3.2 全局趋势
trend = clean_df.groupby("year_quarter")["sales_amount"].sum().reset_index()
trend.columns = ["季度", "总销售额"]
trend["环比增长率"] = trend["总销售额"].pct_change() * 100
# ========== 4. 自动导出 ==========
OUTPUT_FILE = "./销售数据清洗报告.xlsx"
wb = Workbook()
# Sheet 1: 清洗后明细
ws1 = wb.active
ws1.title = "清洗后明细"
for r in dataframe_to_rows(clean_df, index=False, header=True):
ws1.append(r)
# Sheet 2: 区域汇总
ws2 = wb.create_sheet("区域汇总")
for r in dataframe_to_rows(region_summary, index=False, header=True):
ws2.append(r)
# Sheet 3: 趋势分析
ws3 = wb.create_sheet("趋势分析")
for r in dataframe_to_rows(trend, index=False, header=True):
ws3.append(r)
# 美化表头
for ws in [ws1, ws2, ws3]:
for cell in ws[1]:
cell.font = Font(bold=True, color="FFFFFF")
cell.fill = PatternFill(start_color="4472C4", end_color="4472C4", fill_type="solid")
cell.alignment = Alignment(horizontal="center")
wb.save(OUTPUT_FILE)
print(f"✅ 报告已导出:{OUTPUT_FILE}")
2.3 代码关键节点解读
| 步骤 | 核心操作 | 为什么这么做 |
| 批量读取 | glob + pd.concat | 文件夹新增文件时,脚本无需修改 |
| 列名统一 | strip().lower().replace() | 对抗"Sales Amount"和"sales amount"的格式不一致 |
| 缺失值策略 | 分类型填充/丢弃 | 金额填 0 可算汇总,区域填"未知"可追溯 |
| 日期解析 | pd.to_datetime(errors="coerce") | 容忍 "2024/3/1"、"Mar 1, 2024"、"03-01-2024" 等多种格式 |
| 去重 | drop_duplicates | 同客户同一天两笔完全相同的金额,大概率是重复录入 |
| 导出美化 | openpyxl 格式设置 | 交付物看起来像人做的,而不是机器吐的 |
三、从"会写代码"到"会造流水线"
上面的脚本跑通了,但这只是单次任务自动化。真正值钱的思维是:把这段代码变成一条可重复、可扩展的流水线。
3.1 参数化:让脚本适应不同场景
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--input-dir", default="./sales_data")
parser.add_argument("--output", default="./report.xlsx")
parser.add_argument("--date-column", default="date")
args = parser.parse_args()
# 后续代码中使用 args.input_dir / args.output 替代硬编码路径
3.2 配置化:把规则从代码里抽出来
# config.yaml
columns:
date: ["date", "日期", "transaction_date"]
amount: ["sales_amount", "金额", "revenue"]
fill_rules:
amount: 0
region: "未知"
drop_threshold:
amount_negative: true
脚本读取 YAML 配置,不同数据源只需改配置、不动代码。
3.3 日志化:让每一步可追溯
import logging
logging.basicConfig(
filename="etl.log",
level=logging.INFO,
format="%(asctime)s | %(levelname)s | %(message)s"
)
logging.info(f"读取 {len(files)} 个文件,合并 {len(raw_df)} 行")
出问题时,打开日志就知道是哪一步掉了链子。
四、总结:自动化思维的降维打击
回到开头的对比:
| 维度 | 手动操作 | 聊天问答 | 脚本执行 |
| 信息获取 | ❌ 自己摸索 | ✅ 即时回答 | ✅ 代码即文档 |
| 执行落地 | ❌ 人来做 | ❌ 人来做 | ✅ 机器自动做 |
| 可重复性 | ❌ 每次都重来 | ❌ 每次重新问 | ✅ 一键复跑 |
| 规模化 | ❌ 人力瓶颈 | ❌ 人力瓶颈 | ✅ 加机器就行 |
| 错误率 | ❌ 人会累会错 | ❌ 人执行会错 | ✅ 逻辑确定则结果确定 |
豆包告诉你"怎么做",OpenClaw帮你"做掉它"。 中间的差距,不是技术能力的差距,而是思维模式的差距——从"获取信息"进化到"构建系统"。
这段 Excel 自动化脚本只是一个起点。当你开始把每一个重复的数据处理需求都转化为一段带参数、带配置、带日志的可执行代码时,你就已经从"会写 Python 的人"变成了"能造流水线的人"。
而后者,才是 AI 时代开发者真正的护城河。
附:环境要求
- Python >= 3.8
- pip install pandas openpyxl
- 示例数据文件夹./sales_data内放置任意.xlsx文件即可运行