Report generation

End-to-end: title + text + table + image + PDF export

Ported from nbs/01_tutorials/07_usecase_report_generation.ipynb.

The shape

  1. Create a new blank document.
  2. Configure page setup (A4, margins).
  3. Insert a title with a heading char-shape.
  4. Insert body paragraphs.
  5. Insert a table with data.
  6. Insert an image.
  7. Save as HWP + PDF.

Complete script

from pathlib import Path
from hwpapi import App
from hwpapi.context import charshape_scope, parashape_scope
from hwpapi import units as U


def build_report(output_dir: Path, title: str, rows: list[dict], image: Path | None = None):
    output_dir.mkdir(parents=True, exist_ok=True)

    with App(is_visible=False) as app:
        app.new()

        # 1. Page setup (A4 portrait, 25 mm margins)
        app.doc.page.setup(
            width=U.mm(210),
            height=U.mm(297),
            left_margin=U.mm(25),
            right_margin=U.mm(25),
            top_margin=U.mm(30),
            bottom_margin=U.mm(30),
        )

        # 2. Title
        with parashape_scope(app, align="center"):
            with charshape_scope(app, bold=True, size=U.pt(20), color="#1F4E79"):
                app.doc.insert_text(title + "\n")
        app.doc.insert_paragraph_break()

        # 3. Body
        app.doc.insert_text(
            "λ³Έ λ³΄κ³ μ„œλŠ” hwpapi둜 μžλ™ μƒμ„±λ˜μ—ˆμŠ΅λ‹ˆλ‹€. μ•„λž˜ ν‘œλŠ” "
            "μ£Όμš” μ§€ν‘œλ₯Ό μš”μ•½ν•œ κ²ƒμž…λ‹ˆλ‹€.\n\n"
        )

        # 4. Table
        cols = list(rows[0].keys())
        app.doc.tables.add(rows=len(rows) + 1, cols=len(cols))
        tbl = app.doc.tables[-1]

        for c, col in enumerate(cols):
            tbl.cell(0, c).text = col
        for r, row in enumerate(rows, start=1):
            for c, key in enumerate(cols):
                tbl.cell(r, c).text = str(row[key])

        app.doc.cursor.goto_end()
        app.doc.insert_paragraph_break()

        # 5. Image (optional)
        if image is not None:
            app.doc.insert_picture(str(image))
            app.doc.insert_paragraph_break()

        # 6. Save
        hwp_path = output_dir / "report.hwp"
        pdf_path = output_dir / "report.pdf"
        app.save_as(str(hwp_path))
        app.save_as(str(pdf_path))
        print(f"wrote {hwp_path} and {pdf_path}")


if __name__ == "__main__":
    data = [
        {"μ§€ν‘œ": "맀좜", "Q1": 120, "Q2": 135, "Q3": 140},
        {"μ§€ν‘œ": "λΉ„μš©", "Q1": 80, "Q2": 90, "Q3": 88},
        {"μ§€ν‘œ": "이읡", "Q1": 40, "Q2": 45, "Q3": 52},
    ]
    build_report(
        output_dir=Path("out"),
        title="2026λ…„ 1–3λΆ„κΈ° 싀적 λ³΄κ³ μ„œ",
        rows=data,
        image=Path("chart.png"),
    )

Variations

Multi-section report

sections = [
    ("1. κ°œμš”",    "λ³Έ λ³΄κ³ μ„œμ˜ λͺ©μ μ€ …"),
    ("2. 방법둠",  "λ°μ΄ν„°λŠ” …"),
    ("3. κ²°κ³Ό",    "Q1 λŒ€λΉ„ …"),
    ("4. κ²°λ‘ ",    "전사 μ°¨μ›μ—μ„œ …"),
]

with App(is_visible=False) as app:
    app.new()
    for i, (heading, body) in enumerate(sections):
        with charshape_scope(app, bold=True, size=U.pt(14)):
            app.doc.insert_text(heading + "\n")
        app.doc.insert_text(body + "\n\n")
        if i < len(sections) - 1:
            app.doc.insert_page_break()
    app.save_as("report.hwp")

Export each page as an image

from hwpapi.io import export_image

with App(is_visible=False) as app:
    app.open("report.hwp")
    for page in range(1, app.doc.page_count + 1):
        export_image(app, f"out/page-{page:03d}.png", page=page)

See also

Back to top