반응형
완성된 프로그램과 코드입니다..
from tkinter import *
from tkinter import messagebox
from tkinter import ttk
from tkinter import filedialog
import tkinter as tk
import sqlite3
import pandas as pd
# =============================
# 폰트 설정
font = '맑은 고딕', 10
# =============================
# db 연결
conn = sqlite3.connect('data.db')
c = conn.cursor()
# 테이블 생성
c.execute('''CREATE TABLE IF NOT EXISTS applicants
(
phone TEXT,
team TEXT,
name TEXT,
ip TEXT,
etc1 TEXT,
etc2 TEXT
)''')
conn.commit()
# tkinter GUI 생성
root = tk.Tk()
root.title("전화번호 관리대장")
root.geometry("1400x1000+600+200")
# 입력 폼
form_frame = tk.Frame(root, padx=10, pady=10)
form_frame.pack(pady=30)
# 부서명 / 사용자 / 설치장소
# 전화번호 / IP주소 / 기타정보
lab1 = tk.Label(form_frame, text="부서명", font=font)
lab1.grid(row=0, column=0, padx=5, pady=5, sticky=tk.W)
ent1 = tk.Entry(form_frame, font=font)
ent1.grid(row=0, column=1, padx=5, pady=5)
lab2 = tk.Label(form_frame, text="사용자", font=font)
lab2.grid(row=1, column=0, padx=5, pady=5, sticky=tk.W)
ent2 = tk.Entry(form_frame, font=font)
ent2.grid(row=1, column=1, padx=5, pady=5)
lab3 = tk.Label(form_frame, text="설치장소", font=font)
lab3.grid(row=2, column=0, padx=5, pady=5, sticky=tk.W)
ent3 = tk.Entry(form_frame, font=font)
ent3.grid(row=2, column=1, padx=5, pady=5)
lab4 = tk.Label(form_frame, text="전화번호", font=font)
lab4.grid(row=0, column=2, padx=5, pady=5, sticky=tk.W)
ent4 = tk.Entry(form_frame, font=font)
ent4.grid(row=0, column=3, padx=5, pady=5)
lab5 = tk.Label(form_frame, text="IP주소", font=font)
lab5.grid(row=1, column=2, padx=5, pady=5, sticky=tk.W)
ent5 = tk.Entry(form_frame, font=font)
ent5.grid(row=1, column=3, padx=5, pady=5)
lab6 = tk.Label(form_frame, text="기타정보", font=font)
lab6.grid(row=2, column=2, padx=5, pady=5, sticky=tk.W)
ent6 = tk.Entry(form_frame, font=font)
ent6.grid(row=2, column=3, padx=5, pady=5)
lab7 = tk.Label(form_frame, text="검색", font=font)
lab7.grid(row=0, column=4, padx=5, pady=5, sticky=tk.W)
ent7 = tk.Entry(form_frame, font=font)
ent7.grid(row=0, column=5, padx=5, pady=5)
# 검색한 값 가져오기
def search_records():
lookup_record = ent7.get()
print(lookup_record)
# Treeview에서만 데이터 삭제
for record in tree.get_children():
tree.delete(record)
conn = sqlite3.connect('data.db') # db 연결
c = conn.cursor()
# 모든 입력 데이터에 대한 유사 값 검색하기
c.execute("SELECT rowid, * FROM applicants WHERE phone like ? OR team like ? OR name like ? OR ip like ? OR etc1 like ? OR etc2 like ?",
('%' + lookup_record + '%', '%' + lookup_record + '%', '%' + lookup_record + '%', '%' + lookup_record + '%', '%' + lookup_record + '%', '%' + lookup_record + '%',))
records = c.fetchall()
print(records)
if len(records) == 0: # 검색 결과가 없는 경우
messagebox.showinfo("Error", "검색 결과가 없습니다.")
c.execute("SELECT rowid, * FROM applicants")
records = c.fetchall()
for record in records:
tree.insert('', END, values=record[1:]) # rowid는 사용하지 않음
ent7.delete(0, tk.END) # ent 값 제거
# ent7과 enter 키 bind
ent7.bind('<Return>', lambda event: search_records())
# Enter키로 다음 엔트리 이동하는 함수
def next_entry(event):
widget = event.widget
widget.tk_focusNext().focus()
return "break"
def return_ent1():
ent1.focus_set()
# 저장 버튼 함수
def save_data():
# 버튼 비활성화 후 1000의 시간이 지난 뒤 다시 활성화
save_button.config(state=tk.DISABLED)
root.after(1000, lambda: save_button.config(state=tk.NORMAL))
# [전화번호,부서,사용자,IP주소,설치장소]에서 미입력된 정보가 있는지
if not ent1.get() or not ent2.get() or not ent3.get() or not ent4.get() or not ent5.get():
messagebox.showwarning("Warning", "필수 정보를 모두 입력해주세요.")
return
# 중복 데이터 확인 [전화번호/IP]
c.execute("SELECT * FROM applicants WHERE phone=?", (ent4.get(),))
duplicate_data = c.fetchone()
print(duplicate_data)
if duplicate_data: # 중복되는 값이 있는지 확인
messagebox.showwarning("Warning", "중복되는 전화번호가 있습니다.")
else: # 중복된 데이터가 없는 경우 데이터를 저장
c.execute("INSERT INTO applicants (phone, team, name, ip, etc1, etc2) VALUES (?, ?, ?, ?, ?, ?)", (ent1.get(), ent2.get(), ent3.get(), ent4.get(), ent5.get(), ent6.get()))
conn.commit()
# ent 입력 초기화
ent1.delete(0, tk.END)
ent2.delete(0, tk.END)
ent3.delete(0, tk.END)
ent4.delete(0, tk.END)
ent5.delete(0, tk.END)
ent6.delete(0, tk.END)
update_table()# 테이블 갱신
return_ent1()# ent1 입력으로 돌아가기
# 삭제 함수 (Treeview와 DB 모두 삭제)
def delete_data():
selection = tree.selection()
# 선택된 항목이 없는 경우, 오류 표시 후 함수 종료
if not selection:
messagebox.showwarning("Warning", "삭제할 항목을 선택해주세요.")
return
selection = selection[0]
data = tree.item(selection)['values']
c.execute("DELETE FROM applicants WHERE phone=? AND team=? AND name=? AND ip=? AND etc1=? AND etc2=?", data)
conn.commit()
tree.delete(selection)
# 테이블 갱신
update_table()
def select_item_delete(event):
if messagebox.askyesno("Delete", "삭제하시겠습니까?"):
delete_data()
# 파일 선택 버튼 클릭시 실행되는 함수 [저장기능]
def choose_file():
file_path = filedialog.asksaveasfilename(defaultextension='.csv') # 탐색기 열고 csv로 저장하기
if file_path: # 선택한 파일 경로가 있을 경우
df = pd.read_sql_query("SELECT * from applicants", conn) # DB에서 데이터 추출
df.to_csv(file_path, encoding='utf-8-sig', index=False) # CSV 파일로 저장
messagebox.showinfo("완료", "파일 저장이 완료되었습니다.") # 저장 완료 메시지 박스 출력
# 버튼 프레임
btn_frame = tk.Frame(root, padx=10, pady=10)
btn_frame.pack()
# DB to CSV 버튼
save_button = tk.Button(btn_frame, width=10, text="DB to CSV", command=choose_file, font=font)
save_button.grid(row=0, column=1, padx=20, pady=5)
# 트리뷰 스타일 지정
style = ttk.Style()
style.theme_use('clam')
style.configure('Treeview',
background = '#D3D3D3',
foreground = 'black',
rowheight=25,
fieldbackground = '#D3D3D3',
font=font
)
style.map('Treeview',
background = [('selected', 'green')])
# 데이터 테이블 생성
tree = ttk.Treeview(root, height=18, columns=('phone', 'ip', 'team', 'name', 'etc1', 'etc2'), show='headings')
tree.column('phone', width=200)
tree.column('ip', width=200)
tree.column('team', width=200)
tree.column('name', width=200)
tree.column('etc1', width=200)
tree.column('etc2', width=200)
tree.heading('phone', text='전화번호')
tree.heading('ip', text='IP주소')
tree.heading('team', text='부서명')
tree.heading('name', text='사용자')
tree.heading('etc1', text='설치장소')
tree.heading('etc2', text='기타정보')
tree.pack()
# 데이터 업데이트
def update_table():
tree.delete(*tree.get_children())
for row in c.execute("SELECT * FROM applicants"):
tree.insert("", "end", values=row)
# 데이터 새로 고침
def refresh_table(event):
tree.delete(*tree.get_children())
update_table()
messagebox.showinfo("완료", "새로 고침 완료")
# Enter 입력으로 다음 Entry로 이동
ent1.bind('<Return>', next_entry)
ent2.bind('<Return>', next_entry)
ent3.bind('<Return>', next_entry)
ent4.bind('<Return>', next_entry)
ent5.bind('<Return>', next_entry)
# Enter 입력으로 데이터 저장
ent6.bind('<Return>', lambda e:save_data())
# Del 키로 삭제 기능 추가
tree.bind('<Delete>', select_item_delete)
root.bind('<F5>', refresh_table)
# 데이터 테이블 초기화
update_table()
# 프로그램 실행
root.mainloop()
# db 연결 종료
conn.close()
반응형
'python' 카테고리의 다른 글
[파이썬] 접수 프로그램 01 (0) | 2023.03.15 |
---|---|
PYTHON과 C++의 비교 (0) | 2023.03.02 |
[파이썬] 접수 프로그램 (0) | 2023.02.28 |
[파이썬] IP 변경 프로그램 (0) | 2023.02.24 |
[파이썬] 데스크탑 제품번호 정보 확인 (0) | 2023.02.09 |