CodeGym /์ž๋ฐ” ์ฝ”์Šค /Python SELF KO /๋ณด๊ณ ์„œ ์ž๋™ํ™”๋ฅผ ์œ„ํ•œ ํ…์ŠคํŠธ PDF ์ƒ์„ฑ ๊ธฐ๋ณธ

๋ณด๊ณ ์„œ ์ž๋™ํ™”๋ฅผ ์œ„ํ•œ ํ…์ŠคํŠธ PDF ์ƒ์„ฑ ๊ธฐ๋ณธ

Python SELF KO
๋ ˆ๋ฒจ 44 , ๋ ˆ์Šจ 2
์‚ฌ์šฉ ๊ฐ€๋Šฅ

1. ReportLab ๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ•

Canvas ์‚ฌ์šฉ

ReportLab์—์„œ PDF ๋ฌธ์„œ ์ƒ์„ฑ์„ ์œ„ํ•œ ์ฃผ์š” ๋„๊ตฌ๋Š” canvas ํด๋ž˜์Šค์•ผ. ์ด ํด๋ž˜์Šค๋Š” ํ…์ŠคํŠธ, ์„ , ์‚ฌ๊ฐํ˜• ๊ทธ๋ฆฌ๊ณ  ๊ธฐํƒ€ ๊ทธ๋ž˜ํ”ฝ ์š”์†Œ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ธฐ ์œ„ํ•œ ๋ฉ”์„œ๋“œ๋“ค์„ ์ œ๊ณตํ•ด.

๊ฐ„๋‹จํ•œ ํ…์ŠคํŠธ PDF ํŒŒ์ผ ์ƒ์„ฑ

Python

from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A4

# ์ƒˆ๋กœ์šด PDF ํŒŒ์ผ ์ƒ์„ฑ
pdf_file = canvas.Canvas("basic_report.pdf", pagesize=A4)
width, height = A4

# ํ…์ŠคํŠธ ์ถ”๊ฐ€
pdf_file.setFont("Helvetica", 12)  # ํฐํŠธ์™€ ํฌ๊ธฐ ์„ค์ •
pdf_file.drawString(100, height - 100, "์•ˆ๋…•! ์ด๊ฑด ReportLab์œผ๋กœ ์ƒ์„ฑ๋œ ๋ณด๊ณ ์„œ์•ผ.")

# PDF ์ €์žฅํ•˜๊ณ  ๋‹ซ๊ธฐ
pdf_file.save()

์ด ์˜ˆ์ œ์—์„œ ์ƒ์„ฑ๋œ PDF ํŒŒ์ผ์€ ์ฒซ ํŽ˜์ด์ง€์— "์•ˆ๋…•! ์ด๊ฑด ReportLab์œผ๋กœ ์ƒ์„ฑ๋œ ๋ณด๊ณ ์„œ์•ผ."๋ผ๋Š” ํ…์ŠคํŠธ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์–ด.

2. PDF์— ํ…์ŠคํŠธ ์ถ”๊ฐ€

ReportLab์€ ํ…์ŠคํŠธ์˜ ํฌ๊ธฐ, ํฐํŠธ ๋ฐ ์ƒ‰์ƒ์„ ํฌํ•จํ•œ ๋‹ค์–‘ํ•œ ์„ค์ •์ด ๊ฐ€๋Šฅํ•ด. ๋ณด๊ณ ์„œ๋ฅผ ๊ตฌ์กฐ์ ์œผ๋กœ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ์ œ๋ชฉ, ๋ถ€์ œ๋ชฉ, ๋ณธ๋ฌธ ํ…์ŠคํŠธ๋ฅผ ๋‹ค๋ฅด๊ฒŒ ๋ณด์ด๊ฒŒ ํ•  ์ˆ˜ ์žˆ์–ด.

ํ…์ŠคํŠธ ํฐํŠธ์™€ ํฌ๊ธฐ ์„ค์ •

setFont() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํฐํŠธ์™€ ํ…์ŠคํŠธ ํฌ๊ธฐ๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์–ด. ReportLab์€ Helvetica, Times-Roman, Courier ๊ฐ™์€ ํ‘œ์ค€ ํฐํŠธ๋ฅผ ์ง€์›ํ•ด.

