把 CSV 转成 Excel 看似只要另存文件,真正容易出错的是数据含义:编号的前导零消失了,不存在的日期被当成正常文本,重复报名被直接删除,却没有留下依据。XLSX Skill 可以帮助组织表格读取、清洗和输出流程,但你仍需要先定义业务规则,再检查每一类异常。
本文以六行虚构的活动报名记录为例,演练保留原始值、识别重复与日期错误、隔离异常行,并输出三个工作表。示例脚本是本站独立编写的教学代码,已按文末检查项做本地检查;没有调用大模型,也没有自动运行下载包里的脚本。不涉及真实用户、宏、外部链接或财务计算。
一、这个 Skill 适合做什么
Anthropic 官方 skills 仓库的 skills/xlsx 目录用于以电子表格为主要输入或交付物的任务,包括清洗混乱表格、处理 CSV、制作或修改工作簿等。它提供工作方法与辅助资源,不是双击就能启动的 Excel 替代软件。宿主需要能够发现技能、读取文件,并具备实际处理表格所需的依赖。
本例选择 CSV 转 XLSX 的小任务,而不是让 AI 直接修复一个复杂的历史报表。带宏、受保护区域、外部引用和大量公式的文件需要另做兼容性评估,不能套用这段示例脚本处理。
本页下载入口沿用已核验的 Anthropic 完整源码包,目标技能位于 skills/xlsx,版本与下载区显示一致,不把旧包称为最新版。安装前先阅读包内该目录的 SKILL.md 和 LICENSE.txt。本文核对的该目录许可证为 Apache-2.0;涉及其他目录或第三方依赖时,要分别查看其条款。
二、安装技能与准备独立练习目录
如果使用支持官方插件市场的 Claude Code,可按照仓库 README 添加市场并安装文档技能插件。在 Claude Code 的交互界面输入,下面不是 PowerShell 命令:
/plugin marketplace add anthropics/skills
/plugin install document-skills@anthropic-agent-skills按宿主提示启用或重新开始会话,再明确要求使用 XLSX skill。其他工具应遵循自己的技能加载方式,不能默认这些命令到处通用。完整源码下载包用于查看技能文件和保留说明,本文不要求覆盖你已有的插件目录。
创建一个空的练习文件夹,只放本文的虚构样本与自己的脚本。准备可用的 Python 环境,先检查 python --version,再用 python -c "import openpyxl; print(openpyxl.__version__)" 确认依赖。没有安装时,在自己选择的环境中执行 python -m pip install openpyxl。宿主宣称预装依赖,不代表你的本机也已安装。
三、先说明哪些数据可以进入正式表
本例编号必须恰好五位数字,以字符串保存;每条报名只对应一个编号,首次出现后再出现的同编号行进入异常表。日期必须是严格的 YYYY-MM-DD 格式且真实存在。渠道只允许“公众号”或“现场”,备注允许为空。
这些是演示业务规则,不是 CSV 或 Excel 的通用标准。例如,真实系统也许允许同一人报名多次,那么重复键就应改成“人员编号加场次”,不能照搬本例把合法记录排除。先确认重复的业务含义,再决定去重方式。
将下面内容以 UTF-8 保存为 signups.csv。逗号是英文半角,字段顺序保持一致。BOM 与常见换行可由示例读取方式处理。
编号,日期,渠道,备注
00101,2026-11-10,公众号,需要靠前座位
00102,2026-11-10,现场,
00102,2026-11-11,公众号,重复编号待核对
00103,2026-02-30,现场,日期需核对
00104,2026-11-12,,渠道缺失
00105,2026-11-12,公众号,=1+1最后一行备注故意以等号开头,用于检查内容是否保持普通文字。它不是要执行的计算式。此处不真实演示外部链接或恶意命令,也不把所有以符号开头的文本一概删除。
人工作答应为:第 2、3、7 行进入有效表;第 4 行因重复编号、第 5 行因无效日期、第 6 行因渠道缺失进入异常表。行号包含第一行表头,便于回到原 CSV 定位。每条原记录必须恰好落入其中一个去向。
四、用明确的任务说明调用技能
请使用 XLSX skill 分析练习目录中的 signups.csv。
先读取该技能说明,再给出处理计划;不运行包内脚本,不修改原 CSV。
输出 clean-signups.xlsx,包含“原始记录”“有效记录”“异常记录”。
编号保留五位字符串;日期需严格核验;渠道只允许公众号或现场。
编号首次出现后,后续重复行进入异常记录,不自行合并。
原始记录保留输入值;其他表保留来源行号,异常表写明原因。
备注必须作为普通文字保存,等号开头也不能变成公式。
本例不含汇总公式,不添加宏、外部链接或推测出来的字段。
先展示人工参考分类,确认计划后再生成文件,并重新读取检查。这段提示词用于你在自己环境中的练习,不代表本站已经通过 Claude Code 执行过。若模型提出替你删除原始行、自动补齐渠道或猜一个有效日期,应先纠正计划。数据清洗需要保留可追溯路径,而不是只交付一份看起来整齐的新表。
五、独立 Python 参考实现
以下脚本不依赖模型。保存为 clean_signups.py,与 CSV 放在同一空目录,再执行 python clean_signups.py。为了避免覆盖,目标文件存在时会主动停止;要重做请更换输出名或先把自己的旧输出移到备份位置。
import csv
import re
from datetime import date
from pathlib import Path
from openpyxl import Workbook, load_workbook
from openpyxl.styles import Font, PatternFill
source = Path("signups.csv")
target = Path("clean-signups.xlsx")
if target.exists():
raise FileExistsError("输出已存在,请先保留旧文件再重做")
headers = ["编号", "日期", "渠道", "备注"]
with source.open(encoding="utf-8-sig", newline="") as f:
reader = csv.DictReader(f)
if reader.fieldnames != headers:
raise ValueError("表头或列顺序不符合本例约定")
rows = list(reader)
if not rows or any(None in r or any(v is None for v in r.values()) for r in rows):
raise ValueError("无数据或存在缺列、多列,请先检查源文件")
book = Workbook()
raw = book.active
raw.title = "原始记录"
valid = book.create_sheet("有效记录")
bad = book.create_sheet("异常记录")
seen = set()
def append_text(sheet, values):
row = sheet.max_row + 1 if sheet.cell(1, 1).value is not None else 1
for col, value in enumerate(values, 1):
cell = sheet.cell(row, col)
cell.value = str(value)
cell.data_type = "s"
cell.number_format = "@"
append_text(raw, ["来源行号"] + headers)
append_text(valid, ["来源行号"] + headers)
append_text(bad, ["来源行号"] + headers + ["异常原因"])
for line_no, row in enumerate(rows, 2):
original = [row[h] for h in headers]
append_text(raw, [line_no] + original)
values = [x.strip() for x in original]
ident, day, channel, note = values
reasons = []
if not re.fullmatch(r"[0-9]{5}", ident):
reasons.append("编号须为五位数字")
if ident in seen:
reasons.append("重复编号,需人工核对")
seen.add(ident)
try:
if not re.fullmatch(r"[0-9]{4}-[0-9]{2}-[0-9]{2}", day):
raise ValueError()
date.fromisoformat(day)
except ValueError:
reasons.append("日期无效")
if channel not in {"公众号", "现场"}:
reasons.append("渠道缺失或不在允许列表")
if reasons:
append_text(bad, [line_no] + original + [";".join(reasons)])
else:
append_text(valid, [line_no] + values)
for sheet in book:
sheet.freeze_panes = "A2"
sheet.auto_filter.ref = sheet.dimensions
for cell in sheet[1]:
cell.font = Font(name="Arial", bold=True, color="FFFFFF")
cell.fill = PatternFill("solid", fgColor="315866")
for row in sheet.iter_rows(min_row=2):
for cell in row:
cell.font = Font(name="Arial", size=11)
for col in "ABCDEF":
sheet.column_dimensions[col].width = 23 if col != "F" else 42
book.save(target)
check = load_workbook(target, data_only=False)
assert check.sheetnames == ["原始记录", "有效记录", "异常记录"]
assert check["原始记录"].max_row == len(rows) + 1
assert check["有效记录"].max_row + check["异常记录"].max_row == len(rows) + 2
assert all(c.data_type != "f" for s in check for row in s for c in row)
print("已生成工作簿:请继续逐行核对分类与原始值")这里使用字符串单元格保留编号与备注,并用文本格式辅助显示。不能只设置显示格式却先把编号转成整数,否则 00101 已经变成 101,之后再设格式并不能恢复真实原值。脚本对原始表保留空格,对有效数据做首尾空白清理,异常表仍保留原输入,避免修改过程遮住问题。
六、验收不能只看文件能否打开
先核对行数:原始表六条,有效三条,异常三条,不包括各自表头。有效表编号应为 00101、00102、00105,来源行号应为 2、3、7。第二条有效记录的备注为空,不应因此被排除。
再检查异常原因:重复记录不能覆盖首次出现的 00102;2026-02-30 不能自动修成其他日期;缺失渠道不能猜成公众号。这里按“首次出现优先”处理,如果首次本身错误、后续是纠正记录,依然需要人工重新判断,而不是由脚本擅自替换。
最后重新读取单元格,确认 00101 仍是五位字符串,最后一条备注仍是文字 =1+1,没有公式单元格。原 CSV 前后校验值应一致。可以再在自己的 Excel 或兼容软件中打开,检查筛选、冻结表头和列宽;本文的程序验证不替代你实际目标软件的显示检查。
七、把修正结果与原始记录分开维护
清洗结束后,异常记录需要有人联系资料提供方确认,不能就此视作无效报名。建议保留“来源行号、原值、修正值、确认依据”四项记录,例如第 6 行的渠道经本人确认后再补全。下一轮应从保留的原始数据与有依据的修正记录重新生成,不要直接在输出中删掉异常页。
一个编号出现两次,可能是重复提交,也可能是用户改了日期。脚本只报告与规则冲突,不替业务人员决定哪次是真实意愿。只有在确认规则已经改变后,才能调整重复判断与参考答案,并保留修改原因。这样同一份工作簿才有机会被另一位同事复核,而不只是作者自己知道怎样处理过。
八、出现问题怎么排查
提示表头不匹配,先检查编码、英文逗号和列顺序,不要直接删除校验。含逗号的备注需要正确的 CSV 引号,表格软件导出时通常会处理;手工拼接时容易变成多列。
运行时找不到文件,应在练习目录打开终端,或给脚本填写明确路径。导入依赖失败,检查安装 openpyxl 的 Python 是否与执行脚本的是同一个环境。目标文件被占用时,先关闭自己打开的输出文件,不要强制覆盖其他人的工作簿。
本例没有公式,因此不涉及公式重算。以后增加公式时,要区分公式字符串与缓存值;openpyxl 本身不计算公式,不能用“没有报错”冒充计算正确。先按技能说明检查依赖,再完成重算和业务结果复核。更多表格练习见 Skill 资源库。

还没有公开评论,欢迎分享你的想法。