파이썬 엑셀 라이브러리 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이 더 강력해요.
설치와 버전 확인
pip install openpyxl
# 이미지 삽입 기능을 쓰려면 Pillow도 필요해요
pip install pillowimport 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) = 엑셀 파일 한 개.
새 통합 문서 만들기
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 | 외부 통합 문서 링크 보존 |
# 수식이 아니라 값만 읽고 싶을 때
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) = 엑셀의 시트 한 장. 셀·행·열이 여기에 담겨요.
생성·선택·삭제·복사
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") |
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 - 좌표 유틸리티
행·열 번호와 엑셀 문자 좌표를 서로 바꿔주는 필수 도구예요.
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형제가 핵심이에요.
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)
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)
셀에 =로 시작하는 문자열을 넣으면 엑셀 수식이 돼요.
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 설치 필요)
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. 기타 기능
메모·하이퍼링크
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")페이지 설정 (인쇄)
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), 오른쪽엔 학생별 총점 막대 차트가 들어간 파일이 생성돼요. 코드가 하는 일을 그림 한 장으로 정리하면 이래요.

📌 자주 나는 에러
data_only=True인데 값이None으로 나와요- 원인 : 수식의 계산 결과는 엑셀이 저장할 때 캐시돼요. openpyxl로만 만든 파일엔 캐시가 없어요.
- 해결 : 파일을 엑셀로 한 번 열어 저장하거나, 파이썬에서 직접 값을 계산해 넣으세요.
- 병합된 셀에 값·스타일이 안 먹어요
- 원인 : 병합 범위는 좌상단 셀에만 값·스타일이 적용돼요.
- 해결 :
ws["A1"](좌상단)에만 값을 넣으세요. 나머지 셀(MergedCell)에 값을 넣으려 하면AttributeError: 'MergedCell' object attribute 'value' is read-only에러가 나요.
read_only모드에서 수정이 안 돼요- 원인 : 읽기 전용 모드는 값 변경·이미지·차트 추가가 불가능해요.
- 해결 : 수정이 필요하면 일반 모드로 여세요. (대신 메모리를 더 씀)
.xls(구형) 파일을 못 열어요- 원인 : openpyxl은 xlsx 계열만 지원해요.
- 해결 : 구형
.xls는pandas.read_excel(..., engine="xlrd")로 읽거나, 엑셀에서.xlsx로 저장 후 사용하세요.
- 대용량 파일에서 메모리가 부족해요
- 해결 : 읽기는
read_only=True, 쓰기는write_only=True모드를 쓰고, 다 쓰면wb.close()하세요.
- 해결 : 읽기는
💬 마무리
openpyxl의 거의 모든 모듈·클래스·함수를 한 번에 훑어봤어요. 정리하면 흐름은 늘 이래요 — Workbook 만들기 → Worksheet 선택 → Cell에 값 쓰기 → styles로 꾸미기 → 차트·검증·조건부 서식 추가 → save(). 이 뼈대만 기억하면 나머지는 이 글에서 Ctrl+F로 찾아 쓰면 돼요!
이 글이 도움이 됐다면 북마크해두고 필요할 때마다 꺼내 보세요. 다음엔 openpyxl로 여러 엑셀 파일을 한 번에 병합·집계하는 실전 자동화도 다뤄볼게요. 기대해주세요! 🙌
📚 파이썬 업무 자동화 시리즈
- #1 엑셀 자동화 입문 (openpyxl)
- #2 웹 크롤링 입문 (requests + BeautifulSoup)
- #3 파일 정리 자동화 (이름 일괄 변경)
- #4 디스코드 웹훅으로 알림 보내기
- openpyxl 완전정복 (이 글) ← 엑셀 심화 레퍼런스!
