AI 生成的 CSV 怎样导入 Excel?先查引号、编码和公式型内容

用三条虚构商品与只读 Python 检查器,发现列数、重复 SKU、价格格式及公式型前缀问题,再在 Excel 导入预览中保护中文和前导零。

先别双击 AI 刚生成的 CSV。用文本编辑器打开,看到 0007 还在、每行也像有四列,并不表示 Excel 导入后仍然如此:商品名称里的逗号可能被拆成分隔符,备注中的换行可能变成新记录,以等号开头的内容还可能被表格软件当成公式。应先确认文件里到底装了什么,再决定怎样导入。

这篇给经常把 AI 结果交给 Excel 的运营、产品和开发同学。我们只处理三条虚构商品,用 Python 标准库做只读预检,再在 Excel 的导入预览里确认编码与列类型。无需另买 CSV 插件;Excel 是否需要订阅取决于你已有的软件授权,本文不承诺所有版本界面一致。脚本在 Python 3.12.14 下通过 21 项内存检查,没有操作 Excel 界面,也没有把真实业务数据交给模型。

先约定这四列,暂时不要让模型自由加字段

练习表头固定为 sku,name,price,note,顺序与大小写都不变。sku 必须是四位 ASCII 数字并且不重复,允许以零开头;name 不能只有空白;price 只接受非负普通十进制,最多两位小数,不能带货币符号、千位分隔符或科学计数法。note 可以包含逗号、双引号和换行。退款负数不适用这套价格规则,应另定字段与检查方式,而不是临时放宽。

用站内 Claude 或已有的 Microsoft Copilot 起草即可:模型的任务是组织文本与解释规则,不负责给导入结果担保。短小的虚构样本不需要付费高级功能或上传整份客户名单。下面这段保存为 demo.csv,在编辑器中选 UTF-8;不带 BOM 和带 BOM 的 UTF-8 都能被本文检查器读取。

sku,name,price,note
0007,"蓝色,杯",19.90,"首行
次行"
0008,便签,9.00,"他说""今天发货"""
0009,收纳盒,12.50,普通备注

它只有三条数据记录,不是四条:第一条的 note 跨了两行。name 中的半角逗号由双引号包住;note 中真正的双引号用两个双引号表示。不要把网页代码框外的说明、Markdown 围栏或“以下是 CSV”也保存进文件。视觉上的行数和解析后的记录数不是一回事。

让 AI 先输出小样,而不是直接生成一万行

请输出纯 CSV,不要 Markdown 围栏或说明。表头严格为 sku,name,price,note;sku 是四位 ASCII 数字且唯一,必须保留前导零;name 非空,price 为非负十进制且最多两位小数。先生成三条虚构数据,分别覆盖字段内逗号、双引号与备注换行,使用标准 CSV 引号转义。不要输出公式、链接公式或额外列。另在下一条回复解释预期的记录数和字段含义,不要把解释写入 CSV。

提示词不是安全过滤器。模型可能照着要求写,也可能夹带额外列、漏掉引号或把编号改成数字。先对三条样本做完整检查,确认规则能发现问题,再处理业务副本。SKU 的“四位”只是本练习约定,不应原样套到真实商品库;真实字段若允许字母或长编号,先修改规则和对应反例。

本地预检只报告位置,不擅自修复原件

将下列代码另存为 check_csv.py。Python 自带的 csv 模块理解引号和字段内换行,不能用 split(",") 或逐行拆分来替代。程序最多读取 1,000,001 字节,用于拒绝超过 1,000,000 字节的小样;最多接受 10,000 条数据记录。它不改写、不联网,也不把原始单元格打印到终端。

import csv, io, json, re, sys, unicodedata

HEADER = ["sku", "name", "price", "note"]
LIMIT = 1_000_000

def inspect(raw):
    def failure(code):
        return {"records": 0, "issues": [[0, "file", code]]}
    if len(raw) > LIMIT:
        return failure("TOO_LARGE")
    try:
        text = raw.decode("utf-8-sig")
    except UnicodeDecodeError:
        return failure("ENCODING")
    try:
        rows = list(csv.reader(io.StringIO(text, newline=""), strict=True))
    except csv.Error:
        return failure("CSV_PARSE")
    if not rows or rows[0] != HEADER:
        return failure("HEADER")
    if len(rows) > 10001:
        return failure("TOO_MANY_RECORDS")
    issues, seen = [], set()
    for number, row in enumerate(rows[1:], 1):
        if len(row) != 4:
            issues.append([number, "record", "COLUMN_COUNT"])
            continue
        for field, value in zip(HEADER, row):
            probe = unicodedata.normalize("NFKC", value).lstrip()
            if (probe.startswith(("=", "+", "-", "@"))
                    or value.startswith(("\t", "\r", "\n"))
                    or "\x00" in value):
                issues.append([number, field, "REVIEW_PREFIX"])
        sku, name, price, note = row
        if not re.fullmatch(r"[0-9]{4}", sku):
            issues.append([number, "sku", "SKU_FORMAT"])
        if sku in seen:
            issues.append([number, "sku", "DUPLICATE"])
        seen.add(sku)
        if not name.strip():
            issues.append([number, "name", "EMPTY"])
        if not re.fullmatch(r"[0-9]+(?:\.[0-9]{1,2})?", price):
            issues.append([number, "price", "PRICE_FORMAT"])
    return {"records": len(rows) - 1, "issues": issues}

