카테고리: 업무 자동화

파이썬 엑셀 라이브러리 openpyxl 완전정복 - 모듈·클래스·함수 총정리 (2026) 📊

목차44개 항목

안녕하세요! Mojangcam입니다 😎

엑셀 자동화를 하다 보면 openpyxl 문서를 매번 여기저기 뒤지게 되죠. 그래서 이번엔 openpyxl에 관한 거의 모든 것을 모듈·클래스·함수별로 한 글에 몰아넣었어요. 통합 문서 만들기부터 서식, 차트, 이미지, 데이터 검증, 조건부 서식까지 — 북마크해두고 필요할 때 Ctrl+F로 찾아 쓰는 레퍼런스로 만들었습니다!

이 글의 모든 코드는 openpyxl 3.1.5(2026년 7월 기준 최신)에서 실제 실행해 검증했어요. 복붙하면 바로 돌아갑니다!

💬 이 글은 파이썬 업무 자동화 #1 - 엑셀 자동화 입문 (openpyxl)의 심화판이에요. 입문이 처음이라면 #1을 먼저 보고 오시면 좋아요.

🧩 openpyxl이란?

openpyxl은 파이썬으로 엑셀 파일(.xlsx, .xlsm)을 읽고 쓰는 라이브러리예요. 엑셀 프로그램이 설치돼 있지 않아도 파이썬 코드만으로 엑셀 파일을 자유롭게 다룰 수 있어요.

  • ✅ 지원: .xlsx, .xlsm, .xltx, .xltm (엑셀 2010 이후 형식)
  • ❌ 미지원: .xls(구형), .csv(파이썬 기본 csv 모듈 사용)
  • 🐼 pandas의 read_excel/to_excel도 내부적으로 openpyxl을 엔진으로 써요. 셀 단위 서식·차트 제어는 openpyxl이 더 강력해요.

설치와 버전 확인

cmake
pip install openpyxl
# 이미지 삽입 기능을 쓰려면 Pillow도 필요해요
pip install pillow
코드
import openpyxl
print(openpyxl.__version__)   # 3.1.5

🗺️ 전체 구조 - 모듈 지도

openpyxl은 기능별로 모듈이 잘 나뉘어 있어요. 어디서 뭘 import 하는지 이 지도만 알아도 절반은 끝났어요.

모듈 주요 클래스·함수 용도
openpyxl Workbook, load_workbook 통합 문서 생성·열기·저장
openpyxl.worksheet.worksheet Worksheet 시트(셀·행·열) 다루기
openpyxl.cell.cell Cell 개별 셀
openpyxl.styles Font, PatternFill, Border, Side, Alignment, Protection, NamedStyle 셀 서식
openpyxl.utils get_column_letter, column_index_from_string 좌표 변환 유틸
openpyxl.chart BarChart, LineChart, PieChart, Reference, Series 차트
openpyxl.drawing.image Image 이미지 삽입
openpyxl.worksheet.datavalidation DataValidation 데이터 유효성 검사(드롭다운 등)
openpyxl.formatting.rule ColorScaleRule, CellIsRule, DataBarRule 등 조건부 서식
openpyxl.worksheet.table Table, TableStyleInfo 표(엑셀 Table)
openpyxl.comments Comment 셀 메모

📌 1. Workbook - 생성·열기·저장

모든 작업의 시작점이에요. 통합 문서(Workbook) = 엑셀 파일 한 개.

새 통합 문서 만들기

makefile
from openpyxl import Workbook

wb = Workbook()      # 새 통합 문서 (기본 시트 1개 자동 생성)
ws = wb.active       # 현재 활성 시트
wb.save("새파일.xlsx")

load_workbook() 옵션

코드
from openpyxl import load_workbook

wb = load_workbook("기존파일.xlsx")

load_workbook()의 주요 옵션이에요. 대용량·수식 파일에서 특히 중요해요.

옵션 기본값 설명
read_only False 읽기 전용. 대용량 파일을 메모리 적게 쓰며 빠르게 읽어요
data_only False 수식 대신 계산된 값을 읽어요 (아래 '수식' 섹션 주의점 참고)
keep_vba False .xlsm의 매크로(VBA)를 보존해요
keep_links True 외부 통합 문서 링크 보존
INI
# 수식이 아니라 값만 읽고 싶을 때
wb = load_workbook("보고서.xlsx", data_only=True)

# 매크로 파일을 열고 저장할 때
wb = load_workbook("매크로.xlsm", keep_vba=True)

주요 속성·메서드

