본문 바로가기
카테고리 없음

엑셀 데이터를 기반으로 PDF 보고서 자동 생성하기

by jbparkbill 2025. 11. 1.
반응형

엑셀 데이터를 기반으로 PDF 보고서 자동 생성하기
엑셀 데이터를 기반으로 PDF 보고서 자동 생성하기

IT·디지털 자동화 블로그 · 파이썬 보고서 자동화

매일/매주 생성되는 엑셀 데이터를 손대지 않고 PDF 보고서로 배포하는 자동화를 구축한다. 이 글은 3가지 루트를 제공한다: A. ReportLab 직접 생성 · B. Excel(COM) 내보내기 · C. LibreOffice CLI 변환. 환경과 요구사항(템플릿 유지, 서버 무인 실행 등)에 맞춰 선택해 스케줄링까지 연결하면 업무가 끝난다.

왜 PDF 자동화인가

PDF는 배포·보관에 유리하고, 인쇄 시 서식이 깨지지 않는다. 엑셀은 분석과 가공에 강점이 있지만, 공유 시 편집/수정 위험과 폰트 호환 이슈가 잦다. 파이썬 자동화로 엑셀 원본을 읽어 요약/시각화 후 표준 템플릿의 PDF를 생성하면, 보고 품질과 일정 준수율이 동시에 향상된다.

환경 준비

공통 패키지

pip install pandas openpyxl matplotlib

pandas는 엑셀 읽기/요약, matplotlib은 추이 차트 이미지를 생성하는 데 사용한다.

선택 도구

  • ReportLab 설치: pip install reportlab
  • Windows Excel COM: Microsoft Excel(데스크톱) + pip install pywin32
  • LibreOffice: 서버/리눅스에서 soffice CLI
민감 데이터가 포함된 보고서는 네트워크 드라이브 접근 권한, 저장 경로, 암호화 정책을 조직 보안 기준에 맞춘다.

엑셀 읽기·요약·차트 이미지 준비

이 단계의 산출물은 이후 모든 방식(A/B/C)에서 공통으로 재사용한다.

# file: prep_data.py
import pandas as pd
import matplotlib.pyplot as plt
from datetime import datetime

# 1) 데이터 읽기
df = pd.read_excel("sales_data.xlsx")  # 컬럼 예: 날짜, 지역, 매출, 비용
df["날짜"] = pd.to_datetime(df["날짜"])

# 2) 요약 테이블 (지역별 매출 합계)
summary = df.groupby("지역")["매출"].sum().reset_index().sort_values("매출", ascending=False)

# 3) 월별 매출 추이 차트 이미지
monthly = df.set_index("날짜").resample("M")["매출"].sum()
plt.figure()
monthly.plot(marker="o")
plt.title("월별 매출 추이")
plt.xlabel("월")
plt.ylabel("매출")
chart_path = f"chart_{datetime.now():%Y%m%d}.png"
plt.tight_layout()
plt.savefig(chart_path, dpi=150)
plt.close()

# 4) 중간 산출 저장
summary.to_csv("summary.csv", index=False)
print("요약 및 차트 준비 완료:", chart_path)

요약 CSV와 차트 PNG 파일을 생성해 두면, PDF 생성 단계에서 가볍게 끼워 넣을 수 있다.

방법 A: ReportLab으로 PDF 직접 생성(크로스플랫폼)

엑셀 서식을 그대로 쓰지는 않지만, 코드로 레이아웃과 스타일을 정밀 제어할 수 있다는 장점이 있다.

# file: make_pdf_reportlab.py
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, Image
from reportlab.lib.styles import getSampleStyleSheet
import pandas as pd
from datetime import datetime

styles = getSampleStyleSheet()

def build_pdf(summary_csv="summary.csv", chart_path=None, out_path=None, title="월간 실적 보고서"):
    if out_path is None:
        out_path = f"Report_{datetime.now():%Y%m%d}.pdf"

    doc = SimpleDocTemplate(out_path, pagesize=A4)
    story = []

    story += [Paragraph(title, styles["Title"]), Spacer(1, 10)]
    story += [Paragraph("지역별 매출 요약", styles["Heading2"]), Spacer(1, 6)]

    df = pd.read_csv(summary_csv)
    table_data = [["지역", "매출(합계)"]] + df.values.tolist()
    tbl = Table(table_data, colWidths=[200, 200])
    tbl.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,0), colors.HexColor("#E2E8F0")),
        ("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
        ("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#CBD5E1")),
        ("ALIGN", (0,0), (-1,-1), "CENTER")
    ]))
    story += [tbl, Spacer(1, 12)]

    if chart_path:
        story += [Paragraph("월별 매출 추이", styles["Heading2"]), Spacer(1, 6)]
        story += [Image(chart_path, width=420, height=260), Spacer(1, 8)]

    story += [Paragraph("코멘트: 상위 지역 판촉 강화, 하위 지역 원인 분석 및 개선 액션 제안.", styles["Normal"])]

    doc.build(story)
    print("PDF 생성 완료 →", out_path)

if __name__ == "__main__":
    build_pdf(chart_path="chart_{}.png".format(datetime.now().strftime("%Y%m%d")))

서버·크론 환경에서 가장 안정적으로 돌릴 수 있다. 폰트/다국어가 필요하면 ReportLab의 TTF 임베딩을 추가하자.

