본문으로 건너뛰기
Advertisement

업무 자동화

Excel, PowerPoint, 이메일 발송까지 반복 업무를 Python으로 자동화합니다.


설치

pip install openpyxl python-pptx

openpyxl — Excel 자동화

from openpyxl import Workbook, load_workbook
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
from openpyxl.utils import get_column_letter
from openpyxl.chart import BarChart, Reference
import datetime


# 엑셀 파일 생성
def create_sales_report(data: list[dict], filename: str = "sales_report.xlsx"):
wb = Workbook()
ws = wb.active
ws.title = "매출 현황"

# 헤더 스타일
header_font = Font(name="맑은 고딕", bold=True, color="FFFFFF", size=11)
header_fill = PatternFill(fill_type="solid", fgColor="2F5496")
center_align = Alignment(horizontal="center", vertical="center")

# 헤더 작성
headers = ["날짜", "제품명", "카테고리", "수량", "단가", "매출액"]
for col, header in enumerate(headers, 1):
cell = ws.cell(row=1, column=col, value=header)
cell.font = header_font
cell.fill = header_fill
cell.alignment = center_align

# 데이터 작성
for row, item in enumerate(data, 2):
ws.cell(row=row, column=1, value=item["date"])
ws.cell(row=row, column=2, value=item["product"])
ws.cell(row=row, column=3, value=item["category"])
ws.cell(row=row, column=4, value=item["quantity"])
ws.cell(row=row, column=5, value=item["price"]).number_format = "#,##0"
# 매출액 수식
ws.cell(row=row, column=6, value=f"=D{row}*E{row}").number_format = "#,##0"

# 합계 행
last_row = len(data) + 2
ws.cell(row=last_row, column=3, value="합계").font = Font(bold=True)
ws.cell(row=last_row, column=4, value=f"=SUM(D2:D{last_row-1})")
ws.cell(row=last_row, column=6, value=f"=SUM(F2:F{last_row-1})").number_format = "#,##0"

# 열 너비 자동 조정
col_widths = [12, 20, 12, 8, 12, 14]
for col, width in enumerate(col_widths, 1):
ws.column_dimensions[get_column_letter(col)].width = width

# 행 높이
ws.row_dimensions[1].height = 22

# 차트 추가
chart = BarChart()
chart.title = "카테고리별 매출"
chart.style = 10
data_ref = Reference(ws, min_col=6, min_row=1, max_row=len(data)+1)
cats_ref = Reference(ws, min_col=3, min_row=2, max_row=len(data)+1)
chart.add_data(data_ref, titles_from_data=True)
chart.set_categories(cats_ref)
chart.width = 15
chart.height = 10
ws.add_chart(chart, "H2")

wb.save(filename)
print(f"✅ {filename} 저장 완료")


# 기존 파일 수정
def update_excel(filename: str):
wb = load_workbook(filename)
ws = wb.active

# 데이터 읽기
for row in ws.iter_rows(min_row=2, values_only=True):
print(row)

# 셀 수정
ws["A1"] = "수정된 제목"
ws.append(["2024-01-15", "신제품", "전자", 5, 50000])

wb.save(filename)

python-pptx — PowerPoint 자동화

from pptx import Presentation
from pptx.util import Inches, Pt, Emu
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN


def create_presentation(title: str, data: list[dict]) -> Presentation:
prs = Presentation()

# 슬라이드 크기 (16:9)
prs.slide_width = Inches(13.33)
prs.slide_height = Inches(7.5)

# 1. 표지 슬라이드
slide_layout = prs.slide_layouts[0] # 표지 레이아웃
slide = prs.slides.add_slide(slide_layout)
slide.shapes.title.text = title
slide.placeholders[1].text = f"작성일: {datetime.date.today()}"

# 2. 데이터 슬라이드 (텍스트 + 테이블)
slide = prs.slides.add_slide(prs.slide_layouts[5]) # 빈 슬라이드

# 제목 추가
txBox = slide.shapes.add_textbox(Inches(0.5), Inches(0.3), Inches(12), Inches(0.8))
tf = txBox.text_frame
tf.text = "월별 실적 요약"
tf.paragraphs[0].runs[0].font.size = Pt(28)
tf.paragraphs[0].runs[0].font.bold = True
tf.paragraphs[0].runs[0].font.color.rgb = RGBColor(0x2F, 0x54, 0x96)

