Skip to main content

将电子发票按月份自动分组并合并到A4纸上,便于打印报销

Project description

发票合并打印助手 (Invoice Merger)

PyPI version Python Version License: MIT

电子发票按月份自动分组并合并到A4纸上,便于打印报销。

专为中国高铁电子发票设计,支持自动识别乘车日期、票价金额,按月份分组合并,生成统计报表。

功能特点

  • ✅ 自动扫描文件夹中的PDF发票(支持递归扫描子文件夹)
  • ✅ 智能识别乘车日期(基于最早日期原则)
  • ✅ 智能识别票价金额并自动汇总
  • 按票价详细分组统计(显示每种票价的数量和小计)
  • ✅ 基于发票号码自动去重
  • ✅ 按月份自动分组
  • ✅ 同一月份内按时间从小到大排序
  • ✅ 生成统计文件(票数量、总金额)
  • ✅ 保持原始宽高比,不扭曲图片
  • ✅ 可配置每行列数(默认3列)
  • ✅ 自动计算行数,充分利用A4纸空间
  • ✅ 实时进度显示

效果预览

合并后的PDF示例(3列布局,保持原始发票宽高比):

发票合并效果示例

安装

方式一:从 PyPI 安装(推荐)

pip install invoice-merger

方式二:从源码安装

git clone https://github.com/luzhongqiu/invoice-merger.git
cd invoice-merger
pip install -e .

使用方法

基本用法(推荐)

使用 Python 模块方式运行(适用于虚拟环境):

python -m invoice_merger <输入文件夹路径>

例如:

python -m invoice_merger ./invoices

输出文件将保存在输入文件夹的 output 子目录中。

命令行方式

如果全局安装(使用 pip installpipx install),也可以直接使用命令:

invoice-merger ./invoices

高级选项

python -m invoice_merger <输入文件夹> -o <输出文件夹> -c <列数>

参数说明:

  • -o, --output: 指定输出文件夹路径(可选,默认为输入文件夹下的output目录)
  • -c, --columns: 每行放置的列数(可选,默认为3列)
  • -v, --version: 显示版本信息
  • -h, --help: 显示帮助信息

示例

  1. 使用默认设置(3列):

    python -m invoice_merger ./my_invoices
    
  2. 自定义输出目录:

    python -m invoice_merger ./my_invoices -o ./merged_pdfs
    
  3. 自定义列数(如每行2列):

    python -m invoice_merger ./my_invoices -c 2
    
  4. 同时指定输出目录和列数:

    python -m invoice_merger ./my_invoices -o ./output -c 4
    
  5. 查看帮助信息:

    python -m invoice_merger --help
    

输出格式

PDF文件

  • 输出文件按月份命名,格式为 YYYY-MM.pdf
  • 例如:2025-10.pdf, 2025-11.pdf
  • 同一月份内的发票按时间顺序排列

统计文件(info.txt)

程序会自动生成 info.txt 统计文件,包含每个月的汇总信息和详细的按票价分组统计:

============================================================
发票合并统计信息
============================================================

2025-10.pdf           票数量:  35张  总金额:  1285.00元
  票价:   16.00元  ×    1张  =     16.00元
  票价:   17.00元  ×    1张  =     17.00元
  票价:   26.00元  ×    2张  =     52.00元
  票价:   30.00元  ×    3张  =     90.00元
  票价:   38.00元  ×   18张  =    684.00元
  票价:   42.00元  ×    2张  =     84.00元
  票价:   46.00元  ×    5张  =    230.00元
  ...

2025-11.pdf           票数量:  38张  总金额:  1533.00元
  票价:   30.00元  ×    2张  =     60.00元
  票价:   35.00元  ×    5张  =    175.00元
  票价:   38.00元  ×   25张  =    950.00元
  ...

------------------------------------------------------------
合计                    票数量: 119张  总金额:  4602.00元
============================================================

说明

  • 每个月显示总票数和总金额
  • 详细列出每种票价的数量和小计金额
  • 按票价从小到大排序
  • 便于报销时核对不同票价的发票数量
  • 最后一行显示所有月份的总计

