从聊天到执行:用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 需求拆解

我们面对的真实需求通常长这样:

  1. 批量读取:一个文件夹里有 N 个 .xlsx,结构相似但不完全相同
  2. 数据清洗:处理缺失值、统一格式、去重、修正异常值
  3. 简单分析:按区域/时间分组聚合,算总和、均值、增长率
  4. 自动导出:生成一张干净的新 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 文件即可运行