# 테이블 추가
rows, cols = len(data) + 1, 4
table = slide.shapes.add_table(rows, cols,
Inches(0.5), Inches(1.2), Inches(12), Inches(0.5 * rows)
).table

# 헤더
headers = ["월", "매출액", "목표", "달성률"]
for i, header in enumerate(headers):
cell = table.cell(0, i)
cell.text = header
cell.text_frame.paragraphs[0].runs[0].font.bold = True
cell.text_frame.paragraphs[0].alignment = PP_ALIGN.CENTER

# 데이터
for row_idx, item in enumerate(data, 1):
table.cell(row_idx, 0).text = item["month"]
table.cell(row_idx, 1).text = f"{item['sales']:,}원"
table.cell(row_idx, 2).text = f"{item['target']:,}원"
rate = item['sales'] / item['target'] * 100
table.cell(row_idx, 3).text = f"{rate:.1f}%"

return prs


# 저장
data = [
{"month": "1월", "sales": 85000000, "target": 80000000},
{"month": "2월", "sales": 92000000, "target": 90000000},
{"month": "3월", "sales": 78000000, "target": 95000000},
]
prs = create_presentation("2024 상반기 실적 보고", data)
prs.save("report.pptx")

smtplib — 이메일 자동 발송

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
from pathlib import Path
import os


class EmailSender:
def __init__(self, smtp_host: str, smtp_port: int, email: str, password: str):
self.smtp_host = smtp_host
self.smtp_port = smtp_port
self.email = email
self.password = password

def send(
self,
to: str | list[str],
subject: str,
body: str,
html: str = None,
attachments: list[str] = None,
) -> bool:
msg = MIMEMultipart("alternative" if html else "mixed")
msg["From"] = self.email
msg["To"] = to if isinstance(to, str) else ", ".join(to)
msg["Subject"] = subject

# 본문 (텍스트 + HTML)
msg.attach(MIMEText(body, "plain", "utf-8"))
if html:
msg.attach(MIMEText(html, "html", "utf-8"))

# 첨부 파일
for filepath in (attachments or []):
path = Path(filepath)
with open(path, "rb") as f:
part = MIMEApplication(f.read(), Name=path.name)
part["Content-Disposition"] = f'attachment; filename="{path.name}"'
msg.attach(part)

try:
with smtplib.SMTP_SSL(self.smtp_host, self.smtp_port) as server:
server.login(self.email, self.password)
recipients = [to] if isinstance(to, str) else to
server.sendmail(self.email, recipients, msg.as_string())
print(f"✅ 메일 발송 완료: {to}")
return True
except Exception as e:
print(f"❌ 메일 발송 실패: {e}")
return False


# Gmail 사용 예 (앱 비밀번호 필요)
sender = EmailSender(
smtp_host="smtp.gmail.com",
smtp_port=465,
email=os.environ["GMAIL_USER"],
password=os.environ["GMAIL_APP_PASSWORD"],
)

html_body = """
<html><body>
<h2>월간 보고서</h2>
<p>안녕하세요, <strong>이번 달 실적</strong>을 첨부합니다.</p>
<table border="1">
<tr><th>항목</th><th>수치</th></tr>
<tr><td>매출</td><td>9,200만원</td></tr>
</table>
</body></html>
"""

sender.send(
to=["manager@example.com", "ceo@example.com"],
subject="[자동발송] 2024년 3월 월간 보고서",
body="월간 보고서를 첨부 파일로 전달드립니다.",
html=html_body,
attachments=["sales_report.xlsx", "report.pptx"],
)

정리

라이브러리대상 파일주요 기능
openpyxlExcel (.xlsx)셀 스타일, 수식, 차트
python-pptxPowerPoint (.pptx)슬라이드, 텍스트, 테이블
smtplib이메일텍스트/HTML/첨부 발송
pandasCSV/Excel데이터 분석 후 저장

이 조합으로 데이터 수집 → 분석 → 리포트 생성 → 자동 발송까지 완전 자동화가 가능합니다.

Advertisement