본문 바로가기
카테고리 없음

PDF를 EXCEL 로 변환하는 PYTHON) UI 디자인

by j1suya 2025. 1. 7.

python 기록

 

숙제

: PDF 파일을 넣으면 EXCEL 파일로 저장할 수 있는 UI 만들기

- tkinter 활용

 

나는 초보니까 chat GPT의 도움을 많이 받았다.

그치만 아직도 모르는 게 많다.


import tkinter as tk
from tkinterdnd2 import TkinterDnD, DND_FILES
import os
import pdfplumber
import openpyxl
import pandas as pd

# 파일 드롭 이벤트 핸들러
def on_drop(event):
    file_path = event.data.strip().replace("\\", "/").strip("{").strip("}") # 드롭된 파일 경로
    print(f"Dropped file path: {file_path}")  # 경로 출력

    # 이전 내용 초기화
    text_box.delete(1.0, tk.END)  # 텍스트 박스를 초기화
    status_label.config(text="")  # 상태 레이블 초기화

    if file_path.lower().endswith('.pdf'):
        text_box.insert(tk.END, f"Processing: {file_path}\n")
        text_box.insert(tk.END, "Extracting data...\n")
        text_box.update()  # 텍스트 박스 업데이트
        try:
            extract_tables_to_excel(file_path)  # 엑셀로 추출
            show_completion_window()  # 추출 완료 창 띄우기
        except Exception as e:
            text_box.insert(tk.END, f"Error: {e}\n")
            update_status_label("추출 실패")
    else:
        text_box.insert(tk.END, "Only PDF files are supported.\n")
        update_status_label("지원되지 않는 파일 형식")

def extract_tables_to_excel(pdf_path):
    """PDF에서 표를 추출하여 엑셀로 저장"""
    with pdfplumber.open(pdf_path) as pdf:
        all_data = []  # 모든 데이터를 저장할 리스트
        header = []  # 헤더 저장
        header_order = []  # 헤더 순서 저장

        # 두 번째 페이지에서 두 번째 테이블의 첫 번째 행을 헤더로 추출
        for page_number, page in enumerate(pdf.pages, start=1):
            if page_number == 2:  # 두 번째 페이지만 처리
                tables = page.extract_tables()
                if len(tables) > 1:  # 두 번째 테이블이 있는 경우
                    table = tables[1]  # 두 번째 테이블 선택
                    header = table[0]  # 첫 번째 행을 헤더로 설정
                    header_order = table[0]  # 두 번째 테이블의 헤더 순서 저장
                    break  # 두 번째 페이지의 두 번째 테이블을 찾았으면 반복문 종료

        # 데이터 수집
        for page_number, page in enumerate(pdf.pages, start=1):
            tables = page.extract_tables()
            for table in tables:
                data_rows = table[1:]  # 첫 번째 행은 헤더로 간주하고 제외
                for row in data_rows:
                    adjusted_row = [row[header.index(col)] if col in header else '' for col in header_order]
                    all_data.append(adjusted_row)

        # 데이터프레임 생성 후 엑셀로 저장
        df = pd.DataFrame(all_data, columns=header_order)
        excel_path = pdf_path.replace(".pdf", ".xlsx")
        df.to_excel(excel_path, index=False)
        print(f"엑셀 파일 생성 완료: {excel_path}")

def update_status_label(message):
    status_label.config(text=message)

completion_window = None

def show_completion_window():
    # 완료 창 만들기
    global completion_window
    completion_window = tk.Toplevel(window)
    completion_window.title("추출 완료")
    completion_window.geometry("300x150")

    # 완료 메시지 라벨
    completion_message = tk.Label(completion_window, text="추출 완료되었습니다!", font=("Arial", 14))
    completion_message.pack(pady=20)

    # 닫기 버튼
    close_button = tk.Button(completion_window, text="닫기", command=close_completion_window)
    close_button.pack(pady=10)

