업무 자동화 I

백동기·2025년 2월 14일

Python 활용

목록 보기
5/5
post-thumbnail

1. 업무 자동화(RPA)

  • 업무 자동화(RPA : Robotic Process Automation) : 사람이 반복적으로 수행하는 규칙적이고 단순한 업무를 소프트웨어 로봇(봇)을 통해 자동화하는 기술

업무 자동화의 장점

  • 업무 수행 시간 감소, 가용 시간 증가
  • 실수(Human Error) 감소, 업무 수행 정확도 증가

2. 엑셀 자동화

1) openpyxl

  • openpyxl: 엑셀 파일을 읽고 쓸 수 있는 기능을 제공하는 Python 라이브러리

openpyxl 설치

pip install openpyxl

workbook 생성 및 시트 가져오기

  • workbook : 사용자가 접근해야 할 엑셀 파일
from openpyxl import Workbook
wb = Workbook()
ws = wb.active
wb.close()
  • Workbook() : 사용자가 접근해야 할 엑셀 파일 객체
  • .active : 활성화 되어 있는 시트
  • .close() : 문서를 닫음

2) 시트

from openpyxl import Workbook
wb = Workbook()

ws = wb.create_sheet()
ws.title = "MySheet"
ws.sheet_properties.tabColor = "ff66ff"

ws1 = wb.create_sheet("YourSheet")
ws2 = wb.create_sheet("OurSheet", 2) # 생성 위치 지정 

new_ws = wb["OurSheet"] # dictionary 형태로 sheet에 접근 
new_ws["A1"] = "Test"
target = wb.copy_worksheet(new_ws)
target.title = "Copied Sheet"

wb.save("example.xlsx")
  • .create_sheet(이름, index) : 해당 index에 해당 이름으로 새로운 시트를 만듦
  • .title : 시트의 제목을 변경함
  • .sheet_properties.tabColor : 해당 RGB 색상으로 셀 탭 색깔을 바꿈
  • obj[이름] : dictionary 형태로 sheet에 접근
  • .copy_worksheet(워크 시트) : 워크 시트를 복사함

3) 저장 / 불러오기

저장

from openpyxl import Workbook
wb = Workbook()
ws = wb.active
# 작업 부분
ws.title = "example"
wb.save("example.xlsx")
wb.close()
  • .save(파일명) : 엑셀 파일을 저장함

불러오기

from openpyxl import load_workbook
wb = load_workbook("example.xlsx")
ws = wb.active
  • load_workbook(파일명) : 특정 파일명을 가진 엑셀 파일을 가져옴

4) 셀 편집

셀 기본

from openpyxl import Workbook
wb = Workbook()

ws = wb.active
ws.title= "cell"

ws["A1"] = 1
ws["A1"] = 2
ws["A1"] = 3

ws["B1"] = 11
ws["B2"] = 21
ws["B3"] = 31

ws.cell(column=3, row=1, value=111)

print(ws["A1"])
print(ws.cell(column=1, row=1))
print(ws["A1"].value)
print(ws.cell(column=1, row=1).value)
print(ws["A10"].value)

wb.save("example.xlsx")
  • obj[cell] : 특정 셀을 가르킴
  • .cell(row, column, value) : 특정 행과 열에 특정 값을 입력함
  • .value : Cell 객체에서 값을 출력함
Cell 객체, Cell 객체 값, None(내용이 없을 때)를 출력

- 예제1 : 반복문으로 랜덤 숫자로 셀 채우고 파일을 불러 와서 출력해보기

from openpyxl import Workbook
from random import *
wb = Workbook()

ws = wb.active
ws.title= "cell"

for x in range(1, 11):
    for y in range(1, 11):
        ws.cell(column=y, row=x, value=randint(0, 100))

wb.save("example.xlsx")
from openpyxl import load_workbook
wb = load_workbook("example.xlsx")
ws = wb.active

for x in range(1, ws.max_row):
    for y in range(1, ws.max_column):
        print(ws.cell(row=x, column=y).value, end=" ")
    print()

셀 영역

- 영어 성적만 가지고 오기(한 열 지정)

from openpyxl import Workbook
from random import *
wb = Workbook()
ws = wb.active

ws.append(["번호", "영어", "수학"])
for i in range(1, 11):
    ws.append([i, randint(0, 100), randint(0, 100)])

col_b = ws["B"]
for cell in col_b :
    print(cell.value)

wb.save("example.xlsx")

- 영어 및 수학 성적 가지고 오기(여러 열 지정)

from openpyxl import Workbook
from random import *
wb = Workbook()
ws = wb.active

