IT/DEV Study

[Python] Daily Work Log Program (근무일지 프로그램) 만들기 : )

Ella.J 2022. 3. 25. 11:23
728x90
반응형

그동안 Python 공부를 해왔는데 어떻게 활용할까 생각하다가

여태 C# WinForm으로 개발해서 잘 쓰고 있던 프로그램을 Python으로 한 번 만들어 봤다.

 

일을 하면서 그날그날 했던 내용들을 회사 SharePoint에 근무일지를 써서 올려야 하는데,

시간이 지나면서 이 내용들을 다시 찾아보기가 힘들게 되어있어서

개인적으로 쓰려고 만든 근무일지 프로그램이다.

 

아주 간단한 프로그램이다.

기본적인 화면은 아래 왼쪽처럼 메모장과 같다.

오른쪽의 메뉴 아이콘을 클릭하면 화면이 넓어지고,

오른쪽에 그동안 작성했던 근무일지가 나오도록 화면을 구성했다.

검색 기능도 있는데, 검색을 하는 경우 검색 아래의 리스트가 갱신되면서 해당 일자 혹은 해당 검색어에 맞는 리스트로 나오게 했다.

맨 오른쪽은 해당 날짜, 프로젝트 번호, 일지를 작성 후 리스트를 업데이트하거나,

리스트에서 해당 근무일지를 클릭하면 상세 내용이 나오는 부분이다.

 

UI는 Qt Designer를 이용해서 만들었다. 아주 간단하게.

main.ui

 

데이터베이스는 SQLite를 사용했는데,

메모장에 해당하는 templog 테이블과 리스트를 저장하는 worklog로 간단하게 구성해봤다.

dailyLogDB.db

 

Python 프로젝트 생성 후에 main.py 코드에 아래 첨부 코드와 같이 작성하고,

Qt Designer에서 생성했던 main.ui 파일과, SQLite에서 생성한 dailyLogDB.db 를 프로젝트 경로에 복사해 두었다.

윈도우 아이콘 및 메뉴 아이콘은 Images/Note.ico, Images/menu.png 참고해주시면 됩니다.

main.py 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# coding=utf-8
# This is a sample Python script.
 
# Press Shift+F10 to execute it or replace it with your code.
# Press Double Shift to search everywhere for classes, files, tool windows, actions, and settings.
 
import sys
import sqlite3
import re
from datetime import datetime
from PyQt5 import uic
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
 
# Qt Designer 에서 생성한 UI 연동
form_class = uic.loadUiType('main.ui')[0]
# Sqlite3 DB 연동
conn = sqlite3.connect('dailyLogDB.db', isolation_level=None)
# 커서 연결
cursor = conn.cursor()
# 구분자 선언
splitter = "========================================"
 
