| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667 |
- """审计模板:每个表头字段是否都在「填写说明 → 字段依据」中有来源标注。"""
- 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()
|