import pandas as pd
from openpyxl import load_workbook
import time
from datetime import datetime
import os
from openpyxl.utils import get_column_letter as column_letter
start_time = time.perf_counter()
# 상수 정의
SOURCE_FILE = r"G:\회사\인사\급여\2025급여\202502\2025년02월급여준비.xlsm"
TARGET_FILE = r"G:\회사\인사\급여\★급여대장이메일-현재test.xlsm"
SOURCE_SHEET = "4대급여"
TARGET_SHEET = "4대급여"
PAYSTUB_SHEET = "급여명세서사대보험"
# 파일 경로 확인
for file_path in [SOURCE_FILE, TARGET_FILE]:
if not os.path.exists(file_path):
raise FileNotFoundError(f"파일을 찾을 수 없습니다: {file_path}")
# ✅ 1️⃣ 원본 파일 읽기 및 처리
df = pd.read_excel(SOURCE_FILE, sheet_name=SOURCE_SHEET).fillna(0).rename(columns={'지급일': '년월'})
wb_source = load_workbook(SOURCE_FILE, data_only=True)
if SOURCE_SHEET not in wb_source.sheetnames:
raise ValueError(f"시트 '{SOURCE_SHEET}'이(가) {SOURCE_FILE}에 없습니다!")
ws_source = wb_source[SOURCE_SHEET]
b2_value = ws_source["B2"].value
wb_source.close()
if not isinstance(b2_value, datetime):
raise ValueError(f"B2 셀의 값이 날짜 형식이 아닙니다! 현재 값: {b2_value}")
year_month = int(b2_value.strftime("%Y%m"))
df['년월'] = year_month
df['사원코드'] = "임시"
# ✅ 2️⃣ 대상 파일 업데이트
wb_target = load_workbook(TARGET_FILE, keep_vba=True)
ws_target = wb_target[TARGET_SHEET]
ws_paystub = wb_target[PAYSTUB_SHEET]
if ws_target.max_row > 1:
ws_target.delete_rows(2, ws_target.max_row)
ws_paystub["I2"] = year_month
ws_paystub["I3"] = b2_value.strftime("%Y-%m-%d")
for row in df.to_numpy().tolist(): # NumPy 배열을 리스트로 변환
ws_target.append(row)
# ✅ 3️⃣ 카운터 열 추가
header = [cell.value for cell in ws_target[1]]
if "카운터" in header:
counter_col = header.index("카운터") + 1
for i, row_idx in enumerate(range(2, ws_target.max_row + 1), start=1):
ws_target.cell(row=row_idx, column=counter_col, value=i)
# ✅ 4️⃣ 저장
try:
wb_target.save(TARGET_FILE)
except Exception as e:
print(f"❌ 파일 저장 실패: {e}")
raise
finally:
wb_target.close()
print("✅ 실행 완료! ⏳ 실행 시간:", round(time.perf_counter() - start_time, 2), "초")
차선책 xlsx로 저장하기
import pandas as pd
from openpyxl import load_workbook
# 기존 xlsm 파일 경로
xlsm_file_path = "./python_xlsm.xlsm"
# 새로운 xlsx 파일 경로
xlsx_file_path = "./python_xlsx.xlsx"
# 저장할 데이터프레임 생성
data = {
"이름": ["to_excel", "이영희", "박민수"],
"나이": [1, 30, 28],
"부서": ["pandas", "개발", "마케팅"]
}
df = pd.DataFrame(data)
# 기존 xlsm 파일 불러오기 (VBA 매크로 없이)
wb = load_workbook(xlsm_file_path, keep_vba=False)
# 📌 "main" 시트 선택 & 기존 데이터 삭제
ws = wb["main"]
if ws.max_row >= 4:
ws.delete_rows(4, ws.max_row - 3)
# 📌 새로운 xlsx 파일이 없으면 저장 (다른 시트 유지)
wb.save(xlsx_file_path)
# 📌 df.to_excel()을 사용하여 A4부터 데이터 입력
with pd.ExcelWriter(xlsx_file_path, engine="openpyxl", mode="a", if_sheet_exists="overlay") as writer:
df.to_excel(writer, sheet_name="main", startrow=3, startcol=0, index=False, header=False)
print(f"저장 완료: {xlsx_file_path}")
# xlsx 파일로 저장 잘됨
vba 모듈을 별도로 백업
xlsx파일에 포함시켜 xlsm파일로 저장 - qwen
import os
import win32com.client as win32
def backup_vba_module(xlsm_file, backup_folder):
"""
.xlsm 파일의 VBA 모듈을 백업합니다.
:param xlsm_file: 원본 .xlsm 파일 경로
:param backup_folder: 백업할 폴더 경로
"""
if not os.path.isfile(xlsm_file):
raise FileNotFoundError(f"지정된 파일을 찾을 수 없습니다: {xlsm_file}")
excel = win32.Dispatch("Excel.Application")
excel.Visible = False
excel.DisplayAlerts = False
workbook = None
try:
# .xlsm 파일 열기
workbook = excel.Workbooks.Open(os.path.abspath(xlsm_file))
# VBA 프로젝트 접근
vba_project = workbook.VBProject
# 백업 폴더가 없으면 생성
if not os.path.exists(backup_folder):
os.makedirs(backup_folder)
# 각 모듈 백업
for i in range(1, vba_project.VBComponents.Count + 1):
component = vba_project.VBComponents.Item(i)
module_name = component.Name
# 모듈 유형 확인 (표준 모듈만 처리)
if component.Type == 1: # 1: vbext_ct_StdModule (표준 모듈)
code_module = component.CodeModule
if code_module.CountOfLines > 0: # 비어 있지 않은 모듈만 처리
module_code = code_module.Lines(1, code_module.CountOfLines)
# 백업 파일로 저장
backup_file = os.path.join(backup_folder, f"{module_name}.bas")
with open(backup_file, "w", encoding="utf-8") as f:
f.write(module_code)
print(f"'{module_name}' 모듈이 백업되었습니다.")
else:
print(f"'{module_name}' 모듈은 비어 있어 건너뜁니다.")
else:
print(f"'{module_name}'은 표준 모듈이 아니므로 건너뜁니다.")
print(f"모든 VBA 모듈이 '{backup_folder}'에 백업되었습니다.")
finally:
if workbook:
workbook.Close(SaveChanges=False)
excel.Quit()
def insert_vba_module_into_xlsx(xlsx_file, backup_folder, output_xlsm_file):
"""
백업된 VBA 모듈을 .xlsx 파일에 삽입하고 .xlsm 파일로 저장합니다.
:param xlsx_file: 대상 .xlsx 파일 경로
:param backup_folder: 백업된 VBA 모듈이 있는 폴더 경로
:param output_xlsm_file: 결과로 저장될 .xlsm 파일 경로
"""
if not os.path.isfile(xlsx_file):
raise FileNotFoundError(f"지정된 파일을 찾을 수 없습니다: {xlsx_file}")
if not os.path.exists(backup_folder):
raise FileNotFoundError(f"백업 폴더를 찾을 수 없습니다: {backup_folder}")
excel = win32.Dispatch("Excel.Application")
excel.Visible = False
excel.DisplayAlerts = False
workbook = None
try:
# .xlsx 파일 열기
workbook = excel.Workbooks.Open(os.path.abspath(xlsx_file))
# VBA 프로젝트 접근
vba_project = workbook.VBProject
# 백업된 모듈 파일 목록 가져오기
for module_file in os.listdir(backup_folder):
if module_file.endswith(".bas"):
module_name = os.path.splitext(module_file)[0]
module_path = os.path.join(backup_folder, module_file)
# 모듈 코드 읽기
with open(module_path, "r", encoding="utf-8") as f:
module_code = f.read()
# 새 모듈 추가
new_component = vba_project.VBComponents.Add(1) # 1: vbext_ct_StdModule
new_component.Name = module_name
new_component.CodeModule.AddFromString(module_code)
# 결과 파일 저장 (.xlsm 형식으로)
workbook.SaveAs(output_xlsm_file, FileFormat=52) # 52: xlOpenXMLWorkbookMacroEnabled
print(f"VBA 모듈이 삽입된 파일이 '{output_xlsm_file}'로 저장되었습니다.")
finally:
if workbook:
workbook.Close(SaveChanges=False)
excel.Quit()
# 예제 사용
if __name__ == "__main__":
# 현재 디렉터리의 절대 경로를 기준으로 파일 경로 설정
current_dir = os.getcwd()
# 원본 .xlsm 파일 경로
xlsm_file = os.path.join(current_dir, "python_xlsm.xlsm")
# 백업 폴더 경로
backup_folder = os.path.join(current_dir, "backup")
# 대상 .xlsx 파일 경로
xlsx_file = os.path.join(current_dir, "python_xlsx.xlsx")
# 결과 .xlsm 파일 경로
output_xlsm_file = os.path.join(current_dir, "output_with_vba.xlsm")
# 1. VBA 모듈 백업
backup_vba_module(xlsm_file, backup_folder)
# 2. VBA 모듈 삽입 및 .xlsm 파일로 저장
insert_vba_module_into_xlsx(xlsx_file, backup_folder, output_xlsm_file)
'컴퓨터 > Python' 카테고리의 다른 글
python pandas로 기존 xlsm xlsx 파일 수정 vba유지 (0) | 2025.03.26 |
---|---|
국민연금 월불입액 파일 손상된 파일 xlsx로 정상적으로 저장하는 코드 (0) | 2025.03.25 |
python pandas 간이세액표 merge_asof (0) | 2025.01.14 |
python pyside6 exceltoexcel modify same file same sheet (0) | 2025.01.10 |
python 구구단 dataframe 저장 (0) | 2025.01.02 |