167 lines
5.3 KiB
Python
167 lines
5.3 KiB
Python
#!/usr/bin/env python3
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
from datetime import date
|
|
from pathlib import Path
|
|
|
|
from docx import Document
|
|
from docx.enum.section import WD_ORIENTATION
|
|
from docx.enum.text import WD_ALIGN_PARAGRAPH
|
|
from docx.oxml import OxmlElement
|
|
from docx.oxml.ns import qn
|
|
from docx.shared import Cm, Pt, RGBColor
|
|
|
|
|
|
def set_paragraph_spacing(style, before=0, after=6, line=1.15):
|
|
fmt = style.paragraph_format
|
|
fmt.space_before = Pt(before)
|
|
fmt.space_after = Pt(after)
|
|
fmt.line_spacing = line
|
|
|
|
|
|
def ensure_style(doc: Document, name: str, base: str | None = None, size: int = 11, bold=False, color=None):
|
|
styles = doc.styles
|
|
if name in [s.name for s in styles]:
|
|
style = styles[name]
|
|
else:
|
|
style = styles.add_style(name, 1)
|
|
if base:
|
|
style.base_style = styles[base]
|
|
font = style.font
|
|
font.name = "Calibri"
|
|
font.size = Pt(size)
|
|
font.bold = bold
|
|
if color:
|
|
font.color.rgb = RGBColor(*color)
|
|
set_paragraph_spacing(style)
|
|
return style
|
|
|
|
|
|
def insert_page_number(paragraph):
|
|
paragraph.alignment = WD_ALIGN_PARAGRAPH.RIGHT
|
|
run = paragraph.add_run()
|
|
fld_char1 = OxmlElement('w:fldChar')
|
|
fld_char1.set(qn('w:fldCharType'), 'begin')
|
|
instr_text = OxmlElement('w:instrText')
|
|
instr_text.set(qn('xml:space'), 'preserve')
|
|
instr_text.text = " PAGE "
|
|
fld_char2 = OxmlElement('w:fldChar')
|
|
fld_char2.set(qn('w:fldCharType'), 'end')
|
|
run._r.append(fld_char1)
|
|
run._r.append(instr_text)
|
|
run._r.append(fld_char2)
|
|
|
|
|
|
def apply_advanced_layout(doc: Document, landscape=False):
|
|
section = doc.sections[0]
|
|
section.top_margin = Cm(2.2)
|
|
section.bottom_margin = Cm(2.2)
|
|
section.left_margin = Cm(2.4)
|
|
section.right_margin = Cm(2.4)
|
|
|
|
if landscape:
|
|
section.orientation = WD_ORIENTATION.LANDSCAPE
|
|
section.page_width, section.page_height = section.page_height, section.page_width
|
|
|
|
header = section.header.paragraphs[0]
|
|
header.text = "Office Document Specialist Suite"
|
|
header.alignment = WD_ALIGN_PARAGRAPH.LEFT
|
|
|
|
footer = section.footer.paragraphs[0]
|
|
footer.text = ""
|
|
insert_page_number(footer)
|
|
|
|
|
|
def configure_styles(doc: Document):
|
|
normal = doc.styles["Normal"]
|
|
normal.font.name = "Calibri"
|
|
normal.font.size = Pt(11)
|
|
set_paragraph_spacing(normal, before=0, after=6, line=1.15)
|
|
|
|
h1 = doc.styles["Heading 1"]
|
|
h1.font.name = "Calibri"
|
|
h1.font.size = Pt(18)
|
|
h1.font.bold = True
|
|
h1.font.color.rgb = RGBColor(0x1F, 0x4E, 0x78)
|
|
set_paragraph_spacing(h1, before=12, after=8, line=1.2)
|
|
|
|
h2 = doc.styles["Heading 2"]
|
|
h2.font.name = "Calibri"
|
|
h2.font.size = Pt(14)
|
|
h2.font.bold = True
|
|
h2.font.color.rgb = RGBColor(0x2F, 0x55, 0x8C)
|
|
set_paragraph_spacing(h2, before=10, after=6, line=1.2)
|
|
|
|
ensure_style(doc, "Quote Accent", base="Normal", size=11, color=(85, 85, 85))
|
|
|
|
|
|
def cmd_template_report(output: Path, title: str, author: str):
|
|
doc = Document()
|
|
apply_advanced_layout(doc)
|
|
configure_styles(doc)
|
|
|
|
p = doc.add_paragraph(title, style="Title")
|
|
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
|
p2 = doc.add_paragraph(f"Auteur: {author}\nDatum: {date.today().isoformat()}")
|
|
p2.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
|
|
|
doc.add_page_break()
|
|
doc.add_paragraph("Inhoudsopgave", style="Heading 1")
|
|
doc.add_paragraph("(Werk de inhoudsopgave bij in Word/LibreOffice: rechtsklik > Veld bijwerken)")
|
|
|
|
doc.add_page_break()
|
|
doc.add_paragraph("1. Samenvatting", style="Heading 1")
|
|
doc.add_paragraph("Vul hier de managementsamenvatting in.")
|
|
|
|
doc.add_paragraph("2. Analyse", style="Heading 1")
|
|
doc.add_paragraph("Gebruik koppen op niveau 2 en 3 voor structuur.")
|
|
|
|
quote = doc.add_paragraph("Belangrijke observatie of citaat.", style="Quote Accent")
|
|
quote.paragraph_format.left_indent = Cm(1)
|
|
|
|
doc.add_paragraph("2.1 Detailsectie", style="Heading 2")
|
|
doc.add_paragraph("Plaats hier tabellen, figuren en technische uitwerking.")
|
|
|
|
doc.save(output)
|
|
print(f"Template aangemaakt: {output}")
|
|
|
|
|
|
def cmd_style_doc(input_file: Path, output_file: Path, landscape: bool):
|
|
doc = Document(input_file)
|
|
apply_advanced_layout(doc, landscape=landscape)
|
|
configure_styles(doc)
|
|
doc.save(output_file)
|
|
print(f"Opmaak toegepast: {output_file}")
|
|
|
|
|
|
def build_parser():
|
|
parser = argparse.ArgumentParser(description="Office Document Specialist Suite")
|
|
sub = parser.add_subparsers(dest="command", required=True)
|
|
|
|
rep = sub.add_parser("template-report", help="Maak geavanceerd rapporttemplate (.docx)")
|
|
rep.add_argument("--output", default="rapport-template.docx", type=Path)
|
|
rep.add_argument("--title", default="Rapporttitel")
|
|
rep.add_argument("--author", default="Onbekend")
|
|
|
|
sty = sub.add_parser("style-doc", help="Pas geavanceerde opmaak toe op bestaand .docx")
|
|
sty.add_argument("input", type=Path)
|
|
sty.add_argument("--output", default="styled-output.docx", type=Path)
|
|
sty.add_argument("--landscape", action="store_true")
|
|
|
|
return parser
|
|
|
|
|
|
def main():
|
|
parser = build_parser()
|
|
args = parser.parse_args()
|
|
|
|
if args.command == "template-report":
|
|
cmd_template_report(args.output, args.title, args.author)
|
|
elif args.command == "style-doc":
|
|
cmd_style_doc(args.input, args.output, args.landscape)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|