def close_completion_window():
    # 완료 창을 닫고, 초기화
    global completion_window
    completion_window.destroy()
    completion_window = None
   
    reset_drag_and_drop_area()
       
def reset_drag_and_drop_area():
    text_box.delete(1.0, tk.END)
    status_label.config(text="")


# TkinterDnD 사용하여 Tk 객체 생성
window = TkinterDnD.Tk()
window.drop_target_register(DND_FILES)
window.dnd_bind('<<Drop>>', on_drop)

window.title("Jisu's Tkinter")
window.geometry("500x400")
window.configure(bg="white")  # 배경색 설정

# 아이콘 설정
icon_image = tk.PhotoImage(file='C:\\Users\\user\\Desktop\\코딩 죽이자 화이팅\\pdf_excel\\icon.png')  # 아이콘 경로 수정
window.iconphoto(True, icon_image)

# 레이블 생성
label = tk.Label(window, text="PDF 파일을 드래그 앤 드랍하세요.", fg="black", bg="white")
label.pack(pady=20)

frame = tk.Frame(window, bd=1, relief="solid", bg="white") #bd 테두리
frame.pack(pady=20, padx=20, fill="both", expand=True)

# 텍스트 박스 생성
text_box = tk.Text(frame, height=1, width=30, bg="white", relief="flat")
text_box.pack(padx=10, pady=10) #상하좌우 여백

# 상태 레이블 생성
status_label = tk.Label(window, text="", fg="green", bg="white", font=("Arial", 12, "bold"))
status_label.pack(pady=10)

# 실행
window.mainloop()

 

<결과>

 

코드를 실행하면 

위와 같이 (못생긴) 창이 하나 뜬다.

 

네모 칸 안에 PDF파일을 드래그 앤 드랍하면

파일이 엑셀로 변환되어 같은 파일 위치에 저장됨!

 

변환이 완료되면 추출완료 창이 하나 더 뜬다.

닫기를 누르면 드래그앤 드랍 칸의 내용도 초기화 됨!


 

좀 못생기더라도,, 일단 기능부터 구현하자는 마음에 어찌저찌 했는데

못생겨도 너무 못생겼다

 

수정을 일단 해보자구....

window.title("PDF to EXCEL")
window.geometry("500x250")
window.configure(bg="white")  # 배경색 설정

# 아이콘 설정
icon_image = tk.PhotoImage(file='C:\\Users\\user\\Desktop\\코딩 죽이자 화이팅\\pdf_excel\\icon.png')  # 아이콘 경로 수정
window.iconphoto(True, icon_image)

# 레이블 생성
label = tk.Label(window, text="PDF 파일을 드래그 앤 드랍하세요.", fg="black", bg="white", font=("Arial", 12, "bold"))
label.pack(pady=20)

frame = tk.Frame(window, bd=2, relief="solid", bg="white") #bd 테두리
frame.pack(padx=100, pady=10, fill="both", expand=True)

# 텍스트 박스 생성
text_box = tk.Text(frame, height=1, width=40, bg="white", relief="flat")
text_box.pack(padx=10, pady=10) #상하좌우 여백

나머진 그대로구 위 캡쳐된 코드 부분의 숫자만 수정해봤다

(사실 아래 결과 사진의 테두리 두께는 1이다..)

 

- 글씨체, 크기 변경 + 드래그 앤 드랍 칸 작게 수정

아까보단 좀 나은 것 같은... 느낌..^^ (나한테만)

 

너무 꼬리꼬리한 디자인에 변환 사이트를 참고해보니

네모칸 안에 드래그 앤 드랍 글씨를 넣고, 사이트 이름을 네모칸 위에 써둔다.. 

나도 그걸 참고하여 수정해봐야겠다.

 

내일은 네모칸 위치 조정 및 UI 더 꾸미기 + 배경화면에 UI 바로가기 생성을 목표로 잡고 만들어봐야겠다

 

그럼 이만... (ㅡㅡ)