이름 설명
wb.active 현재 활성 시트
wb.sheetnames 시트 이름 리스트
wb.worksheets 시트 객체 리스트
wb["시트명"] 이름으로 시트 접근
wb.create_sheet(title, index) 시트 추가
wb.remove(ws) 시트 삭제
wb.copy_worksheet(ws) 시트 복사
wb.save("파일.xlsx") 저장

📌 2. Worksheet - 시트 다루기

워크시트(Worksheet) = 엑셀의 시트 한 장. 셀·행·열이 여기에 담겨요.

생성·선택·삭제·복사

makefile
ws = wb.active                       # 활성 시트
ws2 = wb.create_sheet("판매")        # 맨 뒤에 새 시트
ws3 = wb.create_sheet("요약", 0)     # 0번 인덱스(맨 앞)에 삽입
sheet = wb["판매"]                   # 이름으로 접근
print(wb.sheetnames)                 # ['요약', 'Sheet', '판매']

wb.remove(wb["판매"])                # 삭제
new = wb.copy_worksheet(wb["요약"])  # 복사 (서식까지 복제)

Worksheet 주요 속성

속성 설명
ws.title 시트 이름
ws.max_row / ws.max_column 데이터가 있는 마지막 행/열 번호
ws.dimensions 사용 범위 (예: "A1:E10")
ws.sheet_state "visible" / "hidden"
ws.sheet_properties.tabColor 시트 탭 색상 (예: "FF0000")
vim
ws.title = "성적표"
ws.sheet_properties.tabColor = "1072BA"   # 탭 색상
print(ws.max_row, ws.max_column, ws.dimensions)

📌 3. Cell - 셀 읽고 쓰기

이 라이브러리의 핵심! 셀에 값을 넣고 읽는 여러 방법이에요.

셀 하나씩 접근

코드
# 방법 1) 엑셀 좌표로
ws["A1"] = "이름"
print(ws["A1"].value)          # 이름

# 방법 2) 행·열 번호로 (1부터 시작!)
ws.cell(row=1, column=2, value="점수")
print(ws.cell(row=1, column=2).value)   # 점수

여러 셀·행 단위 접근

코드
# 한 줄씩 추가 (가장 편함)
ws.append(["철수", 90])
ws.append(["영희", 85])

# 범위로 접근
for row in ws["A1:B3"]:
    for cell in row:
        print(cell.coordinate, cell.value)

# 행 단위 순회
for row in ws.iter_rows(min_row=2, max_col=2, values_only=True):
    이름, 점수 = row
    print(이름, 점수)

# 열 단위 순회
for col in ws.iter_cols(min_col=1, max_col=2, values_only=True):
    print(col)

iter_rows / iter_cols 인자

인자 설명
min_row / max_row 시작·끝 행
min_col / max_col 시작·끝 열
values_only True면 셀 객체 대신 값만 반환 (빠름)

Cell 주요 속성

속성 설명
cell.value 셀 값
cell.row / cell.column 행/열 번호
cell.column_letter 열 문자 (예: "A")
cell.coordinate 좌표 (예: "A1")
cell.data_type 자료형 (n=숫자, s=문자 등)

📌 4. utils - 좌표 유틸리티

행·열 번호와 엑셀 문자 좌표를 서로 바꿔주는 필수 도구예요.

coffeescript
from openpyxl.utils import (
    get_column_letter, column_index_from_string, range_boundaries,
)
# coordinate_from_string만 하위 모듈에서 가져와요 (openpyxl.utils에서 직접 import하면 ImportError!)
from openpyxl.utils.cell import coordinate_from_string

print(get_column_letter(1))            # A
print(get_column_letter(27))           # AA
print(column_index_from_string("B"))   # 2
print(column_index_from_string("AA"))  # 27
print(coordinate_from_string("C5"))    # ('C', 5)
print(range_boundaries("A1:C3"))       # (1, 1, 3, 3)

반복문에서 열 번호를 문자로 바꿀 때 get_column_letter를 정말 자주 써요.

📌 5. styles - 셀 서식

openpyxl.styles에서 서식 객체를 만들어 셀에 할당해요. 폰트·채우기·테두리·정렬 4형제가 핵심이에요.

elm
from openpyxl.styles import (
    Font, PatternFill, GradientFill, Border, Side,
    Alignment, Protection, NamedStyle,
)

Font - 글꼴

코드
ws["A1"].font = Font(
    name="맑은 고딕",   # 글꼴
    size=12,           # 크기
    bold=True,         # 굵게
    italic=False,      # 기울임
    underline="single",# 밑줄 (single/double)
    strike=False,      # 취소선
    color="FFFFFF",    # 글자색 (RRGGBB)
)

