- 여러 엑셀 파일을 하나로 자동 통합 - 원본 파일명 추적 기능 - 에러 처리 및 진행 상황 표시 - 샘플 데이터 생성 스크립트 포함 Features: - Support .xlsx, .xls, .xlsm files - Automatic timestamp in output filename - Error handling for corrupted files - Real-time progress display
172 lines
4.7 KiB
Python
172 lines
4.7 KiB
Python
"""
|
||
엑셀 데이터 통합 자동화 프로그램
|
||
Excel Data Merger RPA
|
||
|
||
여러 엑셀 파일을 하나로 자동 통합하는 RPA 프로그램입니다.
|
||
"""
|
||
|
||
import pandas as pd
|
||
import glob
|
||
import os
|
||
from datetime import datetime
|
||
from pathlib import Path
|
||
|
||
|
||
class ExcelMerger:
|
||
"""엑셀 파일 통합 클래스"""
|
||
|
||
def __init__(self, input_folder="input", output_folder="output"):
|
||
"""
|
||
초기화
|
||
|
||
Args:
|
||
input_folder: 입력 엑셀 파일들이 있는 폴더
|
||
output_folder: 통합 파일을 저장할 폴더
|
||
"""
|
||
self.input_folder = input_folder
|
||
self.output_folder = output_folder
|
||
|
||
# 폴더 생성
|
||
Path(input_folder).mkdir(exist_ok=True)
|
||
Path(output_folder).mkdir(exist_ok=True)
|
||
|
||
def get_excel_files(self):
|
||
"""입력 폴더에서 모든 엑셀 파일 찾기"""
|
||
patterns = [
|
||
f"{self.input_folder}/*.xlsx",
|
||
f"{self.input_folder}/*.xls",
|
||
f"{self.input_folder}/*.xlsm"
|
||
]
|
||
|
||
files = []
|
||
for pattern in patterns:
|
||
files.extend(glob.glob(pattern))
|
||
|
||
return files
|
||
|
||
def merge_excel_files(self, output_filename=None):
|
||
"""
|
||
엑셀 파일들을 하나로 통합
|
||
|
||
Args:
|
||
output_filename: 출력 파일명 (기본값: 현재 시간)
|
||
|
||
Returns:
|
||
통합된 DataFrame과 출력 파일 경로
|
||
"""
|
||
excel_files = self.get_excel_files()
|
||
|
||
if not excel_files:
|
||
print(f"⚠️ '{self.input_folder}' 폴더에 엑셀 파일이 없습니다.")
|
||
return None, None
|
||
|
||
print(f"📂 발견된 파일 수: {len(excel_files)}개")
|
||
print("-" * 50)
|
||
|
||
# 모든 데이터를 담을 리스트
|
||
all_data = []
|
||
|
||
# 각 파일 읽기
|
||
for i, file in enumerate(excel_files, 1):
|
||
try:
|
||
filename = os.path.basename(file)
|
||
print(f"{i}. {filename} 읽는 중...")
|
||
|
||
# 엑셀 파일 읽기
|
||
df = pd.read_excel(file)
|
||
|
||
# 원본 파일명 컬럼 추가 (선택사항)
|
||
df['원본파일'] = filename
|
||
|
||
all_data.append(df)
|
||
print(f" ✓ {len(df)}행 읽기 완료")
|
||
|
||
except Exception as e:
|
||
print(f" ✗ 에러 발생: {e}")
|
||
continue
|
||
|
||
if not all_data:
|
||
print("❌ 읽을 수 있는 파일이 없습니다.")
|
||
return None, None
|
||
|
||
# 데이터 통합
|
||
print("\n🔄 데이터 통합 중...")
|
||
merged_df = pd.concat(all_data, ignore_index=True)
|
||
|
||
# 출력 파일명 생성
|
||
if output_filename is None:
|
||
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||
output_filename = f"통합데이터_{timestamp}.xlsx"
|
||
|
||
output_path = os.path.join(self.output_folder, output_filename)
|
||
|
||
# 파일 저장
|
||
print(f"💾 파일 저장 중: {output_path}")
|
||
merged_df.to_excel(output_path, index=False)
|
||
|
||
print("\n" + "=" * 50)
|
||
print("✅ 통합 완료!")
|
||
print(f"📊 총 {len(merged_df)}행 통합됨")
|
||
print(f"📁 저장 위치: {output_path}")
|
||
print("=" * 50)
|
||
|
||
return merged_df, output_path
|
||
|
||
def get_summary(self):
|
||
"""입력 폴더의 파일 정보 요약"""
|
||
files = self.get_excel_files()
|
||
|
||
if not files:
|
||
print("입력 폴더에 엑셀 파일이 없습니다.")
|
||
return
|
||
|
||
print("\n📋 파일 목록:")
|
||
print("-" * 50)
|
||
|
||
total_rows = 0
|
||
for i, file in enumerate(files, 1):
|
||
try:
|
||
filename = os.path.basename(file)
|
||
df = pd.read_excel(file)
|
||
rows = len(df)
|
||
cols = len(df.columns)
|
||
total_rows += rows
|
||
|
||
print(f"{i}. {filename}")
|
||
print(f" - {rows}행 × {cols}열")
|
||
|
||
except Exception as e:
|
||
print(f"{i}. {os.path.basename(file)}")
|
||
print(f" - 에러: {e}")
|
||
|
||
print("-" * 50)
|
||
print(f"총 {len(files)}개 파일, 예상 통합 행 수: {total_rows}행")
|
||
|
||
|
||
def main():
|
||
"""메인 실행 함수"""
|
||
print("=" * 50)
|
||
print("📊 엑셀 데이터 통합 자동화 프로그램")
|
||
print(" Excel Data Merger RPA")
|
||
print("=" * 50)
|
||
print()
|
||
|
||
# ExcelMerger 객체 생성
|
||
merger = ExcelMerger(input_folder="input", output_folder="output")
|
||
|
||
# 파일 요약 출력
|
||
merger.get_summary()
|
||
|
||
print("\n계속하시겠습니까? (y/n): ", end="")
|
||
response = input().strip().lower()
|
||
|
||
if response == 'y':
|
||
# 통합 실행
|
||
merger.merge_excel_files()
|
||
else:
|
||
print("취소되었습니다.")
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|