expense-tool/README.md
copper-xw 13bf1a0146 保存差旅报销自动化基础文件
仅保存说明、脚本和 Excel 模板,示例中的个人和公司信息已匿名化。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-28 19:28:23 +08:00

12 KiB
Raw Blame History

差旅报销自动化流程

给大模型的自动执行入口

当用户把本 README.md 提供给大模型,或让大模型在本目录处理差旅报销时,大模型应直接按下面流程开始执行,不需要用户再复制额外提示词:

  1. 先阅读本说明,确认当前目录是报销目录。

  2. 检查当前目录是否存在基础文件:差旅报销.py、差旅费明细表.xlsx、本次报销 PDF。

  3. 如果 报销输出/pdf_raw_text.txt 不存在,自动运行:

    python3 差旅报销.py extract
    

    Windows 环境可改用:

    py 差旅报销.py extract
    
  4. 读取 报销输出/pdf_raw_text.txt,按本文的 JSON Schema 分析出差人、日期、事由、费用分类、金额和证据。

  5. 如果出差人、出差事由、出发地、目的地、日期、金额等关键信息无法从原文可靠判断,必须先问用户;不要编造。

  6. 将最终 JSON 保存为 报销输出/analyzed_result.json。

  7. 确认 questions 为空、金额合计一致、附件张数一致后,自动运行:

    python3 差旅报销.py fill 报销输出/analyzed_result.json
    

    Windows 环境可改用:

    py 差旅报销.py fill 报销输出/analyzed_result.json
    
  8. 最后告诉用户生成的 Excel 文件路径,以及是否有任何需要人工复核的证据或假设。

简单说:看到本 README 后,大模型应自动完成“提取 PDF 原文 → 分析生成 JSON → 填写 Excel”,只有在信息不确定时才暂停询问用户。


核心思想

这个流程分成三段:

  1. Python 提取原文:只把 PDF 内容提取成 TXT,不理解、不计算、不猜测。
  2. 大模型分析:读取 TXT,判断出差人、日期、事由、费用分类和金额,输出标准 JSON。
  3. Python 填表:只读取 JSON,把数据填入 Excel 模板,生成最终 XLSX。

也就是说:Python 只做机械衔接,大模型负责理解发票内容。


基础三件套

每次复用这个流程,只需要保留下面三个基础文件:

文件 作用
差旅费明细表.xlsx 原始 Excel 模板,脚本会复制它,不直接修改
差旅报销.py 唯一 Python 脚本,提供 extract / schema / fill 三个命令
README.md 本说明,给人和大模型看

PDF 发票、pdf_raw_text.txt、analyzed_result.json、最终 XLSX 都是每次报销产生的过程文件或结果文件。


为什么使用 XLSX

为了跨平台,模板统一使用 .xlsx。

这样脚本只依赖 Python 包:

pdfplumber  # 提取 PDF 文本
openpyxl    # 复制和填写 xlsx 模板

不再依赖 LibreOffice,也不需要系统命令做 .xls / .xlsx 转换。

如果你手里只有 .xls 模板,请先用 Excel、WPS 或 LibreOffice 手动另存为:

差旅费明细表.xlsx

依赖安装

Windows

py -m pip install pdfplumber openpyxl

运行时使用:

py 差旅报销.py extract
py 差旅报销.py fill 报销输出/analyzed_result.json

Linux / macOS

python3 -m pip install pdfplumber openpyxl

运行时使用:

python3 差旅报销.py extract
python3 差旅报销.py fill 报销输出/analyzed_result.json

标准目录结构

报销目录/
├── 差旅费明细表.xlsx      # 必需:模板
├── 差旅报销.py             # 必需:脚本
├── README.md              # 必需:说明
├── 住宿.pdf               # 本次报销 PDF
├── 机票*.pdf              # 本次报销 PDF
├── 滴滴出行行程报销单*.pdf  # 本次报销 PDF
└── 滴滴电子发票*.pdf       # 本次报销 PDF

脚本输出统一放到:

报销输出/