PatternFill - 배경 채우기

코드
ws["A1"].fill = PatternFill(
    fill_type="solid",   # 채우기 방식 (solid가 일반적)
    fgColor="4F81BD",    # 채울 색 (RRGGBB)
)

💡 색상은 6자리 16진수(RRGGBB)로 넣어요. 파랑 4F81BD, 초록 2ECC71, 빨강 E74C3C, 노랑 FFFF00.

Border·Side - 테두리

코드
thin = Side(style="thin", color="000000")   # 선 하나 정의
ws["A1"].border = Border(left=thin, right=thin, top=thin, bottom=thin)

Side의 style 종류: thin, medium, thick, dashed, dotted, double, hair 등.

Alignment - 정렬

코드
ws["A1"].alignment = Alignment(
    horizontal="center",  # left/center/right/justify
    vertical="center",    # top/center/bottom
    wrap_text=True,       # 자동 줄바꿈
    text_rotation=0,      # 글자 회전 각도
)

number_format - 표시 형식

값은 그대로 두고 보이는 형식만 바꿔요.

코드
ws["B2"].value = 12345.678
ws["B2"].number_format = "#,##0.00"   # 12,345.68
형식 문자열 결과 예시
"#,##0" 1,000
"#,##0.00" 1,000.00
"0%" 85%
"0.00%" 85.00%
'"₩"#,##0' ₩1,000
"yyyy-mm-dd" 2026-07-22
"@" 텍스트로 강제

NamedStyle - 재사용 스타일

같은 서식을 여러 셀에 반복 적용할 때 스타일에 이름을 붙여 재사용해요.

코드
header = NamedStyle(name="헤더")
header.font = Font(bold=True, color="FFFFFF")
header.fill = PatternFill("solid", fgColor="808080")
wb.add_named_style(header)

ws["A1"].style = "헤더"   # 이름으로 적용

📌 6. 행·열 다루기

너비·높이

코드
ws.column_dimensions["A"].width = 20   # A열 너비
ws.row_dimensions[1].height = 30       # 1행 높이

셀 병합·해제

코드
ws.merge_cells("A1:C1")                 # 문자열 범위
ws["A1"] = "병합된 제목"                # 값은 좌상단 셀에만!
ws.unmerge_cells("A1:C1")

# 행·열 번호로도 가능
ws.merge_cells(start_row=1, start_column=1, end_row=1, end_column=3)

틀 고정 (freeze panes)

INI
ws.freeze_panes = "A2"   # 1행 고정 (스크롤해도 헤더가 안 사라짐)
ws.freeze_panes = "B2"   # 1행 + A열 동시 고정

숨김·자동 필터

코드
ws.column_dimensions["C"].hidden = True   # C열 숨김
ws.auto_filter.ref = "A1:E1"              # 헤더에 필터 버튼

📌 7. 수식(Formula)

셀에 =로 시작하는 문자열을 넣으면 엑셀 수식이 돼요.

prolog
ws["C2"] = "=A2+B2"
ws["C3"] = "=SUM(A2:B2)"
ws["C4"] = "=AVERAGE(A2:A10)"

⚠️ 가장 헷갈리는 부분! openpyxl은 수식을 계산하지 않아요. 계산은 엑셀이 파일을 열 때 해줘요. 그래서 파이썬으로 다시 읽을 때 계산된 값이 필요하면 data_only=True로 열어야 하는데, 이건 엑셀로 한 번 열어 저장한 적이 있어야 캐시된 값이 나와요. 방금 openpyxl로 만든 파일은 data_only=True로 읽으면 None이 나올 수 있어요.

📌 8. chart - 차트

막대 차트 기본형

코드
from openpyxl.chart import BarChart, Reference

chart = BarChart()
chart.title = "학생별 총점"
chart.type = "col"          # col=세로막대, bar=가로막대
chart.style = 10

# 데이터 범위 (헤더 포함)
values = Reference(ws, min_col=5, min_row=1, max_row=4)
# 카테고리(X축 라벨)
cats = Reference(ws, min_col=1, min_row=2, max_row=4)

chart.add_data(values, titles_from_data=True)
chart.set_categories(cats)
ws.add_chart(chart, "H2")   # H2 위치에 삽입

차트 종류

클래스 차트
BarChart 막대
LineChart 꺾은선
PieChart 원형
ScatterChart 분산형
AreaChart 영역
DoughnutChart 도넛
RadarChart 방사형

