내가 만드는 클래스
앞서 만든 코드를 GUI가 있는 코드 쪽으로 복사를 해서 사용하면 됩니다. 그런데 이와 같이 엑셀을 비교해야 하는 경우가 많다면 우리가 이미 만들어진 패키지를 사용하듯이 우리가 만든 코드를 패키지로 만들면 어떨까요? 그러면 필요할 때 다시 복사해서 쓸 필요없이 import 해서 사용할 수 있으니 편리할 것입니다. 또한 복사를 해서 혹시라도 잘못 건드릴 경우 에러가 발생할 수 있겠죠. 혹은 복사를 해서 사용하다가 나중에 오류가 난 것이 확인된다면 어떨까요? 일일이 복사를 해서 쓴 코드들을 따라다니면서 에러를 수정해줘야겠죠? 유지보수 하기 어려워지는 것이죠. 그런데 패키지를 만들어 쓴다면 해당 패키지만 찾아서 수정을 하면 관련된 코드들을 일일이 수정할 필요가 없겠습니다.
그럼 우선 완성된 코드를 보도록 하겠습니다.
053_excelCompLib4.py
import openpyxl
from openpyxl.styles import PatternFill, Color
class StaticFormExcelCompare():
def __init__(self):
print("__init__")
self.diff_color = "ffff99"
self.big_color = "ffb399"
self.small_color = "99ffb3"
def setColor(self, diff, big, small):
self.diff_color = diff
self.big_color = big
self.small_color = small
def setFiles(self, ori, new, out):
self.wb_ori = openpyxl.load_workbook(ori, data_only=True)
self.wb_new = openpyxl.load_workbook(new, data_only=True)
self.wb_out = out
def run(self):
ws_ori = self.wb_ori.active
mc_ori = ws_ori.max_column
mr_ori = ws_ori.max_row
ws_new = self.wb_new.active
mc_new = ws_new.max_column
mr_new = ws_new.max_row
if mc_new != mc_ori or mr_ori != mr_new:
print("파일의 데이터 개수에 차이가 있습니다.")
return False
for i in range(1, mr_ori+1, 1):
for j in range(1, mc_ori + 1, 1):
if ws_ori.cell(i, j).value !=
ws_new.cell(i, j).value:
ori = ws_ori.cell(i, j).value
new = ws_new.cell(i, j).value
ws_ori.cell(i, j).value
= f"{ws_ori.cell(i, j).value} →” \
“{ws_new.cell(i, j).value}"
if isinstance(ori, str) or
isinstance(new, str):
ws_ori.cell(i, j).fill
= PatternFill(patternType='solid',
fgColor=Color(self.diff_color))
else:
if ori > new:
ws_ori.cell(i, j).fill
= PatternFill(patternType='solid',
fgColor=Color(self.small_color))
else:
ws_ori.cell(i, j).fill
= PatternFill(patternType='solid',
fgColor=Color(self.big_color))
try:
self.wb_ori.save(self.wb_out)
return True
except:
return False
a = StaticFormExcelCompare()
a.setColor('123456', '789ABC','DEF123')
a.setFiles(r".\files\income_state_org.xlsx",
r".\files\income_state_new.xlsx", r".\files\income_state_comp2.xlsx")
if a.run():
print("파일 비교 완료")
else:
print("파일 비교 에러")
import에 Color가 추가 되었습니다. 이것은 PatternFill() 함수를 앞선 코드에서 사용한 방법이 아닌 다른 방법을 사용해 보기 위해서 추가된 것입니다. 기존의 PatternFill()과는 다르게 다음과 같이 사용되고 있습니다.
ws_ori.cell(i, j).fill
= PatternFill(patternType='solid', fgColor=Color(self.big_color))
이젠 우리가 만든 클래스가 어떤 식으로 구성이 되어있는지를 살펴보도록 하겠습니다.
class StaticFormExcelCompare():
def __init__(self):
def setColor(self, diff, big, small):
def setFiles(self, ori, new, out):
def run(self):
우리가 만든 클래스의 이름은 staticFormExcelCompare 입니다. 이 클래스가 들어 있는 파일명이 053_excelCompLib4.py이므로 나중에 이 클래스를 사용하기 위해서 import는 다음과 같습니다.
from 053_excelCompLib4 import StaticFormExcelCompare
클래스 내에 있는 클래스 멤버 함수들은 총 네개가 있습니다. 그 중에서 __init__() 함수는 클래스가 만들어질 때, 자동으로 호출이 되는 함수입니다. 그러면 남는 것은 세개의 함수가 남죠. setColor()는 비교된 셀들의 색상을 지정하기 위한 함수이고, setFile() 함수는 원본, 사본, 그리고 저장할 파일명을 설정하는 함수입니다. 마지막 run() 함수는 비교를 실행하는 것입니다.
그럼 이 클래스는 어떻게 실행을 하는지 실행하는 코드를 먼저 살펴보도록 하겠습니다. 실행 코드는 맨 아래쪽에 있습니다.
a = StaticFormExcelCompare()
a.setColor('123456', '789ABC','DEF123')
a.setFiles(r".\files\income_state_org.xlsx",
r".\files\income_state_new.xlsx", r
".\files\income_state_comp2.xlsx")
if a.run():
print("파일 비교 완료")
else:
print("파일 비교 에러")
이 코드를 보면서 먼저 생각이 난 것은 import 문입니다. StaticFormExcelCompare를 사용하기 위해서 import를 하지 않았습니다. 바로 위에 해당 클래스가 있기 때문이죠. 그럼 import를 하는 것이 어떤 의미인지 이해가 되시나요? import를 하면 해당 내용을 import가 있는 곳으로 복사해 오는 것과 같은 효과를 가진다는 것입니다.
a라는 변수에 StaticFormExcelCompare() 클래스를 생성해 줍니다. 이때 StaticFormExcelCompare() 안에 있는 __init__() 함수가 자동으로 호출이 됩니다. 다음에 setColor() 함수를 호출해서 세 개의 색상 코드를 전달합니다. 다음은 파일 세개를 넘겨주죠.
마지막으로 ru() 함수를 호출해서 True를 반환 받으면 파일 비교가 완료되어 비교가 된 파일이 생성이 된 것이고 False를 받으면 비교가 안되었거나 비교 된 파일이 생성되지 않은 것입니다. 이렇게 우리가 만든 클래스를 사용할 수 있습니다.
이젠 각 함수에 대해서 좀 더 살펴보도록 하겠습니다.
def __init__(self):
print("__init__")
self.diff_color = "ffff99"
self.big_color = "ffb399"
self.small_color = "99ffb3"
__init__() 함수는 클래스가 생성이 될 때, 자동으로 호출이 된다고 말씀드렸습니다. 자동으로 호출되는 이 함수가 언제 호출이 되는지 확인하기 위해서 print() 함수로 __init__을 출력하도록 했습니다. 다음엔 각 컬러에 대한 RGB 값을 넣어 줬습니다. 각 변수에 self가 붙은 변수들은 클래스 내의 어느 함수에서나 불러서 사용을 할 수 있는 변수입니다. 이렇게 클래스 어디서나 불러 쓸 수 있는 함수를 전역변수라고도 합니다. 이에 비해서 함수 내에서 사용되는 변수는 함수가 끝나면 사라지게 됩니다. 이에 비해 전역변수는 클래스가 존재하는 동안 항상 남아 있어 언제나 불러 쓸 수 있습니다. 색상 코드를 클래스가 생성되면 기본색으로 지정을 하는 것입니다. 항상 색상을 넣도록 불러준다면 없어도 되는 내용이긴 합니다. 따라서 우리는 이 클래스를 사용할 때, 색깔을 지정하는 setColor() 함수를 호출해도 되고, 안해도 무방합니다. 왜냐하면 기본 색상이 이미 정해져 있기 때문입니다.
def setColor(self, diff, big, small):
self.diff_color = diff
self.big_color = big
self.small_color = small
setColor() 함수는 self.diff_color, self.big_color, self.small_color를 받은 색깔로 대체를 합니다. 그런데 이미 클래스가 만들어질 때, __init__() 함수에 의해서 이미 초기화가 된 색상이 있으므로 굳이 이 함수를 호출해서 바꿔줄 필요가 없다는 것입니다.
def setFiles(self, ori, new, out):
self.wb_ori = openpyxl.load_workbook(ori, data_only=True)
self.wb_new = openpyxl.load_workbook(new, data_only=True)
self.wb_out = out
반드시 호출하면서 파일들을 지정해 줘야하는 함수입니다. 원본과 비교할 파일 그리고 저장할 파일입니다. 이전 장에서 살펴본 내용과 다른점은 없습니다.
def run(self):
ws_ori = self.wb_ori.active
mc_ori = ws_ori.max_column
mr_ori = ws_ori.max_row
ws_new = self.wb_new.active
mc_new = ws_new.max_column
mr_new = ws_new.max_row
self가 들어간 두 개의 변수 self.wb_ori.active 및 self.wb_new.active 부분이 기존에 있었던 코드와 다른 점입니다. 왜냐하면 self.wb_ori와 self.wb_new는 setFiles() 함수에서 이미 load한 파일이기 때문에 여기서는 글로벌 변수를 이용해 첫번째 워크시트를 각각 가져옵니다.
ws_ori.cell(i, j).fill
= PatternFill(patternType='solid',
fgColor=Color(self.diff_color))
PatternFill() 함수에 의해서 색을 지정하는 부분이 기존에 사용했던 방법과 변경이 되었습니다. 여기서 Color 클래스가 사용이 되어 맨 앞에 import 부분이 변경이 되었습니다. 마지막으로 파일을 저장하는 루틴입니다.
try:
self.wb_ori.save(self.wb_out)
return True
except:
return False
파일을 저장하는 루틴에 예외처리를 하는 try ~ except ~ 문을 사용하였습니다. 대표적으로 이 부분에서 에러가 발생하는 경우는 출력할 파일을 이미 열려 있는 상태에서 이 부분이 실행이 될 때, 에러가 발생합니다. 에러가 발생하면 파일이 생성되지 않으므로 False를 반환하고 문제가 없이 파일이 생성되면 True를 반환합니다.
클래스는 호출이 되어야 실행이 되기 때문에 이 파일에서 실제로 처음 수행되는 코드는 다음과 같습니다.
a = StaticFormExcelCompare()
이 코드의 StaticFormExcelCompare()의 호출에 따라 클래스가 비로소 호출이 되고 생성이 됩니다.
'IT' 카테고리의 다른 글
파이썬 - 구분코드 엑셀 비교 (0) | 2025.02.04 |
---|---|
파이썬 - 엑셀 비교 -GUI와 고정포맷 엑셀파일 연결 (0) | 2025.02.04 |
파이썬 - 고정 포맷 엑셀 비교 (0) | 2025.02.03 |
파이썬 - 입력값 확인, 엑셀 비교 프로젝트 (0) | 2025.02.03 |
파이썬 - 파일 오픈 다이얼로그, 엑셀 비교 프로젝트 (0) | 2025.02.03 |
댓글