运行后会形成:

报销目录/
└── 报销输出/
    ├── pdf_raw_text.txt
    ├── analyzed_result.json
    ├── schema_example.json       # 可选
    └── 差旅费明细表_xxxx_20260520_广州_售后维修.xlsx

使用流程

Step 1:提取 PDF 原文

python3 差旅报销.py extract

Windows 可用:

py 差旅报销.py extract

输出:

报销输出/pdf_raw_text.txt

这个文件按 PDF 文件分块保存原始文本,例如:

============================================================
文件: 住宿.pdf
============================================================
电子发票(增值税专用发票)
...

============================================================
文件: 滴滴出行行程报销单A.pdf
============================================================
滴滴出行-行程单
...

注意:这一步不会提取金额、不会判断类型、不会计算总额。


Step 2:让大模型分析 TXT 并输出 JSON

把 报销输出/pdf_raw_text.txt 交给大模型,让大模型生成:

报销输出/analyzed_result.json

可以先查看 JSON 模板:

python3 差旅报销.py schema

也可以直接输出模板文件:

python3 差旅报销.py schema --output

输出:

报销输出/schema_example.json

给大模型的推荐提示词

请根据本 README 自动处理当前目录的差旅报销。

你的任务:
1. 如果 `报销输出/pdf_raw_text.txt` 不存在,先运行 `python3 差旅报销.py extract` 提取 PDF 原文。
2. 读取 `报销输出/pdf_raw_text.txt`,从 PDF 原文中识别出差人、出差事由、出发日期、结束日期、出发地、目的地、出行方式、出差天数。
3. 将费用分为:住宿、交通、饮食、其他。
4. 每个费用类别都要给出金额、单据张数、说明。
5. 计算附件总张数、报销总额、预借差旅费、补领金额、退还金额。
6. 每个金额必须写入 evidence,说明来自哪个文件、依据是哪段文本。
7. 如果某个字段无法可靠判断,必须先问用户,不要编造;在未确认前不要填表。
8. 将最终 JSON 保存为 `报销输出/analyzed_result.json`,JSON 必须符合 README 中的 schema。
9. 确认 `questions` 为空、金额合计一致、附件张数一致后,运行 `python3 差旅报销.py fill 报销输出/analyzed_result.json` 生成最终 Excel。
10. 最后告诉用户生成的 Excel 文件路径,并列出需要人工复核的证据或假设。

JSON Schema

大模型必须输出如下结构:

{
  "meta": {
    "出差人": "xxxx",
    "出差事由": "前往广州进行售后维修工作",
    "出发日期": "2026/5/20",
    "结束日期": "2026/5/22",
    "出发地": "北京",
    "目的地": "广州",
    "出行方式": "飞机",
    "出差天数": 3,
    "事由简写": "售后维修"
  },
  "expenses": {
    "住宿": {
      "金额": 510.0,
      "单据张数": 1,
      "说明": "广州市番禺明乐宾馆住宿费"
    },
    "交通": {
      "金额": 2013.77,
      "单据张数": 5,
      "说明": "机票1690.00 + 滴滴323.77"
    },
    "饮食": {
      "金额": 0.0,
      "单据张数": 0,
      "说明": "未发现餐饮发票"
    },
    "其他": {
      "金额": 0.0,
      "单据张数": 0,
      "说明": "无其他费用"
    }
  },
  "summary": {
    "附件总张数": 6,
    "报销总额": 2523.77,
    "预借差旅费": 0.0,
    "补领金额": 2523.77,
    "退还金额": 0.0
  },
  "evidence": [
    {
      "文件": "住宿.pdf",
      "类别": "住宿",
      "金额": 510.0,
      "依据": "价税合计(小写)¥510.00"
    },
    {
      "文件": "机票预订出行订单尾号87377629-电子普通发票.pdf",
      "类别": "交通",
      "金额": 1690.0,
      "依据": "价税合计(小写)¥1690.00"
    }
  ],
  "questions": []
}

字段说明