Reference(ws, min_col, min_row, max_col, max_row)로 데이터 범위를, add_data·set_categories로 값과 라벨을 지정하는 흐름은 모든 차트가 동일해요.

📌 9. 이미지 삽입

로고나 캡처 이미지를 시트에 넣어요. (Pillow 설치 필요)

nix
from openpyxl.drawing.image import Image

img = Image("logo.png")
img.width = 120     # 픽셀 (선택)
img.height = 60
ws.add_image(img, "A1")   # A1 위치에 삽입
wb.save("이미지포함.xlsx")

📌 10. 데이터 검증

드롭다운 목록, 숫자 범위 제한 등 입력 규칙을 만들어요.

코드
from openpyxl.worksheet.datavalidation import DataValidation

# 드롭다운 목록
dv = DataValidation(type="list", formula1='"사과,바나나,포도"', allow_blank=True)
ws.add_data_validation(dv)
dv.add("A2:A10")   # 이 범위에 드롭다운 적용

# 1~100 사이 정수만 허용
dv2 = DataValidation(type="whole", operator="between", formula1=1, formula2=100)
ws.add_data_validation(dv2)
dv2.add("B2:B10")

type 종류: list(목록), whole(정수), decimal(실수), date(날짜), time(시간), textLength(글자 수), custom(수식).

📌 11. 조건부 서식

값에 따라 색이 자동으로 바뀌는 규칙이에요.

코드
from openpyxl.formatting.rule import ColorScaleRule, CellIsRule, DataBarRule
from openpyxl.styles import PatternFill

# 1) 색조(2색 스케일): 낮으면 빨강 → 높으면 초록
ws.conditional_formatting.add(
    "B2:B10",
    ColorScaleRule(start_type="min", start_color="F8696B",
                   end_type="max", end_color="63BE7B"),
)

# 2) 특정 값보다 크면 노란 배경
ws.conditional_formatting.add(
    "B2:B10",
    CellIsRule(operator="greaterThan", formula=["80"],
               fill=PatternFill("solid", fgColor="FFFF00")),
)

# 3) 데이터 막대
ws.conditional_formatting.add(
    "C2:C10",
    DataBarRule(start_type="min", end_type="max", color="638EC6"),
)

주요 규칙: ColorScaleRule(색조), CellIsRule(비교), FormulaRule(수식), DataBarRule(막대), IconSetRule(아이콘).

📌 12. 표(Table) 만들기

범위를 엑셀 '표'로 지정하면 정렬·필터·줄무늬 스타일이 자동 적용돼요.

코드
from openpyxl.worksheet.table import Table, TableStyleInfo

tbl = Table(displayName="성적표", ref="A1:E4")   # displayName은 공백 없이!
tbl.tableStyleInfo = TableStyleInfo(
    name="TableStyleMedium9",   # 내장 스타일 이름
    showRowStripes=True,        # 줄무늬
)
ws.add_table(tbl)

📌 13. 기타 기능

메모·하이퍼링크

nix
from openpyxl.comments import Comment

ws["A1"].comment = Comment("이건 메모예요", "Mojangcam")
ws["A2"].value = "블로그"
ws["A2"].hyperlink = "https://mojangcam.tistory.com"
ws["A2"].style = "Hyperlink"   # 파란 밑줄 스타일

대용량 모드 (read_only / write_only)

수십만 행짜리 파일은 일반 모드로 열면 메모리가 폭발해요. 이럴 때:

코드
# 읽기: 메모리 적게, 순차 접근만
wb = load_workbook("대용량.xlsx", read_only=True)
for row in wb.active.iter_rows(values_only=True):
    ...
wb.close()

# 쓰기: append로만 추가, 서식 최소
from openpyxl import Workbook
wb = Workbook(write_only=True)
ws = wb.create_sheet()
for i in range(100000):
    ws.append([i, i*2])
wb.save("대용량출력.xlsx")

페이지 설정 (인쇄)

INI
ws.print_area = "A1:E20"
ws.page_setup.orientation = "landscape"   # 가로

📌 전체 코드 (복붙 OK)

지금까지 배운 걸 모아 성적표 리포트를 자동 생성하는 완성 코드예요. 그대로 실행하면 스타일·차트가 들어간 엑셀 파일이 만들어져요.

코드
# openpyxl 3.1.5 / Python 3.8+
from openpyxl import Workbook, load_workbook
from openpyxl.styles import Font, PatternFill, Border, Side, Alignment
from openpyxl.chart import BarChart, Reference
from openpyxl.utils import get_column_letter

