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

반복 작업 끝! 파이썬으로 엑셀 시트 자동 생성하기

by jbparkbill 2025. 10. 29.
반응형

반복 작업 끝! 파이썬으로 엑셀 시트 자동 생성하기
반복 작업 끝! 파이썬으로 엑셀 시트 자동 생성하기

IT·디지털 생활형 블로그 · 파이썬 엑셀 자동화

반복적으로 복사하고 이름만 바꾸는 수고는 코드로 끝낼 수 있다. 이 글은 템플릿 시트를 설계하고, openpyxl로 월별·부서별 시트를 자동 생성하며, 데이터·서식·수식을 일괄 배포하는 방법을 단계별 코드로 제공한다. 마지막에는 요약 시트(인덱스)와 하이퍼링크, 보호 설정, 성능 팁까지 정리한다.

왜 시트 자동 생성인가

월별 실적표, 부서별 점검표, 프로젝트별 보고서를 매번 복사해 파일명을 바꾸는 일은 시간이 오래 걸리고 실수가 잦다. 템플릿 하나를 기준으로 시트를 자동 생성하면 일관성, 재현성, 속도를 동시에 얻을 수 있다. 또한 코드로 생성한 구조는 다른 시스템과 연동하기 쉬워 데이터 파이프라인으로 확장할 수 있다.

환경 준비와 템플릿 설계

가상환경을 활성화하고 openpyxl을 설치한다. 템플릿 시트에는 고정 머리글, 기본 서식, 계산 수식, 안내 문구를 포함해 둔다.

pip install --upgrade pip
pip install openpyxl

템플릿 시트 생성

# file: 00_make_template.py
from openpyxl import Workbook
from openpyxl.styles import Font, Alignment, PatternFill, Border, Side
from openpyxl.utils import get_column_letter

wb = Workbook()
ws = wb.active
ws.title = "_TEMPLATE"  # 언더스코어로 숨김 취지 표시

# 머리글
headers = ["일자","항목","수량","단가","금액","메모"]
ws.append(headers)

thin = Side(style="thin", color="9CA3AF")
for cell in ws[1]:
    cell.font = Font(bold=True)
    cell.fill = PatternFill("solid", fgColor="E2E8F0")
    cell.alignment = Alignment(horizontal="center")
    cell.border = Border(top=thin,bottom=thin,left=thin,right=thin)

# 열 너비
widths = [12,22,10,12,14,24]
for i, w in enumerate(widths, start=1):
    ws.column_dimensions[get_column_letter(i)].width = w

# 합계 라벨과 수식 자리
ws["A30"] = "합계"
ws["E30"] = "=SUM(E2:E29)"

wb.save("시트자동_템플릿.xlsx")
print("템플릿 저장 완료")

팁: 템플릿 시트명 앞에 언더스코어를 붙여 사용자가 실수로 수정하지 않도록 구분한다.

월별 시트 자동 생성

템플릿을 복제해 1월부터 12월까지 시트를 만든다. 생성과 동시에 머리글에 월 정보를 기록한다.

# file: 01_clone_months.py
from openpyxl import load_workbook
from datetime import datetime

wb = load_workbook("시트자동_템플릿.xlsx")
tpl = wb["_TEMPLATE"]

months = ["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"]

for m in months:
    ws = wb.copy_worksheet(tpl)
    ws.title = m
    ws["F1"] = f"{m} 입력 가이드"
    ws["A2"] = f"{datetime.now():%Y}-{m[:-1]}-01"  # 예시 날짜

# 템플릿 시트는 맨 뒤로 이동 또는 숨김
wb.move_sheet(tpl, offset=wb.index(wb.worksheets[-1]) - wb.index(tpl))
wb.save("시트자동_월별.xlsx")
print("월별 시트 생성 완료")

부서별 시트 자동 생성

같은 템플릿을 부서 이름 리스트로 복제한다. 부서별 의견 칼럼을 추가하는 등 커스터마이즈도 가능하다.

# file: 02_clone_departments.py
from openpyxl import load_workbook

wb = load_workbook("시트자동_템플릿.xlsx")
tpl = wb["_TEMPLATE"]

departments = ["영업팀","기획팀","개발팀","CS팀","관리팀"]

for d in departments:
    ws = wb.copy_worksheet(tpl)
    ws.title = d
    ws["F1"] = f"{d} 점검표"
    # 필요시 추가 컬럼 제목
    ws["G1"] = "검토자"
    ws["H1"] = "확정여부"

wb.save("시트자동_부서별.xlsx")
print("부서별 시트 생성 완료")

서식·수식·머리글 일괄 배포

