방명록
- [파이썬 신병 교육대] MDB로 부터 Packing List 자동출력 프로그램_3주차_상병2021년 12월 27일 13시 54분 29초에 업로드 된 글입니다.작성자: DandyNow728x90반응형
파이썬 신병 교육대 3주차 상병
마지막 코드 수정이 될 것 같다.
다음주는 전역식(?)이라고 한다.
구현내용
- try except를 이용해 AttributeError 에 대한 예외처리를 했다(이전 실행된 엑셀 파일이 완전히 종료되지 않았을때 발생하는 에러).
- tkinter 모듈(root.iconbitmap)을 이용해서 창 아이콘을 프린터 모양으로 변경했다.
- tkinter 모듈(delete(0,"end"))을 이용해서 패킹리스트 출력 또는 고객사 추가 후 텍스트 입력창이 초기화 되도록 하였다. delete(0,"end")은 텍스트 입력창 내의 모든 내용을 지운다.
- 프로그램이 실행 중일때 mdb의 데이터가 변경되더라도 인쇄시 출력에 반영되지 않는 문제가 있었다. 이 문제를 해결하기 위해 mdb → xls로 만드는 기능을 함수로 만들고 OK버튼을 누를때마다 호출하도록 하였다. 이렇게 만든 함수는 try except에 적용하기에도 용이했다.
작성한 코드
import pandas as pd # pip install pandas from openpyxl import load_workbook # pip install openpyxl from openpyxl.styles import Font, Alignment import os import win32com.client # pip install pywin32 import pyodbc # pip install pyodbc import xlwt, xlrd # pip install xlwt, pip install xlrd import tkinter from math import * from tkinter import * from tkinter import messagebox def mdb_xls(): # mdb > xls 함수 선언함. 프로그램 실행 중일때 mdb 변경될 경우를 고려하여 OK버튼 클릭시 mdb > xls 과정을 재수행하기 위함(3주차) # mdb를 xls로 변환 MDB = os.getcwd()+'/IDCMAINDB.mdb' DRV = '{Microsoft Access Driver (*.mdb, *.accdb)}' PWD = '' # connect to db con = pyodbc.connect('DRIVER={};DBQ={};PWD={}'.format(DRV,MDB,PWD)) cur = con.cursor() # run a query and get the results SQL = """SELECT * FROM TWEIGHT""" # your query goes here rows = cur.execute(SQL).fetchall() cur.close() con.close() wb = xlwt.Workbook() ws = wb.add_sheet("Weighing Data") # use table name for worksheet name cols = ['WDATE', 'SEQ_NO', 'FIELD1', 'NET_WEIGHT', 'TARE_WEIGHT', 'GROSS_WEIGHT', 'UNIT_WEIGHT', 'BARCODE', 'FIELD2', 'FIELD3', 'FIELD4', 'OPERATOR'] # renamed colum headings wbRow = 0 # counter for workbook row i=0 while i<12: ws.write(wbRow, i, cols[i]) # write column heading to first row i+=1 for row in rows: wbRow += 1 # increment workbook row counter i=0 while i<12: ws.write(wbRow, i, row[i]) i+=1 # wb.save(os.path.abspath('./pk.xls')) wb.save(os.getcwd()+'/pk.xls') # tkinter GUI적용 root=Tk() root.title("PACKING LIST 출력") root.geometry("300x300+100+100") root.resizable(False, False) root.iconbitmap(os.getcwd()+'/print.ico') # 창 아이콘 설정(3주차) # 로트번호 입력 lotLab = Label(root, text="로트번호") lotLab.place(x=20, y=20) txt = Entry(root) txt.place(x=80, y=20, height=25) # 고객사 추가 add_customerLab = Label(root, text="고객추가") add_customerLab.place(x=20, y=50) add_txt = Entry(root) add_txt.place(x=80, y=50, height=25) # 고객사 리스트 스크롤바 customerLab = Label(root, text="고객사") customerLab.place(x=20, y=80) frame=tkinter.Frame(root) scrollbar=tkinter.Scrollbar(frame, orient="vertical") scrollbar.pack(side="right", fill="y") # 고객 리스트 정보 customer.txt 가져오기 f = open(os.getcwd()+'/customer.txt', 'r') customerList = f.read().splitlines() f.close() listbox=tkinter.Listbox(frame, yscrollcommand = scrollbar.set) for customer in customerList: listbox.insert(END, customer) listbox.pack() scrollbar["command"]=listbox.yview frame.place(x=80, y=80, height=140) # 회사 UI 적용 image = tkinter.PhotoImage(file=os.getcwd()+'/UI_100.png') ui = tkinter.Label(root, image=image) ui.place(x = 95, y = 270) # Packing list 작성 def pkPrint(lot,company): xl = pd.read_excel(os.getcwd()+'/pk.xls') xl_mask = xl['FIELD2'] == lot filtered_xl = xl[xl_mask] pack = filtered_xl.groupby(['FIELD2','FIELD3','NET_WEIGHT'])['GROSS_WEIGHT'].agg(['count','sum']) GROSS_WEIGHT=filtered_xl.groupby(['FIELD2','FIELD3'])['GROSS_WEIGHT'].agg(['count','sum'],as_index=False).mean() print(GROSS_WEIGHT) path = os.path.abspath(os.getcwd()+'/pk_result.xlsx') with pd.ExcelWriter(path) as writer: pack.to_excel(writer,'packing', startcol=0,startrow=2) GROSS_WEIGHT.to_excel(writer,'packing',header=False, startcol=6,startrow=2) wb = load_workbook(filename = path, read_only=False, data_only=False) ws = wb['packing'] ws.merge_cells('A1:H1') ws['A1'] = 'Packing List' ws['A2'] = '고객사 : ' ws['B2'] = company ca1 = ws['A1'] ca1.font = Font(size=15, bold=True) wb.font = Font(size=15, bold=True) ca1.alignment = Alignment(horizontal='center', vertical='center') wb.save(path) # xlsx to PDF excel = win32com.client.Dispatch("Excel.Application") # Microsoft Excel 열기 # Excel 파일 읽기 sheets = excel.Workbooks.Open(os.getcwd()+'/pk_print.xlsm') sheets.Worksheets[0] work_sheets = sheets.Worksheets[0] work_sheets.ExportAsFixedFormat(0,os.getcwd()+'/pk_result.pdf') # Convert into PDF File(이 과정이 생략되면 인쇄 안됨) excel.Quit() # 엑셀 종료(이 과정이 생략되면 다시 실행시 에러 발생) # 로트번호 유무 확인(2주차) def lot_chk(lot): filename = os.getcwd()+'/pk.xls' wb = xlrd.open_workbook(filename) ws = wb.sheet_by_index(0) nrow=ws.nrows cnt = 0 for i in range(nrow): if ws.col_values(8)[i] == lot: cnt += 1 if cnt >= 1: return True # OK 출력하기 버튼 이벤트 핸들러 def okClick(): try: mdb_xls() # mdb > xls 수행(3주차) lot = txt.get() SelectList = listbox.curselection() company=''.join([listbox.get(i) for i in SelectList]) # 리스트 값 문자열 변환 if lot_chk(lot) == True: pkPrint(lot,company) txt.delete(0,"end") # 출력 후 입력된 로트번호 entry 삭제(3주차) else: tkinter.messagebox.showwarning("알림", "로트번호를 다시 확인하세요!") # 경고용 메시지 상자(2주차) except: tkinter.messagebox.showwarning("알림", "실행된 엑셀 창을 닫아주세요!") # AttributeError: Excel.Application.Workbooks 처리(3주차) # 고객 리스트 정보 추가 버튼 이벤트 핸들러 def add_click(): ctm = add_txt.get() # 고객 리스트 정보 추가 f = open(os.getcwd()+'/customer.txt', 'a') f.write(ctm+'\n') f.close() add_txt.delete(0,"end") # 고객 리스트 추가후 입력된 고객명 entry 삭제(3주차) # 리스트 박스 새로고침 listbox.delete(0, END) f = open(os.getcwd()+'/customer.txt', 'r') customerList = f.read().splitlines() f.close() for customer in customerList: listbox.insert(END, customer) # 고객사 리스트 정보 삭제 버튼 이벤트 핸들러(2주차) def del_click(): # 고객 리스트 정보 삭제 SelectList = listbox.curselection() company=''.join([listbox.get(i) for i in SelectList]) # 리스트 값 문자열 변환 with open(os.getcwd()+'/customer.txt', 'r') as f: lines = f.readlines() with open(os.getcwd()+'/customer.txt', 'w') as f: for line in lines: if line.strip('\n') != company: f.write(line) # 리스트 박스 새로고침 listbox.delete(0, END) f = open(os.getcwd()+'/customer.txt', 'r') customerList = f.read().splitlines() f.close() for customer in customerList: listbox.insert(END, customer) # 입력 버튼 btn = Button(root, text="OK", width=15, command=okClick) btn.place(x=90, y=230) # 고객 추가 버튼 add_btn = Button(root, text="추가", width=5, command=add_click) add_btn.place(x=240, y=50) # 고객 삭제 버튼(2주차) add_btn = Button(root, text="삭제", width=5, command=del_click) add_btn.place(x=240, y=80) root.mainloop()
728x90반응형'영광의 시대! > 2022 파이썬 신병 교육대 1기' 카테고리의 다른 글
[파이썬 신병 교육대] MDB로 부터 Packing List 자동출력 프로그램_4주차_병장_수료식_주특기 시범_최종코드 (0) 2022.01.04 [파이썬 신병 교육대] MDB로 부터 Packing List 자동출력 프로그램_2주차_일등병 (0) 2021.12.22 [파이썬 신병 교육대] MDB로 부터 Packing List 자동출력 프로그램_2주차에 만난 황당한 AttributeError (0) 2021.12.21 [파이썬 신병 교육대] MDB로 부터 Packing List 자동출력 프로그램_1주차_이등병 (0) 2021.12.17 다음글이 없습니다.이전글이 없습니다.댓글