개발/python

실무에 유용한 엑셀 자동화

iris3455 2025. 6. 14. 22:03

 

언젠가는 쓸 날을 위해서

 

 

현재 하고 있는 프로젝트가 지도 데이터 기반 프로젝트라 반복 작업이 디폴트이다. 어느 정도의 수동 작업은 했지만 엑셀 포맷을 맞추거나 반복되는 데이터를 추출하는 작업은 인간보다는 컴퓨터가 하는게 빠르고 정확할것 같아서 파이썬을 이용하여 자동화 프로그램을 개발해보기로 하였다.

이런 작업은 현업에서도 특히 많이 할 것 같아서 GPT한테 물어봐서 현업에서 사용하며 커스터마이징이 자유롭고, 파이썬 기본 패키지이기 때문에 설치도 간편한 tkinter를 사용하기로 하였다. 

또한 tkinter 기반 파이썬 GUI도 만들어서 보기 쉽게 작업을 하기로 하였다.

 

 

1. 설치

나는 Python 3.13.5 버전이 설치되어 있어 파이썬은 따로 설치하지 않았고 Homebrew를 이용하여 Python의 Tkinter 인터페이스를 설치하였다.

brew install python-tk

 

아래 명령어를 터미널에 치면 GUI 테스트 창이 표시된다. 이러면 성공적으로 설치된 것이다.

python3 -c "import tkinter; tkinter._test()"

 

 

 

 

2. 실행 파일 만들기

나는 Mac으로 작업을 하고 있어서 .command 파일로 GUI 실행기를 연결하기로 하였다.

 

가상 환경 설정

필요한 라이브러리는 가상 환경을 만들어서 거기에 설치하기로 하였다.

# 원하는 폴더 이동
cd ~/Desktop/data-automation

# 파이썬 가상환경 생성
python3 -m venv venv

# 가상환경 활성화
source venv/bin/activate

# pip을 통하여 pandas, openpyxl 설치
pip install pandas openpyxl

 

 

스크립트 생성

run_automation.command 

#!/bin/bash
cd "$(dirname "$0")"
source venv/bin/activate
python main.py
 

위의 스크립트는 .command 파일이 있는 폴더로 이동한 뒤, main.py를 실행하도록 하는 스크립트 이다.

 

 

실행 권한 부여

chmod +x run_automation.command

 

또한 해당 실행 파일에 실행 권한을 따로 부여해주어야 한다.

 

 

실행 방법

  • run_automation.command 파일을 더블클릭
  • ./run_automation.command <- 터미널에 입력
 

둘중 하나를 택하여 tkinter GUI를 실행시키면 된다.

 

 

 

 

3. 원하는 기능 추가

일단 내가 필요한 자동화 작업을 정리하자면 아래와 같다.

 

 

1️⃣ 전체 법정동 코드가 있는 .txt 파일에서 원하는 지역의 존재하는 모든 법정동 코드 반환

 

세부적으로:

  • 사용자가 드롭다운으로 시/도 선택 (예: 서울특별시, 강원도)
  • 폐지여부 == "존재"
  • 법정동명이 ~리로 끝나지 않는 경우
  • → 결과를 **filtered_{선택한시도}.txt**로 저장

 

2️⃣  csv 파일 자동 정리, 빈 셀/이상치 제거,  숫자 ↔ 문자 변환, 셀안의 데이터 포맷 통일시킨 후 특정 열 안의 데이터 추출


3️⃣ 1에서 추출한 데이터와 2에서 다듬은 데이터 양방향 비교하여 누락된 데이터 반환

 

예시:

  • CSV: pnus = [1100000000, 1111000000, ...]
  • TXT: 법정동코드 = 1100000000, ...

4️⃣ x, y 좌표가 있는 csv 파일에서 x,y값이 25x25 그리드에 중앙정렬하게 +- 한후 .csv로 반환

 

5️⃣ csv 파일안의 데이터를 swift 코드 포맷으로 변경

 

 

 
 
 

4. 구조 설계

구조는 간단하게 설계했다. main 에 GUI 설계 및 드롭 다운이나 파일 선택등의 기능을 담고 기능별로 .py 파일을 만들어서 main 과 분리했다.

- 📁 data-automation/
    - 📁 venv/
    - 📁 __pycache__/
    - 🏷️ sample_data/
        - 📄 sample_gangwon.csv
    - 📜 legal_zone_code_data.txt
    - 📄 cleaner.py
    - 📄 comparer.py
    - 📄 csv_to_center.py
    - 📄 csv_to_swift.py
    - 📄 extractor.py
    - 📄 main.py
    - 🖥 run_automation.command

 

  • cleaner  : CSV 전처리 및 정리
  • comparer.py : CSV와 txt 간 데이터 누락 비교
  • csv_to_center.py : CSV 그리드 안의 중앙 정렬 기능
  • csv_to_swift.py : CSV안의 Zone data를 Swift 데이터로 변환
  • extractor.py : legal_zone_code_data.txt에서 원하는 지역 필터링 기능
  • main.py  : GUI 앱의 메인 실행 파일
  • run_automation.command : 실행 자동화용 명령어 파일

 

 

 

5. main.py

사실 main 코드가 GUI 실행 코드라서 여기에 주요 코드가 다 모아져있다. 따라서 main 만 간단하게 설명을 해보겠다.

 

  • 라이브러리 import
