"""审计模板:每个表头字段是否都在「填写说明 → 字段依据」中有来源标注。""" from __future__ import annotations import re import sys from pathlib import Path import openpyxl sys.stdout.reconfigure(encoding="utf-8") TPL = Path(r"E:\CODE\knowledge_agent\data\templates") def norm(h: str) -> str: s = h.replace("*", "") for x in ("(选填)", "(必填)", "(工号)", "(非续签留空)"): s = s.replace(x, "") return re.sub(r"\s+", "", s) def main() -> None: for f in sorted(TPL.glob("*.xlsx")): if f.name.startswith("~$"): continue # Excel 临时锁文件 wb = openpyxl.load_workbook(f, read_only=True, data_only=True) data = wb[wb.sheetnames[0]] headers = [c.value for c in data[1] if c.value] note = wb["填写说明"] start = None for r in range(1, 200): if note.cell(row=r, column=1).value == "【字段依据】": start = r break entries: list[str] = [] if start: r = start + 2 while note.cell(row=r, column=1).value: entries.append(str(note.cell(row=r, column=1).value)) r += 1 missing = [] for h in headers: hn = norm(h) if re.fullmatch(r"\d+日", hn): continue # 1日..31日 由「1-31日」条目覆盖 covered = False for e in entries: toks = [t for t in re.split(r"[/、,,]", norm(e)) if t] for tk in toks: if hn == tk or (len(tk) >= 2 and (tk in hn or hn in tk)): covered = True break if covered: break if not covered: missing.append(h) print(f"=== {f.name}: {len(headers)} 列 / 依据 {len(entries)} 条 / 未覆盖 {len(missing)}") for m in missing: print(f" ✗ {m}") wb.close() if __name__ == "__main__": main()