이미 템플릿에 들어 있는 서식과 수식은 복제 시 자동으로 따라간다. 추가로 공통 머리글, 로고, 고정 범위 이름 등을 일괄 적용할 수 있다.

# file: 03_distribute_common.py
from openpyxl import load_workbook
from openpyxl.styles import Alignment

wb = load_workbook("시트자동_월별.xlsx")
sheets = [ws for ws in wb.worksheets if ws.title != "_TEMPLATE"]

for ws in sheets:
    ws["A1"] = f"{ws.title} 지출 보고서"
    ws.merge_cells("A1:E1")
    ws["A1"].alignment = Alignment(horizontal="center")

# 이름 정의 예시
for ws in sheets:
    wb.create_named_range(f"{ws.title}_합계", ws, "E30")

wb.save("시트자동_월별_배포.xlsx")
print("공통 설정 배포 완료")

요약 시트 인덱스와 하이퍼링크

첫 시트에 모든 시트로 이동하는 링크와 합계 집계를 제공한다. 여러 시트를 관리할 때 탐색 효율이 크게 올라간다.

# file: 04_make_index.py
from openpyxl import load_workbook
from openpyxl.utils import get_column_letter

wb = load_workbook("시트자동_월별_배포.xlsx")

# 인덱스 시트가 있으면 삭제 후 새로 생성
if "INDEX" in wb.sheetnames:
    idx = wb["INDEX"]
    wb.remove(idx)
idx = wb.create_sheet("INDEX", 0)

idx.append(["시트명","이동","합계"])
row = 2
for ws in wb.worksheets:
    if ws.title in ["INDEX","_TEMPLATE"]:
        continue
    idx[f"A{row}"] = ws.title
    idx[f"B{row}"] = f"#{ws.title}!A1"   # 표시는 링크 텍스트로 바꿈
    idx[f"B{row}"].hyperlink = f"#{ws.title}!A1"
    idx[f"B{row}"].style = "Hyperlink"
    idx[f"C{row}"] = f"='{ws.title}'!E30"  # 각 시트 합계 참조
    row += 1

# 열 너비
for i, w in enumerate([18,18,14], start=1):
    idx.column_dimensions[get_column_letter(i)].width = w

wb.save("시트자동_월별_인덱스.xlsx")
print("인덱스 생성 완료")

시트 보호와 입력 영역

계산식과 머리글은 잠그고, 데이터 입력 칸만 열어둔다. 템플릿 단계에서 설정하면 복제본에도 동일하게 적용된다.

# file: 05_protect_sheets.py
from openpyxl import load_workbook
from openpyxl.styles import Protection

wb = load_workbook("시트자동_월별_인덱스.xlsx")

targets = [ws for ws in wb.worksheets if ws.title not in ["INDEX","_TEMPLATE"]]
for ws in targets:
    # 우선 전체 잠금
    for row in ws.iter_rows(min_row=1, max_row=30, min_col=1, max_col=6):
        for c in row:
            c.protection = Protection(locked=True)
    # 입력 열만 해제
    for r in range(2, 30):
        for col in ["A","B","C","D","F"]:
            ws[f"{col}{r}"].protection = Protection(locked=False)
    ws.protection.sheet = True
    ws.protection.password = "1234"  # 필요 시 정책에 맞춰 변경

wb.save("시트자동_월별_보호.xlsx")
print("보호 설정 완료")

성능 최적화 팁

  • 대용량에서는 셀 단위 서식 적용을 최소화하고, 템플릿에 서식을 담아 복제한다.
  • 반복 쓰기 대신 ws.append 사용을 기본으로 한다.
  • 여러 파일을 생성할 때는 출력 폴더를 고정하고 날짜 스탬프로 버전 관리한다.
  • 대량 데이터 계산은 pandas에서 처리 후 결과만 openpyxl로 전달한다.

체크리스트

  • 템플릿 시트에 머리글·수식·서식을 설계했는가
  • 월별 또는 부서별 리스트로 자동 생성했는가
  • 공통 머리글, 이름 정의, 병합 등 일괄 배포가 되었는가
  • INDEX 시트에서 링크와 합계를 제공하는가
  • 입력 칸과 보호 영역을 구분했는가
  • 출력 규칙과 버전 관리가 정해졌는가

다음 글 예고: 자동 보고서 PDF 변환과 메일 발송

다음 편에서는 생성된 월별 시트를 PDF로 일괄 변환하고, 파일을 이메일로 자동 발송하는 워크플로를 구성한다.

다음 글 보러 가기

관련 읽을거리: openpyxl 완벽 정리 · 셀 값 수정과 데이터 입력 자동화

참고: Python 및 openpyxl 공식 문서. 조직 정책에 맞게 경로·권한·암호·보존 기간을 조정하자.

반응형