컴퓨터/Python
python pandas로 기존 xlsm xlsx 파일 수정 vba유지
풍경소리^^
2025. 3. 26. 12:29
deepseek
import pandas as pd
from openpyxl import load_workbook
import os
def update_excel_sheets(file_path, sheet_updates, output_path=None, start_row=0, start_col=0, include_header=False):
"""경로 문제를 해결한 최종 버전"""
# 절대 경로로 변환 (중복 경로 제거)
file_path = os.path.abspath(file_path)
print(f"실제 접근 경로: {file_path}") # 디버깅용 출력
if output_path is None:
output_path = file_path
else:
output_path = os.path.abspath(output_path)
# 확장자 확인
ext = os.path.splitext(file_path)[1].lower()
is_xlsm = (ext == '.xlsm')
try:
# 파일 로드
book = load_workbook(file_path, keep_vba=is_xlsm)
existing_sheets = book.sheetnames
with pd.ExcelWriter(
output_path,
engine='openpyxl',
mode='a',
if_sheet_exists='overlay'
) as writer:
writer._book = book
writer._sheets = {ws.title: ws for ws in book.worksheets}
for sheet_name, df in sheet_updates.items():
if sheet_name not in existing_sheets:
ws = book.create_sheet(sheet_name)
writer._sheets[sheet_name] = ws
else:
ws = book[sheet_name]
# 기존 데이터 삭제 (선택적)
if start_row > 0 or start_col > 0:
for row in ws.iter_rows(min_row=start_row+1, min_col=start_col+1):
for cell in row:
cell.value = None
# 새 데이터 쓰기
df.to_excel(
writer,
sheet_name=sheet_name,
index=False,
startrow=start_row,
startcol=start_col,
header=include_header
)
print(f"파일 저장 완료: {output_path}")
except FileNotFoundError:
print(f"⚠️ 오류: 파일을 찾을 수 없습니다. 경로를 확인하세요.\n{file_path}")
except Exception as e:
print(f"⚠️ 예상치 못한 오류: {str(e)}")
# 사용 예시 (3가지 경로 지정 방법)
# 방법 1: 절대 경로 직접 지정 (추천)
file_path = "test.xlsx"
# file_path = r"B:\python\pandas\pandas_xlsm\test.xlsm"
# 방법 2: os.path.join() 정확한 사용법
# file_path = os.path.join(r"B:\", "python", "pandas", "pandas_xlsm", file_name)
# 방법 3: 상대 경로 사용 시 (작업 디렉토리 확인 필수)
# print("현재 작업 디렉토리:", os.getcwd())
# file_path = os.path.join("python", "pandas", "pandas_xlsm", file_name)
# 데이터프레임 생성
df_new = pd.DataFrame({"A": ['row3col1', 'row4col1', 'row5col1'], "B": ['row3col2', 'row4col2', 'row5col2']})
updates = {"Sheet3": df_new}
# 실행
update_excel_sheets(file_path, updates, start_row=3, start_col=1, include_header=False)
대리점잔액계산.xlsm
import pandas as pd
from openpyxl import load_workbook
from openpyxl.styles import Alignment
import os
def update_excel_sheets(file_path, sheet_updates, output_path=None, start_row=0, start_col=0, include_header=False):
"""숫자 오른쪽 정렬이 적용된 최종 버전"""
# 절대 경로로 변환
file_path = os.path.abspath(file_path)
print(f"실제 접근 경로: {file_path}")
if output_path is None:
output_path = file_path
else:
output_path = os.path.abspath(output_path)
# 확장자 확인
ext = os.path.splitext(file_path)[1].lower()
is_xlsm = (ext == '.xlsm')
try:
# 파일 로드
book = load_workbook(file_path, keep_vba=is_xlsm)
existing_sheets = book.sheetnames
with pd.ExcelWriter(
output_path,
engine='openpyxl',
mode='a',
if_sheet_exists='overlay'
) as writer:
writer._book = book
writer._sheets = {ws.title: ws for ws in book.worksheets}
for sheet_name, df in sheet_updates.items():
if sheet_name not in existing_sheets:
ws = book.create_sheet(sheet_name)
writer._sheets[sheet_name] = ws
else:
ws = book[sheet_name]
if start_row > 0 or start_col > 0:
for row in ws.iter_rows(min_row=start_row+1, min_col=start_col+1):
for cell in row:
cell.value = None
# 데이터 쓰기
df.to_excel(
writer,
sheet_name=sheet_name,
index=False,
startrow=start_row,
startcol=start_col,
header=include_header
)
# 스타일 적용
ws = writer.sheets[sheet_name]
# right_align = Alignment(horizontal='right')
# 숫자 컬럼 오른쪽 정렬
# numeric_cols = ['입금예정액', '입금액', '잔액']
# for col_name in numeric_cols:
# if col_name in df.columns:
# col_idx = df.columns.get_loc(col_name) + 1 # 1-based index
# for row in range(start_row + 1, start_row + len(df) + 1):
# ws.cell(row=row, column=col_idx).alignment = right_align
# 날짜 형식 및 정렬
date_cols = ['기간마침', '실제입금일']
for col_name in date_cols:
if col_name in df.columns:
col_idx = df.columns.get_loc(col_name) + 1
for row in range(start_row + 1, start_row + len(df) + 1):
cell = ws.cell(row=row, column=col_idx)
cell.number_format = 'yyyy-mm-dd'
# cell.alignment = right_align
print(f"파일 저장 완료: {output_path}")
except FileNotFoundError:
print(f"⚠️ 오류: 파일을 찾을 수 없습니다. 경로를 확인하세요.\n{file_path}")
except Exception as e:
print(f"⚠️ 예상치 못한 오류: {str(e)}")
# 사용 예시
file_path = "대리점잔액계산.xlsm"
sheet_name = "대리점입금관리"
try:
# 데이터 읽기
df = pd.read_excel(file_path, sheet_name=sheet_name)
# 데이터 전처리
df['입금예정액'] = df['입금예정액'].fillna(0).astype('int')
df['입금액'] = df['입금액'].fillna(0).astype('int')
df['잔액'] = df.groupby('지점')['입금예정액'].cumsum() - df.groupby('지점')['입금액'].cumsum()
# 날짜 처리
df['기간마침'] = pd.to_datetime(df['기간마침'], errors='coerce')
df['실제입금일'] = pd.to_datetime(df['실제입금일'], errors='coerce').fillna(pd.Timestamp('1900-01-01'))
# 숫자 포맷 (콤마 표시)
# for col in ['입금예정액', '입금액', '잔액']:
# df[col] = df[col].apply(lambda x: f"{x:,}")
# 함수 실행
update_excel_sheets(
file_path=file_path,
sheet_updates={sheet_name: df},
start_row=1,
start_col=0,
include_header=False
)
except FileNotFoundError:
print(f"파일을 찾을 수 없습니다: {file_path}")
except Exception as e:
print(f"오류 발생: {str(e)}")