138 lines
5.0 KiB
Markdown
138 lines
5.0 KiB
Markdown
---
|
||
name: csv-to-xlsx
|
||
label: CSV → Excel 변환
|
||
description: CSV 파일을 서식이 완성된 Excel(.xlsx)로 변환합니다. 헤더 고정, 필터, 조건부 서식, 자동 열 너비를 적용합니다.
|
||
icon: \uE9F9
|
||
allowed-tools:
|
||
- folder_map
|
||
- file_read
|
||
- file_write
|
||
- process
|
||
- format_convert
|
||
- data_pivot
|
||
- template_render
|
||
tabs: cowork
|
||
---
|
||
|
||
CSV 파일을 전문적인 서식이 적용된 Excel 파일로 변환하세요.
|
||
## 실행 경로 선택 (Python 가능/불가)
|
||
- 먼저 `process`로 `python --version`을 확인하세요.
|
||
- Python 가능: 기존 Python 스크립트 경로로 변환/서식 자동화를 수행하세요.
|
||
- Python 불가: `format_convert`로 CSV를 XLSX로 변환하고, `data_pivot`으로 핵심 요약 시트를 구성한 뒤 `file_write`로 사용 안내를 남기세요.
|
||
|
||
|
||
## 사전 준비
|
||
먼저 필요한 패키지가 설치되어 있는지 확인하고, 없으면 설치하세요:
|
||
```
|
||
process: pip install openpyxl pandas
|
||
```
|
||
|
||
## 작업 절차
|
||
|
||
1. **파일 확인**: folder_map으로 작업 폴더에서 CSV 파일을 탐색
|
||
2. **CSV 분석**: file_read로 CSV 파일의 구조(컬럼, 행 수, 인코딩, 구분자) 파악
|
||
3. **변환 옵션 확인**: 사용자에게 다음 옵션을 확인
|
||
- 헤더 행 고정 여부 (기본: 활성)
|
||
- 자동 필터 적용 여부 (기본: 활성)
|
||
- 조건부 서식 대상 컬럼 (숫자 컬럼 자동 감지)
|
||
- 시트 이름 (기본: 파일명)
|
||
4. **Python 스크립트 작성**: file_write로 변환 스크립트 생성
|
||
5. **스크립트 실행**: `process`로 Python 스크립트 실행
|
||
6. **결과 확인**: 생성된 .xlsx 파일 경로와 요약 정보를 안내
|
||
|
||
## Python 스크립트 템플릿
|
||
```python
|
||
import pandas as pd
|
||
from openpyxl import load_workbook
|
||
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
|
||
from openpyxl.utils import get_column_letter
|
||
from openpyxl.formatting.rule import CellIsRule
|
||
|
||
# CSV 읽기 (인코딩 자동 감지)
|
||
for enc in ['utf-8', 'cp949', 'euc-kr', 'utf-8-sig']:
|
||
try:
|
||
df = pd.read_csv('input.csv', encoding=enc)
|
||
break
|
||
except (UnicodeDecodeError, Exception):
|
||
continue
|
||
|
||
# Excel 저장
|
||
output_path = 'output.xlsx'
|
||
df.to_excel(output_path, index=False, sheet_name='Sheet1')
|
||
|
||
# 서식 적용
|
||
wb = load_workbook(output_path)
|
||
ws = wb.active
|
||
|
||
# 헤더 스타일
|
||
header_font = Font(bold=True, color='FFFFFF', size=11)
|
||
header_fill = PatternFill(start_color='4472C4', end_color='4472C4', fill_type='solid')
|
||
header_align = Alignment(horizontal='center', vertical='center', wrap_text=True)
|
||
thin_border = Border(
|
||
left=Side(style='thin'),
|
||
right=Side(style='thin'),
|
||
top=Side(style='thin'),
|
||
bottom=Side(style='thin')
|
||
)
|
||
|
||
for col_idx, cell in enumerate(ws[1], 1):
|
||
cell.font = header_font
|
||
cell.fill = header_fill
|
||
cell.alignment = header_align
|
||
cell.border = thin_border
|
||
|
||
# 자동 열 너비
|
||
for col_idx in range(1, ws.max_column + 1):
|
||
max_length = 0
|
||
col_letter = get_column_letter(col_idx)
|
||
for row in ws.iter_rows(min_col=col_idx, max_col=col_idx):
|
||
for cell in row:
|
||
if cell.value:
|
||
max_length = max(max_length, len(str(cell.value)))
|
||
ws.column_dimensions[col_letter].width = min(max_length + 4, 50)
|
||
|
||
# 헤더 행 고정 (Freeze Panes)
|
||
ws.freeze_panes = 'A2'
|
||
|
||
# 자동 필터
|
||
ws.auto_filter.ref = ws.dimensions
|
||
|
||
# 숫자 컬럼 조건부 서식 (음수 빨강)
|
||
for col_idx in range(1, ws.max_column + 1):
|
||
col_letter = get_column_letter(col_idx)
|
||
sample_values = [ws.cell(row=r, column=col_idx).value for r in range(2, min(ws.max_row + 1, 12))]
|
||
if any(isinstance(v, (int, float)) for v in sample_values if v is not None):
|
||
cell_range = f'{col_letter}2:{col_letter}{ws.max_row}'
|
||
ws.conditional_formatting.add(cell_range,
|
||
CellIsRule(operator='lessThan', formula=['0'],
|
||
font=Font(color='FF0000')))
|
||
|
||
# 데이터 행 줄무늬 (가독성)
|
||
light_fill = PatternFill(start_color='D9E2F3', end_color='D9E2F3', fill_type='solid')
|
||
for row_idx in range(2, ws.max_row + 1):
|
||
for col_idx in range(1, ws.max_column + 1):
|
||
cell = ws.cell(row=row_idx, column=col_idx)
|
||
cell.border = thin_border
|
||
if row_idx % 2 == 0:
|
||
cell.fill = light_fill
|
||
|
||
wb.save(output_path)
|
||
print(f'변환 완료: {output_path} ({ws.max_row - 1}행 × {ws.max_column}열)')
|
||
```
|
||
|
||
## 서식 옵션
|
||
- **헤더 스타일**: 파란 배경 + 흰색 굵은 글씨 + 가운데 정렬
|
||
- **줄무늬**: 짝수 행 연한 파랑 배경 (가독성 향상)
|
||
- **열 너비**: 내용 기준 자동 조정 (최대 50)
|
||
- **조건부 서식**: 숫자 컬럼 음수 빨강 표시
|
||
- **Freeze Panes**: 헤더 행 고정
|
||
- **Auto Filter**: 전체 컬럼 필터 활성화
|
||
|
||
## 규칙
|
||
- 원본 CSV 파일은 수정하지 않음
|
||
- 인코딩 자동 감지 (UTF-8 → CP949 → EUC-KR 순)
|
||
- 대용량 파일 (100,000행 이상) 경고 후 진행
|
||
- 출력 파일명: 원본 파일명 기준 (.csv → .xlsx)
|
||
|
||
한국어로 안내하세요. 작업 폴더에 Python 스크립트와 결과 파일을 저장하세요.
|