Python

pdf_file.setFont("Helvetica-Bold", 16)  # ๊ตต์€ ํฐํŠธ
pdf_file.drawString(100, height - 50, "ํŒ๋งค ๋ณด๊ณ ์„œ")  # ์ œ๋ชฉ

ํ…์ŠคํŠธ ์ƒ‰์ƒ ๋ณ€๊ฒฝ

ReportLab์€ setFillColorRGB() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ RGB ๊ฐ’(0์—์„œ 1 ์‚ฌ์ด)์„ ๋ฐ›์•„ ํ…์ŠคํŠธ ์ƒ‰์ƒ์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์–ด.

Python

pdf_file.setFillColorRGB(0, 0, 1)  # ํŒŒ๋ž€์ƒ‰
pdf_file.drawString(100, height - 150, "์ด ํ…์ŠคํŠธ๋Š” ํŒŒ๋ž€์ƒ‰์ด์•ผ.")

3. ํ…์ŠคํŠธ ๋ธ”๋ก๊ณผ ์—ฌ๋Ÿฌ ์ค„ ํ…์ŠคํŠธ ์ž‘์—…

ํ…์ŠคํŠธ๊ฐ€ ๊ธธ๋‹ค๋ฉด, drawString()์„ ์‚ฌ์šฉํ•˜์—ฌ ์ค„๋ณ„๋กœ ์ขŒํ‘œ๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์–ด. ํ•˜์ง€๋งŒ, ์ž๋™ ์ค„๋ฐ”๊ฟˆ์ด ํ•„์š”ํ•˜๋‹ค๋ฉด drawText()์™€ TextObject๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒŒ ๋” ํŽธ๋ฆฌํ•ด.

TextObject๋ฅผ ์‚ฌ์šฉํ•œ ์—ฌ๋Ÿฌ ์ค„ ํ…์ŠคํŠธ ์ถ”๊ฐ€

Python

text = """
2023๋…„๋„ ํŒ๋งค ๋ณด๊ณ ์„œ.
์ด ๋ณด๊ณ ์„œ๋Š” ํŒ๋งค ๋ฐ์ดํ„ฐ, ๋ฐ์ดํ„ฐ ๋ถ„์„ ๋ฐ ์˜ˆ์ธก์— ๋Œ€ํ•œ ์„ธ๋ถ€ ์ •๋ณด๋ฅผ ํฌํ•จํ•˜๊ณ  ์žˆ์–ด.
"""

# ํ…์ŠคํŠธ ๊ฐ์ฒด ์ƒ์„ฑ
text_object = pdf_file.beginText(100, height - 200)
text_object.setFont("Helvetica", 12)
text_object.setFillColorRGB(0, 0, 0)

# ํ…์ŠคํŠธ ์ถ”๊ฐ€
for line in text.split("\n"):
    text_object.textLine(line)

pdf_file.drawText(text_object)

์ด ์˜ˆ์ œ์—์„œ๋Š” ํ…์ŠคํŠธ ๊ฐ์ฒด TextObject๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๊ฐ ํ…์ŠคํŠธ ์ค„์„ ์ž๋™์œผ๋กœ ์ค„๋ฐ”๊ฟˆํ•ด.

4. ์—ฌ๋Ÿฌ ํŽ˜์ด์ง€๋กœ ๊ตฌ์„ฑ๋œ ๋ณด๊ณ ์„œ ์ƒ์„ฑ

์—ฌ๋Ÿฌ ํŽ˜์ด์ง€๋กœ ๊ตฌ์„ฑ๋œ ๋ณด๊ณ ์„œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋” ๋งŽ์€ ๋ฐ์ดํ„ฐ๋ฅผ ํฌํ•จํ•  ์ˆ˜ ์žˆ๊ณ  ์ฝ๊ธฐ ์‰ฌ์šด ๋ฌธ์„œ ๊ตฌ์กฐ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์–ด. ReportLab์—์„œ๋Š” showPage() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ƒˆ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•ด.