방법 B: Excel(COM, Windows)로 PDF 내보내기(템플릿 유지)

기존 엑셀 서식·차트·인쇄 영역을 그대로 유지해 PDF를 만든다. Windows + 데스크톱 Excel 환경에서 강력하다.

# file: export_pdf_excel_com.py
# 필요: Microsoft Excel(데스크톱) 설치, pip install pywin32
import os
from datetime import datetime
import win32com.client as win32

def export_pdf(xlsx_path, sheet_name=None, out_dir="pdf_out"):
    os.makedirs(out_dir, exist_ok=True)
    excel = win32.gencache.EnsureDispatch("Excel.Application")
    excel.Visible = False
    wb = excel.Workbooks.Open(os.path.abspath(xlsx_path))

    targets = [wb.Sheets(sheet_name)] if sheet_name else wb.Worksheets
    for sht in targets:
        out = os.path.join(out_dir, f"{sht.Name}_{datetime.now():%Y%m%d}.pdf")
        # Type=0: PDF
        sht.ExportAsFixedFormat(Type=0, Filename=out, Quality=0, IncludeDocProperties=True,
                                IgnorePrintAreas=False, OpenAfterPublish=False)
        print("내보내기 완료 →", out)

    wb.Close(SaveChanges=False)
    excel.Quit()

if __name__ == "__main__":
    export_pdf("보고서_템플릿.xlsx", sheet_name="대시보드")

팁: “페이지 레이아웃 → 인쇄영역 지정”과 “여백/머리말/바닥글”을 템플릿에서 미리 세팅하면 PDF 결과 품질이 일관된다.

방법 C: LibreOffice CLI로 일괄 PDF 변환(서버 친화)

Excel이 없는 리눅스/서버 환경에서 대량 변환에 적합하다. 서식 호환성이 100%는 아니므로 테스트가 필요하다.

# file: convert_with_soffice.py
# 사전 설치: LibreOffice (soffice)
import os, subprocess
from datetime import datetime

def convert_to_pdf(xlsx_path, out_dir="pdf_out"):
    os.makedirs(out_dir, exist_ok=True)
    cmd = [
        "soffice", "--headless", "--convert-to", "pdf", "--outdir", out_dir, xlsx_path
    ]
    subprocess.run(cmd, check=True)
    base = os.path.splitext(os.path.basename(xlsx_path))[0]
    out = os.path.join(out_dir, f"{base}.pdf")
    # 날짜 스탬프 부여
    stamped = os.path.join(out_dir, f"{base}_{datetime.now():%Y%m%d}.pdf")
    if os.path.exists(out):
        os.replace(out, stamped)
        print("변환 완료 →", stamped)

if __name__ == "__main__":
    convert_to_pdf("보고서_템플릿.xlsx")

헤드리스 모드로 무인 실행이 가능하다. 대량 변환 시 큐잉/로그/재시도 로직을 덧붙이면 운영 안정성이 올라간다.

자동 실행과 파일명 규칙

Windows 작업 스케줄러

  1. 작업 만들기 → 트리거: 매일 08:55
  2. 동작: 프로그램 시작 → python 경로 + 스크립트 지정
  3. 권한: 사용자가 로그온하지 않아도 실행

macOS·Linux 크론

# 매일 08:55 실행(요약→PDF)
55 8 * * * /usr/bin/python3 /path/prep_data.py && /usr/bin/python3 /path/make_pdf_reportlab.py

파일명에는 YYYYMMDD 스탬프를 부여해 버전 관리와 검색성을 확보하자. 예: Report_20251030.pdf

체크리스트

  • 원본 엑셀 컬럼 타입과 날짜 파싱이 올바른가
  • 요약 테이블과 차트 이미지가 정상 생성되는가
  • PDF 방식(A/B/C) 중 환경에 맞는 경로를 선택했는가
  • 로그/에러 처리/재시도 정책이 포함되어 있는가
  • 스케줄러/크론에 안전하게 등록되어 있는가

자주 묻는 질문

폰트가 깨져 보일 때는?

ReportLab은 한글 TTF 임베딩을 설정한다. Excel/LibreOffice는 서버에 폰트를 설치하고 동일 폰트를 템플릿에서 지정한다.

대량 변환 시 느리면?

요약/차트 생성은 캐시 하고, PDF 변환만 병렬 처리한다. I/O 병목을 줄이고, 필요 없는 시트는 제외한다.

메일 발송까지 자동화하려면?

생성된 PDF 경로를 읽어 email.message.EmailMessagesmtplib로 첨부 발송한다. 그룹별 템플릿 분기와 재시도/로그를 더하면 운영이 수월하다.

다음 글 예고: PDF 자동 발송과 수신자 그룹 템플릿

생성된 PDF를 부서/경영진 등 그룹별 제목·본문으로 자동 발송하고, 실패 재시도·로그·알림까지 갖춘 운영형 파이프라인을 만든다.

다음 글 보러 가기

관련 읽을거리: 매일 자동 보고서 만들기 · 엑셀+이메일 자동 발송

참고: Python pandas·openpyxl·matplotlib, ReportLab, pywin32, LibreOffice CLI. 본 튜토리얼은 월간 실적, 지점별 취합, 운영지표 리포트 등 반복 보고 업무에 즉시 적용 가능하다.

반응형