Enterprise Report Merger — 企业报表合并技能
概述
将多个来源(Excel/PDF)的企业报表合并为统一结果,并将合并数据填入 Word 模板,生成成品文档。
核心能力(默认行为):
- 读取 Excel(.xlsx/.xls)和 PDF 文件中的表格数据
- 三种合并模式:简单拼接 / 按关键字合并 / 合并报表+抵销分录
- 将合并结果写入格式化 Excel 文件
- 将合并数据填入 Word(.docx)模板,生成最终报告
按需能力(仅用户明确要求时触发):
- 无模板时自动生成完整分析报告(如贷后分析报告),含数据表格+自动分析文字+财务比率+风险评估
优先级原则:技能的基础行为就是「合并报表 → 填入 Word 模板 → 生成成品文档」。自动生成报告等高级功能属于按需扩展,仅当用户明确提出"生成分析报告""生成贷后分析报告""没有模板,帮我生成一份报告"等需求时才启用,不得在用户只要求合并/填模板时主动建议或触发。
触发条件
核心触发(合并 + 填模板):
- "合并报表""合并多个Excel""汇总报表""报表合并"
- "子公司报表合并""集团合并报表""合并财务报表"
- "把数据填到Word模板里""填充Word模板"
- "从PDF提取表格""PDF转Excel"
- "多部门数据汇总""汇总各部门数据"
按需触发(仅用户明确要求时):
- "生成报告""自动生成分析报告""生成贷后分析报告""没有模板生成报告"
默认行为是合并+填模板。当用户只说"合并""填模板"时,直接执行合并和/或填充流程,不主动询问是否需要生成分析报告。只有当用户明确提出生成报告的需求,且未提供 Word 模板时,才进入"无模板自动生成报告"流程。
环境准备
Python 依赖
执行脚本前确保以下依赖已安装(在隔离 venv 中安装):
# 使用 WorkBuddy 管理的 Python 环境
pip install openpyxl pdfplumber python-docx xlrd PyMuPDF
如果用户只使用 Excel 输入输出,只需 openpyxl。
如果输入包含旧版 .xls 文件,需要额外安装 xlrd。
如果需要 PDF 提取,需要 pdfplumber。
如果需要检测图片型 PDF,需要 PyMuPDF(即 fitz)。
如果需要 Word 模板填充,需要 python-docx。
图片型 PDF 不自动识别:视觉识别精度有限(数字误读率较高),检测到图片型 PDF 后告知用户谨慎检查或手动合并。如用户明确要求尝试自动识别,可参考
references/image_pdf_guide.md中的流程,但务必逐项核对。
运行环境
Python: python3 (需 3.8+)
脚本路径: <skill_dir>/scripts/merge_reports.py
使用流程
第一步:分析用户需求
确定以下关键信息:
- 输入文件:用户提供了哪些文件?格式是什么(Excel/PDF)?
- 合并模式:用户需要哪种合并方式?(参考下方决策指南)
- 输出格式:用户需要 Excel 结果还是 Word 报告?是否提供了 Word 模板?如提供了模板则直接填充;如未提供模板且用户只要求合并,则输出 Excel 合并结果,不主动建议生成分析报告。仅当用户明确要求"生成分析报告"时,才进入"无模板自动生成报告"流程。
- 键值列:如果需要按关键字合并或编制合并报表,键值列是什么(如"科目代码""部门名称")?
- 抵销分录:如果是集团合并报表,是否有内部交易需要抵销?
第二步:选择合并模式
参考 references/merge_modes.md 中的决策指南:
各来源报表的列结构是否一致?
├─ 是 → 是否需要按行匹配(而非简单堆叠)?
│ ├─ 否 → concat(简单拼接)
│ └─ 是 → key(按关键字合并)
└─ 否 → 是否有共同的键值列?
├─ 是 → 是否需要处理内部交易抵销?
│ ├─ 否 → key(按关键字合并)
│ └─ 是 → consolidation(合并报表+抵销)
└─ 否 → 需要人工预处理
第三步:执行合并
使用 scripts/merge_reports.py 执行合并操作。所有命令通过 Bash 工具运行。
模式一:简单拼接
<python_path> <skill_dir>/scripts/merge_reports.py merge \
--input file1.xlsx file2.xlsx file3.xlsx \
--mode concat \
--output 合并结果.xlsx \
[--source-labels "来源1" "来源2" "来源3"] \
[--header-row 1] \
[--sheet "工作表名"]
模式二:按关键字合并
<python_path> <skill_dir>/scripts/merge_reports.py merge \
--input 子公司A.xlsx 子公司B.xlsx \
--mode key \
--key-column "科目代码" \
--output 合并对照表.xlsx \
[--source-labels "子公司A" "子公司B"]
模式三:合并报表 + 抵销分录
<python_path> <skill_dir>/scripts/merge_reports.py merge \
--input 母公司.xlsx 子公司A.xlsx 子公司B.xlsx \
--mode consolidation \
--key-column "科目代码" \
--elimination-entries 抵销分录.json \
--output 合并报表.xlsx \
[--source-labels "母公司" "子公司A" "子公司B"]
抵销分录 JSON 格式见 references/merge_modes.md。
PDF 表格提取
如果输入包含 PDF 文件,可以先单独提取检查:
<python_path> <skill_dir>/scripts/merge_reports.py extract-pdf \
--input report.pdf \
--output extracted.xlsx \
[--pages "0-5"] \
[--table-index 0]
PDF 提取的注意事项见 references/pdf_extraction.md。
图片型 PDF 处理(扫描件)
如果 PDF 是扫描件/图片型,pdfplumber 无法提取表格。视觉识别精度有限,可能存在数字误读(如 5↔6、8↔9、首位数字错位等),不建议自动填入。
处理策略:检测到图片型 PDF 后,告知用户该文件为图片型,提示谨慎检查或手动合并。
<python_path> <skill_dir>/scripts/pdf_to_images.py \
--input report.pdf \
--output-dir ./pdf_images \
--detect-only
返回 JSON 中 type 字段:
text:文本型,直接用 pdfplumber 提取image:图片型,提示用户谨慎检查或手动合并mixed:混合型,文本页用 pdfplumber,图片页提示用户
推荐方案:如果用户愿意截屏发送,精度远高于自动渲染识别。告知用户可将三表分别截屏发来,由 AI 直接识别截图数据,然后填入模板(详见 references/image_pdf_guide.md 中的"截图识别方案")。
⚠️ 无论截图还是自动渲染,识别完成后必须执行多维度交叉验证:调用 validate_financial_data() 自动检查全部 10 项勾稽关系(表内 8 项 + 表间 2 项),任何一项不通过必须重读图片修正。详见 references/image_pdf_guide.md 中的"多维度交叉验证框架"。
如果用户仍希望尝试自动渲染识别,可参考 references/image_pdf_guide.md 中的备用流程,但务必逐项核对关键数字。
第四步:填充 Word 模板
如果用户提供了 Word 模板(.docx),使用以下方式填充:
方式一:合并时直接填充
<python_path> <skill_dir>/scripts/merge_reports.py merge \
--input file1.xlsx file2.xlsx \
--mode consolidation \
--key-column "科目代码" \
--output 合并报表.xlsx \
--word-template 模板.docx \
--word-output 最终报告.docx \
--mapping 映射配置.json
方式二:单独填充(已有合并后的 Excel)
<python_path> <skill_dir>/scripts/merge_reports.py fill-template \
--input 合并数据.xlsx \
--template 模板.docx \
--output 最终报告.docx \
--mapping 映射配置.json
Word 模板填充策略
脚本支持两种填充策略(可同时使用):
1. 占位符替换:将文档中的 {{占位符}} 替换为对应值。
模板中文本写法:
报告日期:{{报告日期}}
编制单位:{{编制单位}}
映射配置 JSON:
{
"placeholders": {
"报告日期": "2024年12月31日",
"编制单位": "XX集团有限公司"
}
}
如果不提供映射配置,脚本会自动用合并数据第一行的值填充同名占位符。
2. 表格填充:将合并数据填入 Word 文档中的表格。
映射配置 JSON:
{
"table_mapping": {
"target_table_index": 0,
"column_map": {
"模板表格列名": "数据列名"
},
"key_column": "科目代码"
}
}
target_table_index:Word 文档中第几个表格(从 0 开始)column_map:模板表格表头与数据列名的映射(不指定则按位置匹配)key_column:如果指定,会按此列的值匹配模板中已有的行(更新而非追加)
第五步:检查并交付结果
- 读取输出 Excel 文件,检查合并结果是否正确
- 如果填充了 Word 模板,读取输出 Word 文件检查格式
- 将最终文件交付给用户
无模板自动生成报告(按需功能,仅用户明确要求时启用)
此功能为按需扩展,不是默认行为。只有当用户明确提出"生成分析报告""生成贷后分析报告""没有模板帮我生成一份报告"等需求时才启用。用户只要求合并报表或填模板时,不主动进入此流程。
当用户提供了财务报表但没有 Word 模板,且明确要求生成分析报告时,可使用 scripts/generate_report.py 自动生成一份完整的分析报告(如贷后分析报告)。
使用场景(仅以下情况触发,不主动建议)
- 用户明确说"帮我生成一份贷后分析报告""没有模板,直接生成""生成分析报告"
- 用户提供 Excel/PDF 报表并明确要求生成分析报告,但未提供 Word 模板
工作流程
- 从源文件(Excel/PDF)提取财务数据,整理为三个字典:
bs_data(资产负债表)、is_data(利润表)、cf_data(现金流量表) - 询问用户:企业名称、报告期间(如"2025年12月")、贷款信息(可选)
- 将数据写入 JSON 文件(或直接在 Python 脚本中调用)
- 运行
generate_report.py生成 Word 文档
CLI 用法
<python_path> <skill_dir>/scripts/generate_report.py \
--company "XX公司" \
--period "2025年12月" \
--bs-data bs.json \
--is-data is.json \
[--cf-data cf.json] \
--output 贷后分析报告.docx \
[--prev-bs-data prev_bs.json] \
[--prev-is-data prev_is.json] \
[--prev-cf-data prev_cf.json] \
[--loan-amount 50000000] \
[--loan-type "流动资金贷款"] \
[--guarantor "保证担保"] \
[--report-type "贷后分析报告"] \
[--establish-date "2005年"] \
[--registered-capital "6000"] \
[--main-business "包装材料生产"] \
[--industry "制造业"] \
[--loan-period "2024.01-2027.01"] \
[--collateral "厂房及设备"]
模块调用用法
from generate_report import generate_report
generate_report(
company="XX公司",
period="2025年12月",
bs_data={"货币资金": "35677380.72", "资产总计": "623198671.81", ...},
is_data={"营业收入": "645841626.73", "净利润": "42820418.29", ...},
cf_data={"经营活动产生的现金流量净额": "35000000.00", ...},
output_path="贷后分析报告.docx",
loan_amount=50000000,
loan_type="流动资金贷款",
)
JSON 数据格式
每个 JSON 文件是一个字典,key 为科目名称(中文),value 为金额字符串(元为单位):
{
"货币资金": "35677380.72",
"应收账款": "219143915.18",
"资产总计": "623198671.81",
"负债合计": "237117278.05",
"所有者权益合计": "386081393.76"
}
生成的报告结构
标准贷后分析报告模板(详见 references/standard_report_template.md):
| 章节 | 内容 |
|---|---|
| 标题页 | 企业名称 + 报告类型 + 报告期间 + 编制日期 |
| 一、企业基本情况 | (一)企业概况(名称/成立日期/注册资本/主营/行业)+(二)贷款情况(类型/金额/期限/担保/抵押物) |
| 二、财务状况分析 | (一)资产负债分析(表格+资产/负债/权益三段文字)+(二)利润分析(表格+文字)+(三)现金流量分析(表格+文字) |
| 三、主要财务指标分析 | 4 类 18 项财务比率表格(偿债能力/营运效率/盈利能力/发展能力分表,含参考值与评估列)+ 四类分析文字 |
| 四、贷款风险评估 | 风险评估文字 + 风险评级表格(4维度+综合评级) |
| 五、结论与建议 | 综合结论 + 编号贷后管理建议(3-5条,基于数据自动生成) |
企业信息参数(均可选,未提供则省略对应内容):
--establish-date、--registered-capital、--main-business、--industry、--loan-period、--collateral
自动分析文字示例
脚本会根据实际数据自动生成分析文字,例如:
截至2025年12月末,公司资产总额为80,000万元,其中流动资产56,000万元,占资产总额的70.00%;非流动资产24,000万元,占资产总额的30.00%。流动资产中,货币资金6,000万元,应收账款30,000万元,存货20,000万元,是流动资产的主要构成部分。
如提供上期数据,还会自动生成同比变动分析:
与上期末相比,资产总额增加了1,234万元,增幅2.0%。
标蓝规则
所有自动生成的文字和表格数据均标为蓝色(RGBColor(0, 0, 255)),与"填模板"模式保持一致,便于审阅时识别。使用 --no-blue 参数可关闭标蓝。
v2 增强功能(实测改进)
以下功能已在实际贷后分析报告填充中验证通过,处理 PDF 集团报表 → Word 模板的场景。
1. 四舍五入精确到万元
使用 to_wan_rounded() 将元转换为万元并四舍五入到整数:
from merge_reports import to_wan_rounded
# 837,023,674.68 元 → "83,702" 万元
# -307,361.88 元 → "-31" 万元
# 884.77 元 → "0" 万元
适用场景:PDF 报表以"元"为单位,Word 模板以"万元"为单位时自动转换。
2. 科目名模糊匹配
使用 find_account_match() 自动匹配不同来源的科目名称:
from merge_reports import find_account_match
# "固定资产净额" → 匹配 PDF 中的 "固定资产" [alias]
# "营业税金及附加" → 匹配 PDF 中的 "税金及附加" [alias]
# "所有者权益合计" → 匹配 PDF 中的 "股东权益合计" [alias]
# "实收资本(股本)" → 匹配 PDF 中的 "股本" [alias]
匹配策略(按优先级):
- 精确匹配:名称完全一致
- 别名匹配:通过内置别名表(
ACCOUNT_ALIASES)查找已知同义科目 - 归一化匹配:去除"其中:""合计""小计""净额"等后缀后比较
- 子串匹配:名称包含关系(仅≥3字符)
- 相似度匹配:difflib 相似度 ≥ 0.7
冲突检测:自动拒绝"应收"↔"应付"、"资产"↔"负债"等方向相反的误匹配。
3. 财务分析文字更新
使用 set_paragraph_blue() 更新 Word 文档中的财务分析段落:
from merge_reports import set_paragraph_blue
# 将 "截至2026年2月末,总资产80,499万元..."
# 更新为 "截至2026年6月末,总资产83,702万元..."
# 更新后的文字自动标蓝
4. 财务比率计算(4 类 18 项,v1.1)
使用 calculate_financial_ratios(bs_data, is_data, cf_data=None, prev_bs_data=None, prev_is_data=None, prev_cf_data=None) 自动计算。签名支持现金流量表与上期数据(上期用于平均余额与增长率)。返回固定 18 个 key 的字典,数据缺失时对应项为 -(表格保留指标行)。
1. 偿债能力(7 项)
| 子类 | 比率 | 公式 |
|---|---|---|
| 短期 | 流动比率 | 流动资产合计 / 流动负债合计 |
| 短期 | 速动比率 | (流动资产合计 - 存货) / 流动负债合计 |
| 长期 | 资产负债率 | 负债合计 / 资产总计 × 100% |
| 长期 | 权益乘数 | 资产总计 / 所有者权益合计 |
| 长期 | 利息保障倍数 | (利润总额 + 利息支出) / 利息支出(利息缺失 → -) |
| 长期 | 现金流量负债率 | 经营活动现金流量净额 / 负债合计 × 100%(需现金流量表) |
| 长期 | 负债权益比 | 负债合计 / 所有者权益合计 × 100% |
2. 营运效率(3 项,平均余额口径,需上期数据)
| 比率 | 公式 |
|---|---|
| 存货周转率 | 营业成本 / 平均存货 |
| 应收账款周转率 | 营业收入 / 平均应收账款 |
| 总资产周转率 | 营业收入 / 平均总资产 |
3. 盈利能力(5 项)
| 比率 | 公式 |
|---|---|
| 净资产收益率(ROE) | 净利润 / 所有者权益合计 × 100% |
| 毛利率 | (营业收入 - 营业成本) / 营业收入 × 100% |
| 营业净利率 | 净利润 / 营业收入 × 100% |
| 总资产收益率 | 净利润 / 平均总资产 × 100% |
| 总资产报酬率 | (利润总额 + 利息支出) / 平均总资产 × 100%;利息不可得时退化为 (利润总额或净利润) / 平均总资产 |
4. 发展能力(3 项,需上期数据)
| 比率 | 公式 |
|---|---|
| 销售增长率 | (本期营业收入 - 上期营业收入) / |上期营业收入| × 100% |
| 净利润增长率 | (本期净利润 - 上期净利润) / |上期净利润| × 100% |
| 每股收益增长率 | (本期基本每股收益 - 上期基本每股收益) / |上期基本每股收益| × 100% |
- 平均余额 = (期初 + 期末) / 2,期初即上期期末;上期数据缺失时对应指标为
- - 增长率分母取绝对值,上期缺失或为 0 时显示
- - 报告展示:按 4 类分 5 个表格(偿债能力拆短期/长期),每表列 [指标, 本期值, 上期值, 参考值, 评估];周转率/增长率行业差异大,参考值与评估列显示
-
⚠️ 重要规则:若 Word 模板中没有自带的财务比率板块/表格,在添加财务比率内容前必须先询问用户是否需要添加,不得自动添加。只有在模板已有对应板块时才直接填充。
5. 标蓝标记
使用 set_cell_blue() 和 set_paragraph_blue() 将所有填写或改动的文字标为蓝色(RGBColor(0, 0, 255)),便于审阅时快速识别新增内容。
PDF 双栏资产负债表提取
PDF 资产负债表通常为双栏布局(左资产右负债),表格结构为 8 列:
[资产项目, 行次, 期末数, 年初数, 负债项目, 行次, 期末数, 年初数]
提取时需使用正确的列索引:
- 资产类:col 0 = 名称, col 2 = 期末数
- 负债/权益类:col 4 = 名称, col 6 = 期末数
利润表通常为 4 列:[项目, 行次, 本月数, 本年累计数]
- col 0 = 名称, col 3 = 本年累计数
使用 clean_item_name() 清理 PDF 提取的科目名称(去除"一、""减:""加:"等前缀)。
关键注意事项
-
PDF 提取不保证 100% 准确:文本型 PDF 用 pdfplumber 提取效果较好;图片型/扫描件 PDF 视觉识别精度有限,检测到图片型 PDF 后应提示用户谨慎检查或手动合并。详见
references/pdf_extraction.md和references/image_pdf_guide.md。 -
抵销分录方向:借方减少资产/费用类科目金额,贷方增加。这与会计准则一致,但在配置时需仔细确认方向。
-
模糊匹配:键值列名支持模糊匹配。指定
--key-column "科目"可匹配到"科目代码""科目名称"等列。抵销分录中的"科目"字段也支持模糊匹配。 -
Word 模板占位符:占位符格式为
{{字段名}},字段名只能包含字母、数字和下划线。中文占位符需要在映射配置中显式指定。 -
数据类型处理:脚本自动识别数值列进行加总。包含逗号的数字(如
1,234,567)会自动清洗。非数值列(如科目名称、备注)不做加总,取第一个非空值。 -
大文件处理:如果输入文件很大(超过 10MB),建议先拆分或筛选数据,避免内存不足。
-
PDF 双栏布局:资产负债表 PDF 通常为左右双栏(资产|负债),提取时需注意列索引。资产期末数在 col 2,负债期末数在 col 6。详见上方"PDF 双栏资产负债表提取"。
-
科目名差异:不同来源的报表科目名可能不一致(如"固定资产"vs"固定资产净额"、"税金及附加"vs"营业税金及附加")。使用
find_account_match()自动匹配,避免手工映射。 -
单位转换(以模板为准):源数据单位向 Word 模板对齐,而非反过来。填充前先读模板判断单位(看表头"单位:万元/元/亿元"标注,或看已有数据列的量级推断),然后按模板单位转换源数据:
- 模板用元 → 源数据(通常也是元)直接填入,不转换
- 模板用万元 → 用
to_wan_rounded()将元转为万元并四舍五入到整数 - 模板用亿元 → 除以 1 亿,保留两位小数
- 模板用千元 → 除以 1000
- 填入后抽查关键科目(如资产总计、净利润),确认量级与模板已有列一致,防止单位搞反。
-
标蓝审阅:填充 Word 模板时,建议使用
set_cell_blue()和set_paragraph_blue()将所有新增/修改内容标蓝,便于审阅。 -
.xls 格式支持:旧版
.xls文件(非.xlsx)需要xlrd库。read_excel()会自动检测文件后缀并选择对应库。安装:pip install xlrd。 -
中文全角引号:Excel/PDF 中的科目名可能含中文全角引号(如
所有者权益(或股东权益)合计),与代码中的直引号不匹配。使用find_in_data()代替直接.get(),内部调用normalize_quotes()自动转换。 -
子串匹配误匹配:查找"负债合计"时,直接子串匹配会命中"流动负债合计"。
find_in_data()使用四级查找(精确→归一化→排除前缀修饰词→兜底),避免此类问题。前缀修饰词包括:流动、非流动、其他、一年内到期。 -
财务比率规则:若 Word 模板中没有自带的财务比率板块/表格,在添加财务比率内容前必须先询问用户是否需要添加,不得自动添加。只有在模板已有对应板块时才直接填充。
-
图片型 PDF 必须多维度验证:截图或渲染识别后,必须调用
validate_financial_data()进行 10 项勾稽关系验证(表内 8 项 + 表间 2 项)。任何合计项偏差 > 0 必须重读图片修正,不得直接填入模板。
脚本文件说明
| 文件 | 说明 |
|---|---|
scripts/merge_reports.py |
核心脚本,包含数据读取、合并、输出、Word 填充、PDF 类型检测、多维度交叉验证(validate_financial_data())全部功能 |
scripts/generate_report.py |
无模板自动生成报告脚本,从财务数据字典生成完整的贷后分析报告(含企业概况+表格+分析文字+财务比率+风险评估表+编号建议) |
scripts/pdf_to_images.py |
PDF 类型检测工具,可检测文本型/图片型/混合型,并支持转图片功能(检测到图片型后提示用户谨慎检查或手动合并) |
references/merge_modes.md |
三种合并模式的详细说明、参数配置、示例 |
references/pdf_extraction.md |
PDF 表格提取的注意事项、常见问题和处理策略 |
references/image_pdf_guide.md |
图片型/扫描件 PDF 的检测方法、转换流程和视觉识别指南 |
references/standard_report_template.md |
标准贷后分析报告模板规范(基于4份实际模板提炼) |