์—ฌ๋Ÿฌ ํŽ˜์ด์ง€ PDF ํŒŒ์ผ ์ƒ์„ฑ

Python

from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A4

# PDF ์ƒ์„ฑ
pdf_file = canvas.Canvas("multi_page_report.pdf", pagesize=A4)
width, height = A4

# ์ฒซ ๋ฒˆ์งธ ํŽ˜์ด์ง€
pdf_file.setFont("Helvetica-Bold", 16)
pdf_file.drawString(100, height - 100, "ํŽ˜์ด์ง€ 1: ์†Œ๊ฐœ")
pdf_file.setFont("Helvetica", 12)
pdf_file.drawString(100, height - 130, "์ด๊ฒƒ์€ ๋ณด๊ณ ์„œ์˜ ์ฒซ ๋ฒˆ์งธ ํŽ˜์ด์ง€์•ผ.")
pdf_file.showPage()  # ๋‹ค์Œ ํŽ˜์ด์ง€๋กœ ์ด๋™

# ๋‘ ๋ฒˆ์งธ ํŽ˜์ด์ง€
pdf_file.setFont("Helvetica-Bold", 16)
pdf_file.drawString(100, height - 100, "ํŽ˜์ด์ง€ 2: ๋ฐ์ดํ„ฐ")
pdf_file.setFont("Helvetica", 12)
pdf_file.drawString(100, height - 130, "์ด๊ฒƒ์€ ๋ณด๊ณ ์„œ์˜ ๋‘ ๋ฒˆ์งธ ํŽ˜์ด์ง€์•ผ.")

# PDF ์ €์žฅ ๋ฐ ๋‹ซ๊ธฐ
pdf_file.save()

์ด ์˜ˆ์ œ์—์„œ๋Š” ๋‘ ๊ฐœ์˜ ํŽ˜์ด์ง€๋ฅผ ๊ฐ€์ง„ PDF๊ฐ€ ์ƒ์„ฑ๋˜๋ฉฐ, ๊ฐ๊ฐ ์ œ๋ชฉ๊ณผ ํ…์ŠคํŠธ๊ฐ€ ํฌํ•จ๋ผ ์žˆ์–ด. showPage() ๋ฉ”์„œ๋“œ๋Š” ํ˜„์žฌ ํŽ˜์ด์ง€๋ฅผ ์ข…๋ฃŒํ•˜๊ณ  ๋‹ค์Œ ํŽ˜์ด์ง€๋ฅผ ์‹œ์ž‘ํ•ด.

5. PDF์— ๋™์  ๋ฐ์ดํ„ฐ ์ถ”๊ฐ€

ReportLab์€ ๋ณด๊ณ ์„œ ์ž๋™ํ™”๋ฅผ ์œ„ํ•ด ๋ฆฌ์ŠคํŠธ๋‚˜ dictionary์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋™์ ์œผ๋กœ ์ถ”๊ฐ€ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ด. ์ด ๊ธฐ๋Šฅ์€ ๋ฐ์ดํ„ฐ ํ…Œ์ด๋ธ”์ด๋‚˜ ๋ชฉ๋ก์ด ์ •๊ธฐ์ ์œผ๋กœ ์—…๋ฐ์ดํŠธ๋˜๋Š” ๋ณด๊ณ ์„œ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐ ์œ ์šฉํ•ด.

๋ฆฌ์ŠคํŠธ์—์„œ ๋ฐ์ดํ„ฐ ์ถ”๊ฐ€

Python

from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A4

data = [
    {"์›”": "1์›”", "ํŒ๋งค": 200},
    {"์›”": "2์›”", "ํŒ๋งค": 300},
    {"์›”": "3์›”", "ํŒ๋งค": 250},
]

pdf_file = canvas.Canvas("sales_report.pdf", pagesize=A4)
width, height = A4

# ์ œ๋ชฉ
pdf_file.setFont("Helvetica-Bold", 16)
pdf_file.drawString(100, height - 100, "ํŒ๋งค ๋ณด๊ณ ์„œ")

