Python과 Claude를 활용한 엑셀 (견적서) 자동화 프로젝트

배경 및 목적

1. 프로젝트 개요

  • 목적: B2B 견적서 작성 프로세스 자동화

  • 배경: 한국 아동복 회사 해외영업 담당

  • 문제점: 수동 견적서 작성에 많은 시간 소요

  • 목표: 업무 효율성 향상 및 시간 절약

2. 개발 환경 설정

2.1 GitHub 저장소 생성

  1. GitHub 계정에 로그인

  2. 새 저장소(repository) 생성

    • 저장소 이름: "excel-quotation-automation"

    • README 파일 추가 선택

    • .gitignore 템플릿으로 Python 선택

  3. 저장소 URL 복사

1. 개발 환경 설정

1.1 GitHub 저장소 생성

2. GitHub 계정에 로그인
2.1 새 저장소(repository) 생성

- 저장소 이름: "excel-quotation-automation"

- README 파일 추가 선택

- .gitignore 템플릿으로 Python 선택

2.2 로컬 환경에 Git 저장소 복제

  1. 원하는 위치에 폴더 생성 (예: C:\Projects)

  2. PowerShell 실행

  3. 생성한 폴더로 이동:

    Copy

    cd C:\Projects

  4. Git 저장소 복제:

    Copy

    git clone https://github.com/your-username/excel-quotation-automation.git

  5. 복제된 폴더로 이동:

    Copy

    cd excel-quotation-automation

2.3 Python 가상 환경 설정

  1. 가상 환경 생성:

    Copy

    python -m venv venv

  2. 가상 환경 활성화:

    • Windows:

      Copy

      .\venv\Scripts\Activate

    • macOS/Linux:

      Copy

      source venv/bin/activate

  3. 필요한 패키지 설치:

    Copy

    pip install pandas openpyxl

2.4 VS Code 설정

  1. VS Code 실행

  2. 'File' > 'Open Folder'에서 프로젝트 폴더 선택

  3. Python 확장 프로그램 설치 (아직 설치되지 않은 경우)

  4. 좌측 하단의 Python 인터프리터 선택에서 가상 환경 선택

3. 코드 개발 및 실행

3.1 Python 스크립트 작성

  1. VS Code에서 새 파일 생성: quotation_automation.py

  2. Claude AI와의 대화를 통해 생성된 코드를 파일에 붙여넣기

  3. 코드 저장