ws.append(["번호", "영어", "수학"])
for i in range(1, 11):
    ws.append([i, randint(0, 100), randint(0, 100)])

col_range = ws["B:C"]
for cols in col_range:
    for cell in cols:
        print(cell.value)

wb.save("example.xlsx")
  • obj[셀 범위]: 특정 셀 범위를 선택함

- 문서의 앞 부분만 가지고 오기(한 행 선택하기)

from openpyxl import Workbook
from random import *
wb = Workbook()
ws = wb.active

ws.append(["번호", "영어", "수학"])
for i in range(1, 11):
    ws.append([i, randint(0, 100), randint(0, 100)])

row_title = ws[1]
for cell in row_title:
    print(cell.value)

wb.save("example.xlsx")

- 모든 학생의 성적 데이터 가지고 오기(여러 행 선택하기)

from openpyxl import Workbook
from random import *
wb = Workbook()
ws = wb.active

ws.append(["번호", "영어", "수학"])
for i in range(1, 11):
    ws.append([i, randint(0, 100), randint(0, 100)])

row_range = ws[2:ws.max_row]
for row in row_range:
    for cell in row:
        print(cell.value, end=" ")
    print()

wb.save("example.xlsx")

- 각 셀의 정보를 가지고 오기

from openpyxl import Workbook
from random import *
from openpyxl.utils.cell import coordinate_from_string

wb = Workbook()
ws = wb.active

ws.append(["번호", "영어", "수학"])
for i in range(1, 11):
    ws.append([i, randint(0, 100), randint(0, 100)])

row_range = ws[1:ws.max_row]
for row in row_range:
    for cell in row:
        print(cell.coordinate, end=" ")
        xy = coordinate_from_string(cell.coordinate)
        print(xy[0], end="")
        print(xy[1], end=" ")
    print()

wb.save("example.xlsx")
  • openpyxl.utils.cell의 coordinate_from_string를 import 해야 함
  • .coordinate : 셀의 정보를 가지고 있음
  • coordinate_from_string(cell.coordinate): 셀을 정보를 행과 열 형식의 list로 저장함 ([0]: 행, [1]: 열)

- 행과 열을 지정하는 방법

from openpyxl import Workbook
from random import *
from openpyxl.utils.cell import coordinate_from_string

wb = Workbook()
ws = wb.active

ws.append(["번호", "영어", "수학"])
for i in range(1, 11):
    ws.append([i, randint(0, 100), randint(0, 100)])

# method 1
for row in tuple(ws.rows):
    print(row)
    print(row[1].value)

for column in tuple(ws.columns):
    print(column)
    print(column[0].value)

# method 2
for row in ws.iter_rows():
    print(row)
    print(row[1].value)

for column in ws.iter_cols():
    print(column)
    print(column[0].value)

# therefore
for row in ws.iter_rows(min_row=2, max_row=11, min_col=2, max_col=3):
    print(row[1].value)
print(" ")
for col in ws.iter_cols(min_row=1, max_row=5, min_col=1, max_col=3):
	print(col[1].value)
wb.save("example.xlsx")
  • 방법 1 : tuple을 이용하는 방법
    - tuple(obj.rows) : 행들의 정보를 한 줄씩 tuple 형태로 묶어서 가지고 옴
    - tuple(obj.cols) : 열들의 정보를 한 줄씩 tuple 형태로 묶어서 가지고 옴

  • 방법 2 : iter_rows(), iter_cols() 사용하는 방법
    - iter_rows(min_row, max_row, min_col, max_col) : 해당 범위 내의 행의 정보를 가지고 옴
    - iter_cols(min_row, max_row, min_col, max_col) : 해당 범위 내의 열의 정보를 가지고 옴
    ※ 해당 방법은 범위를 지정해줄 수 있기 때문에 해당 방법 사용이 좋음

row 실행 결과 col 실행 결과 iter를 이용하여 특정 범위를 출력

셀 삽입

from openpyxl import load_workbook
wb = load_workbook("example.xlsx")
ws = wb.active

ws.insert_rows(8) 
ws.insert_cols(2, 3)

wb.save("example_insert.xlsx")
  • .insert_rows(위치, 행 수) : 특정 행 옆에 지정한 행 수 만큼 행을 추가
  • .insert_cols(위치, 열 수) : 특정 열 옆에 지정한 열 수 만큼 열을 추가

셀 삭제

from openpyxl import load_workbook
wb = load_workbook("example.xlsx")
ws = wb.active

ws.delete_rows(8, 3)
ws.delete_cols(2)