class MyApp(QMainWindow, form_class):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        
        # 창 크기, 위치 조절
        self.setFixedSize(500600)
        self.move(300300)
        # 메뉴 버튼 아이콘 설정, 테두리 제거
        self.btnMenu.setStyleSheet('border-image:url(Images/menu.png);border:0px;')
        # 창 타이틀 설정
        self.setWindowTitle('Work Log')
        # 아이콘 설정
        self.setWindowIcon(QIcon('Images/Note.ico'))
 
        # 날짜 라벨 초기화
        now = QDate.currentDate()
        self.lblDate.setText(now.toString('MMMM dd, yyyy'))
        self.lblDay.setText(now.toString('dddd'))
        self.txtDate.setText(now.toString('yyyy-MM-dd'))
        self.dtpSearch.setDate(now)
 
        # DB 데이터 읽어오기
        self.initialize()
 
        # 버튼 이벤트 생성
        self.btnMenu.clicked.connect(self.btnMenuClick)
        self.btnReset.clicked.connect(self.btnResetClick)
        self.btnSearch.clicked.connect(self.btnSearchClick)
        self.btnUpdate.clicked.connect(self.btnUpdateClick)
        self.btnSave.clicked.connect(self.btnSaveClick)
 
        # 메모 변경 textChanged 이벤트 연결
        self.txtRemarks.textChanged.connect(self.txtRemarksChanged)
        # Work Log List 선택 itemClicked 이벤트 연결
        self.lbWorkLogList.itemClicked.connect(self.lbWorkLogListClick)
        # 검색 날짜 선택 dateChanged 이벤트 연결
        self.dtpSearch.dateChanged.connect(self.dtpSearchDateChanged)
 
        # 메모 저장 단축키 설정
        self.saveSC = QShortcut(QKeySequence('Ctrl+S'), self)
        self.saveSC.activated.connect(self.txtRemarksSave)
        # 종료 단축키 설정
        self.quitSC = QShortcut(QKeySequence('Ctrl+W'), self)
        self.quitSC.activated.connect(QApplication.instance().quit)
 
    # DB 내역 가져오기 함수
    def initialize(self):
        # templog 내역 가져와서 txtRemarks에 뿌려주기
        cursor.execute('SELECT * FROM templog')
        self.txtRemarks.setText(str(cursor.fetchone()[0]))
        # worklog 내역 가져와서 lbWorkLogList에 추가하기
        cursor.execute('SELECT COUNT(*) FROM worklog')
        self.listCount = cursor.fetchone()[0]
        if self.listCount != 0:
            cursor.execute('SELECT * FROM worklog ORDER BY no DESC')
            self.lbWorkLogList.clear()
            for r in cursor:
                self.lbWorkLogList.addItem(f"{splitter}\n{str(r[0])} "
                                           f"/ {r[1]} / {r[2]}\n{splitter}\n{r[3]}")
 
    # 메모 저장 단축키 이벤트
    def txtRemarksSave(self):
        cursor.execute(f"UPDATE templog SET temp='{self.txtRemarks.toPlainText()}'")
        self.lblDate.setText(QDate.currentDate().toString('MMMM dd, yyyy'))
 
    # 메모 변경 체크 이벤트
    def txtRemarksChanged(self):
        self.lblDate.setText("* " + QDate.currentDate().toString('MMMM dd, yyyy'))
 
    # 메뉴 버튼 창 크기 조절 이벤트
    def btnMenuClick(self):
        if self.width() == 500:
            self.setFixedSize(1200600)
        else:
            self.setFixedSize(500600)
 
    # 검색 리셋 버튼 이벤트
    def btnResetClick(self):
        self.txtDate.setText(QDate.currentDate().toString('yyyy-MM-dd'))
        self.txtPJno.setText('')
        self.txtLog.setText('')
        self.initialize()
 
    # 검색 버튼 이벤트
    def btnSearchClick(self):
        searchValue = self.txtSearch.text()
        if searchValue != '':
            whereValue = f"WHERE remarks LIKE '%{searchValue}%' OR pj_no LIKE '%{searchValue}%' " \
                         f"ORDER BY no DESC"
            cursor.execute(f"SELECT * FROM worklog {whereValue}")
            self.lbWorkLogList.clear()
            for r in cursor:
                self.lbWorkLogList.addItem(f"{splitter}\n{str(r[0])} "
                                           f"/ {r[1]} / {r[2]}\n{splitter}\n{r[3]}")
 
    # 검색 날짜 선택 이벤트
    def dtpSearchDateChanged(self):
        searchDate = self.dtpSearch.date().toString('yyyy-MM-dd')
        cursor.execute(f"SELECT * FROM worklog WHERE work_date like '%{searchDate}%' "
                       f"ORDER BY no DESC")
        self.lbWorkLogList.clear()
        for r in cursor:
            self.lbWorkLogList.addItem(f"{splitter}\n{str(r[0])} "
                                       f"/ {r[1]} / {r[2]}\n{splitter}\n{r[3]}")
 
    # 로그 내용 업데이트 버튼 이벤트
    def btnUpdateClick(self):
        if self.lbWorkLogList.currentItem() is not None:
            curItem = self.lbWorkLogList.currentItem().text()
            logNo = re.search(r'=\n(.+?) /(.+?)', curItem).group(1)
            if self.txtDate.text() != '' and self.txtPJno.text() != '':
                setValue = f"work_date='{self.txtDate.text()}', pj_no='{self.txtPJno.text()}', " \
                           f"remarks='{self.txtLog.toPlainText()}'"
                cursor.execute(f"UPDATE worklog SET {setValue} WHERE NO={logNo}")
                self.initialize()
            else:
                QMessageBox.warning(self'Warning''항목을 빠짐없이 입력해주세요.')
        else:
            QMessageBox.warning(self'Warning''리스트에서 항목을 선택해 주세요.')
 
    # 로그 저장 버튼 이벤트
    def btnSaveClick(self):
        if self.txtDate.text() != '' and self.txtPJno.text() != '':
            value = f"{self.listCount + 1}, '{self.txtDate.text()}', " \
                    f"'{self.txtPJno.text()}', '{self.txtLog.toPlainText()}'"
            cursor.execute(f'INSERT INTO worklog VALUES ({value})')
            self.initialize()
        else:
            QMessageBox.warning(self'Warning''항목을 빠짐없이 입력해주세요.')
 
    # 로그 내용 선택 시 내용 보여주는 함수
    def lbWorkLogListClick(self):
        curItem = self.lbWorkLogList.currentItem().text()
        try:
            logDate = re.search(r'\d{4}-\d{2}-\d{2}', curItem).group()
            self.txtDate.setText(logDate)
            logPJno = re.search('/ (.+?) / (.+?)\n=', curItem).group(2)
            self.txtPJno.setText(logPJno)
            logText = curItem.split('=\n')[2]
            self.txtLog.setText(logText)
        except:
            QMessageBox.critical(self'Critical''에러가 발생했습니다.')
 
# Press the green button in the gutter to run the script.
if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = MyApp()
    ex.show()
    sys.exit(app.exec_())
 
# See PyCharm help at https://www.jetbrains.com/help/pycharm/
cs

 

이렇게 하면 근무일지 프로그램이 완성! ㅋㅋㅋㅋㅋ

쫌,, 설명이 부족하지만,,, 혹시나 추가 설명이 필요하신 분은 댓글로 남겨주세요,,, ^^

그럼 20000,,,

728x90
반응형