字段 说明
meta.出差人 出差人姓名,不确定就问用户
meta.出差事由 出差目的,不确定就问用户
meta.出发日期 / meta.结束日期 格式建议为 YYYY/M/D
meta.出差天数 含首尾日期,例如 5/20 至 5/22 为 3 天
expenses.住宿 酒店住宿类费用
expenses.交通 机票、火车、打车等交通类费用
expenses.饮食 餐饮费用,没有就 0
expenses.其他 不属于前三类的费用,没有就 0
summary.附件总张数 四类费用单据张数之和
summary.报销总额 四类费用金额之和
evidence 每笔金额的来源证据,便于人工核对
questions 如果大模型无法判断,可以列出问题;最终填表前应为空

Step 3:读取 JSON 并填表

python3 差旅报销.py fill 报销输出/analyzed_result.json

Windows 可用:

py 差旅报销.py fill 报销输出/analyzed_result.json

脚本会:

  1. 校验 JSON 字段是否完整
  2. 校验金额合计是否一致
  3. 校验附件张数是否一致
  4. 复制 差旅费明细表.xlsx
  5. 用 openpyxl 填入固定单元格
  6. 输出最终 XLSX 到 报销输出/

输出文件命名规则:

差旅费明细表_[出差人]_[出发日期YYYYMMDD]_[目的地]_[事由简写].xlsx

示例:

报销输出/差旅费明细表_xxxx_20260520_广州_售后维修.xlsx

Excel 填写位置

脚本只填写这些单元格:

单元格 内容
E3 出差事由
A6 出发日期-结束日期
B6 出发地-目的地
C6 出差天数
D6 出行方式
H6 / I6 住宿单据张数 / 住宿金额
H7 / I7 饮食单据张数 / 饮食金额
H8 / I8 交通单据张数 / 交通金额
H9 / I9 其他单据张数 / 其他金额

脚本不会覆盖公式单元格,例如:

单元格 公式
H2 附件张数合计
F9 天数合计
C10 报销总额
H10 补领金额
H11 退还金额

校验规则

fill 命令会检查:

summary.报销总额 = 住宿金额 + 交通金额 + 饮食金额 + 其他金额
summary.附件总张数 = 住宿单据张数 + 交通单据张数 + 饮食单据张数 + 其他单据张数

如果不一致,脚本会停止,不会写 Excel。


本次数据示例

{
  "meta": {
    "出差人": "xxxx",
    "出差事由": "前往广州进行售后维修工作",
    "出发日期": "2026/5/20",
    "结束日期": "2026/5/22",
    "出发地": "北京",
    "目的地": "广州",
    "出行方式": "飞机",
    "出差天数": 3,
    "事由简写": "售后维修"
  },
  "expenses": {
    "住宿": {"金额": 510.0, "单据张数": 1, "说明": "住宿费"},
    "交通": {"金额": 2013.77, "单据张数": 5, "说明": "机票1690.00 + 滴滴323.77"},
    "饮食": {"金额": 0.0, "单据张数": 0, "说明": "无餐饮发票"},
    "其他": {"金额": 0.0, "单据张数": 0, "说明": "无其他费用"}
  },
  "summary": {
    "附件总张数": 6,
    "报销总额": 2523.77,
    "预借差旅费": 0.0,
    "补领金额": 2523.77,
    "退还金额": 0.0
  },
  "evidence": [],
  "questions": []
}

常见错误

1. 找不到模板文件:差旅费明细表.xlsx

确认当前目录存在:

差旅费明细表.xlsx

如果只有 .xls,请先用 Excel / WPS / LibreOffice 另存为 .xlsx。

2. 报销总额不一致

说明 JSON 里的总额和分类费用合计不一致,检查:

住宿 + 交通 + 饮食 + 其他

3. 附件总张数不一致

说明 JSON 里的附件总数和分类单据张数合计不一致。

4. 缺少 Python 库

Windows:

py -m pip install pdfplumber openpyxl

Linux / macOS:

python3 -m pip install pdfplumber openpyxl