wb.save("example_delete_row.xlsx")
  • .delete_rows(위치, 행 수) : 특정 행 옆에 지정한 행 수 만큼 행을 삭제
  • .delete_cols(위치, 열 수) : 특정 열 옆에 지정한 열 수 만큼 열을 삭제

셀 이동

- 국어 성적을 영어 왼쪽으로 추가하기

from openpyxl import load_workbook
from random import *
wb = load_workbook("example.xlsx")
ws = wb.active

ws.move_range("B1:C11", rows=0, cols=1)

ws["B1"].value = "국어"
for i in range(2, ws.max_row + 1):
    ws[f"B{i}"].value = randint(0, 100)

wb.save("example_move.xlsx")
  • .move_range("셀 범위", rows, cols) : 특정 셀 범위를 rows행, cols열 만큼 이동함

셀 병합 및 해제

from openpyxl import Workbook
wb = Workbook()
ws = wb.active

ws.merge_cells('B2:D2')
ws['B2'].value = "merged cell"

wb.save("sample_merge.xlsx")
  • merge_cells(범위) : 해당 범위의 셀들을 병합함
from openpyxl import load_workbook
wb = load_workbook("sample_merge.xlsx")
ws = wb.active

ws.unmerge_cells('B2:D2')
wb.save("sample_merge.xlsx")
  • unmerge_cells(범위) : 해당 범위의 병합된 셀을 분할함

5) 찾기 / 수식

데이터 찾기

성적 정보 (example.xlsx)

- 영어 점수가 80점 이상의 학생을 영어 경시대회에 출전하게 하도록 명단을 추리기

from openpyxl import load_workbook
wb = load_workbook("example.xlsx")
ws = wb.active

for row in ws.iter_rows(min_row=2):
    if int(row[1].value) >= 80:
        print(row[0].value, "번 학생은 영어 장학생입니다.")

- 영어 점수는 사실 생명과학 점수이기 때문에 수정 하기

from openpyxl import load_workbook
wb = load_workbook("example.xlsx")
ws = wb.active

for row in ws.iter_rows(max_row=1):
    for cell in row:
        if cell.value == "영어":
            cell.value = "생명과학"
            
wb.save("example.xlsx")

수식

import datetime
from openpyxl import Workbook
wb = Workbook()
ws = wb.active

ws['A1'] = datetime.datetime.today()
ws['A2'] = "=SUM(1, 2, 3)"
ws["A3"] = "=Average(1, 2, 3)"

ws["A4"] = 10 
ws["A5"] = 20
ws["A6"] = "=AVERAGE(A4:A5)"

wb.save("calc.xlsx")
  • python 라이브러리를 이용한 값이든, excel의 함수이든, 상수형이든 위의 예제와 같은 형태로 입력하면 값이 들어감

from openpyxl import load_workbook
wb = load_workbook("calc.xlsx")
ws = wb.active

for row in ws.values:
    for cell in row:
        print(cell)
  • 다음과 같이 하면 수식 그대로를 불러오게 됨
from openpyxl import load_workbook
# 수식이 아닌 실제 데이터를 가지고 옴
# evaluate되지 않는 데이터는 None으로 표시됨 
wb = load_workbook("calc.xlsx", data_only=True)
ws = wb.active

for row in ws.values:
    for cell in row:
        print(cell)
  • data_only : 수식이 아닌 데이터만 가져오는 여부 선택

  • 다음과 같이 excel 함수를 입력한 셀의 값은 None값으로 출력함 (이는 evaluate되지 않는 데이터는 None으로 표시하기 때문임)

  • excel 파일에 들어가서 저장을 해야지 정상적으로 값이 나오게 된다. (이는 excel에서 저장을 해야 숫자 값으로 저장함

6) 차트

from openpyxl import load_workbook
from openpyxl.chart import BarChart, Reference
wb = load_workbook("example.xlsx")
ws = wb.active

line_value = Reference(ws, min_row=1, max_row=11, min_col=2, max_col=4)
line_chart = BarChart()
line_chart.add_data(line_value, titles_from_data=True)
line_chart.title = "Line Chart"
line_chart.style = 10
line_chart.y_axis.title = "Score"
line_chart.x_axis.title = "Student"
ws.add_chart(line_chart, "F1")

