import os import sys import docx from docx import Document from docx.shared import Inches, Pt, RGBColor from docx.enum.text import WD_ALIGN_PARAGRAPH from docx.enum.table import WD_TABLE_ALIGNMENT, WD_ALIGN_VERTICAL from docx.oxml import OxmlElement, parse_xml from docx.oxml.ns import nsdecls, qn def set_cell_background(cell, hex_color): """Set background color of a table cell.""" tcPr = cell._tc.get_or_add_tcPr() shd = parse_xml(f'') tcPr.append(shd) def set_cell_margins(cell, top=100, bottom=100, left=150, right=150): """Set cell padding (in twips: 1 pt = 20 twips).""" tcPr = cell._tc.get_or_add_tcPr() tcMar = parse_xml( f'' f' ' f' ' f' ' f' ' f'' ) tcPr.append(tcMar) def set_table_borders(table, color="CCCCCC", sz="4", val="single"): """Set light borders on table.""" tblPr = table._tbl.tblPr tblBorders = parse_xml( f'' f' ' f' ' f' ' f' ' f' ' f' ' f'' ) tblPr.append(tblBorders) def add_callout(doc, text, title="참고 / 주의사항", bg_color="F0F4F8", border_color="1B365D"): """Add a styled callout box.""" tbl = doc.add_table(rows=1, cols=1) tbl.alignment = WD_TABLE_ALIGNMENT.CENTER tbl.autofit = False cell = tbl.cell(0, 0) cell.width = Inches(6.5) set_cell_background(cell, bg_color) set_cell_margins(cell, top=140, bottom=140, left=200, right=200) tcPr = cell._tc.get_or_add_tcPr() tcBorders = parse_xml( f'' f' ' f' ' f' ' f' ' f'' ) tcPr.append(tcBorders) p = cell.paragraphs[0] p.paragraph_format.space_before = Pt(2) p.paragraph_format.space_after = Pt(2) p.paragraph_format.line_spacing = 1.15 r_title = p.add_run(f"📌 {title}\n") r_title.font.name = "Malgun Gothic" r_title.font.size = Pt(10) r_title.font.bold = True r_title.font.color.rgb = RGBColor(0x1B, 0x36, 0x5D) r_text = p.add_run(text) r_text.font.name = "Malgun Gothic" r_text.font.size = Pt(9.5) r_text.font.color.rgb = RGBColor(0x33, 0x33, 0x33) doc.add_paragraph().paragraph_format.space_after = Pt(4) def add_code_block(doc, code_text): """Add a styled code block.""" tbl = doc.add_table(rows=1, cols=1) tbl.alignment = WD_TABLE_ALIGNMENT.CENTER tbl.autofit = False cell = tbl.cell(0, 0) cell.width = Inches(6.5) set_cell_background(cell, "F8F9FA") set_cell_margins(cell, top=120, bottom=120, left=180, right=180) tcPr = cell._tc.get_or_add_tcPr() tcBorders = parse_xml( f'' f' ' f' ' f' ' f' ' f'' ) tcPr.append(tcBorders) p = cell.paragraphs[0] p.paragraph_format.space_before = Pt(2) p.paragraph_format.space_after = Pt(2) p.paragraph_format.line_spacing = 1.1 r = p.add_run(code_text) r.font.name = "Consolas" r.font.size = Pt(9) r.font.color.rgb = RGBColor(0x22, 0x22, 0x22) doc.add_paragraph().paragraph_format.space_after = Pt(4) def format_table(table, col_widths, headers, data, align_cols=None): """Helper to populate and format a table nicely.""" table.alignment = WD_TABLE_ALIGNMENT.CENTER set_table_borders(table, color="D0D7DE", sz="6") # Header Row hdr_cells = table.rows[0].cells for i, title in enumerate(headers): hdr_cells[i].text = title set_cell_background(hdr_cells[i], "1B365D") set_cell_margins(hdr_cells[i], top=120, bottom=120, left=140, right=140) p = hdr_cells[i].paragraphs[0] p.alignment = WD_ALIGN_PARAGRAPH.CENTER for r in p.runs: r.font.name = "Malgun Gothic" r.font.size = Pt(9.5) r.font.bold = True r.font.color.rgb = RGBColor(0xFF, 0xFF, 0xFF) # Data Rows for row_idx, row_data in enumerate(data): row_cells = table.add_row().cells bg_c = "F8F9FB" if row_idx % 2 == 1 else "FFFFFF" for col_idx, text in enumerate(row_data): row_cells[col_idx].text = str(text) set_cell_background(row_cells[col_idx], bg_c) set_cell_margins(row_cells[col_idx], top=100, bottom=100, left=140, right=140) p = row_cells[col_idx].paragraphs[0] if align_cols and col_idx < len(align_cols): p.alignment = align_cols[col_idx] else: p.alignment = WD_ALIGN_PARAGRAPH.LEFT for r in p.runs: r.font.name = "Malgun Gothic" r.font.size = Pt(9) r.font.color.rgb = RGBColor(0x33, 0x33, 0x33) # Column widths for row in table.rows: for i, w in enumerate(col_widths): row.cells[i].width = Inches(w) print("Base helper defined successfully.")