SmartFarm/SOURCE/SmartFarmHMI/Docs/make_docs.py
2026-09-04 10:53:44 +09:00

162 lines
5.8 KiB
Python

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'<w:shd {nsdecls("w")} w:fill="{hex_color}"/>')
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'<w:tcMar {nsdecls("w")}>'
f' <w:top w:w="{top}" w:type="dxa"/>'
f' <w:bottom w:w="{bottom}" w:type="dxa"/>'
f' <w:left w:w="{left}" w:type="dxa"/>'
f' <w:right w:w="{right}" w:type="dxa"/>'
f'</w:tcMar>'
)
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'<w:tblBorders {nsdecls("w")}>'
f' <w:top w:val="{val}" w:sz="{sz}" w:space="0" w:color="{color}"/>'
f' <w:bottom w:val="{val}" w:sz="{sz}" w:space="0" w:color="{color}"/>'
f' <w:left w:val="none"/>'
f' <w:right w:val="none"/>'
f' <w:insideH w:val="{val}" w:sz="{sz}" w:space="0" w:color="{color}"/>'
f' <w:insideV w:val="none"/>'
f'</w:tblBorders>'
)
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'<w:tcBorders {nsdecls("w")}>'
f' <w:top w:val="none"/>'
f' <w:left w:val="single" w:sz="24" w:space="0" w:color="{border_color}"/>'
f' <w:bottom w:val="none"/>'
f' <w:right w:val="none"/>'
f'</w:tcBorders>'
)
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'<w:tcBorders {nsdecls("w")}>'
f' <w:top w:val="single" w:sz="4" w:space="0" w:color="E0E0E0"/>'
f' <w:left w:val="single" w:sz="16" w:space="0" w:color="4A90E2"/>'
f' <w:bottom w:val="single" w:sz="4" w:space="0" w:color="E0E0E0"/>'
f' <w:right w:val="single" w:sz="4" w:space="0" w:color="E0E0E0"/>'
f'</w:tcBorders>'
)
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.")