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 바로가기 생성을 목표로 잡고 만들어봐야겠다
그럼 이만... (ㅡㅡ)