wb.save("example_chart.xlsx")
  • Reference(워크시트, 데이터 범위) : 차트를 생성할 범위를 지정함
  • BarChart(), LineChart(), PieChart(), ... : 차트 종류 설정
  • .add_data(line_value, 옵션) : 차트 데이터 추가
    - titles_from_data: 데이터 범위의 첫 행이 제목으로 사용할지 여부 설정
  • .title : 차트 제목
  • .style : 미리 정의된 스타일을 적용, 사용 가능한 스타일의 종류는 1 ~ 48
  • .y_axis.title : Y축 제목
  • .x_axis.title : X축 제목
  • .add_chart(차트 객체, 위치) : 차트 넣을 위치 정의

7) 스타일

샐 크기

from openpyxl.styles import Font, Border, Side, PatternFill, Alignment
from openpyxl import load_workbook
wb = load_workbook("example.xlsx")
ws = wb.active

a1 = ws["A1"]
b1 = ws["B1"]
c1 = ws["C1"]

ws.column_dimensions["A"].width = 5 
ws.row_dimensions[1].height = 50

wb.save("example_style.xlsx")
  • column_dimensions[c].width : 열 너비를 설정함
  • row_dimensions[r].width : 행 높이를 설정함

폰트 스타일

from openpyxl.styles import Font, Border, Side, PatternFill, Alignment
from openpyxl import load_workbook
wb = load_workbook("example.xlsx")
ws = wb.active

a1 = ws["A1"]
b1 = ws["B1"]
c1 = ws["C1"]

a1.font = Font(color="FF0000", italic=True, bold=True)
b1.font = Font(color="CC33FF", name="Arial", strike=True)
c1.font = Font(color="0000FF", size=20, underline="single")

wb.save("example_style.xlsx")
  • Font(옵션) : 폰트 스타일을 설정함
    - 옵션
    • color : 색깔을 지정함
    • italic : 기울림꼴로 설정할지 결정
    • bold : 굵게 표시할지 설정
    • name : 글꼴 종류 설정
    • strike : 취소선 설정
    • size : 글자 크기 설정
    • underline : 밑줄 설정

테두리

from openpyxl.styles import Font, Border, Side, PatternFill, Alignment
from openpyxl import load_workbook
wb = load_workbook("example.xlsx")
ws = wb.active

a1 = ws["A1"]
b1 = ws["B1"]
c1 = ws["C1"]

thin_border = Border(left=Side(style="thin"), right=Side(style="thin"), top=Side(style="thin"), bottom=Side(style="thin"))
a1.border = thin_border
b1.border = thin_border
c1.border = thin_border

wb.save("example_style.xlsx")
  • Border(방향 = Side(옵션)) : 테두리를 설정함
    - 옵션
    • style: 테두리 형태를 설정함
  • .border : 해당 셀에 적용함

정렬과 셀 배경색

from openpyxl.styles import Font, Border, Side, PatternFill, Alignment
from openpyxl import load_workbook
wb = load_workbook("example.xlsx")
ws = wb.active

a1 = ws["A1"]
b1 = ws["B1"]
c1 = ws["C1"]

for row in ws.rows:
    for cell in row:
        cell.alignment = Alignment(horizontal="center", vertical="center")
        if cell.column == 1:
            continue
        if isinstance(cell.value, int) and cell.value > 80:
            cell.fill = PatternFill(fgColor="00FF00", fill_type="solid")
            cell.font = Font(color="FF0000")

wb.save("example_style.xlsx")
  • Alignment(horizontal, vertical): 셀 안에 글자를 정렬함
    • horizontal: 가로 방향 (center, left, right, top, bottom)
    • vertical: 세로 방향
  • PatternFill(옵션) : 셀에 색깔을 입힘
    -
    • fgColor: 색깔을 지정함
    • fill_type: 채우기 종류를 설정함

틀 고정

from openpyxl.styles import Font, Border, Side, PatternFill, Alignment
from openpyxl import load_workbook
wb = load_workbook("example.xlsx")
ws = wb.active

a1 = ws["A1"]
b1 = ws["B1"]
c1 = ws["C1"]

ws.freeze_panes = "B2"

wb.save("example_style.xlsx")
  • .freeze_panes: 설정한 셀 기준으로 틀을 고정함

8) 이미지

from openpyxl import Workbook
from openpyxl.drawing.image import Image

wb = Workbook()
ws = wb.active

img = Image('img.png')
ws.add_image(img, 'C3')

wb.save('image.xlsx')
  • Image(이미지 이름) : 이미지를 객체로 만듦
  • .add_image(객체, 위치) : 특정 위치에 이미지를 추가함
Pillow를 install를 해야 실행됨

profile
코딩하는 찍찍이 🐀

1개의 댓글

comment-user-thumbnail
2025년 3월 19일

여기까진가..

답글 달기