# 投资月报《弹窗提示》规则(定稿 2026-09-17) > 用户要求:「程序里面设置一个提示,只要有不对的地方就弹窗提示」。 > 本文件把**所有检查项、级别、弹窗文案、建议动作**写死成一张表; > 《匹配校验报告_.md》开头与 `弹窗提示_.tsv` 都按本表产出。 > 将来搬进 Java 后端/网页时**按此逐条弹窗,规则一字不改**。 ## 一、级别定义 | 级别 | 含义 | 程序行为 | | --- | --- | --- | | **阻断** | 数据不齐/解析失败,不能写表 | 不执行写入,必须先处理 | | **警告** | 数据有疑点,需人工确认 | 可写入,但必须人工确认后再写 | | **提示** | 仅告知,不阻断 | 记录备查,可继续 | ## 二、检查项清单(17 项) | 编号 | 类型 | 级别 | 触发条件 | 数据来源 | 建议动作 | | --- | --- | --- | --- | --- | --- | | 1 | 缺本期投资系统表 | 阻断 | 「输入」目录里找不到本期《模板_查询结果》(按文件名或『时期』列识别) | 输入目录 | 把本期投资系统导出放进 `docs\投资\输入\` 后重跑 | | 2 | 缺上月投资系统表 | 警告 | 找不到上月《模板_查询结果》→ 月度校验无法执行 | 输入目录 | 每月把上月、本月两份都放进 `输入\` | | 3 | 缺源文件解析校验 | 阻断 | 没有 `解析校验_<月>.tsv` | 输出目录 | 先跑 `市州月报解析.py --month <月>` | | 4 | 源文件解析异常 | 阻断/警告 | 源文件「未选中工作表」(警告) 或「解析失败」(阻断) | `解析校验_<月>.tsv` | 人工打开源文件确认表头/数据;必要时登记特例 | | 5 | 源文件内部对不上 | 警告 | 项目行求和 ≠ 合计/小计/市州行 | `解析校验_<月>.tsv` | 让市州核对源文件(合计行或项目行有错) | | 6 | 源文件与投资系统不一致 | 警告 | 5 个数值字段任一:市州月报 vs 投资系统 差额 > 1 | 源文件 + 投资系统 | 人工确认以哪个为准 | | 7 | **疑似取列错位** | 警告 | 市州月报某字段的值**恰好等于**投资系统另一个字段 | 源文件 + 投资系统 | 检查源文件表头(组表头合并单元格最易错位),修取列规则后重跑 | | 8 | 投资系统名称写法不同 | 提示 | 名称去间隔号/括注后能对上投资系统记录 | 源文件 + 投资系统 | 已按投资系统记录做数值对照(项目名称不动) | | 9 | 投资系统查无此项目 | 提示 | 投资系统本期没有这个项目名 | 投资系统 | 知悉即可;如需以系统为准请人工核对名称 | | 10 | 疑似同一项目(名称写法不同) | 警告 | 与目标表已有项目「宽松等价」或「去括注/间隔号后相同」或相似度 ≥ 0.90 | 目标表 + 源文件 | 人工确认:是同一项目 → **不改名称**、按投资系统名称更新;否 → 整行新增 | | 11 | 将新增项目 | 提示 | 目标表没有该项目(且不构成第 10 条) | 目标表 + 源文件 | 确认是真实新项目后整行插入(复制相邻行格式);相似度 0.80–0.90 会在详情里附提示 | | 12 | 月度等式不符 | 警告 | 本月自年初累计 ≠ 上月自年初累计 + 本月完成 | 上月/本月投资系统 | 写入时按等式纠正,并让市州确认 | | 13 | 本期无该市州数据 | 提示 | 某市州本期一个项目行都没有 | 源文件 | 确认是「确实没有项目」还是「漏报」,漏报则让市州补报 | | 14 | 本期源文件里没有的项目 | 提示 | 目标表有、本期源文件没报 | 目标表 + 源文件 | 按口径保持上月原值;若已停建请人工确认是否保留 | | 15 | 源文件缺关键列 | 警告 | 按表头找不到「自开始建设累计/自年初累计/本月完成」任一列 | `解析校验_<月>.tsv` 的「列位」 | 人工确认源文件表头是否被改过;必要时登记特例 | | 16 | 目标表列位置与预期不符 | 警告 | 目标明细表按表头定位出的列 ≠ 母版默认列位(关键列) | 目标明细表 | 确认母版是否被改动;程序已按表头写入,仍请人工核对 | | 17 | 目标表个别列按母版默认 | 提示 | 非关键列(如「建设阶段/形象进度」)母版里没有子表头,按默认列位写入 | 目标明细表 | 知悉即可 | ## 三、2026-07 期实际触发情况(跑 `匹配与校验.py --month 2026-07`) 共 **47 项**:**阻断 0 / 警告 10 / 提示 37**。 - 警告 10:源文件与投资系统不一致 4(宜都供销商贸物流园、巴东青龙桥、松滋星络、麻城农产品综合物流园)、疑似同一项目 4(鄂湘赣一期、中国供销公安、荆门北洋、荆门智慧冷链)、缺上月投资系统表 1、源文件缺关键列 1(武汉客运《站场固投(南山、汉口站)》没有「自年初累计」列表头)。 - 提示 37:将新增项目 5、投资系统名称写法不同 5、投资系统查无此项目 15、本期无该市州数据 2、本期源文件里没有的项目 2、目标表个别列按母版默认 1、其它 7。 ## 四、2026-09-17 取列错位修复记录(对应第 7 条规则) - **现象**:报告里出现「`九州通沃田国际供应链中心项目` 自年初累计 市州月报 8000 / 投资系统 4200」。 - **根因**:鄂州《2026年7月企业月报汇总(鄂州).xls》表头是**两级表头**:R5 组表头「自年初累计完成投资(万元)」是**合并单元格 I5:K5**,R6 子表头 I=本年计划投资、J=合计、K=其中:本月完成投资。 原解析规则只认「命中最靠上、词最短」,于是把「自年初累计」定位到了 **I 列(本年计划投资)** → 8000。 - **用户核实**:`九州通沃田国际供应链中心项目` 的**本年计划投资就是 8000,是对的**(与投资系统 F 列 8000 一致)。 - **修复**:`市州月报解析.py` 改为**合并区感知**:如果某字段的命中落在跨多列的合并单元格里,就在该合并区内排除「其它字段更深的子表头」所占的列,只剩唯一一列时才用它。 → 「自年初累计」落在 **J 列**,值与投资系统 G 列(4200)、目标明细表 J 列(4200)三方一致。 - **影响面**:全量复跑 2026-07,**只有 4 行变化**(鄂州 3 行 + 天门 1 行),其余 147 行逐字不变; 天门那行同样有 I5:K5 组表头(源文件 I=36835 是本年计划投资,J=16177.7 才是自年初累计,与目标表一致)。 - **防复发**:新增第 7 条「疑似取列错位」自动告警。回归验证:把修复前的解析结果喂给程序,会自动弹出 5 条「疑似取列错位」,命中的正是 4 个受影响项目。 ## 五、怎么跑 ```powershell python docs\投资\工具\市州月报解析.py --month 2026-07 # 产出 解析结果 / 解析报告 / 解析校验 python docs\投资\工具\匹配与校验.py --month 2026-07 # 产出 变更清单 / 匹配校验报告 / 弹窗提示 ``` 产出(`docs\投资\输出\`): | 文件 | 用途 | | --- | --- | | `解析结果_<月>.tsv` | 一行一个项目(机器可读) | | `解析报告_<月>.md` | 人读:每个文件的市州/项目数/字段求和/一致性 | | `解析校验_<月>.tsv` | 每个源文件的自洽性(项目行求和 vs 合计行) | | `变更清单_<月>.tsv` | 给写入侧:动作/目标行号/6 列新值 | | `匹配校验报告_<月>.md` | 人读:弹窗总览 + 匹配统计 + 三方比对 + 月度校验 | | **`弹窗提示_<月>.tsv`** | **机器可读弹窗清单(级别/类型/品类/市州/项目名称/来源/详情/建议动作)** | ## 六、取列机制:**按表头定位,不是按固定列号**(2026-09-17 追加) > 用户提问:「你是不是只跟列来取数据了,而不是根据标头来定位的?」——下面把每一处的口径写清楚。 ### 6.1 源文件(市州报上来的 27 份):**按表头关键字定位** - 在前 14 行 × 前 34 列里用正则匹配表头(`格式探测.py` 的 `FIELD_PAT`),命中哪个单元格就用哪一列: `项目名称 / 建设单位 / 建设性质 / 开工时间 / 竣工时间 / 总投资 / 自开始建设累计 / 本年计划投资 / 自年初累计 / 本月完成 / 建设阶段 / 形象进度`。 - 证据:**同一批文件识别出的列号并不相同**(见 `解析报告_<月>.md` 的「各源文件识别到的列位」一节): - 多数文件:项目名称 B、总投资 G、自开始建设 H、本年计划 I、自年初 J、本月 K; - 襄阳 `.et`:依次是 B/H/I/J/K(整体右移一列); - 随州物流:项目名称在 **A 列**(没有序号列); - 武汉客运《站场固投(南山、汉口站)》:总投资在 **F 列**,而且**没有「自年初累计」列表头**(已按第 15 条弹窗)。 - 三处仍然按位置的处理(已明确记录,不是漏改): 1. **序号/分类行/小计合计行**的文字假定在 **A 列**; 2. **市州行**(判断市州分段)只看**前 5 列**; 3. 「项目行」还需要 A 列是序号或空(兼容随州这种无序号列的写法)。 - 两级表头消歧(同列冲突):字段命中落在**跨多列的合并单元格**里时,在该合并区内排除其它字段更深的子表头所占列,只剩唯一一列才采用(鄂州 J 列就是这么定出来的)。 - 同名列消歧(同类不同列):同一字段命中多列时,**优先「表头下方真的有数字」的那一列**,同分再取更靠左的。 例:武汉物流「自开始建设累计**完成投资**」在 H、「自开始建设累计**新增建筑面积**」在 P —— 取 H; 修好后武汉物流该字段项目行求和 = **146313.9**,与目标表武汉市场州行 H 列 **146313.9** 完全一致(此前误取 P,求和为 0)。 ### 6.2 目标明细表(两张):原来是**写死列号**,现已改为「按表头定位 + 与母版默认列位比对」 - 客运 `X月客运站投资明细表.xlsx / 明细` 与物流 `X月物流站场投资明细.xls / 分项目投资完成情况` 现在都用同一套表头定位(母版默认列位 B/C/D/E/F/G/H/I/J/K/L/M 作为兜底)。 - **母版列位与预期不符时会弹窗**:报告里出现「目标表列位置与预期不符」即表示母版被动过,程序仍按表头写入,但请人工核对。 - 注意:物流目标表本身也是**两级表头**(R5/R6,J5:K5 合并),与鄂州格式同源 —— 这正是「按表头定位」的价值所在。