컴퓨터/Python

엑셀투파이썬 python xls xlsx pandas dataframe 특정범위 지우기, 특정범위 덮어쓰기

풍경소리^^ 2023. 10. 25. 16:25

참고 데이터 엑셀투파이썬 

https://www.youtube.com/watch?v=PLimrYVDhvE&list=PLrpXwtuxGqcJ03uulbSY3CEUK_n6ySb2t

 

단점

특정범위의 양식은 지워짐

module이 있었다면 지워짐

01vlookup.xls
0.01MB
01vlookup.xlsx
0.01MB
pandas_exceltopython003.py
0.01MB

import pandas as pd
import os
import xlrd
import openpyxl
from openpyxl.utils.cell import column_index_from_string  # 엑셀 열 이름을 숫자로 변환
from openpyxl.utils import get_column_letter  # 숫자를 엑셀 열 이름으로 변환
import xlwt  # xlwt는 .xls 파일을 수정하기 위해 사용합니다.
from xlutils.copy import copy  # xlutils를 사용하여 기존 .xls 파일 복사

FILE = "01vlookup.xls"  # .xls 파일 경로
# FILE = "01vlookup.xlsx"  # .xlsx 파일 경로
SOURCE_SH = "Sheet1"
COL_START = "A"
COL_END = "B"

# 파일 확장자 확인
file_ext = os.path.splitext(FILE)[1]  # 확장자만 추출 (.xls 또는 .xlsx)

COUNT_SKIPROW = 0  # 초기화

if file_ext == '.xls':
    # .xls 파일 처리 (xlrd 엔진 사용)
    wb = xlrd.open_workbook(FILE)
    ws = wb.sheet_by_name(SOURCE_SH)

    # "이름"이 나올 때까지 카운트
    for row in range(ws.nrows):  # 총 행 수 만큼 반복
        if ws.cell_value(row, 0) == "이름":  # 첫 번째 열에서 "이름" 확인
            break
        COUNT_SKIPROW += 1  # "이름"이 나오기 전까지 카운트

    # DataFrame 생성
    df1 = pd.read_excel(FILE, sheet_name=SOURCE_SH,
                        header=COUNT_SKIPROW,
                        usecols=f"{COL_START}:{COL_END}",
                        engine='xlrd')

elif file_ext == '.xlsx':
    # .xlsx 파일 처리 (openpyxl 엔진 사용)
    FIND_COL = "A"
    FIND_TITLE = "이름"
    COUNT_SKIPROW = 0  # 초기화

    wb = openpyxl.load_workbook(FILE)  # 워크북 객체 생성
    ws = wb[SOURCE_SH]  # 시트 객체 생성
    for row in ws.iter_rows(min_col=column_index_from_string(FIND_COL), max_col=column_index_from_string(FIND_COL)):  # A열만 확인
        if row[0].value == FIND_TITLE:  # "이름"이 있는지 확인
            break
        COUNT_SKIPROW += 1  # "이름"이 나오기 전까지 카운트

    df1 = pd.read_excel(FILE, sheet_name=SOURCE_SH,
                        header=COUNT_SKIPROW,
                        usecols=f"{COL_START}:{COL_END}",
                        engine='openpyxl')

else:
    raise ValueError("지원하지 않는 파일 형식입니다. .xls 또는 .xlsx 파일을 사용하십시오.")

# skiprow 구하기 - 데이터 없는 행 갯수 - 무시해야 할 행 갯수
FIND_COL = "F"
FIND_TITLE = "제품"
COUNT_SKIPROW = 0  # 초기화

if file_ext == '.xls':
    for row in range(ws.nrows):
        if ws.cell_value(row, 5) == FIND_TITLE:  # F열에서 "제품" 확인 (열 인덱스는 0부터 시작)
            break
        COUNT_SKIPROW += 1

else:
    for row in ws.iter_rows(min_col=column_index_from_string(FIND_COL), max_col=column_index_from_string(FIND_COL)):  # F열만 확인
        if row[0].value == FIND_TITLE:  # "제품"이 있는지 확인
            break
        COUNT_SKIPROW += 1

# 데이터 갯수 세기
DATA_MAXROW = COUNT_SKIPROW  # 초기값 = 0

if file_ext == '.xls':
    for row in range(COUNT_SKIPROW + 1, ws.nrows):
        if ws.cell_value(row, 5) is not None:  # F열에서 값 확인
            DATA_MAXROW += 1
        else:
            break
else:
    for cell in ws[FIND_COL][COUNT_SKIPROW + 1:]:  # 제목행이 있으니까 +1
        if cell.value is not None:
            DATA_MAXROW += 1
        else:
            break