支持的日期格式

程序会自动识别PDF中的以下日期格式:

  • 2025年10月15日2025-10-15
  • 2025.10.15
  • 10/15/2025

如果无法从PDF内容中提取日期,将使用文件的修改时间作为日期。

工作原理

  1. 扫描阶段:递归扫描指定文件夹及所有子文件夹中的PDF文件(自动排除output目录)
  2. 识别阶段:从PDF文本内容中提取日期、发票号码和金额信息
  3. 去重阶段:根据发票号码自动去除重复文件
  4. 分组阶段:按月份分组,组内按时间排序
  5. 合并阶段
    • 按指定列数排列
    • 计算缩放比例,保持原始宽高比
    • 自动计算行数,充分利用A4纸空间
    • 当前页放不下时自动创建新页面
    • 同时统计每个月的票数量、总金额、按票价分组统计
  6. 统计阶段:生成info.txt文件,包含:
    • 每个月的票数和总金额汇总
    • 详细的按票价分组统计(票价 × 张数 = 小计)
    • 所有月份的总计

日期识别逻辑

程序专门针对高铁电子发票设计,使用智能算法识别乘车日期:

识别原理

  1. 提取所有日期:从PDF中查找所有 YYYY年MM月DD日 格式的日期
  2. 智能选择:选择最早的日期作为乘车日期
  3. 原理依据:开票时间总是晚于或等于乘车时间

示例

PDF内容包含两个日期:
  - 2025年10月31日  ← 乘车日期
  - 2026年01月07日  ← 开票日期

程序选择:2025-10-31(最早日期)

重要假设

⚠️ 本程序假设开票日期晚于乘车日期

这个假设适用于绝大多数场景,因为:

  • ✅ 高铁票通常在乘车后统一开票
  • ✅ 即使乘车当天开票,日期也不会早于乘车日期
  • 不适用:如果PDF中包含其他更早的日期(如打印日期、系统生成日期等),可能导致识别错误

去重机制

