docs/¹¤¾ß/»ã×Ü´ó±í²îÒì±È¶Ô.py
@@ -91,7 +91,37 @@
            for k in range(i2-i1): pairs[i1+k] = j1+k
    return pairs
NOTE = """
> **已确认口径(2026-09-28,用户)——以下不计入问题**
> 1. ` è´§è¿` æ¯å¸‚å·ž 6 è¡Œ vs æ‰‹å·¥ 4 è¡Œï¼šç¨‹åºæ–°å¢žã€Œè§„上+规下货运量(万吨)」「规下货运量(万吨)」各 17 è¡Œï¼ˆå…± 34 è¡Œï¼‰ï¼Œå±žæ¯ç‰ˆè®¾è®¡ â†’ å½’入「已知设计(母版新增行)」。
>    å› è¡Œæ•°ä¸åŒï¼Œç¬¬ k ä¸ªå¸‚州在程序里比手工低 2×(k-1) è¡Œï¼ˆæ­¦æ±‰éƒ½ä»Žç¬¬ 11 è¡Œèµ·ï¼›é»„石 ç¨‹åº 17 / æ‰‹å·¥ 15;神农架 ç¨‹åº 107 / æ‰‹å·¥ 75)——**纯位置偏移,按"地区+指标"对齐后数值一致**。
> 2. ` è´§è¿!U5:U112`(无表头辅助列)是人工草稿 â†’ å½’入「已知设计(无表头草稿列)」。
> 3. å„排名表「当月块」是当初做母版时就加上的设计 â†’ å½’入「已知设计(排名表当月/累计块)」。
> 4. å¸‚州名短名/全名(武汉 vs æ­¦æ±‰å¸‚)不影响 â†’ å·²åšå½’一化。
> 5. å–整尾差、文本型数字只在汇总里计数,不进「实质数值差异」清单。
>
> **仍需处理/核对**
> - `班线包车` 3 æ ¼ï¼š`EO36`/`FN36`/`FO36`(荆门 å®¢è¿é‡ 2020 ç´¯è®¡/累计同比)——**程序生成时重算为 -2731.41 / -1.0008 / -1.0002**,母版与手工定稿均为 0.181777 / 2312.2199 / -0.586419;疑母版 2020 å¹´å—分母为 0,需核对公式与数据。
> - ` è´§è¿` 10 æ¡ 2022 å¹´å„市州「累计同比」:业务已确认**软件口径正确**(手工那列错)。
> - æ‰‹å·¥ä¾§å¾…改:304 æ ¼è‰ç¨¿åˆ—、286 æ ¼æ–‡æœ¬åž‹æ•°å­—、4 å¤„脏数据(`班线包车!IL4/IL5` æ–­é“¾ã€`IL50` åå¼•号、` è´§è¿!EA93/EA111` çš„ `#DIV/0!`)。
> - æ¯ç‰ˆ/程序自身:11 ä¸ª `#REF!` + 356 ä¸ª `#DIV/0!`(历史遗留)、`城市客运` ç¬¬ 2 è¡Œç¬¬ 3 ä¸ªæœˆèµ·è¡¨å¤´ä¸ºæ—¥æœŸåºåˆ—号、缺 2026-09 æ¯ç‰ˆã€å¯¼å‡ºå‰åŸºæ•°ä½“检未做。
"""
def main(gen, dgf, prefix):
    ACTION = ("实质数值差异", "错误值(程序)", "错误值(手工)", "文本不同")
    IGNORE = ("已忽略(单边有值)", "已忽略(结构/设计)", "取整尾差(可忽略)", "文本型数字(可忽略)",
              "已知设计(母版新增行)", "已知设计(无表头草稿列)", "已知设计(排名表当月/累计块)", "其它")
    cats = list(ACTION) + list(IGNORE)
    REASON = {(" è´§è¿", "EA"): "2022年各市州累计同比:业务已确认软件口径正确(手工那列错)",
              ("班线包车", "EO"): "程序生成时重算(疑母版2020年块分母为0):母版/手工为 0.1818,待核对",
              ("班线包车", "FN"): "同上:母版/手工为 2312.2199",
              ("班线包车", "FO"): "同上:母版/手工为 -0.5864"}
    def reason_of(x):
        ref = x[1]
        col = "".join(ch for ch in ref if ch.isalpha())
        return REASON.get((x[0], col), "")
    g = load_workbook(gen, data_only=True); d = load_workbook(dgf, data_only=True)
    rows_out = []
    per_sheet = []
@@ -114,24 +144,26 @@
            if c < 2: continue
            if cl_g[c] == "(无表头列)":
                bump("已知设计(无表头草稿列)"); continue
            bump("仅程序有(列)"); rows_out.append([sh, "%s*" % get_column_letter(c+1), "(整列)", cl_g[c], "仅程序有(列)", "", "", "生成件多出此列"])
            bump("已忽略(结构/设计)")
        for c in unmatched_cols_d:
            if c < 2: continue
            if cl_d[c] == "(无表头列)":
                bump("已知设计(无表头草稿列)"); continue
            bump("仅手工有(列)"); rows_out.append([sh, "(无)", "(整列)", cl_d[c], "仅手工有(列)", "", "", "手工定稿多出此列"])
            bump("已忽略(结构/设计)")
        for r in unmatched_rows_g:
            if r < 4: continue
            rowb = "%s" % wg.cell(row=r+1, column=2).value
            if is_known_extra_row(sh, rowb, "程序"):
                bump("已知设计(母版新增行)"); continue
            bump("仅程序有(行)"); rows_out.append([sh, "第%d行" % (r+1), rl_g[r], "(整行)", "仅程序有(行)", "", "", "生成件多出此区段"])
            bump("已忽略(结构/设计)")
        for r in unmatched_rows_d:
            if r < 4: continue
            if "当月块" in rl_d[r] or "累计块" in rl_d[r]:
                bump("已知设计(排名表当月/累计块)"); continue
            bump("仅手工有(行)"); rows_out.append([sh, "(无)", rl_d[r], "(整行)", "仅手工有(行)", "", "", "手工定稿多出此区段"])
            bump("已忽略(结构/设计)")
        for i, j in sorted(colmap.items()):
            if cl_g[i] == "(无表头列)" or cl_d[j] == "(无表头列)":
                bump("已知设计(无表头草稿列)"); continue
            for p, q in sorted(rowmap.items()):
                vg = wg.cell(row=p+1, column=i+1).value; vd = wd.cell(row=q+1, column=j+1).value
                if vg == vd: continue
@@ -148,9 +180,9 @@
                    else: cat = "实质数值差异"
                    note = "å·®=%.6g" % diff
                elif num(vg) and (vd is None):
                    cat = "仅程序有";
                    cat = "已忽略(单边有值)"
                elif num(vd) and (vg is None):
                    cat = "仅手工有"
                    cat = "已忽略(单边有值)"
                elif tg is not None and num(vd) and abs(tg - vd) <= 1e-9:
                    cat = "文本型数字(可忽略)"; note = "手工为文本'%s'" % vg
                elif td is not None and num(vg) and abs(td - vg) <= 1e-9:
@@ -173,9 +205,9 @@
    with io.open(csv, "w", encoding="utf-8-sig", newline="") as f:
        f.write("页签,生成件单元格,行标签,列表头,类别,生成件值,手工值,备注\n")
        for x in rows_out:
            if x[4] not in ACTION: continue
            f.write(",".join('"%s"' % str(v).replace('"', "'") for v in x) + "\n")
    # è¾“出 MD
    cats = ["实质数值差异", "错误值(程序)", "错误值(手工)", "文本不同", "仅手工有", "仅程序有", "仅程序有(列)", "仅手工有(列)", "仅程序有(行)", "仅手工有(行)", "取整尾差(可忽略)", "文本型数字(可忽略)", "已知设计(母版新增行)", "已知设计(无表头草稿列)", "已知设计(排名表当月/累计块)", "其它"]
    md = prefix + ".md"
    with io.open(md, "w", encoding="utf-8", newline="\n") as f:
        f.write("# æ±‡æ€»å¤§è¡¨å·®å¼‚明细(生成件 vs æ‰‹å·¥å®šç¨¿ï¼‰\n\n")
@@ -183,17 +215,20 @@
        f.write("## é€é¡µæ±‡æ€»\n\n| é¡µç­¾ | " + " | ".join(cats[:7]) + " |\n|---|" + "---|"*7 + "\n")
        for sh, cnt in per_sheet:
            f.write("| %s | %s |\n" % (sh, " | ".join(str(cnt.get(c, 0)) for c in cats[:7])))
        f.write("\n## å®žè´¨æ•°å€¼å·®å¼‚(全部)\n\n")
        subs = [x for x in rows_out if x[4] == "实质数值差异"]
        f.write("\n## éœ€å¤„理差异(全部,含原因)\n\n")
        subs = [x for x in rows_out if x[4] in ACTION and x[4] != "文本不同"]
        if not subs: f.write("(无)\n")
        for x in subs[:200]:
            f.write("- %s %s [%s] ç”Ÿæˆä»¶=%s æ‰‹å·¥=%s(%s)\n" % (x[0], x[1], x[2], x[5], x[6], x[7]))
        f.write("\n## ä»…手工有(前 200 æ¡ï¼‰\n\n")
        for x in [y for y in rows_out if y[4] in ("仅手工有", "仅手工有(列)")][:200]:
            f.write("- %s %s [%s] %s æ‰‹å·¥=%s\n" % (x[0], x[1], x[2], x[3], x[6]))
        f.write("\n## ä»…程序有(前 200 æ¡ï¼‰\n\n")
        for x in [y for y in rows_out if y[4] in ("仅程序有", "仅程序有(列)", "仅程序有(行)")][:200]:
            f.write("- %s %s [%s] %s ç”Ÿæˆä»¶=%s\n" % (x[0], x[1], x[2], x[3], x[5]))
        for x in subs[:300]:
            f.write("- **%s** %s [%s] ç”Ÿæˆä»¶=%s æ‰‹å·¥=%s%s\n" % (x[0], x[1], x[2], x[5], x[6],
                    ("(原因:%s)" % reason_of(x)) if reason_of(x) else ""))
        f.write("\n## æ ‡é¢˜/表头措辞差异\n\n")
        tt = [x for x in rows_out if x[4] == "文本不同"]
        if not tt: f.write("(无)\n")
        for x in tt[:50]:
            f.write("- %s %s [%s] ç”Ÿæˆä»¶=%s æ‰‹å·¥=%s\n" % (x[0], x[1], x[2], x[5], x[6]))
        f.write("\n## å·²æŒ‰å£å¾„忽略(仅计数,明细见 CSV ä¹‹å¤–不列出)\n\n| é¡µç­¾ | " + " | ".join(IGNORE) + " |\n|---|" + "---|"*len(IGNORE) + "\n")
        for sh, cnt in per_sheet:
            f.write("| %s | %s |\n" % (sh, " | ".join(str(cnt.get(c, 0)) for c in IGNORE)))
    print("已输出:", md, "|", csv, "| æ˜Žç»†æ¡æ•°:", len(rows_out))
    for sh, cnt in per_sheet:
        if cnt: print("   %-12s %s" % (sh, dict(cnt)))