# -*- coding: utf-8 -*- """공용 docx 헬퍼 — 한글 폰트/표/제목 스타일. 각 문서 생성기가 import.""" from docx.shared import Pt, Cm, RGBColor from docx.enum.text import WD_ALIGN_PARAGRAPH from docx.enum.table import WD_TABLE_ALIGNMENT from docx.oxml.ns import qn from docx.oxml import OxmlElement NAVY = RGBColor(0x1F, 0x29, 0x3A) ACCENT = RGBColor(0x11, 0x6D, 0xC3) GREY = RGBColor(0x55, 0x5F, 0x6B) KFONT = "맑은 고딕" def setup(doc): st = doc.styles["Normal"]; st.font.name = KFONT; st.font.size = Pt(10.5) _rf(st.element.get_or_add_rPr()) for m in ("Heading 1","Heading 2","Heading 3"): doc.styles[m].font.name = KFONT; _rf(doc.styles[m].element.get_or_add_rPr()) s = doc.sections[0] s.top_margin = Cm(2.2); s.bottom_margin = Cm(2.0); s.left_margin = Cm(2.3); s.right_margin = Cm(2.3) def _rf(rpr): rf = rpr.find(qn('w:rFonts')) if rf is None: rf = OxmlElement('w:rFonts'); rpr.append(rf) for a in ('w:ascii','w:hAnsi','w:eastAsia','w:cs'): rf.set(qn(a), KFONT) def shade(cell, hexcolor): tcpr = cell._tc.get_or_add_tcPr() sh = OxmlElement('w:shd'); sh.set(qn('w:val'),'clear'); sh.set(qn('w:fill'),hexcolor) tcpr.append(sh) def h(doc, level, text): p = doc.add_heading(text, level=level) for run in p.runs: run.font.color.rgb = NAVY if level == 1 else ACCENT return p def para(doc, text, size=10.5, bold=False, italic=False, color=None, align=None, space_after=6): p = doc.add_paragraph(); r = p.add_run(text); r.bold = bold; r.italic = italic r.font.size = Pt(size) if color: r.font.color.rgb = color if align: p.alignment = align p.paragraph_format.space_after = Pt(space_after) return p def bullets(doc, items, style="List Bullet"): for it in items: p = doc.add_paragraph(it, style=style); p.paragraph_format.space_after = Pt(2) def table(doc, headers, rows, widths=None, header_fill="1F293A", first_col_bold=False, fontsize=9.5): t = doc.add_table(rows=1, cols=len(headers)); t.style = "Table Grid"; t.alignment = WD_TABLE_ALIGNMENT.CENTER hd = t.rows[0].cells for i, htext in enumerate(headers): hd[i].text = ""; run = hd[i].paragraphs[0].add_run(htext) run.bold = True; run.font.size = Pt(fontsize); run.font.color.rgb = RGBColor(0xFF,0xFF,0xFF) shade(hd[i], header_fill) for row in rows: cells = t.add_row().cells for i, val in enumerate(row): cells[i].text = ""; run = cells[i].paragraphs[0].add_run(str(val)); run.font.size = Pt(fontsize) if first_col_bold and i == 0: run.bold = True cells[i].paragraphs[0].paragraph_format.space_after = Pt(1) if widths: for r_ in t.rows: for i, w in enumerate(widths): r_.cells[i].width = Cm(w) doc.add_paragraph().paragraph_format.space_after = Pt(4) return t