if __name__ == "__main__":
    try:
        with open(sys.argv[1], "rb") as source:
            report = inspect(source.read(LIMIT + 1))
    except (OSError, IndexError):
        report = {"records": 0, "issues": [[0, "file", "INPUT_ERROR"]]}
    print(json.dumps(report, ensure_ascii=True))
    raise SystemExit(1 if report["issues"] else 0)

在文件所在文件夹运行 python check_csv.py demo.csv;某些系统使用 python3。Windows 可在随后用 $LASTEXITCODE 查看退出码。上面的样本应返回 {"records": 3, "issues": []},退出码为 0;有问题则为 1。issues 每项依次是数据记录序号、字段和错误码,序号从表头后的第一条记录开始,不是文本编辑器行号。文件级错误的序号是 0。

COLUMN_COUNT 表示解析后不是四列,CSV_PARSE 表示解析器拒绝了输入,ENCODING 表示不是可解码的 UTF-8,DUPLICATE 表示编号重复。strict 模式不证明所有 CSV 方言都合规;表头、列数与业务字段仍须单独判断。只有表头的空批次会显示 records 为 0,即使没有格式问题也不能当成三条记录交付。

引号包住了内容,也不等于公式风险消失

可在副本中把一个 note 改成 =1+1,只运行检查器,先不要用表格软件打开。应看到 REVIEW_PREFIX。规则还会把开头空白后的加号、减号、@、部分全角对应字符,以及开头的制表符或换行送去人工复核。NFKC 归一化仅用于探测,不会替你修改原数据;合法的“-尺寸说明”也可能被标记,标记不是恶意判定。

OWASP 的 CSV Injection 说明提醒,电子表格可能把特定开头内容解释为公式,保存后重新打开也可能改变转义效果。所以本文选择停下来审查,不自动加引号、删等号或加单引号。这个小检查器不是覆盖所有软件、语言环境和绕过方式的安全认证;不可信内容应走组织批准的文本导入流程,不能只看 issues 为空就关闭警告。

进入 Excel 之前,还要决定编码和类型

原件保留不动。Microsoft 官方说明,带 BOM 的 UTF-8 CSV 通常可正常打开;没有 BOM 时可通过“数据 → 获取数据 → 从文件 → 从文本/CSV”等入口导入,具体名称随版本变化。在预览中核对 UTF-8 编码和逗号分隔符,不要为了乱码反复另存原件。中文是否正常、带逗号的名称是否仍是一格、备注换行是否仍在同一条记录,都要检查。

尤其把 sku 列按文本处理,不依赖自动识别。若导入预览自动加了类型转换,应在加载前调整,避免 0007 变成 7;价格列是否转成数值则按业务约定决定。本文没有实测某个 Excel 版本的按钮位置,依据的是 Microsoft 编码导入说明。编码正确不等于类型正确,更不等于数据内容可信。

交付的是一份可核对的批次,不是一句“已清洗”

给 AI 的复核请求可以很短:“检查器在第 2 条 note 报 REVIEW_PREFIX。请解释可能原因,不补数据、不改商品事实,列出需要人工决定的项。”只传规则、脱敏小样和错误码;不要把真实姓名、订单和完整财务数据粘过去。修正副本后重新运行全部检查,再对照 Excel 预览抽查。AI 的“已修好”不能代替新一次运行结果。

  • 保留原始 CSV、规则版本及模型输出来源;修改只在新副本进行。
  • 核对记录数、列数、重复编号和价格格式;分别抽查正常项与异常项。
  • 确认公式型内容已经按批准流程处理,SKU 前导零及中文未变。
  • 记录实际退出码、检查时间、导入设置与仍未确认的问题,不宣称做过未执行的 Excel 实测。

批次扩大后,还需要文件来源验证、资源限制、日志权限以及目标系统的字段校验,不能把教学脚本直接当生产导入器。若你的起点是 PDF 表格,可以先了解站内 Docling 的结构提取;但从 PDF 提取出来的 CSV,同样要经过这轮检查,而不是因为换了工具就跳过验收。

本文由 AI Islands 根据产品官网及公开资料独立整理。工具功能和价格可能变化,请以官网最新信息为准。