# 1) 통합 문서 + 시트
wb = Workbook()
ws = wb.active
ws.title = "성적표"

# 2) 헤더 + 데이터
headers = ["이름", "국어", "영어", "수학", "총점"]
ws.append(headers)
data = [
    ["김철수", 90, 85, 95],
    ["이영희", 88, 92, 100],
    ["박민수", 75, 80, 70],
]
for row in data:
    ws.append(row + [sum(row[1:])])   # 총점 자동 계산

# 3) 헤더 스타일
header_font = Font(bold=True, color="FFFFFF", size=12)
header_fill = PatternFill("solid", fgColor="4F81BD")
thin = Side(style="thin", color="999999")
border = Border(left=thin, right=thin, top=thin, bottom=thin)
center = Alignment(horizontal="center", vertical="center")
for col in range(1, len(headers) + 1):
    c = ws.cell(row=1, column=col)
    c.font, c.fill, c.border, c.alignment = header_font, header_fill, border, center

# 4) 열 너비 + 틀 고정
for col in range(1, len(headers) + 1):
    ws.column_dimensions[get_column_letter(col)].width = 12
ws.freeze_panes = "A2"

# 5) 막대 차트 (이름별 총점)
chart = BarChart()
chart.title = "학생별 총점"
chart.type = "col"
values = Reference(ws, min_col=5, min_row=1, max_row=1 + len(data))
cats = Reference(ws, min_col=1, min_row=2, max_row=1 + len(data))
chart.add_data(values, titles_from_data=True)
chart.set_categories(cats)
ws.add_chart(chart, "G2")

# 6) 저장
wb.save("성적표_리포트.xlsx")
print("성적표_리포트.xlsx 저장 완료!")

실행하면 헤더는 파란 배경·흰 글씨로, 총점 열은 자동 계산(270 / 280 / 225), 오른쪽엔 학생별 총점 막대 차트가 들어간 파일이 생성돼요. 코드가 하는 일을 그림 한 장으로 정리하면 이래요.

📌 자주 나는 에러

  1. data_only=True인데 값이 None으로 나와요
    • 원인 : 수식의 계산 결과는 엑셀이 저장할 때 캐시돼요. openpyxl로만 만든 파일엔 캐시가 없어요.
    • 해결 : 파일을 엑셀로 한 번 열어 저장하거나, 파이썬에서 직접 값을 계산해 넣으세요.
  2. 병합된 셀에 값·스타일이 안 먹어요
    • 원인 : 병합 범위는 좌상단 셀에만 값·스타일이 적용돼요.
    • 해결 : ws["A1"](좌상단)에만 값을 넣으세요. 나머지 셀(MergedCell)에 값을 넣으려 하면 AttributeError: 'MergedCell' object attribute 'value' is read-only 에러가 나요.
  3. read_only 모드에서 수정이 안 돼요
    • 원인 : 읽기 전용 모드는 값 변경·이미지·차트 추가가 불가능해요.
    • 해결 : 수정이 필요하면 일반 모드로 여세요. (대신 메모리를 더 씀)
  4. .xls(구형) 파일을 못 열어요
    • 원인 : openpyxl은 xlsx 계열만 지원해요.
    • 해결 : 구형 .xls는 pandas.read_excel(..., engine="xlrd")로 읽거나, 엑셀에서 .xlsx로 저장 후 사용하세요.
  5. 대용량 파일에서 메모리가 부족해요
    • 해결 : 읽기는 read_only=True, 쓰기는 write_only=True 모드를 쓰고, 다 쓰면 wb.close() 하세요.

💬 마무리

openpyxl의 거의 모든 모듈·클래스·함수를 한 번에 훑어봤어요. 정리하면 흐름은 늘 이래요 — Workbook 만들기 → Worksheet 선택 → Cell에 값 쓰기 → styles로 꾸미기 → 차트·검증·조건부 서식 추가 → save(). 이 뼈대만 기억하면 나머지는 이 글에서 Ctrl+F로 찾아 쓰면 돼요!

이 글이 도움이 됐다면 북마크해두고 필요할 때마다 꺼내 보세요. 다음엔 openpyxl로 여러 엑셀 파일을 한 번에 병합·집계하는 실전 자동화도 다뤄볼게요. 기대해주세요! 🙌

📚 파이썬 업무 자동화 시리즈

글쓴이

Mojangcam

직접 코드를 짜고, 서버를 돌리고, 막힌 에러를 해결하며 배운 것들을 기록하는 개발·IT 실전 기록 블로그