程序通过文件名自动去重:

  • 从文件名中提取发票ID(格式:{id}-电子发票.pdf
  • 如果发现相同ID,自动跳过
  • 避免重复下载的文件被合并多次

示例

26319130671000153108-电子发票.pdf         ✓ 保留
26319130671000153108-电子发票 (1).pdf    ✗ 跳过(重复)

金额识别逻辑

程序自动从PDF中提取票价信息:

识别方法

  • 查找 票价:¥xx.xx 格式的金额
  • 验证金额合理性(0-10000元范围)
  • 按月份自动汇总

金额统计(详细分组)

程序生成 info.txt 统计文件,包含以下信息:

  • 月度汇总:每个月的PDF文件显示总票数和总金额
  • 按票价分组:详细列出每种票价的数量和小计金额(按票价从小到大排序)
  • 计算公式:票价 × 张数 = 小计金额
  • 总计统计:最后显示所有月份的合计

示例

2025-10.pdf           票数量:  35张  总金额:  1285.00元
  票价:   38.00元  ×   18张  =    684.00元  ← 一目了然哪种票价最多
  票价:   46.00元  ×    5张  =    230.00元
  ...

这样的详细统计让报销时可以:

  • ✅ 快速核对不同票价的发票数量
  • ✅ 确认每种票价的小计是否正确
  • ✅ 方便财务审核时分类统计

⚠️ 重要安全保护机制

为保证报销准确性,程序内置了金额识别保护机制:

如果无法识别票价金额,程序会立即报错并停止运行

这是有意设计的安全措施,因为:

  1. 金额=0是严重错误:报销金额不准确会造成财务问题
  2. 及时发现问题:在合并前就发现问题,避免打印后才发现错误
  3. 保证报销准确:只有所有金额都正确识别,才允许生成报销文件

当遇到金额识别错误时:

⚠️  金额识别错误 - 程序已停止
错误: 无法从 xxx.pdf 提取票价金额!
建议:
  1. 检查PDF文件是否损坏
  2. 检查是否为扫描版PDF(需要OCR处理)
  3. 手动打开PDF确认是否包含票价信息

这意味着:

  • ✅ 所有生成的 info.txt 中的金额都是准确的
  • ✅ 可以放心用于报销,无需担心金额错误
  • ✅ 程序不会"悄悄"地把金额设为0

目录结构示例

程序支持递归扫描,可以处理包含子文件夹的复杂目录结构:

my_invoices/
├── 2025年10月/
│   ├── 发票1.pdf
│   └── 发票2.pdf
├── 2025年11月/
│   ├── 发票3.pdf
│   └── 发票4.pdf
├── 其他发票/
│   └── 发票5.pdf
└── output/           ← 输出目录(自动排除扫描)
    ├── 2025-10.pdf    (合并后的PDF)
    ├── 2025-11.pdf    (合并后的PDF)
    └── info.txt       (统计信息)

说明

  • 程序会自动递归扫描所有子文件夹
  • 无需手动整理文件夹结构
  • output 目录会被自动排除,避免重复处理
  • info.txt 自动生成,包含所有月份的统计汇总

注意事项

  • 确保输入的PDF文件包含文本内容(非纯图片扫描)
  • 如果是扫描版PDF,建议先进行OCR处理
  • 程序会在处理过程中输出详细的日志信息
  • 如果某个PDF无法提取日期,会使用文件修改时间并给出警告

技术栈

  • Python 3.8+
  • PyMuPDF (fitz) - PDF处理库
  • tqdm - 进度条显示

FAQ

为什么推荐使用 python -m invoice_merger 方式?

  1. 虚拟环境友好:在虚拟环境中无需激活即可使用
  2. 跨平台一致:Windows/Mac/Linux 都是相同的命令
  3. 明确 Python 版本:可以指定使用哪个 Python(如 python3.11 -m invoice_merger
  4. 开发更方便:使用 pip install -e . 安装后立即可用

如何在任何地方使用?

# 方式1: 使用 python -m(推荐)
python -m invoice_merger /path/to/invoices

# 方式2: 全局安装后使用命令
pip install invoice-merger
invoice-merger /path/to/invoices

# 方式3: pipx 隔离安装
pipx install invoice-merger
invoice-merger /path/to/invoices

开发时如何测试?

# 1. 克隆仓库
git clone https://github.com/luzhongqiu/invoice-merger.git
cd invoice-merger

# 2. 创建虚拟环境
python -m venv venv
source venv/bin/activate  # Windows: venv\Scripts\activate

# 3. 安装开发版
pip install -e .

# 4. 测试运行
python -m invoice_merger ./test_data

贡献

欢迎提交 Issue 和 Pull Request!

项目地址:https://github.com/luzhongqiu/invoice-merger

许可证

MIT License

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

invoice_merger-1.1.0.tar.gz (1.1 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

invoice_merger-1.1.0-py3-none-any.whl (13.3 kB view details)

Uploaded Python 3

File details

Details for the file invoice_merger-1.1.0.tar.gz.

File metadata

  • Download URL: invoice_merger-1.1.0.tar.gz
  • Upload date:
  • Size: 1.1 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for invoice_merger-1.1.0.tar.gz
Algorithm Hash digest
SHA256 271771428fdb387a19c40946136e65ceae81cda4159b4b8c1b59a01921adf329
MD5 abbe6365d000a9fa08dd3e2d13cb2c6e
BLAKE2b-256 e029135778fa35d4f4ad2e03a0c2f3b24d5f6f8c326686af2cd4afee78b902d3

See more details on using hashes here.

File details

Details for the file invoice_merger-1.1.0-py3-none-any.whl.

File metadata

  • Download URL: invoice_merger-1.1.0-py3-none-any.whl
  • Upload date:
  • Size: 13.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for invoice_merger-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c25063cc35df8322b1d312c314c9ea7fea2a029c1d1aedd4f345d670db31cc1f
MD5 9aba9c5584ec66174b7078094aad91a9
BLAKE2b-256 8d4a141b3f8bed5756f21e41f245c0beadcdc3ed92b2cae260b18b6d8202a49f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page