# GUI를 위해 필요한 라이브러리 import
import tkinter as tk
from tkinter import filedialog, messagebox
from tkinter import ttk
import os
import pandas as pd

# 기능 함수가 들어있는 파일 import
import cleaner
import comparer
import extractor
import csv_to_center
import csv_to_swift

 

  • GUI 생성 및 초기화
class ExcelAutomationApp:
    def __init__(self, root):
        self.root = root
        self.root.title("CSV 자동화 도구")
        self.root.geometry("500x500")

        
        
if __name__ == "__main__":
    root = tk.Tk()
    app = ExcelAutomationApp(root)
    root.mainloop()

 

  • GUI 프로그램 사용자 인터페이스 요소를 생성, CSV 자동화 도구의 주요 기능과 입력을 연결
    • 딕셔너리를 이용하여 지역과 zone_code 를 매핑하여 사용자가 선택한 지역의 zone_code를 데이터로 input
        self.csv_path = ""
        self.txt_path = os.path.join(os.path.dirname(__file__), "legal_zone_code_data.txt")
        self.selected_region = tk.StringVar()
        
        self.region_code_map = {
            "서울특별시": 1100000000,
            "부산광역시": 2600000000,
            "대구광역시": 2700000000,
            "인천광역시": 2800000000,
            "광주광역시": 2900000000,
            "대전광역시": 3000000000,
            "울산광역시": 3100000000,
            "세종특별자치시": 3611000000,
            "경기도": 4100000000,
            "강원특별자치도": 4200000000,
            "충청북도": 4300000000,
            "충청남도": 4400000000,
            "전북특별자치도": 5200000000,
            "전라남도": 4600000000,
            "경상북도": 4700000000,
            "경상남도": 4800000000,
            "제주특별자치도": 5000000000
        }

        self.create_widgets()

    def create_widgets(self):
        tk.Button(self.root, text="CSV 파일 선택", command=self.load_csv).pack(pady=10)

        tk.Label(self.root, text="시/도 선택").pack()
        region_combo = ttk.Combobox(
            self.root,
            textvariable=self.selected_region,
            values=list(self.region_code_map.keys())
        )
        region_combo.pack(pady=5)

        tk.Button(self.root, text="실행 (정리 + 비교)", command=self.run_processing).pack(pady=10)
        tk.Button(self.root, text="중앙 정렬 CSV 저장", command=self.coord_to_center).pack(pady=10)
        tk.Button(self.root, text="Swift 코드로 저장", command=self.convert_csv_to_swift).pack(pady=10)

 

  • 기능 함수 추가
    def load_csv(self):
        path = filedialog.askopenfilename(filetypes=[("CSV files", "*.csv")])
        if path:
            self.csv_path = path
            messagebox.showinfo("파일 선택됨", f"CSV 파일: {path}")

    def run_processing(self):
        if not self.csv_path or not self.selected_region.get():
            messagebox.showwarning("경고", "CSV 파일과 시/도를 선택하세요.")
            return

        filtered_path = f"filtered_{self.selected_region.get()}.txt"
        filtered_df = extractor.filter_zone_in_txt(self.txt_path, self.selected_region.get(), filtered_path)

        cleaned_df = cleaner.clean_csv(self.csv_path)
        missing_csv, missing_txt = comparer.compare_bidirectional(cleaned_df, filtered_df)

        pd.DataFrame({"누락된 법정동코드": missing_csv}).to_csv("누락_from_csv.csv", index=False)
        pd.DataFrame({"누락된 법정동코드": missing_txt}).to_csv("누락_from_txt.csv", index=False)

        messagebox.showinfo("완료", f"처리 완료!\n{filtered_path}\n누락_from_csv.csv\n누락_from_txt.csv")

    def coord_to_center(self):
        if not self.csv_path:
            messagebox.showwarning("경고", "CSV 파일을 먼저 선택하세요.")
            return

        try:
            output_path = csv_to_center.coord_to_center(self.csv_path)
            messagebox.showinfo("완료", f"중앙 정렬된 CSV 저장됨:\n{output_path}")
        except Exception as e:
            messagebox.showerror("오류", str(e))

    def convert_csv_to_swift(self):
        if not self.csv_path or not self.selected_region.get():
            messagebox.showwarning("경고", "CSV 파일과 시/도를 선택하세요.")
            return

        try:
            region_code = self.region_code_map.get(self.selected_region.get())
            output_path = csv_to_swift.convert_csv_to_swift(self.csv_path, region_code)
            messagebox.showinfo("완료", f"Swift 코드 파일 생성됨:\n{output_path}")
        except Exception as e:
            messagebox.showerror("오류", str(e))

 

 

완료.

완성

 

 

6. 최종 코드

 

아래를 클릭하면 최종 코드 볼 수 있다.

 

https://github.com/irismake/data-automation

 

GitHub - irismake/data-automation

Contribute to irismake/data-automation development by creating an account on GitHub.

github.com

 

 

 

 

끝으로

오래 걸릴뻔 했지만 다행히 자동화 프로그램을 개발해 둔 덕분에 데이터를 정리 및 가공하는데 크게 오래걸리지 않았다. 무사히 (지루한) 지도 데이터 작업이 끝났고 앞으로의 개발이 기다려진다. 사실 현업에서 이렇게 데이터를 자동화하는 작업이 필요할까 궁금하다. 아직 겪어보지 않아서 잘 모르겠지만 😝. 나중에 업무를 할때 모쪼록 도움이 되길 바란다.