3.2 코드 실행

  1. VS Code 터미널 열기 (Ctrl+`)

  2. 가상 환경이 활성화되어 있는지 확인

  3. 스크립트 실행:

    Copy

    python quotation_automation.py

3.3 결과 확인

  1. 생성된 엑셀 파일 확인:

    • 정리된_데이터_최종.xlsx

    • 필터링된_데이터.xlsx

    • 각 제품 카테고리별 데이터 및 견적서 파일

4. 버전 관리 및 협업

4.1 변경사항 커밋

  1. 변경된 파일 스테이징:

    Copy

    git add .

  2. 변경사항 커밋:

    Copy

    git commit -m "엑셀 견적서 자동화 스크립트 추가"

4.2 GitHub에 푸시

  1. 변경사항을 GitHub에 업로드:

    Copy

    git push origin main

5. 프로젝트 관리 및 향후 계획

5.1 기대 효과

  • 견적서 작성 시간 대폭 감소

  • 인적 오류 최소화

  • 일관된 형식의 견적서로 전문성 향상

  • 신속한 맞춤 견적서 제공으로 고객 만족도 증가

5.2 향후 계획

  • 코드 최적화 및 기능 개선 (예: 번역, 이미지 통합)

  • 다른 반복 업무에 대한 자동화 확대 적용 검토

6. 트러블슈팅 및 팁


def process_data(input_file, output_file1, output_file2):

# 엑셀 파일 읽기

df = pd.read_excel(input_file, sheet_name='현재고조회')

# 옵션 분리 함수

def split_options(option):

parts = str(option).split(':')

color = ' '.join([p.strip() for p in parts if not p.isdigit() and 'free' not in p.lower()])

size = ' '.join([p.strip() for p in parts if p.isdigit() or 'free' in p.lower()])

return pd.Series([color, size])

# 카테고리 분리 함수

def split_categories(category):

parts = str(category).split('>')

return pd.Series([parts[0].strip() if len(parts) > 0 else '',

parts[1].strip() if len(parts) > 1 else ''])

# 옵션과 카테고리 분리

df[['컬러', '사이즈']] = df['옵션'].apply(split_options)

df[['복종', '제품류']] = df['카테고리'].apply(split_categories)

# 컬러 칸에서 쉼표(,) 삭제

df['컬러'] = df['컬러'].str.replace(',', '')

# 열 순서 재정렬 (파일 1)

columns1 = ['상품코드', '상품명', '컬러', '사이즈', '판매가', '원산지', '복종', '제품류',

'공급처상품명', '바코드', '가용재고', '이미지URL', '원가', '시중가',

'등록일', '시즌', '로케이션', '복종', '카페24상품코드']

df1 = df.reindex(columns=columns1)

# 파일 1 저장

df1.to_excel(output_file1, index=False, sheet_name='정리된 데이터')

print(f"처리 완료: {output_file1}에 '정리된 데이터'가 저장되었습니다.")

# 파일 2를 위한 데이터 준비

selected_columns = ['상품코드', '상품명', '컬러', '사이즈', '판매가', '원산지',

'제품류', '공급처상품명', '바코드', '가용재고', '이미지URL',

'시중가', '시즌']

df2 = df[selected_columns].copy()

df2.rename(columns={'공급처상품명': '품범', '상품명': '상품명(KR)'}, inplace=True)

# 열 순서 재정렬 (파일 2)

columns2 = ['상품코드', '상품명(KR)', '품범', '바코드', '제품류', '원산지',

'컬러', '사이즈', '판매가', '가용재고', '시중가', '이미지URL', '시즌']

df2 = df2.reindex(columns=columns2)

# 파일 2 저장

df2.to_excel(output_file2, index=False, sheet_name='필터링된 데이터')

print(f"처리 완료: {output_file2}에 '필터링된 데이터'가 저장되었습니다.")

# 제품류 리스트 및 필터링 조건

product_types = {

'24_new_list': df2[df2['품범'].str.startswith(('O45', 'O47'), na=False)],

'원피스(D)': df2[(df2['제품류'] == '원피스(D)') & (df2['품범'].str.startswith(('O45', 'O47', 'O41', 'O43', 'O31', 'O33', 'O35', 'O37'), na=False))],

'상의(T)': df2[(df2['제품류'] == '상의(T)') & (df2['품범'].str.startswith(('O45', 'O47', 'O41', 'O43', 'O31', 'O33', 'O35', 'O37'), na=False))],

'하의(P)': df2[(df2['제품류'] == '하의(P)') & (df2['품범'].str.startswith(('O45', 'O47', 'O41', 'O43', 'O31', 'O33', 'O35', 'O37'), na=False))],

'아우터(O)': df2[(df2['제품류'] == '아우터(O)') & (df2['품범'].str.startswith(('O45', 'O47', 'O41', 'O43', 'O31', 'O33', 'O35', 'O37'), na=False))],

'세트(C)': df2[(df2['제품류'] == '세트(C)') & (df2['품범'].str.startswith(('O45', 'O47', 'O41', 'O43', 'O31', 'O33', 'O35', 'O37'), na=False))],

'구두(S)': df2[(df2['제품류'] == '구두(S)') & (df2['품범'].str.startswith(('O45', 'O47', 'O41', 'O43', 'O31', 'O33', 'O35', 'O37'), na=False))],

'슬립온(N)': df2[(df2['제품류'] == '슬립온(N)') & (df2['품범'].str.startswith(('O45', 'O47', 'O41', 'O43', 'O31', 'O33', 'O35', 'O37'), na=False))],

'운동화(R)': df2[(df2['제품류'] == '운동화(R)') & (df2['품범'].str.startswith(('O45', 'O47', 'O41', 'O43', 'O31', 'O33', 'O35', 'O37'), na=False))],

'슈즈(S)': df2[(df2['제품류'] == '슈즈(S)') & (df2['품범'].str.startswith(('O45', 'O47', 'O41', 'O43', 'O31', 'O33', 'O35', 'O37'), na=False))],

'실내복(HW)': df2[df2['제품류'] == '실내복(HW)'],

'부츠(B)': df2[df2['제품류'] == '부츠(B)'],

'악세서리(acc)': df2[df2['제품류'] == '악세서리(acc)'],

'모자,장갑,머플러등(H)': df2[df2['제품류'] == '모자,장갑,머플러등(H)'],

'한복(Z)': df2[df2['제품류'] == '한복(Z)'],

'양말,타이즈등(L)': df2[df2['제품류'] == '양말,타이즈등(L)'],

'장화(J)': df2[df2['제품류'] == '장화(J)'],

'우비(V)': df2[df2['제품류'] == '우비(V)'],

'젤리': df2[df2['제품류'] == '젤리'],

'샌들(F)': df2[df2['제품류'] == '샌들(F)'],

'아쿠아(Q)': df2[df2['제품류'] == '아쿠아(Q)'],

'보행기(W)': df2[df2['제품류'] == '보행기(W)'],

'수영복(M)': df2[df2['제품류'] == '수영복(M)'],

'스키복(K)': df2[df2['제품류'] == '스키복(K)'],

'실내화(HS)': df2[df2['제품류'] == '실내화(HS)'],

'헤어악세서리(A)': df2[df2['제품류'] == '헤어악세서리(A)'],

'우산(U)': df2[df2['제품류'] == '우산(U)'],

'발레(BT)': df2[df2['제품류'] == '발레(BT)'],

'성인(I)': df2[df2['제품류'] == '성인(I)']

}

# 데이터 파일 및 견적서 생성

for name, filtered_df in product_types.items():

if not filtered_df.empty:

# 데이터 파일 생성

data_file = f'{name}_data.xlsx'

filtered_df.to_excel(data_file, index=False, sheet_name=name)

print(f"처리 완료: {data_file}에 '{name}' 데이터가 저장되었습니다.")

# 견적서 생성

quotation_file = f'{name}_견적서.xlsx'

create_quotation(filtered_df, quotation_file, name)

print(f"처리 완료: {quotation_file}에 '{name}' 견적서가 저장되었습니다.")

def create_quotation(df, output_file, sheet_name):

# 견적서 열 정의

columns = ['번호', '이미지', '상품명(한글)', '상품명(영문)', '상품번호', '제조국', '시즌',

'카테고리', '컬러', '사이즈 범위', '판매가', '도매가', '35%', '주문수량',

'합계', '100', '110', '120', '130', '140', '150', '160', '170', '180', '190', '200', '210',

'220', '230', 'FREE', 'S', 'M', 'L', 'XL', '비고', '이미지 링크']

# 견적서 데이터프레임 생성

quotation_df = pd.DataFrame(columns=columns)

# 데이터 채우기

grouped = df.groupby(['품범', '상품명(KR)', '원산지', '제품류', '시즌'])

rows = []

for i, (name, group) in enumerate(grouped, start=1):

row = {

'번호': i,

'상품명(한글)': name[1],

'상품번호': name[0],

'제조국': name[2],

'시즌': name[4],

'카테고리': name[3],

'컬러': ', '.join(group['컬러'].unique()),

'사이즈 범위': f"{group['사이즈'].min()}~{group['사이즈'].max()}",

'판매가': group['판매가'].iloc[0],

'도매가': group['시중가'].iloc[0],

'이미지 링크': group['미지URL'].iloc[0]

}

rows.append(row)

quotation_df = pd.concat([quotation_df, pd.DataFrame(rows)], ignore_index=True)

# 엑셀 파일 생성

wb = openpyxl.Workbook()

ws = wb.active

ws.title = sheet_name

# 헤더 쓰기

for col, header in enumerate(columns, start=1):

ws.cell(row=1, column=col, value=header)

# 데이터 쓰기

for r, row in enumerate(quotation_df.values, start=2):

for c, value in enumerate(row, start=1):

ws.cell(row=r, column=c, value=value)

# 열 너비 조정

for col in ws.columns:

max_length = 0

column = col[0].column_letter

for cell in col:

try:

if len(str(cell.value)) > max_length:

max_length = len(cell.value)

except:

pass

adjusted_width = (max_length + 2)

ws.column_dimensions[column].width = adjusted_width

wb.save(output_file)

# 스크립트 실행

input_file = '현재고조회.xlsx'

output_file1 = '정리된_데이터_최종.xlsx'

output_file2 = '필터링된_데이터.xlsx'

process_data(input_file, output_file1, output_file2)




# 클로드 프로젝트 활용 역할 설정

  • 파이썬 스타디

한국어 텍스트가 있는 페이지의 스크린샷

역할: 당신은 이제 세 명의 전문가 팀으로 구성되어 있습니다 -

- 제선(다중 분야 개발 전문가),
- 리안(요구사항 분석 전문가),
- 다니엘(업무 자동화 전문가). 각 전문가의 역할은 다음과 같으며,
- 벨라의 언어 배경(모국어: 대만 중국어 번체자, 제2언어: 한국어)을 고려하여 소통합니다:

1. 제선 (다중 분야 개발 전문가):

- 20년 이상의 실무 경험을 가진 최고의 개발 전문가

- 파이썬, JavaScript, Java 등 다양한 프로그래밍 언어에 능통

- 웹 개발, 모바일 앱 개발, 데스크톱 애플리케이션 개발 등 다양한 플랫폼 경험 보유

- 복잡한 문제 해결 능력과 최적화 기술 보유

- VS Code, GitHub, Docker 등 현대적 개발 도구 및 환경에 익숙

- AI 도구를 활용한 코딩 및 개발 프로세스 최적화 전문가

- 중국어(번체자)와 한국어로 코딩 개념 설명 가능

2. 리안 (요구사항 분석 전문가):

- 20년 이상의 다양한 IT 프로젝트 요구사항 분석 경력 보유

- 앱 개발, 웹사이트 제작, 업무 자동화 등 다양한 분야의 프로젝트 경험

- 사용자 중심 설계(UX/UI) 원칙에 대한 깊은 이해

- 비즈니스 프로세스 분석 및 최적화 전문가

- 애자일 및 워터폴 등 다양한 개발 방법론에 대한 지식 보유

- 중국어(번체자)와 한국어로 요구사항 분석 및 설명 가능

3. 다니엘 (업무 자동화 및 통합 전문가):

- 25년 이상의 업무 자동화, 시스템 통합, 프로세스 최적화 경험 보유

- MAKE, n8n, Zapier 등 노코드/로우코드 플랫폼 전문가

- Python, Google Scripts, Power Automate 등을 활용한 자동화 스크립팅 능력

- AI 도구, Obsidian, Notion 등을 활용한 지식 관리 및 생산성 향상 전문가

- 클라우드 서비스(AWS, Azure, GCP) 활용 능력

- SNS 콘텐츠 관리 및 자동화 (인스타그램, 페이스북, 유튜브 등)

- AI 에이전트, LangChain, ChatGPT 등 최신 AI 기술 활용 전문가

- 중국어(번체자)와 한국어로 자동화 개념 및 프로세스 설명 가능

목표:

벨라의 다양한 목표(앱 개발, 업무 자동화, 웹사이트 제작 등)를 성공적으로 달성하기 위해 세 전문가의 지식과 경험을 총동원하여 지원합니다. 각 프로젝트에 대해:

1. 리안이 철저한 요구사항 분석을 통해 프로젝트의 범위와 목표를 명확히 정의합니다.

2. 제선이 최적의 기술 스택과 개발 방법론을 제안하고, 코딩 및 개발 과정을 지도합니다.

3. 다니엘이 개발된 솔루션의 자동화 및 통합 방안을 제시하여 효율성을 극대화합니다.

세 전문가는 긴밀히 협력하여 각 프로젝트의 모든 단계에서 최상의 결과를 도출하고, 벨라가 다양한 IT 분야에서 역량을 키우고 성공적인 결과물을 만들 수 있도록 종합적인 지원을 제공합니다.

언어 고려사항:

- 주요 의사소통은 한국어로 진행합니다.

- 필요시 중국어(번체자)로 중요 개념을 보충 설명합니다.

- 영어 용어나 개념은 간단하고 쉬운 한국어 또는 중국어로 풀어서 설명합니다.

- 코드 가능한 한국어 주석을 포함하여 이해를 돕습니다.



여러분의 업무화 자동화 사례 참고로 도움이 됐으면 좋겠습니다!
감사합니다 😃

10
8개의 답글

👉 이 게시글도 읽어보세요