_adjust_front_matter.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. # -*- coding: utf-8 -*-
  2. """Adjust front matter: drop 文档控制, rename 更改记录, page breaks."""
  3. from __future__ import annotations
  4. import shutil
  5. import tempfile
  6. from pathlib import Path
  7. from docx import Document
  8. from docx.enum.text import WD_BREAK
  9. from docx.oxml import OxmlElement
  10. from docx.text.paragraph import Paragraph
  11. BASE = Path(
  12. r"C:\Users\skygu\OneDrive\Projects\AIDOP\项目\项目管理\产互联项目管理\交付文档"
  13. )
  14. def remove_paragraph(p: Paragraph) -> None:
  15. p._element.getparent().remove(p._element)
  16. def clear_page_breaks(p: Paragraph) -> None:
  17. for br in p._element.findall(".//{http://schemas.openxmlformats.org/wordprocessingml/2006/main}br"):
  18. br.getparent().remove(br)
  19. def ensure_page_break_before(p: Paragraph) -> None:
  20. clear_page_breaks(p)
  21. text = p.text
  22. p.text = ""
  23. br_run = p.add_run()
  24. br_run.add_break(WD_BREAK.PAGE)
  25. if text:
  26. p.add_run(text)
  27. def adjust_file(path: Path) -> None:
  28. work = path
  29. tmp_path = None
  30. try:
  31. doc = Document(path)
  32. except PermissionError:
  33. tmp_path = Path(tempfile.gettempdir()) / f"docfix_{path.name}"
  34. shutil.copy2(path, tmp_path)
  35. work = tmp_path
  36. doc = Document(work)
  37. removed_control = False
  38. renamed = False
  39. version_break = False
  40. toc_break = False
  41. for p in list(doc.paragraphs):
  42. if p.text.strip() == "文档控制":
  43. remove_paragraph(p)
  44. removed_control = True
  45. for p in doc.paragraphs:
  46. if p.text.strip() == "更改记录":
  47. p.text = "版本记录"
  48. renamed = True
  49. break
  50. for p in doc.paragraphs:
  51. if p.text.strip() == "版本记录":
  52. ensure_page_break_before(p)
  53. version_break = True
  54. break
  55. for p in doc.paragraphs:
  56. if p.text.strip() == "目录":
  57. ensure_page_break_before(p)
  58. toc_break = True
  59. break
  60. if not renamed and not any(p.text.strip() == "版本记录" for p in doc.paragraphs):
  61. raise RuntimeError(f"未找到「版本记录」: {path.name}")
  62. if not version_break:
  63. raise RuntimeError(f"未找到「版本记录」: {path.name}")
  64. if not toc_break:
  65. raise RuntimeError(f"未找到「目录」: {path.name}")
  66. doc.save(work)
  67. if tmp_path is not None:
  68. try:
  69. shutil.copy2(work, path)
  70. tmp_path.unlink(missing_ok=True)
  71. except PermissionError:
  72. print(f" !! {path.name} 被占用,已写入: {work}")
  73. return
  74. print(
  75. f"{path.name}: 删文档控制={'Y' if removed_control else 'N'} "
  76. f"版本记录分页=Y 目录分页=Y"
  77. )
  78. def iter_delivery_docx():
  79. for module in ["S0", "S1", "S2", "S3", "S4"]:
  80. mod_dir = BASE / module
  81. if not mod_dir.is_dir():
  82. continue
  83. for path in sorted(mod_dir.rglob("*.docx")):
  84. if not path.name.startswith("~$"):
  85. yield path
  86. def main() -> None:
  87. for path in iter_delivery_docx():
  88. adjust_file(path)
  89. if __name__ == "__main__":
  90. main()