DATA_ROW_COUNT = DATA_MAXROW - COUNT_SKIPROW  # 전체 데이터 갯수

# df2 데이터 생성 ################################
COL_START = "F"
COL_END = "G"
COL_TITLE_NAME = ['제품', '가격']

if file_ext == '.xls':
    df2 = pd.read_excel(FILE, sheet_name=SOURCE_SH,
                        header=0,
                        names=COL_TITLE_NAME,
                        index_col=None,
                        usecols=f"{COL_START}:{COL_END}",
                        skiprows=COUNT_SKIPROW,
                        engine='xlrd')
else:
    df2 = pd.read_excel(FILE, sheet_name=SOURCE_SH,
                        header=0,
                        names=COL_TITLE_NAME,
                        index_col=None,
                        usecols=f"{COL_START}:{COL_END}",
                        skiprows=COUNT_SKIPROW)

# df3 데이터 병합 ################################
COL_STANDARD_NAME = "제품"
JOIN_HOW = "left"
df3 = df1.merge(df2, on=COL_STANDARD_NAME, how=JOIN_HOW)

# 가격을 정수형으로 변환
df3['가격'] = df3['가격'].astype(int)

# 특정 범위 지우기 ########################################
COL_START = "J"
COL_END = "L"
START_ROW = 4  # 제목열 타이핑 되어있는 상태 - 데이터 시작행 0,1,2,3,4,5

if file_ext == '.xls':
    # xlrd로 파일 열기
    wb = xlrd.open_workbook(FILE, formatting_info=True)  # 포맷 정보를 가져오기
    ws = wb.sheet_by_name(SOURCE_SH)
    
    # 수정할 Workbook 생성
    new_wb = copy(wb)  # 기존 워크북 복사
    new_ws = new_wb.get_sheet(0)  # 첫 번째 시트 가져오기
    
    # 데이터 지우기
    for column_letter in range(column_index_from_string(COL_START), column_index_from_string(COL_END) + 1):
        for row in range(START_ROW, ws.nrows):  # START_ROW부터 끝까지 반복
            new_ws.write(row, column_letter - 1, '')  # 값을 빈 문자열로 설정하여 지우기

    # 수정된 파일 저장
    new_wb.save(FILE)
    
elif file_ext == ".xlsx":
    for column_letter in range(column_index_from_string(COL_START), column_index_from_string(COL_END) + 1): # 10,11,12
        column_cells = ws[get_column_letter(column_letter)][START_ROW:] # 10열 전체, 11열 전체, 12열 전체
        
        # 열 범위의 모든 셀을 확인하고 데이터가 있는 경우 삭제
        for cell in column_cells:
            if cell.value is not None:
                cell.value = None
    #             cell.fill = openpyxl.styles.PatternFill(fill_type='solid', fgColor=Color('FFFF00'))
    #             cell.fill = openpyxl.styles.PatternFill(fill_type=None)

    # 지운 내용을 파일에 저장
    wb.save(FILE)
    # 파일 닫기
    wb.close()

else:
    raise ValueError("지원하지 않는 파일 형식입니다.")

# 최종 파일 저장 특정 범위에 쓰기
if file_ext == '.xls':
    # .xls 파일 처리 (xlrd와 xlwt 사용)
    wb = xlrd.open_workbook(FILE, formatting_info=True)  # 포맷 정보를 가져오기
    new_wb = copy(wb)  # 기존 워크북 복사
    new_ws = new_wb.get_sheet(0)  # 첫 번째 시트 가져오기

    # df3의 데이터를 새로운 위치에 쓰기
    for row_idx, row in df3.iterrows():
        for col_idx, value in enumerate(row):
            new_ws.write(START_ROW + row_idx, column_index_from_string(COL_START) - 1 + col_idx, value)

    # 수정된 파일 저장
    new_wb.save(FILE)
    # new_wb.close()

elif file_ext == '.xlsx':
    # .xlsx 파일 처리 (openpyxl 사용)
    with pd.ExcelWriter(FILE, mode='a', engine='openpyxl', if_sheet_exists='overlay') as w:
        df3.to_excel(w, sheet_name=SOURCE_SH, index=False, header=False,
                     startcol=column_index_from_string(COL_START) - column_index_from_string("A"),
                     startrow=START_ROW)  # 제목열 제외하고 데이터 시작행 0,1,2,3,4,5
else:
    raise ValueError("지원하지 않는 파일 형식입니다. .xls 또는 .xlsx 파일을 사용하십시오.")