# ๋ฐ์ดํ„ฐ ์ถ”๊ฐ€
pdf_file.setFont("Helvetica", 12)
y_position = height - 150
for item in data:
    line = f"{item['์›”']}: ํŒ๋งค = {item['ํŒ๋งค']}"
    pdf_file.drawString(100, y_position, line)
    y_position -= 20

# PDF ์ €์žฅ
pdf_file.save()

์ด ์ฝ”๋“œ๋Š” ๋งค์›” ํŒ๋งค ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ„๋„ ์ค„์— ์ถ”๊ฐ€ํ•˜์—ฌ PDF ํŒŒ์ผ์„ ์ƒ์„ฑํ•ด.

6. ์ด๋ฏธ์ง€ ์ถ”๊ฐ€

ํ…์ŠคํŠธ ์™ธ์—๋„ PDF ๋ฌธ์„œ์— ์ด๋ฏธ์ง€์™€ ๊ทธ๋ž˜ํ”„๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์–ด. ์ง€๊ธˆ๋ถ€ํ„ฐ ์ด๋ฏธ์ง€๋ฅผ ์ถ”๊ฐ€ํ•ด ๋ณผ๊ฒŒ!

Python

from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas

def create_pdf_with_image(file_path):
    c = canvas.Canvas(file_path, pagesize=letter)
    width, height = letter

    c.drawString(100, height - 100, "์—ฌ๊ธฐ์— ์ด๋ฏธ์ง€๊ฐ€ ๋“ค์–ด๊ฐˆ ๊ฑฐ์•ผ:")
    # ์ด๋ฏธ์ง€ ๊ฒฝ๋กœ
    image_path = "example_image.jpg"
    c.drawImage(image_path, 100, height - 300, width=200, height=150)

    c.showPage()
    c.save()

file_path = "image_example.pdf"
create_pdf_with_image(file_path)

์‰ฝ์ง€ ์•Š์•„? ์ด์ œ PDF์— ์ด๋ฏธ์ง€๊ฐ€ ํฌํ•จ๋˜์—ˆ์–ด!

ํ…์ŠคํŠธ์™€ ์ด๋ฏธ์ง€๋ฅผ ํฌํ•จํ•œ PDF๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์› ์œผ๋‹ˆ, ์‹ค์ œ๋กœ ์–ด๋–ป๊ฒŒ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์„์ง€ ์ƒ๊ฐํ•ด๋ณด์ž. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋‹น์‹ ์ด ๋ฐ์ดํ„ฐ ๋ถ„์„ ํšŒ์‚ฌ์—์„œ ์ผํ•˜๊ณ  ๋งค๋‹ฌ ํŒ๋งค ๋ณด๊ณ ์„œ๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ•œ๋‹ค๋ฉด, ๋งค๋ฒˆ ์ˆ˜์ž‘์—…์œผ๋กœ ๋ฌธ์„œ๋ฅผ ์ค€๋น„ํ•˜๋Š” ๋Œ€์‹ , ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ง‘ํ•˜๊ณ  PDF ๋ณด๊ณ ์„œ๋ฅผ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•˜๋Š” ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์–ด. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์‹œ๊ฐ„๋„ ์ ˆ์•ฝํ•˜๊ณ  ๋ณด๊ณ ์„œ ๋ฐ์ดํ„ฐ์˜ ์ •ํ™•์„ฑ๊ณผ ์ผ๊ด€์„ฑ์„ ๋†’์ผ ์ˆ˜ ์žˆ์–ด.

7. PDF์— ํ…Œ์ด๋ธ” ์ถ”๊ฐ€

์ด์ œ ๊ฐ„๋‹จํ•œ ํ…์ŠคํŠธ๋ฅผ ๋‹ค๋ฃจ๋Š” ๊ฒƒ์„ ์ž ๊น ์‰ฌ์–ด๋ณผ๊นŒ? ๋งŒ์•ฝ ์ œํ’ˆ ๋ชฉ๋ก๊ณผ ๊ฐ€๊ฒฉ ๊ฐ™์€ ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ? ๊ฐ„๋‹จํ•œ ์˜ˆ๋ฅผ ๋“ค์–ด๋ณผ๊ฒŒ:

Python

from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas

items = [("๋‹ค๋ฆฌ๋ฏธ", 42.99), ("์ฃผ์ „์ž", 15.00), ("ํ…”๋ ˆ๋น„์ „", 250.00)]

def create_pdf_with_table(file_path):
    c = canvas.Canvas(file_path, pagesize=letter)
    width, height = letter

    c.drawString(100, height - 100, "์ œํ’ˆ ๋ชฉ๋ก๊ณผ ๊ฐ€๊ฒฉ:")
    
    y = height - 150
    for item in items:
        c.drawString(100, y, f"{item[0]} - {item[1]:.2f} $")
        y -= 20

    c.showPage()
    c.save()

file_path = "table_example.pdf"
create_pdf_with_table(file_path)

์ด ์ฝ”๋“œ์—์„œ๋Š” ์ œํ’ˆ ์ด๋ฆ„๊ณผ ๊ฐ€๊ฒฉ์œผ๋กœ ๊ตฌ์„ฑ๋œ ๊ฐ„๋‹จํ•œ ๋ฆฌ์ŠคํŠธ๋ฅผ PDF๋กœ ์ถ”๊ฐ€ํ•ด. ์ด์ œ pandas DataFrame๊ฐ™์ด ๋” ๋ณต์žกํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜๋„ ์žˆ์–ด!

8. ๋ณด๊ณ ์„œ ์ž๋™ํ™”๋ฅผ ์œ„ํ•œ ํ…œํ”Œ๋ฆฟ ์‚ฌ์šฉ

๋ณด๊ณ ์„œ ์ž๋™ํ™”๋ฅผ ์œ„ํ•œ ๊ฐ€์žฅ ๊ฐ•๋ ฅํ•œ ์ ‘๊ทผ ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜๋Š” ํ…œํ”Œ๋ฆฟ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฑฐ์•ผ. ํ…œํ”Œ๋ฆฟ์€ ๋ฌธ์„œ์˜ ๊ตฌ์กฐ์™€ ๋””์ž์ธ์„ ๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด๋‘๊ณ , ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ฑ„์šฐ๋Š” ๋ฐฉ์‹์ด์•ผ.

ํ…œํ”Œ๋ฆฟ ๋ฌธ์„œ ๋งŒ๋“ค๊ธฐ

๊ณ ์ •๋œ ์š”์†Œ(์˜ˆ: ๋กœ๊ณ , ๊ณ ์ •๋œ ์ œ๋ชฉ)๊ฐ€ ํฌํ•จ๋œ ๊ธฐ๋ณธ ํ…œํ”Œ๋ฆฟ์„ ๋งŒ๋“  ๋‹ค์Œ, ๋‚ ์งœ, ๊ทธ๋ž˜ํ”„, ๋ชฉ๋ก ๊ฐ™์€ ๋™์  ๋ฐ์ดํ„ฐ๋กœ ์ฑ„์šธ ์ˆ˜ ์žˆ์–ด. Jinja2 ๊ฐ™์€ ํ…œํ”Œ๋ฆฟ ์—”์ง„์„ ์‚ฌ์šฉํ•˜์—ฌ ํ…์ŠคํŠธ ํ…œํ”Œ๋ฆฟ์„ ์ž‘์„ฑํ•˜๊ณ , ์ตœ์ข… PDF๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜๋„ ์žˆ์–ด.

ReportLab์„ ์‚ฌ์šฉํ•˜์—ฌ ํ…œํ”Œ๋ฆฟ์„ ๋งŒ๋“ค ๋•Œ, ๊ณ ์ •๋œ ๋ฐ์ดํ„ฐ๋ฅผ ํฌํ•จํ•œ ๋ณด๊ณ ์„œ ํ…œํ”Œ๋ฆฟ์„ ๋ฏธ๋ฆฌ ์ค€๋น„ํ•˜๊ณ , ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ฐ์ดํ„ฐ๋กœ ๋™์  ์ปจํ…์ธ ๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ์ด๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์–ด.

์ฝ”๋ฉ˜ํŠธ
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION