| | |
| | | 说æ: é页æ"è¡æ ç¾/å表头"ååºå对é½ï¼difflibï¼ï¼å¯æ£ç¡®å¤çå¤å/å¤è¡/éå¤è¡¨å¤´ï¼ |
| | | æ¯ä¸ªä¸ä¸è´æ ¼å½å
¥ ç»æä½ç§»|忴尾差|ææ¬åæ°å|è稿/è¾
å©å|ä»
ç¨åºæ|ä»
æå·¥æ|ææ¬ä¸å|é误å¼|å®è´¨æ°å¼å·®å¼ã |
| | | """ |
| | | import datetime, io, os, sys |
| | | import datetime, io, os, re, sys |
| | | from difflib import SequenceMatcher |
| | | from openpyxl import load_workbook |
| | | from openpyxl.utils import get_column_letter |
| | |
| | | return "%d-%02d" % (d.year, d.month) |
| | | if isinstance(v, str) and v.strip() and not v.startswith("="): |
| | | return v.strip()[:20] |
| | | return "" |
| | | return "(æ 表头å)" |
| | | |
| | | def row_label(ws): |
| | | out = []; cur = ""; seen = {} |
| | | for r in range(1, ws.max_row+1): |
| | | a = ws.cell(row=r, column=1).value; b = ws.cell(row=r, column=2).value |
| | | if isinstance(a, str) and a.strip(): cur = a.strip() |
| | | lab = ("%s|%s" % (cur, b.strip())) if (isinstance(b, str) and b.strip()) else (cur or "") |
| | | if isinstance(b, str) and b.strip(): |
| | | lab = "%s|%s|%s" % (block_of(ws, r), norm_region(cur), norm_indicator(b)) |
| | | else: |
| | | lab = "%s|%s|" % (block_of(ws, r), norm_region(cur)) |
| | | seen[lab] = seen.get(lab, 0) + 1 |
| | | out.append("%s#%d" % (lab, seen[lab])) |
| | | return out |
| | | |
| | | def norm(s): |
| | | """æ ç¾å½ä¸åï¼å»ç©ºç½ãå»å
¨è§ç©ºæ ¼ãç»ä¸å¼å·ã廿âå¸/ç/å·âåç¼å·®å¼""" |
| | | if not isinstance(s, str): return "" |
| | | t = s.replace("\u3000", " ").replace("ï¼", "(").replace("ï¼", ")").strip() |
| | | t = re.sub(r"[\s]+", "", t) |
| | | return t |
| | | |
| | | def norm_region(s): |
| | | t = norm(s) |
| | | for suf in ("å¸", "ç", "èªæ²»å·", "å·"): |
| | | if t.endswith(suf) and len(t) > len(suf): t = t[:-len(suf)] |
| | | return t |
| | | |
| | | def norm_indicator(s): |
| | | t = norm(s).replace("(ä¸å¨å
¬é)", "").replace("(ä¸å¨)", "").replace("(ä¸äººå
¬é)", "").replace("(ä¸äºº)", "") |
| | | t = t.replace("å
¶ä¸è§ä¸", "è§ä¸").replace("å
¶ä¸è§ä¸", "è§ä¸") |
| | | return t |
| | | |
| | | def block_of(ws, r): |
| | | """å䏿¾æè¿ä¸ä¸ª"æ é¢è¡"ï¼B åä¸ºç©ºä¸ A/æåè¾é¿ï¼å¤ææå±åï¼ç´¯è®¡ / 彿 / å
¶å®""" |
| | | for rr in range(r, 0, -1): |
| | | a = ws.cell(row=rr, column=1).value; b = ws.cell(row=rr, column=2).value |
| | | txt = " ".join(str(x) for x in (a, b) if isinstance(x, str)) |
| | | if not isinstance(b, str) or not b.strip(): |
| | | if len(norm(txt)) >= 6: |
| | | if "累计" in txt: return "累计å" |
| | | if "åå¸å·" in txt or "æå" in txt or "æç»è¡¨" in txt: return "彿å" |
| | | return "å
¶å®" |
| | | |
| | | # å·²ç¥è®¾è®¡å·®å¼ï¼ä¸è®¡å
¥é®é¢ï¼æç¨æ· 2026-09-28 å£å¾ï¼ |
| | | KNOWN_ROWS = {" è´§è¿": ("è§ä¸+è§ä¸è´§è¿é", "è§ä¸è´§è¿é")} |
| | | KNOWN_SHEETS_ANY_BLOCK = () # æå表ç彿åç± block_of å¤ç |
| | | |
| | | def is_known_extra_row(sheet, indicator, side): |
| | | if sheet in KNOWN_ROWS and side == "ç¨åº": |
| | | for pat in KNOWN_ROWS[sheet]: |
| | | if norm_indicator(indicator) == norm_indicator(pat): return True |
| | | return False |
| | | |
| | | def num(v): |
| | | return isinstance(v, (int, float)) and not isinstance(v, bool) |
| | |
| | | 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): |
| | | g = load_workbook(gen, data_only=True); d = load_workbook(dgf, data_only=True) |
| | | rows_out = [] |
| | |
| | | unmatched_rows_g = [r-1 for r in range(1, len(rl_g)+1) if r-1 not in rowmap] |
| | | unmatched_rows_d = [r-1 for r in range(1, len(rl_d)+1) if r-1 not in set(rowmap.values())] |
| | | for c in unmatched_cols_g: |
| | | if c >= 2: bump("ä»
ç¨åºæ(å)"); rows_out.append([sh, "%s*" % get_column_letter(c+1), "ï¼æ´åï¼", cl_g[c], "ä»
ç¨åºæ(å)", "", "", "çæä»¶å¤åºæ¤å"]) |
| | | if c < 2: continue |
| | | if cl_g[c] == "(æ 表头å)": |
| | | bump("å·²ç¥è®¾è®¡(æ 表头è稿å)"); continue |
| | | bump("ä»
ç¨åºæ(å)"); rows_out.append([sh, "%s*" % get_column_letter(c+1), "ï¼æ´åï¼", cl_g[c], "ä»
ç¨åºæ(å)", "", "", "çæä»¶å¤åºæ¤å"]) |
| | | for c in unmatched_cols_d: |
| | | if c >= 2: bump("ä»
æå·¥æ(å)"); rows_out.append([sh, "ï¼æ ï¼", "ï¼æ´åï¼", cl_d[c], "ä»
æå·¥æ(å)", "", "", "æå·¥å®ç¨¿å¤åºæ¤å"]) |
| | | if c < 2: continue |
| | | if cl_d[c] == "(æ 表头å)": |
| | | bump("å·²ç¥è®¾è®¡(æ 表头è稿å)"); continue |
| | | bump("ä»
æå·¥æ(å)"); rows_out.append([sh, "ï¼æ ï¼", "ï¼æ´åï¼", cl_d[c], "ä»
æå·¥æ(å)", "", "", "æå·¥å®ç¨¿å¤åºæ¤å"]) |
| | | for r in unmatched_rows_g: |
| | | if r >= 4: bump("ä»
ç¨åºæ(è¡)"); rows_out.append([sh, "第%dè¡" % (r+1), rl_g[r], "ï¼æ´è¡ï¼", "ä»
ç¨åºæ(è¡)", "", "", "çæä»¶å¤åºæ¤åºæ®µ"]) |
| | | 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], "ï¼æ´è¡ï¼", "ä»
ç¨åºæ(è¡)", "", "", "çæä»¶å¤åºæ¤åºæ®µ"]) |
| | | for r in unmatched_rows_d: |
| | | if r >= 4: bump("ä»
æå·¥æ(è¡)"); rows_out.append([sh, "ï¼æ ï¼", rl_d[r], "ï¼æ´è¡ï¼", "ä»
æå·¥æ(è¡)", "", "", "æå·¥å®ç¨¿å¤åºæ¤åºæ®µ"]) |
| | | if r < 4: continue |
| | | if "彿å" in rl_d[r] or "累计å" in rl_d[r]: |
| | | bump("å·²ç¥è®¾è®¡(æåè¡¨å½æ/累计å)"); continue |
| | | bump("ä»
æå·¥æ(è¡)"); rows_out.append([sh, "ï¼æ ï¼", rl_d[r], "ï¼æ´è¡ï¼", "ä»
æå·¥æ(è¡)", "", "", "æå·¥å®ç¨¿å¤åºæ¤åºæ®µ"]) |
| | | for i, j in sorted(colmap.items()): |
| | | 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 |
| | |
| | | diff = abs(vg - vd) |
| | | if diff <= 1e-6: continue |
| | | rel = diff / max(abs(vd), 1e-9) |
| | | if diff <= 0.01 or rel <= 1e-4: cat = "忴尾差" |
| | | if diff <= 0.01 or rel <= 1e-4: cat = "忴尾差(å¯å¿½ç¥)" |
| | | else: cat = "å®è´¨æ°å¼å·®å¼" |
| | | note = "å·®=%.6g" % diff |
| | | elif num(vg) and (vd is None): |
| | |
| | | elif num(vd) and (vg is None): |
| | | cat = "ä»
æå·¥æ" |
| | | elif tg is not None and num(vd) and abs(tg - vd) <= 1e-9: |
| | | cat = "ææ¬åæ°å"; note = "æå·¥ä¸ºææ¬'%s'" % vg |
| | | cat = "ææ¬åæ°å(å¯å¿½ç¥)"; note = "æå·¥ä¸ºææ¬'%s'" % vg |
| | | elif td is not None and num(vg) and abs(td - vg) <= 1e-9: |
| | | cat = "ææ¬åæ°å"; note = "ç¨åºä¸ºææ¬'%s'" % vd |
| | | cat = "ææ¬åæ°å(å¯å¿½ç¥)"; note = "ç¨åºä¸ºææ¬'%s'" % vd |
| | | elif isinstance(vg, str) and isinstance(vd, str): |
| | | cat = "ææ¬ä¸å"; note = "ç¨åº'%s' / æå·¥'%s'" % (vg[:18], vd[:18]) |
| | | elif isinstance(vg, str) and vg.startswith("#") : |
| | |
| | | for x in rows_out: |
| | | f.write(",".join('"%s"' % str(v).replace('"', "'") for v in x) + "\n") |
| | | # è¾åº MD |
| | | cats = ["å®è´¨æ°å¼å·®å¼", "ä»
æå·¥æ", "ä»
ç¨åºæ", "忴尾差", "ææ¬åæ°å", "ææ¬ä¸å", "é误å¼(ç¨åº)", "é误å¼(æå·¥)", "ä»
ç¨åºæ(å)", "ä»
æå·¥æ(å)", "ä»
ç¨åºæ(è¡)", "ä»
æå·¥æ(è¡)", "å
¶å®"] |
| | | cats = ["å®è´¨æ°å¼å·®å¼", "é误å¼(ç¨åº)", "é误å¼(æå·¥)", "ææ¬ä¸å", "ä»
æå·¥æ", "ä»
ç¨åºæ", "ä»
ç¨åºæ(å)", "ä»
æå·¥æ(å)", "ä»
ç¨åºæ(è¡)", "ä»
æå·¥æ(è¡)", "忴尾差(å¯å¿½ç¥)", "ææ¬åæ°å(å¯å¿½ç¥)", "å·²ç¥è®¾è®¡(æ¯çæ°å¢è¡)", "å·²ç¥è®¾è®¡(æ 表头è稿å)", "å·²ç¥è®¾è®¡(æåè¡¨å½æ/累计å)", "å
¶å®"] |
| | | md = prefix + ".md" |
| | | with io.open(md, "w", encoding="utf-8", newline="\n") as f: |
| | | f.write("# æ±æ»å¤§è¡¨å·®å¼æç»ï¼çæä»¶ vs æå·¥å®ç¨¿ï¼\n\n") |