pyqt5_excel_qtablewidget01.py--------------------
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QTableWidget, QTableWidgetItem, QPushButton, QHeaderView, QHBoxLayout, QVBoxLayout
from PyQt5.QtCore import Qt
import pandas as pd # pip install pandas
class MyApp(QWidget):
def __init__(self):
super().__init__()
self.window_width, self.window_height = 700, 500
self.resize(self.window_width, self.window_height)
self.setWindowTitle('Load Excel (or CSV) data to QTableWidget')
layout_main = QHBoxLayout()
self.setLayout(layout_main)
layout_v = QVBoxLayout()
self.button = QPushButton('&Load Data')
self.button.clicked.connect(lambda _, xl_path=excel_file_path, sheet_name=worksheet_name: self.loadExcelData(xl_path, sheet_name))
layout_v.addWidget(self.button)
self.table = QTableWidget()
layout_v.addWidget(self.table)
layout_main.addLayout(layout_v)
def loadExcelData(self, excel_file_dir, worksheet_name):
df = pd.read_excel(excel_file_dir, worksheet_name)
if df.size == 0:
return
# print(df.columns[4])
df.fillna('', inplace=True)
df_name = df[['성명']]
# print(df_name)
# self.table.setRowCount(df.shape[0])
# self.table.setColumnCount(df.shape[1])
self.table.setRowCount(df_name.shape[0])
self.table.setColumnCount(df_name.shape[1])
# self.table.setHorizontalHeaderLabels(df.columns)
self.table.setHorizontalHeaderLabels(df_name.columns)
# returns pandas array object
# for row in df.iterrows():
for row in df_name.iterrows():
values = row[1]
for col_index, value in enumerate(values):
if isinstance(value, (float, int)):
value = '{0:0,.0f}'.format(value)
tableItem = QTableWidgetItem(str(value))
self.table.setItem(row[0], col_index, tableItem)
self.table.setColumnWidth(2, 300)
if __name__ == '__main__':
# don't auto scale when drag app to a different monitor.
# QGuiApplication.setHighDpiScaleFactorRoundingPolicy(Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
excel_file_path = '급여1.xlsx'
worksheet_name = '4대급여'
app = QApplication(sys.argv)
app.setStyleSheet('''
QWidget {
font-size: 17px;
}
''')
myApp = MyApp()
myApp.show()
try:
sys.exit(app.exec())
except SystemExit:
print('Closing Window...')
====================
pyqt5_excel_qtablewidget02.py--------------------
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QTableWidget, QTableWidgetItem, QPushButton, QHeaderView, QHBoxLayout, QVBoxLayout
from PyQt5.QtCore import Qt
import pandas as pd # pip install pandas
class MyApp(QWidget):
def __init__(self):
super().__init__()
self.window_width, self.window_height = 700, 500
self.resize(self.window_width, self.window_height)
self.setWindowTitle('Load Excel (or CSV) data to QTableWidget')
layout_main = QHBoxLayout()
self.setLayout(layout_main)
layout_v = QVBoxLayout()
self.button = QPushButton('&Load Data')
self.button.clicked.connect(lambda _, xl_path=excel_file_path, sheet_name=worksheet_name: self.loadExcelData(xl_path, sheet_name))
layout_v.addWidget(self.button)
self.table = QTableWidget()
layout_v.addWidget(self.table)
layout_main.addLayout(layout_v)
def loadExcelData(self, excel_file_dir, worksheet_name):
# df = pd.read_excel(excel_file_dir, worksheet_name)
# if df.size == 0:
# return
# print(df.columns[4])
# df.fillna('', inplace=True)
# df_name = df[['성명']]
# print(df_name)
df_work_sheet = pd.read_excel(excel_file_path, worksheet_name)
df_email_sheet = pd.read_excel(excel_file_path, emailsheet_name)
df_table = df_work_sheet.merge(df_email_sheet, how='left')[['성명','이메일']]
# self.table.setRowCount(df.shape[0])
# self.table.setColumnCount(df.shape[1])
self.table.setRowCount(df_table.shape[0])
self.table.setColumnCount(df_table.shape[1])
# self.table.setHorizontalHeaderLabels(df.columns)
self.table.setHorizontalHeaderLabels(df_table.columns)
# returns pandas array object
# for row in df.iterrows():
for row in df_table.iterrows():
values = row[1]
for col_index, value in enumerate(values):
if isinstance(value, (float, int)):
value = '{0:0,.0f}'.format(value)
tableItem = QTableWidgetItem(str(value))
self.table.setItem(row[0], col_index, tableItem)
self.table.setColumnWidth(2, 300)
if __name__ == '__main__':
# don't auto scale when drag app to a different monitor.
# QGuiApplication.setHighDpiScaleFactorRoundingPolicy(Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
excel_file_path = '급여1.xlsx'
worksheet_name = '4대급여'
emailsheet_name = '이메일'
app = QApplication(sys.argv)
app.setStyleSheet('''
QWidget {
font-size: 17px;
}
''')
myApp = MyApp()
myApp.show()
try:
sys.exit(app.exec())
except SystemExit:
print('Closing Window...')
====================
pyqt5_excel_qtablewidget03.py--------------------
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QTableWidget, QTableWidgetItem, QPushButton, QHeaderView, QHBoxLayout, QVBoxLayout
from PyQt5.QtCore import Qt
import pandas as pd # pip install pandas
class MyApp(QWidget):
def __init__(self):
super().__init__()
self.window_width, self.window_height = 700, 500
self.resize(self.window_width, self.window_height)
self.setWindowTitle('Load Excel (or CSV) data to QTableWidget')
layout_main = QHBoxLayout()
self.setLayout(layout_main)
layout_v = QVBoxLayout()
self.button = QPushButton('&Load Data')
self.button.clicked.connect(lambda _, xl_path=excel_file_path, sheet_name=worksheet_name: self.loadExcelData(xl_path, sheet_name))
layout_v.addWidget(self.button)
self.table = QTableWidget()
layout_v.addWidget(self.table)
layout_main.addLayout(layout_v)
def loadExcelData(self, excel_file_dir, worksheet_name):
# df = pd.read_excel(excel_file_dir, worksheet_name)
# if df.size == 0:
# return
# print(df.columns[4])
# df.fillna('', inplace=True)
# df_name = df[['성명']]
# print(df_name)
df_work_sheet = pd.read_excel(excel_file_path, worksheet_name)
df_email_sheet = pd.read_excel(excel_file_path, emailsheet_name)
df_table = df_work_sheet.merge(df_email_sheet, how='left')
df_table_mail = df_table[['성명','이메일']]
# self.table.setRowCount(df.shape[0])
# self.table.setColumnCount(df.shape[1])
self.table.setRowCount(df_table_mail.shape[0])
self.table.setColumnCount(df_table_mail.shape[1])
# self.table.setHorizontalHeaderLabels(df.columns)
self.table.setHorizontalHeaderLabels(df_table_mail.columns)
header = self.table.horizontalHeader()
# header.setSectionResizeMode(0, QHeaderView.Stretch)
# header.setSectionResizeMode(0, QHeaderView.ResizeToContents)
header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
# returns pandas array object
# for row in df.iterrows():
for row in df_table_mail.iterrows():
values = row[1]
for col_index, value in enumerate(values):
if isinstance(value, (float, int)):
value = '{0:0,.0f}'.format(value)
tableItem = QTableWidgetItem(str(value))
self.table.setItem(row[0], col_index, tableItem)
self.table.setColumnWidth(2, 300)
if __name__ == '__main__':
# don't auto scale when drag app to a different monitor.
# QGuiApplication.setHighDpiScaleFactorRoundingPolicy(Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
excel_file_path = '급여1.xlsx'
worksheet_name = '4대급여'
emailsheet_name = '이메일'
app = QApplication(sys.argv)
app.setStyleSheet('''
QWidget {
font-size: 17px;
}
''')
myApp = MyApp()
myApp.show()
try:
sys.exit(app.exec())
except SystemExit:
print('Closing Window...')
====================
pyqt5_excel_qtablewidget04.py--------------------
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QTableWidget, QTableWidgetItem, QPushButton, \
QHeaderView, QHBoxLayout, QVBoxLayout
from PyQt5.QtCore import Qt
import pandas as pd # pip install pandas
class MyApp(QWidget):
def __init__(self):
super().__init__()
self.window_width, self.window_height = 400, 500
self.resize(self.window_width, self.window_height)
self.setWindowTitle('Load Excel (or CSV) data to QTableWidget')
layout_main = QHBoxLayout()
self.setLayout(layout_main)
layout_v = QVBoxLayout()
self.button = QPushButton('&Load Data')
self.button.clicked.connect(lambda _, xl_path=excel_file_path, sheet_name=worksheet_name: self.loadExcelData(xl_path, sheet_name))
layout_v.addWidget(self.button)
self.table = QTableWidget()
layout_v.addWidget(self.table)
layout_main.addLayout(layout_v)
def loadExcelData(self, excel_file_dir, worksheet_name):
# df = pd.read_excel(excel_file_dir, worksheet_name)
# if df.size == 0:
# return
# print(df.columns[4])
# df.fillna('', inplace=True)
# df_name = df[['성명']]
# print(df_name)
df_work_sheet = pd.read_excel(excel_file_path, worksheet_name)
df_email_sheet = pd.read_excel(excel_file_path, emailsheet_name)
df_table = df_work_sheet.merge(df_email_sheet, how='left')
df_table_mail = df_table[['성명','이메일']]
# self.table.setRowCount(df.shape[0])
# self.table.setColumnCount(df.shape[1])
self.table.setRowCount(df_table_mail.shape[0])
self.table.setColumnCount(df_table_mail.shape[1])
# self.table.setHorizontalHeaderLabels(df.columns)
self.table.setHorizontalHeaderLabels(df_table_mail.columns)
header = self.table.horizontalHeader()
# header.setSectionResizeMode(0, QHeaderView.Stretch)
# header.setSectionResizeMode(0, QHeaderView.ResizeToContents)
header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
# returns pandas array object
# for row in df.iterrows():
for row in df_table_mail.iterrows():
values = row[1]
for col_index, value in enumerate(values):
if isinstance(value, (float, int)):
value = '{0:0,.0f}'.format(value)
tableItem = QTableWidgetItem(str(value))
if value == "nan":
tableItem.setBackground(Qt.red)
self.table.setItem(row[0], col_index, tableItem)
self.table.setColumnWidth(2, 300)
if __name__ == '__main__':
# don't auto scale when drag app to a different monitor.
# QGuiApplication.setHighDpiScaleFactorRoundingPolicy(Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
excel_file_path = '급여1.xlsx'
worksheet_name = '4대급여'
emailsheet_name = '이메일'
app = QApplication(sys.argv)
app.setStyleSheet('''
QWidget {
font-size: 17px;
}
''')
myApp = MyApp()
myApp.show()
try:
sys.exit(app.exec())
except SystemExit:
print('Closing Window...')
====================
pay01.py--------------------
from operator import index
import sys
from unittest import result
from PyQt5.QtWidgets import QApplication, QWidget, QTableWidget, QTableWidgetItem, QPushButton, \
QHeaderView, QHBoxLayout, QVBoxLayout, QAbstractScrollArea
from PyQt5.QtCore import Qt
from PyQt5 import QtGui
import pandas as pd # pip install pandas
class MyApp(QWidget):
def __init__(self):
super().__init__()
self.window_width, self.window_height = 300, 400
# self.resize(self.window_width, self.window_height)
self.setWindowTitle('pay')
layout_main = QHBoxLayout()
self.setLayout(layout_main)
layout_v = QVBoxLayout()
# self.button = QPushButton('&Load Data')
# self.button.clicked.connect(lambda _, xl_path=excel_file_path, sheet_name=worksheet_name: self.loadExcelData(xl_path, sheet_name))
# layout_v.addWidget(self.button)
self.table = QTableWidget()
layout_v.addWidget(self.table)
layout_main.addLayout(layout_v)
# table_data = self.loadExcelData(excel_file_path, worksheet_name)
# print(table_data.keys())
table_df = self.loadExcelData(excel_file_path, worksheet_name)
# print(table_df["성명"][0])
table_02 = table_df.set_index("성명")
index = table_02.index.to_list()
# print(index)
# for i in table_02["이메일"]:
for idx in index:
# print(idx)
# print(table_02.loc[idx][0])
print(idx, table_02.loc[idx][0])
def loadExcelData(self, excel_file_dir, worksheet_name):
df_work_sheet = pd.read_excel(excel_file_path, worksheet_name)
df_email_sheet = pd.read_excel(excel_file_path, emailsheet_name)
df_table = df_work_sheet.merge(df_email_sheet, how='left')
df_table_mail = df_table[['성명','이메일']]
res = df_table_mail
# res = df_table_mail.to_dict()
# self.table.setRowCount(df.shape[0])
# self.table.setColumnCount(df.shape[1])
self.table.setRowCount(df_table_mail.shape[0])
self.table.setColumnCount(df_table_mail.shape[1])
# self.table.setHorizontalHeaderLabels(df.columns)
self.table.setHorizontalHeaderLabels(df_table_mail.columns)
header = self.table.horizontalHeader()
# header.setSectionResizeMode(0, QHeaderView.Stretch)
# header.setSectionResizeMode(0, QHeaderView.ResizeToContents)
header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
# returns pandas array object
# for row in df.iterrows():
for row in df_table_mail.iterrows():
values = row[1]
for col_index, value in enumerate(values):
if isinstance(value, (float, int)):
value = '{0:0,.0f}'.format(value)
tableItem = QTableWidgetItem(str(value))
if value == "nan":
tableItem.setBackground(Qt.red)
self.table.setItem(row[0], col_index, tableItem)
self.table.setColumnWidth(2, 300)
return res
def print_name(self, name):
print(name)
if __name__ == '__main__':
# don't auto scale when drag app to a different monitor.
# QGuiApplication.setHighDpiScaleFactorRoundingPolicy(Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
excel_file_path = '급여1.xlsx'
worksheet_name = '4대급여'
emailsheet_name = '이메일'
app = QApplication(sys.argv)
app.setStyleSheet('''
QWidget {
font-size: 17px;
}
''')
myApp = MyApp()
myApp.show()
try:
sys.exit(app.exec())
except SystemExit:
print('Closing Window...')
====================
pay02.py--------------------
from operator import index
import sys
from unittest import result
from PyQt5.QtWidgets import QApplication, QWidget, QTableWidget, QTableWidgetItem, QPushButton, \
QHeaderView, QHBoxLayout, QVBoxLayout, QAbstractScrollArea
from PyQt5.QtCore import Qt
from PyQt5 import QtGui
import pandas as pd # pip install pandas
class MyApp(QWidget):
def __init__(self):
super().__init__()
self.window_width, self.window_height = 300, 400
# self.resize(self.window_width, self.window_height)
self.setWindowTitle('pay')
layout_main = QHBoxLayout()
self.setLayout(layout_main)
layout_v = QVBoxLayout()
# self.button = QPushButton('&Load Data')
# self.button.clicked.connect(lambda _, xl_path=excel_file_path, sheet_name=worksheet_name: self.loadExcelData(xl_path, sheet_name))
# layout_v.addWidget(self.button)
self.table = QTableWidget()
layout_v.addWidget(self.table)
layout_main.addLayout(layout_v)
# table_data = self.loadExcelData(excel_file_path, worksheet_name)
# print(table_data.keys())
table_df = self.loadExcelData(excel_file_path, worksheet_name)
# print(table_df["성명"][0])
self.table_02 = table_df.set_index("성명")
index = self.table_02.index.to_list()
# print(index)
# for i in table_02["이메일"]:
for idx in index:
# print(idx)
# print(table_02.loc[idx][0])
# print(idx, table_02.loc[idx][0])
self.print_name(idx)
def loadExcelData(self, excel_file_dir, worksheet_name):
df_work_sheet = pd.read_excel(excel_file_path, worksheet_name)
df_email_sheet = pd.read_excel(excel_file_path, emailsheet_name)
df_table = df_work_sheet.merge(df_email_sheet, how='left')
df_table_mail = df_table[['성명','이메일']]
res = df_table_mail
# res = df_table_mail.to_dict()
# self.table.setRowCount(df.shape[0])
# self.table.setColumnCount(df.shape[1])
self.table.setRowCount(df_table_mail.shape[0])
self.table.setColumnCount(df_table_mail.shape[1])
# self.table.setHorizontalHeaderLabels(df.columns)
self.table.setHorizontalHeaderLabels(df_table_mail.columns)
header = self.table.horizontalHeader()
# header.setSectionResizeMode(0, QHeaderView.Stretch)
# header.setSectionResizeMode(0, QHeaderView.ResizeToContents)
header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
# returns pandas array object
# for row in df.iterrows():
for row in df_table_mail.iterrows():
values = row[1]
for col_index, value in enumerate(values):
if isinstance(value, (float, int)):
value = '{0:0,.0f}'.format(value)
tableItem = QTableWidgetItem(str(value))
if value == "nan":
tableItem.setBackground(Qt.red)
self.table.setItem(row[0], col_index, tableItem)
self.table.setColumnWidth(2, 300)
return res
def print_name(self, name):
print(name, self.table_02.loc[name][0])
if __name__ == '__main__':
# don't auto scale when drag app to a different monitor.
# QGuiApplication.setHighDpiScaleFactorRoundingPolicy(Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
excel_file_path = '급여1.xlsx'
worksheet_name = '4대급여'
emailsheet_name = '이메일'
app = QApplication(sys.argv)
app.setStyleSheet('''
QWidget {
font-size: 17px;
}
''')
myApp = MyApp()
myApp.show()
try:
sys.exit(app.exec())
except SystemExit:
print('Closing Window...')
====================
pay03.py--------------------
from operator import index
from unittest import result
from PyQt5.QtWidgets import QApplication, QWidget, QTableWidget, QTableWidgetItem, QPushButton, \
QHeaderView, QHBoxLayout, QVBoxLayout, QGridLayout, QAbstractScrollArea, QLabel, QListWidget, \
QFileDialog, QMessageBox, QTextEdit, QAbstractItemView
from PyQt5.QtCore import Qt
from PyQt5 import QtGui
import sys
import pandas as pd # pip install pandas
import os
class MyApp(QWidget):
def __init__(self):
super().__init__()
self.window_width, self.window_height = 800, 600
self.resize(self.window_width, self.window_height)
self.setWindowTitle('pay')
##### layout_main #####
layout_main = QHBoxLayout()
self.setLayout(layout_main)
##### layout_1 #####
layout_1 = QVBoxLayout()
label11 = QLabel('직원 메일')
# self.button = QPushButton('&Load Data')
# self.button.clicked.connect(lambda _, xl_path=excel_file_path, sheet_name=worksheet_name: self.loadExcelData(xl_path, sheet_name))
# layout_v.addWidget(self.button)
layout_1.addWidget(label11)
self.table = QTableWidget()
self.table.setFixedWidth(310)
layout_1.addWidget(self.table)
layout_main.addLayout(layout_1)
##### layout_2 #####
layout_2 = QGridLayout()
label21 = QLabel('첨부파일')
layout_2.addWidget(label21, 0, 0, 1, 1)
self.listwidget21 = QListWidget()
self.listwidget21.setFixedWidth(300)
self.listwidget21.setSelectionMode(QAbstractItemView.ExtendedSelection)
layout_2.addWidget(self.listwidget21, 1, 0, 5, 1)
self.btn_file_add = QPushButton('파일 추가') # sendlist
# self.btn_file_add.setMinimumHeight(80)
layout_2.addWidget(self.btn_file_add, 1, 2, 1, 1)
self.btn_file_add.clicked.connect(self.fn_fileadd)
self.btn_file_del = QPushButton('파일 삭제')
layout_2.addWidget(self.btn_file_del, 2, 2, 1, 1)
self.btn_file_del.clicked.connect(self.fn_filedel)
label21 = QLabel('본문 (HTML형식)')
layout_2.addWidget(label21, 6, 0, 1, 1)
self.textedit22 = QTextEdit()
self.textedit22.setFixedWidth(300)
layout_2.addWidget(self.textedit22, 7, 0, 5, 1)
layout_main.addLayout(layout_2)
# table_data = self.loadExcelData(excel_file_path, worksheet_name)
# print(table_data.keys())
df_table = self.loadExcelData(excel_file_path, worksheet_name)
# print(table_df["성명"][0])
self.df_table_02 = df_table.set_index("성명")
index = self.df_table_02.index.to_list()
# print(index)
# for i in table_02["이메일"]:
for idx in index:
# print(idx)
# print(table_02.loc[idx][0])
# print(idx, table_02.loc[idx][0])
self.print_name(idx)
def loadExcelData(self, excel_file_dir, worksheet_name):
df_work_sheet = pd.read_excel(excel_file_path, worksheet_name)
df_email_sheet = pd.read_excel(excel_file_path, emailsheet_name)
df_table = df_work_sheet.merge(df_email_sheet, how='left')
df_table_mail = df_table[['성명','이메일']]
res = df_table_mail
# res = df_table_mail.to_dict()
# self.table.setRowCount(df.shape[0])
# self.table.setColumnCount(df.shape[1])
self.table.setRowCount(df_table_mail.shape[0])
self.table.setColumnCount(df_table_mail.shape[1])
# self.table.setHorizontalHeaderLabels(df.columns)
self.table.setHorizontalHeaderLabels(df_table_mail.columns)
header = self.table.horizontalHeader()
# header.setSectionResizeMode(0, QHeaderView.Stretch)
# header.setSectionResizeMode(0, QHeaderView.ResizeToContents)
header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
# returns pandas array object
# for row in df.iterrows():
for row in df_table_mail.iterrows():
values = row[1]
for col_index, value in enumerate(values):
if isinstance(value, (float, int)):
value = '{0:0,.0f}'.format(value)
tableItem = QTableWidgetItem(str(value))
if value == "nan":
tableItem.setBackground(Qt.red)
self.table.setItem(row[0], col_index, tableItem)
self.table.setColumnWidth(2, 300)
return res
def print_name(self, name):
print(name, self.df_table_02.loc[name][0])
def fn_fileadd(self):
# f_name = QFileDialog.getOpenFileName(None, '열기', '', "All Files(*.*)")
f_names = QFileDialog.getOpenFileNames(None, '열기', '', "All Files(*.*)")
# txtPath = f_name[0]
filelist = f_names[0]
if filelist:
for f_name in filelist:
# ext = os.path.splitext(f_name[0])[1]
ext = os.path.splitext(f_name)[1] # 확장자 확인
# if f_names[0]:
icnt = 0
for i in range(self.listwidget21.count()):
# if str(self.listwidget21.item(i).text()) == txtPath.replace("/","\\") or str(self.listwidget21.item(i).text()) == txtPath:
if str(self.listwidget21.item(i).text()) == f_name.replace("/","\\") or str(self.listwidget21.item(i).text()) == f_name:
icnt = 1
break
if icnt != 1:
f_path = f_name
if ext == '.exe':
QMessageBox.about(self,'파일 형식 확인','exe파일은 전송할 수 없습니다.')
pass
else:
cnt = self.listwidget21.count() +1
# self.listwidget21.insertItem(cnt, os.path.basename(txtPath))
# self.listwidget21.insertItem(cnt, txtPath)
# f_path = f_names[0]
# print(f_path)
self.listwidget21.insertItem(cnt, f_path)
# self.listwidget21.insertItem(cnt, f_path.replace("/","\\"))
def fn_filedel(self):
currentrow = self.listwidget21.currentRow()
self.listwidget21.takeItem(currentrow) # currentrowRight번째 항목을 삭제합니다
self.listwidget21.clearSelection()
if __name__ == '__main__':
# don't auto scale when drag app to a different monitor.
# QGuiApplication.setHighDpiScaleFactorRoundingPolicy(Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
excel_file_path = '급여1.xlsx'
worksheet_name = '4대급여'
emailsheet_name = '이메일'
app = QApplication(sys.argv)
app.setStyleSheet('''
QWidget {
font-size: 17px;
}
''')
myApp = MyApp()
myApp.show()
try:
sys.exit(app.exec())
except SystemExit:
print('Closing Window...')
====================
pay04.py--------------------
from operator import index
from unittest import result
from PyQt5.QtWidgets import QApplication, QWidget, QTableWidget, QTableWidgetItem, QPushButton, \
QHeaderView, QHBoxLayout, QVBoxLayout, QGridLayout, QAbstractScrollArea, QLabel, QListWidget, \
QFileDialog, QMessageBox, QTextEdit, QAbstractItemView
from PyQt5.QtCore import Qt
from PyQt5 import QtGui
import sys
import pandas as pd # pip install pandas
import os
import smtplib
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email.mime.image import MIMEImage
from email import encoders
import io
import secret
class MyApp(QWidget):
def __init__(self):
super().__init__()
self.window_width, self.window_height = 800, 600
self.resize(self.window_width, self.window_height)
self.setWindowTitle('pay')
##### layout_main #####
layout_main = QHBoxLayout()
self.setLayout(layout_main)
##### layout_1 #####
layout_1 = QVBoxLayout()
label11 = QLabel('직원 메일')
# self.button = QPushButton('&Load Data')
# self.button.clicked.connect(lambda _, xl_path=excel_file_path, sheet_name=worksheet_name: self.loadExcelData(xl_path, sheet_name))
# layout_v.addWidget(self.button)
layout_1.addWidget(label11)
self.table = QTableWidget()
self.table.setFixedWidth(310)
layout_1.addWidget(self.table)
layout_main.addLayout(layout_1)
##### layout_2 #####
layout_2 = QGridLayout()
label21 = QLabel('첨부파일')
layout_2.addWidget(label21, 0, 0, 1, 1)
self.listwidget21 = QListWidget()
self.listwidget21.setFixedWidth(300)
self.listwidget21.setSelectionMode(QAbstractItemView.ExtendedSelection)
layout_2.addWidget(self.listwidget21, 1, 0, 5, 1)
self.btn_file_add = QPushButton('파일 추가') # sendlist
# self.btn_file_add.setMinimumHeight(80)
layout_2.addWidget(self.btn_file_add, 1, 2, 1, 1)
self.btn_file_add.clicked.connect(self.fn_fileadd)
self.btn_file_del = QPushButton('파일 삭제')
layout_2.addWidget(self.btn_file_del, 2, 2, 1, 1)
self.btn_file_del.clicked.connect(self.fn_filedel)
label21 = QLabel('본문 (HTML형식)')
layout_2.addWidget(label21, 6, 0, 1, 1)
self.textedit22 = QTextEdit()
self.textedit22.setFixedWidth(300)
layout_2.addWidget(self.textedit22, 7, 0, 5, 1)
self.btn_send = QPushButton("보내기")
layout_2.addWidget(self.btn_send, 7, 2, 1, 1)
self.btn_send.clicked.connect(self.fn_test) #@@@@@@@@@@@@@@@@@@@@@@@@@@
layout_main.addLayout(layout_2)
# html 파일이 존재하면
filename = 'html0.txt'
if os.path.isfile(filename) == True:
html_text = open(filename,'r', encoding="UTF-8").read()
self.textedit22.setText(html_text)
# table_data = self.loadExcelData(excel_file_path, worksheet_name)
# print(table_data.keys())
df_table = self.loadExcelData(excel_file_path, worksheet_name)
# print(table_df["성명"][0])
self.df_table_02 = df_table.set_index("성명")
self.idx_list = self.df_table_02.index.to_list()
# print(index)
# for i in table_02["이메일"]:
def fn_test(self):
for idx in self.idx_list:
# print(idx)
# print(self.df_table_02.loc[idx][0])
# print(idx, table_02.loc[idx][0])
self.fn_print_name(idx, self.df_table_02.loc[idx][0])
def loadExcelData(self, excel_file_dir, worksheet_name):
df_work_sheet = pd.read_excel(excel_file_path, worksheet_name)
df_email_sheet = pd.read_excel(excel_file_path, emailsheet_name)
df_table = df_work_sheet.merge(df_email_sheet, how='left')
df_table_mail = df_table[['성명','이메일']]
res = df_table_mail
# res = df_table_mail.to_dict()
# self.table.setRowCount(df.shape[0])
# self.table.setColumnCount(df.shape[1])
self.table.setRowCount(df_table_mail.shape[0])
self.table.setColumnCount(df_table_mail.shape[1])
# self.table.setHorizontalHeaderLabels(df.columns)
self.table.setHorizontalHeaderLabels(df_table_mail.columns)
header = self.table.horizontalHeader()
# header.setSectionResizeMode(0, QHeaderView.Stretch)
# header.setSectionResizeMode(0, QHeaderView.ResizeToContents)
header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
# returns pandas array object
# for row in df.iterrows():
for row in df_table_mail.iterrows():
values = row[1]
for col_index, value in enumerate(values):
if isinstance(value, (float, int)):
value = '{0:0,.0f}'.format(value)
tableItem = QTableWidgetItem(str(value))
if value == "nan":
tableItem.setBackground(Qt.red)
self.table.setItem(row[0], col_index, tableItem)
self.table.setColumnWidth(2, 300)
return res
def fn_fileadd(self):
# f_name = QFileDialog.getOpenFileName(None, '열기', '', "All Files(*.*)")
f_names = QFileDialog.getOpenFileNames(None, '열기', '', "All Files(*.*)")
# txtPath = f_name[0]
filelist = f_names[0]
if filelist:
for f_name in filelist:
# ext = os.path.splitext(f_name[0])[1]
ext = os.path.splitext(f_name)[1] # 확장자 확인
# if f_names[0]:
icnt = 0
for i in range(self.listwidget21.count()):
# if str(self.listwidget21.item(i).text()) == txtPath.replace("/","\\") or str(self.listwidget21.item(i).text()) == txtPath:
if str(self.listwidget21.item(i).text()) == f_name.replace("/","\\") or str(self.listwidget21.item(i).text()) == f_name:
icnt = 1
break
if icnt != 1:
f_path = f_name
if ext == '.exe':
QMessageBox.about(self,'파일 형식 확인','exe파일은 전송할 수 없습니다.')
pass
else:
cnt = self.listwidget21.count() +1
# self.listwidget21.insertItem(cnt, os.path.basename(txtPath))
# self.listwidget21.insertItem(cnt, txtPath)
# f_path = f_names[0]
# print(f_path)
self.listwidget21.insertItem(cnt, f_path)
# self.listwidget21.insertItem(cnt, f_path.replace("/","\\"))
def fn_filedel(self):
currentrow = self.listwidget21.currentRow()
self.listwidget21.takeItem(currentrow) # currentrowRight번째 항목을 삭제합니다
self.listwidget21.clearSelection()
def fn_print_name(self, name, email):
# print(name, self.df_table_02.loc[name][0])
# print(name, email)
if len(self.textedit22.toPlainText())>0:
S__File = os.path.join(os.getcwd(),'html0.txt')
# print(len(self.textedit22.toPlainText()))
# print(S__File)
pretext = f'{name} 님<br><br>'
pretext += f'당신의 이메일은 {email} 입니다.'
contents = self.textedit22.toPlainText()
nexttext = f'<img src="cid:{attachment}" >'
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
file.write(pretext)
file.write(contents)
file.write(nexttext)
# print(contents)
# msgText = MIMEText(contents, 'html')
def fn_html_save(self):
if len(self.textedit22.toPlainText())>0:
# print(len(self.textedit.toPlainText()))
# S__File = QFileDialog.getSaveFileName(None,'문자 파일저장','/', "Text Files (*.txt)")
# S__File = QFileDialog.getSaveFileName(None,'문자 파일저장','html0', "Text Files (*.txt)")
S__File = os.path.join(os.getcwd(),'html0.txt')
# This will let you access the test in your QTextEdit
Text = self.textedit22.toPlainText()
# This will prevent you from an error if pressed cancel on file dialog.
# if S__File[0]:
if S__File:
# Finally this will Save your file to the path selected.
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
file.write(Text)
# txtPath = S__File[0]
# icnt = 0
# for i in range(self.listwidget31.count()):
# if str(self.listwidget31.item(i).text()) == txtPath.replace("/","\\"):
# icnt = 1
# break
# if icnt != 1:
# cnt = self.listwidget31.count() +1
# self.listwidget31.insertItem(cnt, os.path.basename(txtPath))
# self.listwidget31.insertItem(cnt, txtPath)
else:
QMessageBox.about(self,'메시지 입력 확인','메시지를 입력하셔야 합니다.')
def fn_send(self, name, email_i):
# 메일 서버를 설정합니다.
# server = smtplib.SMTP('smtp.com', port_number)
# server = smtplib.SMTP_SSL('smtp.kakao.com:465')
server = smtplib.SMTP_SSL('smtp.kakao.com')
# server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# 로그인이 필요하면 로그인 설정
server.login(secret.kakao_id, secret.kakao_pw)
# 보내는 사람, 받는 사람 설정
msg_from = 'miero@kakao.com'
msg_to = email_i
# cc = 'b@b.com, c@c.com'
cc = ''
# 메세지 구성
msg = MIMEBase('multipart','mixed')
msg['Subject'] = f'{name} 님 - 2022년 08월 급여명세서'
msg['From'] = msg_from
msg['To'] = msg_to
msg['Cc'] = cc
logo_file = r"C:\Users\newstep\Pictures\number1.jpg"
img_f_name = logo_file.replace("\\","/")
# with io.open('file_name.html','r') as f:
with io.open(img_f_name,'r') as f:
# emailtext = f.read()
emailtext = img_f_name
# attachment = 'attachment_file_name.png'
attachment = img_f_name
fp = open(attachment, 'rb')
img = MIMEImage(fp.read())
fp.close()
img.add_header('Content-ID', '<{}>'.format(attachment))
msg.attach(img)
# 메일 본문 작성
# # html 로 되어있던 파일을 불러 오고 거기에 파일을 붙여서 보냅니다.
# msgText = MIMEText('<h1>%s</h1><hr>, <img src="cid:%s" >' % (emailtext, attachment), 'html')
# contents = '<h1>%s</h1>'
# contents += '<hr>'
# contents += '<img src="cid:%s" >'
# msgText = MIMEText(contents % (emailtext, attachment), 'html')
# contents = f'<h1>{emailtext}</h1>'
# contents += f'<h2>{msg_to} 님 메일이 도착했습니다.</h2>'
# contents += '<hr>'
# contents += f'<img src="cid:{attachment}" >'
# msgText = MIMEText(contents, 'html')
contents = self.textedit22.toPlainText()
msgText = MIMEText(contents, 'html')
# 메세지를 메일에 붙여 줍니다.
msg.attach(msgText)
# 메일 서버를 이용하여 메일을 발송합니다.
# server.sendmail(msg_from, msg["To"].split(",") + msg["Cc"].split(","), msg.as_string())
server.sendmail(msg_from, msg_to, msg.as_string())
server.quit()
if __name__ == '__main__':
# don't auto scale when drag app to a different monitor.
# QGuiApplication.setHighDpiScaleFactorRoundingPolicy(Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
excel_file_path = '급여1.xlsx'
worksheet_name = '4대급여'
emailsheet_name = '이메일'
app = QApplication(sys.argv)
app.setStyleSheet('''
QWidget {
font-size: 17px;
}
''')
myApp = MyApp()
myApp.show()
try:
sys.exit(app.exec())
except SystemExit:
print('Closing Window...')
====================
pay05.py--------------------
from operator import index
from unittest import result
from xml.dom.minidom import Document
from PyQt5.QtWidgets import QApplication, QWidget, QTableWidget, QTableWidgetItem, QPushButton, \
QHeaderView, QHBoxLayout, QVBoxLayout, QGridLayout, QAbstractScrollArea, QLabel, QListWidget, \
QFileDialog, QMessageBox, QTextEdit, QAbstractItemView
from PyQt5.QtCore import Qt
# from PyQt5 import QtGui
from PyQt5.QtGui import QTextCursor
import sys
import pandas as pd # pip install pandas
import os
import smtplib
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email.mime.image import MIMEImage
from email import encoders
import io
import secret
class MyApp(QWidget):
def __init__(self):
super().__init__()
self.window_width, self.window_height = 800, 600
self.resize(self.window_width, self.window_height)
self.setWindowTitle('pay')
##### layout_main #####
layout_main = QHBoxLayout()
self.setLayout(layout_main)
##### layout_1 #####
layout_1 = QVBoxLayout()
label11 = QLabel('직원 메일')
# self.button = QPushButton('&Load Data')
# self.button.clicked.connect(lambda _, xl_path=excel_file_path, sheet_name=worksheet_name: self.loadExcelData(xl_path, sheet_name))
# layout_v.addWidget(self.button)
layout_1.addWidget(label11)
self.table = QTableWidget()
self.table.setFixedWidth(310)
layout_1.addWidget(self.table)
layout_main.addLayout(layout_1)
##### layout_2 #####
layout_2 = QGridLayout()
label21 = QLabel('첨부파일')
layout_2.addWidget(label21, 0, 0, 1, 1)
self.listwidget21 = QListWidget()
self.listwidget21.setFixedWidth(300)
self.listwidget21.setSelectionMode(QAbstractItemView.ExtendedSelection)
layout_2.addWidget(self.listwidget21, 1, 0, 5, 1)
self.btn_file_add = QPushButton('파일 추가') # sendlist
# self.btn_file_add.setMinimumHeight(80)
layout_2.addWidget(self.btn_file_add, 1, 2, 1, 1)
self.btn_file_add.clicked.connect(self.fn_fileadd)
self.btn_file_del = QPushButton('파일 삭제')
layout_2.addWidget(self.btn_file_del, 2, 2, 1, 1)
self.btn_file_del.clicked.connect(self.fn_filedel)
label21 = QLabel('본문 (HTML형식)')
layout_2.addWidget(label21, 6, 0, 1, 1)
self.textedit22 = QTextEdit()
self.textedit22.setFixedWidth(300)
self.textedit22.setAcceptRichText(False)
layout_2.addWidget(self.textedit22, 7, 0, 5, 1)
self.btn_send = QPushButton("보내기")
layout_2.addWidget(self.btn_send, 7, 2, 1, 1)
self.btn_send.clicked.connect(self.fn_test) #@@@@@@@@@@@@@@@@@@@@@@@@@@
layout_main.addLayout(layout_2)
# html 파일이 존재하면
filename = 'html0.txt'
if os.path.isfile(filename) == True:
source_text = open(filename,'r', encoding="UTF-8").read()
# self.textedit22.setText(source_text) # TextEdit에 RichText 형식의 글을 입력합니다.
self.textedit22.setPlainText(source_text) # TextEdit에 PlainText 형식의 글을 새로 입력합니다.
# table_data = self.loadExcelData(excel_file_path, worksheet_name)
# print(table_data.keys())
df_table = self.loadExcelData(excel_file_path, worksheet_name)
# print(table_df["성명"][0])
self.df_table_02 = df_table.set_index("성명")
self.idx_list = self.df_table_02.index.to_list()
# print(index)
# for i in table_02["이메일"]:
def loadExcelData(self, excel_file_dir, worksheet_name):
df_work_sheet = pd.read_excel(excel_file_path, worksheet_name)
df_email_sheet = pd.read_excel(excel_file_path, emailsheet_name)
df_table = df_work_sheet.merge(df_email_sheet, how='left')
df_table_mail = df_table[['성명','이메일']]
res = df_table_mail
# res = df_table_mail.to_dict()
# self.table.setRowCount(df.shape[0])
# self.table.setColumnCount(df.shape[1])
self.table.setRowCount(df_table_mail.shape[0])
self.table.setColumnCount(df_table_mail.shape[1])
# self.table.setHorizontalHeaderLabels(df.columns)
self.table.setHorizontalHeaderLabels(df_table_mail.columns)
header = self.table.horizontalHeader()
# header.setSectionResizeMode(0, QHeaderView.Stretch)
# header.setSectionResizeMode(0, QHeaderView.ResizeToContents)
header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
# returns pandas array object
# for row in df.iterrows():
for row in df_table_mail.iterrows():
values = row[1]
for col_index, value in enumerate(values):
if isinstance(value, (float, int)):
value = '{0:0,.0f}'.format(value)
tableItem = QTableWidgetItem(str(value))
if value == "nan":
tableItem.setBackground(Qt.red)
self.table.setItem(row[0], col_index, tableItem)
self.table.setColumnWidth(2, 300)
return res
def fn_fileadd(self):
# f_name = QFileDialog.getOpenFileName(None, '열기', '', "All Files(*.*)")
f_names = QFileDialog.getOpenFileNames(None, '열기', '', "All Files(*.*)")
# txtPath = f_name[0]
filelist = f_names[0]
if filelist:
for f_name in filelist:
# ext = os.path.splitext(f_name[0])[1]
ext = os.path.splitext(f_name)[1] # 확장자 확인
# if f_names[0]:
icnt = 0
for i in range(self.listwidget21.count()):
# if str(self.listwidget21.item(i).text()) == txtPath.replace("/","\\") or str(self.listwidget21.item(i).text()) == txtPath:
if str(self.listwidget21.item(i).text()) == f_name.replace("/","\\") or str(self.listwidget21.item(i).text()) == f_name:
icnt = 1
break
if icnt != 1:
f_path = f_name
if ext == '.exe':
QMessageBox.about(self,'파일 형식 확인','exe파일은 전송할 수 없습니다.')
pass
else:
cnt = self.listwidget21.count() +1
# self.listwidget21.insertItem(cnt, os.path.basename(txtPath))
# self.listwidget21.insertItem(cnt, txtPath)
# f_path = f_names[0]
# print(f_path)
self.listwidget21.insertItem(cnt, f_path)
# self.listwidget21.insertItem(cnt, f_path.replace("/","\\"))
def fn_filedel(self):
currentrow = self.listwidget21.currentRow()
self.listwidget21.takeItem(currentrow) # currentrowRight번째 항목을 삭제합니다
self.listwidget21.clearSelection()
def fn_html_save(self):
if len(self.textedit22.toPlainText())>0:
# print(len(self.textedit.toPlainText()))
# S__File = QFileDialog.getSaveFileName(None,'문자 파일저장','/', "Text Files (*.txt)")
# S__File = QFileDialog.getSaveFileName(None,'문자 파일저장','html0', "Text Files (*.txt)")
S__File = os.path.join(os.getcwd(),'html0.txt')
# This will let you access the test in your QTextEdit
Text = self.textedit22.toPlainText()
# document = self.textedit22.document()
# cursor = QTextCursor(document)
# p1 = cursor.position() # return int
# cursor.insertImage(r"C:\Users\newstep\Pictures\number1.jpg")
# This will prevent you from an error if pressed cancel on file dialog.
# if S__File[0]:
if S__File:
# Finally this will Save your file to the path selected.
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
file.write(Text)
# txtPath = S__File[0]
# icnt = 0
# for i in range(self.listwidget31.count()):
# if str(self.listwidget31.item(i).text()) == txtPath.replace("/","\\"):
# icnt = 1
# break
# if icnt != 1:
# cnt = self.listwidget31.count() +1
# self.listwidget31.insertItem(cnt, os.path.basename(txtPath))
# self.listwidget31.insertItem(cnt, txtPath)
else:
QMessageBox.about(self,'메시지 입력 확인','메시지를 입력하셔야 합니다.')
def fn_print_name(self, name, email):
# f_name_pre = r"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' width='50%' height='0%'></center>"
# f_name = f_name_pre.replace("\\","/")
# with io.open('file_name.html','r') as f:
# with io.open(f_name,'r') as f:
# # emailtext = f.read()
# emailtext = f_name
# attachment = 'attachment_file_name.png'
# attachment = f_name
# print(name, self.df_table_02.loc[name][0])
# print(name, email)
if len(self.textedit22.toPlainText())>0:
S__File = os.path.join(os.getcwd(),'html0.txt')
# print(len(self.textedit22.toPlainText()))
# print(S__File)
pretext = f'{name} 님<br/><br/>'
# pretext += f'당신의 이메일은 {email} 입니다.<br/>'
contents = self.textedit22.toPlainText()
# nexttext = f'<br/><img src="cid:{attachment}" >'
nexttext = f"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' width='50%' height='0%'></center>"
# document = self.textedit22.document()
# cursor = QTextCursor(document)
# p1 = cursor.position() # return int
# cursor.insertImage(f_name)
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
# file.write(pretext)
file.write(contents)
# file.write(nexttext)
# print(contents)
# msgText = MIMEText(contents, 'html')
print(name,email,"전송완료")
def fn_send(self, name, email_i):
# 메일 서버를 설정합니다.
# server = smtplib.SMTP('smtp.com', port_number)
# server = smtplib.SMTP_SSL('smtp.kakao.com:465')
server = smtplib.SMTP_SSL('smtp.kakao.com')
# server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# 로그인이 필요하면 로그인 설정
server.login(secret.kakao_id, secret.kakao_pw)
# 보내는 사람, 받는 사람 설정
msg_from = 'miero@kakao.com'
msg_to = email_i
# cc = 'b@b.com, c@c.com'
cc = ''
# print(name,email_i)
# 메세지 구성
msg = MIMEBase('multipart','mixed')
msg['Subject'] = f'{name} 님 - 2022년 08월 급여명세서'
msg['From'] = msg_from
msg['To'] = msg_to
msg['Cc'] = cc
# 메일 본문 작성
# # html 로 되어있던 파일을 불러 오고 거기에 파일을 붙여서 보냅니다.
# msgText = MIMEText('<h1>%s</h1><hr>, <img src="cid:%s" >' % (emailtext, attachment), 'html')
# contents = '<h1>%s</h1>'
# contents += '<hr>'
# contents += '<img src="cid:%s" >'
# msgText = MIMEText(contents % (emailtext, attachment), 'html')
# contents = f'<h1>{emailtext}</h1>'
# contents += f'<h2>{msg_to} 님 메일이 도착했습니다.</h2>'
# contents += '<hr>'
# contents += f'<img src="cid:{attachment}" >'
# msgText = MIMEText(contents, 'html')
pretext = f'수신: {name}<br/>'
pretext += '발신: 주식회사 밀앤아이, 주식회사 헴펠 대표이사<br/>'
pretext += '<br/>'
msgpreText = MIMEText(pretext, 'html')
msg.attach(msgpreText)
contents = self.textedit22.toPlainText()
msgText = MIMEText(contents, 'html')
# 메세지를 메일에 붙여 줍니다.
msg.attach(msgText)
# 메일 제일 밑에 로고그림 붙여 줍니다.
# logo_file = "logo.jpg"
# img_f_name = logo_file.replace("\\","/")
# logo_file = r"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' width='10%' height='0%'></center>"
# img_f_name = logo_file.replace("\\","/")
# # with io.open('file_name.html','r') as f:
# with io.open(img_f_name,'r') as f:
# # emailtext = f.read()
# emailtext = img_f_name
# # attachment = 'attachment_file_name.png'
# attachment = img_f_name
# attachment = logo_file
# fp = open(attachment, 'rb')
# img = MIMEImage(fp.read())
# fp.close()
# img.add_header('Content-ID', '<{}>'.format(attachment))
# msg.attach(img)
# # 메일 서버를 이용하여 메일을 발송합니다.
# # server.sendmail(msg_from, msg["To"].split(",") + msg["Cc"].split(","), msg.as_string())
server.sendmail(msg_from, msg_to, msg.as_string())
server.quit()
def fn_test(self):
# self.fn_send("밀1", self.df_table_02.loc["밀1"][0])
# self.fn_print_name("밀1", self.df_table_02.loc["밀1"][0])
for idx in self.idx_list:
# print(idx)
# print(self.df_table_02.loc[idx][0])
# print(idx, table_02.loc[idx][0])
self.fn_send(idx, self.df_table_02.loc[idx][0])
self.fn_print_name(idx, self.df_table_02.loc[idx][0])
# self.fn_send(idx, self.df_table_02.loc[idx][0])
if __name__ == '__main__':
# don't auto scale when drag app to a different monitor.
# QGuiApplication.setHighDpiScaleFactorRoundingPolicy(Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
excel_file_path = '급여1.xlsx'
worksheet_name = '4대급여'
emailsheet_name = '이메일'
app = QApplication(sys.argv)
app.setStyleSheet('''
QWidget {
font-size: 17px;
}
''')
myApp = MyApp()
myApp.show()
try:
sys.exit(app.exec())
except SystemExit:
print('Closing Window...')
====================
pay06.py--------------------
from operator import index
from unittest import result
from xml.dom.minidom import Document
from PyQt5.QtWidgets import QApplication, QWidget, QTableWidget, QTableWidgetItem, QPushButton, \
QHeaderView, QHBoxLayout, QVBoxLayout, QGridLayout, QAbstractScrollArea, QLabel, QListWidget, \
QFileDialog, QMessageBox, QTextEdit, QAbstractItemView
from PyQt5.QtCore import Qt
# from PyQt5 import QtGui
from PyQt5.QtGui import QTextCursor
import sys
import pandas as pd # pip install pandas
import os
import smtplib
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email.mime.image import MIMEImage
from email import encoders
from email.encoders import encode_base64
import io
import secret
class MyApp(QWidget):
def __init__(self):
super().__init__()
self.window_width, self.window_height = 800, 600
self.resize(self.window_width, self.window_height)
self.setWindowTitle('pay')
##### layout_main #####
layout_main = QHBoxLayout()
self.setLayout(layout_main)
##### layout_1 #####
layout_1 = QVBoxLayout()
label11 = QLabel('직원 메일')
# self.button = QPushButton('&Load Data')
# self.button.clicked.connect(lambda _, xl_path=excel_file_path, sheet_name=worksheet_name: self.loadExcelData(xl_path, sheet_name))
# layout_v.addWidget(self.button)
layout_1.addWidget(label11)
self.table = QTableWidget()
self.table.setFixedWidth(310)
layout_1.addWidget(self.table)
layout_main.addLayout(layout_1)
##### layout_2 #####
layout_2 = QGridLayout()
label21 = QLabel('첨부파일')
layout_2.addWidget(label21, 0, 0, 1, 1)
self.listwidget21 = QListWidget()
self.listwidget21.setFixedWidth(300)
self.listwidget21.setSelectionMode(QAbstractItemView.ExtendedSelection)
layout_2.addWidget(self.listwidget21, 1, 0, 5, 1)
self.btn_file_add = QPushButton('파일 추가') # sendlist
# self.btn_file_add.setMinimumHeight(80)
layout_2.addWidget(self.btn_file_add, 1, 2, 1, 1)
self.btn_file_add.clicked.connect(self.fn_fileadd)
self.btn_file_del = QPushButton('파일 삭제')
layout_2.addWidget(self.btn_file_del, 2, 2, 1, 1)
self.btn_file_del.clicked.connect(self.fn_filedel)
label21 = QLabel('본문 (HTML형식)')
layout_2.addWidget(label21, 6, 0, 1, 1)
self.textedit22 = QTextEdit()
self.textedit22.setFixedWidth(300)
self.textedit22.setAcceptRichText(False)
layout_2.addWidget(self.textedit22, 7, 0, 5, 1)
self.btn_send = QPushButton("보내기")
layout_2.addWidget(self.btn_send, 7, 2, 1, 1)
self.btn_send.clicked.connect(self.fn_test) #@@@@@@@@@@@@@@@@@@@@@@@@@@
layout_main.addLayout(layout_2)
# html 파일이 존재하면
filename = 'html0.txt'
if os.path.isfile(filename) == True:
source_text = open(filename,'r', encoding="UTF-8").read()
# self.textedit22.setText(source_text) # TextEdit에 RichText 형식의 글을 입력합니다.
self.textedit22.setPlainText(source_text) # TextEdit에 PlainText 형식의 글을 새로 입력합니다.
# table_data = self.loadExcelData(excel_file_path, worksheet_name)
# print(table_data.keys())
df_table = self.loadExcelData(excel_file_path, worksheet_name)
# print(table_df["성명"][0])
self.df_table_02 = df_table.set_index("성명")
self.idx_list = self.df_table_02.index.to_list()
# print(index)
# for i in table_02["이메일"]:
def loadExcelData(self, excel_file_dir, worksheet_name):
df_work_sheet = pd.read_excel(excel_file_path, worksheet_name)
df_email_sheet = pd.read_excel(excel_file_path, emailsheet_name)
df_table = df_work_sheet.merge(df_email_sheet, how='left')
df_table_mail = df_table[['성명','이메일']]
res = df_table_mail
# res = df_table_mail.to_dict()
# self.table.setRowCount(df.shape[0])
# self.table.setColumnCount(df.shape[1])
self.table.setRowCount(df_table_mail.shape[0])
self.table.setColumnCount(df_table_mail.shape[1])
# self.table.setHorizontalHeaderLabels(df.columns)
self.table.setHorizontalHeaderLabels(df_table_mail.columns)
header = self.table.horizontalHeader()
# header.setSectionResizeMode(0, QHeaderView.Stretch)
# header.setSectionResizeMode(0, QHeaderView.ResizeToContents)
header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
# returns pandas array object
# for row in df.iterrows():
for row in df_table_mail.iterrows():
values = row[1]
for col_index, value in enumerate(values):
if isinstance(value, (float, int)):
value = '{0:0,.0f}'.format(value)
tableItem = QTableWidgetItem(str(value))
if value == "nan":
tableItem.setBackground(Qt.red)
self.table.setItem(row[0], col_index, tableItem)
self.table.setColumnWidth(2, 300)
return res
def fn_fileadd(self):
# f_name = QFileDialog.getOpenFileName(None, '열기', '', "All Files(*.*)")
f_names = QFileDialog.getOpenFileNames(None, '열기', '', "All Files(*.*)")
# txtPath = f_name[0]
filelist = f_names[0]
if filelist:
for f_name in filelist:
# ext = os.path.splitext(f_name[0])[1]
ext = os.path.splitext(f_name)[1] # 확장자 확인
# if f_names[0]:
icnt = 0
for i in range(self.listwidget21.count()):
# if str(self.listwidget21.item(i).text()) == txtPath.replace("/","\\") or str(self.listwidget21.item(i).text()) == txtPath:
if str(self.listwidget21.item(i).text()) == f_name.replace("/","\\") or str(self.listwidget21.item(i).text()) == f_name:
icnt = 1
break
if icnt != 1:
f_path = f_name
if ext == '.exe':
QMessageBox.about(self,'파일 형식 확인','exe파일은 전송할 수 없습니다.')
pass
else:
cnt = self.listwidget21.count() +1
# self.listwidget21.insertItem(cnt, os.path.basename(txtPath))
# self.listwidget21.insertItem(cnt, txtPath)
# f_path = f_names[0]
# print(f_path)
self.listwidget21.insertItem(cnt, f_path)
# self.listwidget21.insertItem(cnt, f_path.replace("/","\\"))
def fn_filedel(self):
currentrow = self.listwidget21.currentRow()
self.listwidget21.takeItem(currentrow) # currentrowRight번째 항목을 삭제합니다
self.listwidget21.clearSelection()
def fn_html_save(self):
if len(self.textedit22.toPlainText())>0:
# print(len(self.textedit.toPlainText()))
# S__File = QFileDialog.getSaveFileName(None,'문자 파일저장','/', "Text Files (*.txt)")
# S__File = QFileDialog.getSaveFileName(None,'문자 파일저장','html0', "Text Files (*.txt)")
S__File = os.path.join(os.getcwd(),'html0.txt')
# This will let you access the test in your QTextEdit
Text = self.textedit22.toPlainText()
# document = self.textedit22.document()
# cursor = QTextCursor(document)
# p1 = cursor.position() # return int
# cursor.insertImage(r"C:\Users\newstep\Pictures\number1.jpg")
# This will prevent you from an error if pressed cancel on file dialog.
# if S__File[0]:
if S__File:
# Finally this will Save your file to the path selected.
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
file.write(Text)
# txtPath = S__File[0]
# icnt = 0
# for i in range(self.listwidget31.count()):
# if str(self.listwidget31.item(i).text()) == txtPath.replace("/","\\"):
# icnt = 1
# break
# if icnt != 1:
# cnt = self.listwidget31.count() +1
# self.listwidget31.insertItem(cnt, os.path.basename(txtPath))
# self.listwidget31.insertItem(cnt, txtPath)
else:
QMessageBox.about(self,'메시지 입력 확인','메시지를 입력하셔야 합니다.')
def fn_print_name(self, name, email):
# f_name_pre = r"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' width='50%' height='0%'></center>"
# f_name = f_name_pre.replace("\\","/")
# with io.open('file_name.html','r') as f:
# with io.open(f_name,'r') as f:
# # emailtext = f.read()
# emailtext = f_name
# attachment = 'attachment_file_name.png'
# attachment = f_name
# print(name, self.df_table_02.loc[name][0])
# print(name, email)
if len(self.textedit22.toPlainText())>0:
S__File = os.path.join(os.getcwd(),'html0.txt')
# print(len(self.textedit22.toPlainText()))
# print(S__File)
pretext = f'{name} 님<br/><br/>'
# pretext += f'당신의 이메일은 {email} 입니다.<br/>'
contents = self.textedit22.toPlainText()
# nexttext = f'<br/><img src="cid:{attachment}" >'
nexttext = f"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' width='50%' height='0%'></center>"
# document = self.textedit22.document()
# cursor = QTextCursor(document)
# p1 = cursor.position() # return int
# cursor.insertImage(f_name)
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
# file.write(pretext)
file.write(contents)
# file.write(nexttext)
# print(contents)
# msgText = MIMEText(contents, 'html')
print(name,email,"전송완료")
def fn_send(self, name, email_i):
# 메일 서버를 설정합니다.
# server = smtplib.SMTP('smtp.com', port_number)
# server = smtplib.SMTP_SSL('smtp.kakao.com:465')
server = smtplib.SMTP_SSL('smtp.kakao.com')
# server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# 로그인이 필요하면 로그인 설정
server.login(secret.kakao_id, secret.kakao_pw)
# 보내는 사람, 받는 사람 설정
msg_from = 'miero@kakao.com'
msg_to = email_i
# cc = 'b@b.com, c@c.com'
cc = ''
# print(name,email_i)
# 메세지 구성
msg = MIMEBase('multipart','mixed')
msg['Subject'] = f'{name} 님 - 2022년 08월 급여명세서'
msg['From'] = msg_from
msg['To'] = msg_to
msg['Cc'] = cc
# 메일 본문 작성
# # html 로 되어있던 파일을 불러 오고 거기에 파일을 붙여서 보냅니다.
# msgText = MIMEText('<h1>%s</h1><hr>, <img src="cid:%s" >' % (emailtext, attachment), 'html')
# contents = '<h1>%s</h1>'
# contents += '<hr>'
# contents += '<img src="cid:%s" >'
# msgText = MIMEText(contents % (emailtext, attachment), 'html')
# contents = f'<h1>{emailtext}</h1>'
# contents += f'<h2>{msg_to} 님 메일이 도착했습니다.</h2>'
# contents += '<hr>'
# contents += f'<img src="cid:{attachment}" >'
# msgText = MIMEText(contents, 'html')
pretext = f'수신: {name}<br/>'
pretext += '발신: 주식회사 밀앤아이, 주식회사 헴펠 대표이사<br/>'
pretext += '<br/>'
msgpreText = MIMEText(pretext, 'html')
msg.attach(msgpreText)
contents = self.textedit22.toPlainText()
msgText = MIMEText(contents, 'html')
# 메세지를 메일에 붙여 줍니다.
msg.attach(msgText)
# 메일 제일 밑에 로고그림 붙여 줍니다.
# logo_file = "logo.jpg"
# img_f_name = logo_file.replace("\\","/")
# logo_file = r"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' width='10%' height='0%'></center>"
# img_f_name = logo_file.replace("\\","/")
# # with io.open('file_name.html','r') as f:
# with io.open(img_f_name,'r') as f:
# # emailtext = f.read()
# emailtext = img_f_name
# # attachment = 'attachment_file_name.png'
# attachment = img_f_name
# attachment = logo_file
# fp = open(attachment, 'rb')
# img = MIMEImage(fp.read())
# fp.close()
# img.add_header('Content-ID', '<{}>'.format(attachment))
# msg.attach(img)
# 파일 첨부
files = list()
for i in range(self.listwidget21.count()):
files.append(self.listwidget21.item(i).text())
for f in files:
part = MIMEBase('application', "octet-stream")
part.set_payload(open(f,"rb").read())
encode_base64(part)
part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(f))
msg.attach(part)
# 메일 서버를 이용하여 메일을 발송합니다.
# server.sendmail(msg_from, msg["To"].split(",") + msg["Cc"].split(","), msg.as_string())
server.sendmail(msg_from, msg_to, msg.as_string())
server.quit()
def fn_test(self):
self.fn_send("밀1", self.df_table_02.loc["밀1"][0])
self.fn_print_name("밀1", self.df_table_02.loc["밀1"][0])
# for idx in self.idx_list:
# print(idx)
# print(self.df_table_02.loc[idx][0])
# print(idx, table_02.loc[idx][0])
# self.fn_send(idx, self.df_table_02.loc[idx][0])
# self.fn_print_name(idx, self.df_table_02.loc[idx][0])
if __name__ == '__main__':
# don't auto scale when drag app to a different monitor.
# QGuiApplication.setHighDpiScaleFactorRoundingPolicy(Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
excel_file_path = '급여1.xlsx'
worksheet_name = '4대급여'
emailsheet_name = '이메일'
app = QApplication(sys.argv)
app.setStyleSheet('''
QWidget {
font-size: 17px;
}
''')
myApp = MyApp()
myApp.show()
try:
sys.exit(app.exec())
except SystemExit:
print('Closing Window...')
====================
pay07.py--------------------
from operator import index
from unittest import result
from xml.dom.minidom import Document
from PyQt5.QtWidgets import QApplication, QWidget, QTableWidget, QTableWidgetItem, QPushButton, \
QHeaderView, QHBoxLayout, QVBoxLayout, QGridLayout, QAbstractScrollArea, QLabel, QListWidget, \
QFileDialog, QMessageBox, QTextEdit, QAbstractItemView
from PyQt5.QtCore import Qt
# from PyQt5 import QtGui
from PyQt5.QtGui import QTextCursor
import sys
import pandas as pd # pip install pandas
import os
import smtplib
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email.mime.image import MIMEImage
from email import encoders
from email.encoders import encode_base64
import io
import secret
class MyApp(QWidget):
def __init__(self):
super().__init__()
self.window_width, self.window_height = 800, 600
self.resize(self.window_width, self.window_height)
self.setWindowTitle('pay')
##### layout_main #####
layout_main = QHBoxLayout()
self.setLayout(layout_main)
##### layout_1 #####
layout_1 = QVBoxLayout()
label11 = QLabel('직원 메일')
# self.button = QPushButton('&Load Data')
# self.button.clicked.connect(lambda _, xl_path=excel_file_path, sheet_name=worksheet_name: self.loadExcelData(xl_path, sheet_name))
# layout_v.addWidget(self.button)
layout_1.addWidget(label11)
self.table = QTableWidget()
self.table.setFixedWidth(310)
layout_1.addWidget(self.table)
layout_main.addLayout(layout_1)
##### layout_2 #####
layout_2 = QGridLayout()
label21 = QLabel('첨부파일')
layout_2.addWidget(label21, 0, 0, 1, 1)
self.listwidget21 = QListWidget()
self.listwidget21.setFixedWidth(300)
self.listwidget21.setSelectionMode(QAbstractItemView.ExtendedSelection)
layout_2.addWidget(self.listwidget21, 1, 0, 5, 1)
self.btn_file_add = QPushButton('파일 추가') # sendlist
# self.btn_file_add.setMinimumHeight(80)
layout_2.addWidget(self.btn_file_add, 1, 2, 1, 1)
self.btn_file_add.clicked.connect(self.fn_fileadd)
self.btn_file_del = QPushButton('파일 삭제')
layout_2.addWidget(self.btn_file_del, 2, 2, 1, 1)
self.btn_file_del.clicked.connect(self.fn_filedel)
label21 = QLabel('본문 (HTML형식)')
layout_2.addWidget(label21, 6, 0, 1, 1)
self.textedit22 = QTextEdit()
self.textedit22.setFixedWidth(300)
self.textedit22.setAcceptRichText(False)
layout_2.addWidget(self.textedit22, 7, 0, 5, 1)
self.btn_send = QPushButton("보내기")
layout_2.addWidget(self.btn_send, 7, 2, 1, 1)
self.btn_send.clicked.connect(self.fn_test) #@@@@@@@@@@@@@@@@@@@@@@@@@@
layout_main.addLayout(layout_2)
# html 파일이 존재하면
filename = 'html0.txt'
if os.path.isfile(filename) == True:
source_text = open(filename,'r', encoding="UTF-8").read()
# self.textedit22.setText(source_text) # TextEdit에 RichText 형식의 글을 입력합니다.
self.textedit22.setPlainText(source_text) # TextEdit에 PlainText 형식의 글을 새로 입력합니다.
# table_data = self.loadExcelData(excel_file_path, worksheet_name)
# print(table_data.keys())
df_table = self.loadExcelData(excel_file_path, worksheet_name)
# print(table_df["성명"][0])
self.df_table_02 = df_table.set_index("성명")
self.idx_list = self.df_table_02.index.to_list()
# print(index)
# for i in table_02["이메일"]:
def loadExcelData(self, excel_file_dir, worksheet_name):
df_work_sheet = pd.read_excel(excel_file_path, worksheet_name)
df_email_sheet = pd.read_excel(excel_file_path, emailsheet_name)
df_table = df_work_sheet.merge(df_email_sheet, how='left')
df_table_mail = df_table[['성명','이메일']]
res = df_table_mail
# res = df_table_mail.to_dict()
# self.table.setRowCount(df.shape[0])
# self.table.setColumnCount(df.shape[1])
self.table.setRowCount(df_table_mail.shape[0])
self.table.setColumnCount(df_table_mail.shape[1])
# self.table.setHorizontalHeaderLabels(df.columns)
self.table.setHorizontalHeaderLabels(df_table_mail.columns)
header = self.table.horizontalHeader()
# header.setSectionResizeMode(0, QHeaderView.Stretch)
# header.setSectionResizeMode(0, QHeaderView.ResizeToContents)
header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
# returns pandas array object
# for row in df.iterrows():
for row in df_table_mail.iterrows():
values = row[1]
for col_index, value in enumerate(values):
if isinstance(value, (float, int)):
value = '{0:0,.0f}'.format(value)
tableItem = QTableWidgetItem(str(value))
if value == "nan":
tableItem.setBackground(Qt.red)
self.table.setItem(row[0], col_index, tableItem)
self.table.setColumnWidth(2, 300)
return res
def fn_fileadd(self):
# f_name = QFileDialog.getOpenFileName(None, '열기', '', "All Files(*.*)")
f_names = QFileDialog.getOpenFileNames(None, '열기', '', "All Files(*.*)")
# txtPath = f_name[0]
filelist = f_names[0]
if filelist:
for f_name in filelist:
# ext = os.path.splitext(f_name[0])[1]
ext = os.path.splitext(f_name)[1] # 확장자 확인
# if f_names[0]:
icnt = 0
for i in range(self.listwidget21.count()):
# if str(self.listwidget21.item(i).text()) == txtPath.replace("/","\\") or str(self.listwidget21.item(i).text()) == txtPath:
if str(self.listwidget21.item(i).text()) == f_name.replace("/","\\") or str(self.listwidget21.item(i).text()) == f_name:
icnt = 1
break
if icnt != 1:
f_path = f_name
if ext == '.exe':
QMessageBox.about(self,'파일 형식 확인','exe파일은 전송할 수 없습니다.')
pass
else:
cnt = self.listwidget21.count() +1
# self.listwidget21.insertItem(cnt, os.path.basename(txtPath))
# self.listwidget21.insertItem(cnt, txtPath)
# f_path = f_names[0]
# print(f_path)
self.listwidget21.insertItem(cnt, f_path)
# self.listwidget21.insertItem(cnt, f_path.replace("/","\\"))
def fn_filedel(self):
currentrow = self.listwidget21.currentRow()
self.listwidget21.takeItem(currentrow) # currentrowRight번째 항목을 삭제합니다
self.listwidget21.clearSelection()
def fn_html_save(self):
if len(self.textedit22.toPlainText())>0:
# print(len(self.textedit.toPlainText()))
# S__File = QFileDialog.getSaveFileName(None,'문자 파일저장','/', "Text Files (*.txt)")
# S__File = QFileDialog.getSaveFileName(None,'문자 파일저장','html0', "Text Files (*.txt)")
S__File = os.path.join(os.getcwd(),'html0.txt')
# This will let you access the test in your QTextEdit
Text = self.textedit22.toPlainText()
# document = self.textedit22.document()
# cursor = QTextCursor(document)
# p1 = cursor.position() # return int
# cursor.insertImage(r"C:\Users\newstep\Pictures\number1.jpg")
# This will prevent you from an error if pressed cancel on file dialog.
# if S__File[0]:
if S__File:
# Finally this will Save your file to the path selected.
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
file.write(Text)
# txtPath = S__File[0]
# icnt = 0
# for i in range(self.listwidget31.count()):
# if str(self.listwidget31.item(i).text()) == txtPath.replace("/","\\"):
# icnt = 1
# break
# if icnt != 1:
# cnt = self.listwidget31.count() +1
# self.listwidget31.insertItem(cnt, os.path.basename(txtPath))
# self.listwidget31.insertItem(cnt, txtPath)
else:
QMessageBox.about(self,'메시지 입력 확인','메시지를 입력하셔야 합니다.')
def fn_print_name(self, name, email):
# f_name_pre = r"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' width='50%' height='0%'></center>"
# f_name = f_name_pre.replace("\\","/")
# with io.open('file_name.html','r') as f:
# with io.open(f_name,'r') as f:
# # emailtext = f.read()
# emailtext = f_name
# attachment = 'attachment_file_name.png'
# attachment = f_name
# print(name, self.df_table_02.loc[name][0])
# print(name, email)
if len(self.textedit22.toPlainText())>0:
S__File = os.path.join(os.getcwd(),'html0.txt')
# print(len(self.textedit22.toPlainText()))
# print(S__File)
pretext = f'{name} 님<br/><br/>'
# pretext += f'당신의 이메일은 {email} 입니다.<br/>'
contents = self.textedit22.toPlainText()
# nexttext = f'<br/><img src="cid:{attachment}" >'
nexttext = f"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' width='50%' height='0%'></center>"
# document = self.textedit22.document()
# cursor = QTextCursor(document)
# p1 = cursor.position() # return int
# cursor.insertImage(f_name)
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
# file.write(pretext)
file.write(contents)
# file.write(nexttext)
# print(contents)
# msgText = MIMEText(contents, 'html')
print(name,email,"전송완료")
def fn_send(self, name, email_i):
# 메일 서버를 설정합니다.
# server = smtplib.SMTP('smtp.com', port_number)
# server = smtplib.SMTP_SSL('smtp.kakao.com:465')
server = smtplib.SMTP_SSL('smtp.kakao.com')
# server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# 로그인이 필요하면 로그인 설정
server.login(secret.kakao_id, secret.kakao_pw)
# 보내는 사람, 받는 사람 설정
msg_from = 'miero@kakao.com'
msg_to = email_i
# cc = 'b@b.com, c@c.com'
cc = ''
# print(name,email_i)
# 메세지 구성
msg = MIMEBase('multipart','mixed')
msg['Subject'] = f'2022년 08월 급여명세서-{name}'
msg['From'] = msg_from
msg['To'] = msg_to
msg['Cc'] = cc
# 메일 본문 작성
# # html 로 되어있던 파일을 불러 오고 거기에 파일을 붙여서 보냅니다.
# msgText = MIMEText('<h1>%s</h1><hr>, <img src="cid:%s" >' % (emailtext, attachment), 'html')
# contents = '<h1>%s</h1>'
# contents += '<hr>'
# contents += '<img src="cid:%s" >'
# msgText = MIMEText(contents % (emailtext, attachment), 'html')
# contents = f'<h1>{emailtext}</h1>'
# contents += f'<h2>{msg_to} 님 메일이 도착했습니다.</h2>'
# contents += '<hr>'
# contents += f'<img src="cid:{attachment}" >'
# msgText = MIMEText(contents, 'html')
# pretext = f'수신: {name}<br/>'
# pretext += '발신: 주식회사 밀앤아이, 주식회사 헴펠 대표이사<br/>'
# pretext += '<br/>'
# msgpreText = MIMEText(pretext, 'html')
# msg.attach(msgpreText)
contents = self.textedit22.toPlainText()
con_before = self.textedit22.toPlainText()
# 문자치환 f-string 사용하여 변수 적용하기
contents = con_before.replace("{성명}",f'수신: {name}')
msgText = MIMEText(contents, 'html')
# 메세지를 메일에 붙여 줍니다.
msg.attach(msgText)
# 메일 제일 밑에 로고그림 붙여 줍니다.
# logo_file = "logo.jpg"
# img_f_name = logo_file.replace("\\","/")
# logo_file = r"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' width='10%' height='0%'></center>"
# img_f_name = logo_file.replace("\\","/")
# # with io.open('file_name.html','r') as f:
# with io.open(img_f_name,'r') as f:
# # emailtext = f.read()
# emailtext = img_f_name
# # attachment = 'attachment_file_name.png'
# attachment = img_f_name
# attachment = logo_file
# fp = open(attachment, 'rb')
# img = MIMEImage(fp.read())
# fp.close()
# img.add_header('Content-ID', '<{}>'.format(attachment))
# msg.attach(img)
# 파일 첨부
files = list()
for i in range(self.listwidget21.count()):
files.append(self.listwidget21.item(i).text())
for f in files:
part = MIMEBase('application', "octet-stream")
part.set_payload(open(f,"rb").read())
encode_base64(part)
part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(f))
msg.attach(part)
# 메일 서버를 이용하여 메일을 발송합니다.
# server.sendmail(msg_from, msg["To"].split(",") + msg["Cc"].split(","), msg.as_string())
server.sendmail(msg_from, msg_to, msg.as_string())
server.quit()
def fn_test(self):
self.fn_send("밀1", self.df_table_02.loc["밀1"][0])
self.fn_print_name("밀1", self.df_table_02.loc["밀1"][0])
# for idx in self.idx_list:
# print(idx)
# print(self.df_table_02.loc[idx][0])
# print(idx, table_02.loc[idx][0])
# self.fn_send(idx, self.df_table_02.loc[idx][0])
# self.fn_print_name(idx, self.df_table_02.loc[idx][0])
if __name__ == '__main__':
# don't auto scale when drag app to a different monitor.
# QGuiApplication.setHighDpiScaleFactorRoundingPolicy(Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
excel_file_path = '급여1.xlsx'
worksheet_name = '4대급여'
emailsheet_name = '이메일'
app = QApplication(sys.argv)
app.setStyleSheet('''
QWidget {
font-size: 17px;
}
''')
myApp = MyApp()
myApp.show()
try:
sys.exit(app.exec())
except SystemExit:
print('Closing Window...')
====================
pay08.py--------------------
from operator import index
from unittest import result
from xml.dom.minidom import Document
from PyQt5.QtWidgets import QApplication, QWidget, QTableWidget, QTableWidgetItem, QPushButton, \
QHeaderView, QHBoxLayout, QVBoxLayout, QGridLayout, QAbstractScrollArea, QLabel, QListWidget, \
QFileDialog, QMessageBox, QTextEdit, QAbstractItemView
from PyQt5.QtCore import Qt
# from PyQt5 import QtGui
from PyQt5.QtGui import QTextCursor
import sys
import pandas as pd # pip install pandas
import os
import smtplib
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email.mime.image import MIMEImage
from email import encoders
from email.encoders import encode_base64
import io
import secret
class MyApp(QWidget):
def __init__(self):
super().__init__()
self.window_width, self.window_height = 800, 600
self.resize(self.window_width, self.window_height)
self.setWindowTitle('pay')
self.server = smtplib.SMTP_SSL('smtp.kakao.com')
self.server.login(secret.kakao_id, secret.kakao_pw)
##### layout_main #####
layout_main = QHBoxLayout()
self.setLayout(layout_main)
##### layout_1 #####
layout_1 = QVBoxLayout()
label11 = QLabel('직원 메일')
# self.button = QPushButton('&Load Data')
# self.button.clicked.connect(lambda _, xl_path=excel_file_path, sheet_name=worksheet_name: self.loadExcelData(xl_path, sheet_name))
# layout_v.addWidget(self.button)
layout_1.addWidget(label11)
self.table = QTableWidget()
self.table.setFixedWidth(310)
layout_1.addWidget(self.table)
layout_main.addLayout(layout_1)
##### layout_2 #####
layout_2 = QGridLayout()
label21 = QLabel('첨부파일')
layout_2.addWidget(label21, 0, 0, 1, 1)
self.listwidget21 = QListWidget()
self.listwidget21.setFixedWidth(300)
self.listwidget21.setSelectionMode(QAbstractItemView.ExtendedSelection)
layout_2.addWidget(self.listwidget21, 1, 0, 5, 1)
self.btn_file_add = QPushButton('파일 추가') # sendlist
# self.btn_file_add.setMinimumHeight(80)
layout_2.addWidget(self.btn_file_add, 1, 2, 1, 1)
self.btn_file_add.clicked.connect(self.fn_fileadd)
self.btn_file_del = QPushButton('파일 삭제')
layout_2.addWidget(self.btn_file_del, 2, 2, 1, 1)
self.btn_file_del.clicked.connect(self.fn_filedel)
label21 = QLabel('본문 (HTML형식)')
layout_2.addWidget(label21, 6, 0, 1, 1)
self.textedit22 = QTextEdit()
self.textedit22.setFixedWidth(300)
self.textedit22.setAcceptRichText(False)
layout_2.addWidget(self.textedit22, 7, 0, 5, 1)
self.btn_send = QPushButton("보내기")
layout_2.addWidget(self.btn_send, 7, 2, 1, 1)
self.btn_send.clicked.connect(self.fn_run) #@@@@@@@@@@@@@@@@@@@@@@@@@@
layout_main.addLayout(layout_2)
# html 파일이 존재하면
filename = 'html0.txt'
if os.path.isfile(filename) == True:
source_text = open(filename,'r', encoding="UTF-8").read()
# self.textedit22.setText(source_text) # TextEdit에 RichText 형식의 글을 입력합니다.
self.textedit22.setPlainText(source_text) # TextEdit에 PlainText 형식의 글을 새로 입력합니다.
# table_data = self.loadExcelData(excel_file_path, worksheet_name)
# print(table_data.keys())
df_table = self.loadExcelData(excel_file_path, worksheet_name)
# print(table_df["성명"][0])
self.df_table_02 = df_table.set_index("성명")
self.idx_list = self.df_table_02.index.to_list()
# print(index)
# for i in table_02["이메일"]:
def loadExcelData(self, excel_file_dir, worksheet_name):
df_work_sheet = pd.read_excel(excel_file_path, worksheet_name)
df_email_sheet = pd.read_excel(excel_file_path, emailsheet_name)
df_table = df_work_sheet.merge(df_email_sheet, how='left')
df_table_mail = df_table[['성명','이메일']]
res = df_table_mail
# res = df_table_mail.to_dict()
# self.table.setRowCount(df.shape[0])
# self.table.setColumnCount(df.shape[1])
self.table.setRowCount(df_table_mail.shape[0])
self.table.setColumnCount(df_table_mail.shape[1])
# self.table.setHorizontalHeaderLabels(df.columns)
self.table.setHorizontalHeaderLabels(df_table_mail.columns)
header = self.table.horizontalHeader()
# header.setSectionResizeMode(0, QHeaderView.Stretch)
# header.setSectionResizeMode(0, QHeaderView.ResizeToContents)
header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
# returns pandas array object
# for row in df.iterrows():
for row in df_table_mail.iterrows():
values = row[1]
for col_index, value in enumerate(values):
if isinstance(value, (float, int)):
value = '{0:0,.0f}'.format(value)
tableItem = QTableWidgetItem(str(value))
if value == "nan":
tableItem.setBackground(Qt.red)
self.table.setItem(row[0], col_index, tableItem)
self.table.setColumnWidth(2, 300)
return res
def fn_fileadd(self):
# f_name = QFileDialog.getOpenFileName(None, '열기', '', "All Files(*.*)")
f_names = QFileDialog.getOpenFileNames(None, '열기', '', "All Files(*.*)")
# txtPath = f_name[0]
filelist = f_names[0]
if filelist:
for f_name in filelist:
# ext = os.path.splitext(f_name[0])[1]
ext = os.path.splitext(f_name)[1] # 확장자 확인
# if f_names[0]:
icnt = 0
for i in range(self.listwidget21.count()):
# if str(self.listwidget21.item(i).text()) == txtPath.replace("/","\\") or str(self.listwidget21.item(i).text()) == txtPath:
if str(self.listwidget21.item(i).text()) == f_name.replace("/","\\") or str(self.listwidget21.item(i).text()) == f_name:
icnt = 1
break
if icnt != 1:
f_path = f_name
if ext == '.exe':
QMessageBox.about(self,'파일 형식 확인','exe파일은 전송할 수 없습니다.')
pass
else:
cnt = self.listwidget21.count() +1
# self.listwidget21.insertItem(cnt, os.path.basename(txtPath))
# self.listwidget21.insertItem(cnt, txtPath)
# f_path = f_names[0]
# print(f_path)
self.listwidget21.insertItem(cnt, f_path)
# self.listwidget21.insertItem(cnt, f_path.replace("/","\\"))
def fn_filedel(self):
currentrow = self.listwidget21.currentRow()
self.listwidget21.takeItem(currentrow) # currentrowRight번째 항목을 삭제합니다
self.listwidget21.clearSelection()
def fn_html_save(self):
if len(self.textedit22.toPlainText())>0:
# print(len(self.textedit.toPlainText()))
# S__File = QFileDialog.getSaveFileName(None,'문자 파일저장','/', "Text Files (*.txt)")
# S__File = QFileDialog.getSaveFileName(None,'문자 파일저장','html0', "Text Files (*.txt)")
S__File = os.path.join(os.getcwd(),'html0.txt')
# This will let you access the test in your QTextEdit
Text = self.textedit22.toPlainText()
# document = self.textedit22.document()
# cursor = QTextCursor(document)
# p1 = cursor.position() # return int
# cursor.insertImage(r"C:\Users\newstep\Pictures\number1.jpg")
# This will prevent you from an error if pressed cancel on file dialog.
# if S__File[0]:
if S__File:
# Finally this will Save your file to the path selected.
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
file.write(Text)
# txtPath = S__File[0]
# icnt = 0
# for i in range(self.listwidget31.count()):
# if str(self.listwidget31.item(i).text()) == txtPath.replace("/","\\"):
# icnt = 1
# break
# if icnt != 1:
# cnt = self.listwidget31.count() +1
# self.listwidget31.insertItem(cnt, os.path.basename(txtPath))
# self.listwidget31.insertItem(cnt, txtPath)
else:
QMessageBox.about(self,'메시지 입력 확인','메시지를 입력하셔야 합니다.')
def fn_print_name(self, name, email):
# f_name_pre = r"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' width='50%' height='0%'></center>"
# f_name = f_name_pre.replace("\\","/")
# with io.open('file_name.html','r') as f:
# with io.open(f_name,'r') as f:
# # emailtext = f.read()
# emailtext = f_name
# attachment = 'attachment_file_name.png'
# attachment = f_name
# print(name, self.df_table_02.loc[name][0])
# print(name, email)
if len(self.textedit22.toPlainText())>0:
S__File = os.path.join(os.getcwd(),'html0.txt')
# print(len(self.textedit22.toPlainText()))
# print(S__File)
pretext = f'{name} 님<br/><br/>'
# pretext += f'당신의 이메일은 {email} 입니다.<br/>'
contents = self.textedit22.toPlainText()
# nexttext = f'<br/><img src="cid:{attachment}" >'
nexttext = f"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' width='50%' height='0%'></center>"
# document = self.textedit22.document()
# cursor = QTextCursor(document)
# p1 = cursor.position() # return int
# cursor.insertImage(f_name)
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
# file.write(pretext)
file.write(contents)
# file.write(nexttext)
# print(contents)
# msgText = MIMEText(contents, 'html')
print(name,email,"전송완료")
def fn_send(self, name, email_i):
# # 메일 서버를 설정합니다.
# # server = smtplib.SMTP('smtp.com', port_number)
# # server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# server = smtplib.SMTP_SSL('smtp.kakao.com')
# # server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# # 로그인이 필요하면 로그인 설정
# server.login(secret.kakao_id, secret.kakao_pw)
# # 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
# msg_to = email_i
# cc = 'b@b.com, c@c.com'
# cc = ''
# print(name,email_i)
# 메세지 구성
msg = MIMEBase('multipart','mixed')
msg['Subject'] = f'2022년 08월 급여명세서-{name}'
msg['From'] = 'miero@kakao.com'
msg['To'] = email_i
msg['Cc'] = ""
# 메일 본문 작성
# # html 로 되어있던 파일을 불러 오고 거기에 파일을 붙여서 보냅니다.
# msgText = MIMEText('<h1>%s</h1><hr>, <img src="cid:%s" >' % (emailtext, attachment), 'html')
# contents = '<h1>%s</h1>'
# contents += '<hr>'
# contents += '<img src="cid:%s" >'
# msgText = MIMEText(contents % (emailtext, attachment), 'html')
# contents = f'<h1>{emailtext}</h1>'
# contents += f'<h2>{msg_to} 님 메일이 도착했습니다.</h2>'
# contents += '<hr>'
# contents += f'<img src="cid:{attachment}" >'
# msgText = MIMEText(contents, 'html')
# pretext = f'수신: {name}<br/>'
# pretext += '발신: 주식회사 밀앤아이, 주식회사 헴펠 대표이사<br/>'
# pretext += '<br/>'
# msgpreText = MIMEText(pretext, 'html')
# msg.attach(msgpreText)
contents = self.textedit22.toPlainText()
con_before = self.textedit22.toPlainText()
# 문자치환 f-string 사용하여 변수 적용하기
contents = con_before.replace("{성명}",f'수신: {name}')
msgText = MIMEText(contents, 'html')
# 메세지를 메일에 붙여 줍니다.
msg.attach(msgText)
# 메일 제일 밑에 로고그림 붙여 줍니다.
# logo_file = "logo.jpg"
# img_f_name = logo_file.replace("\\","/")
# logo_file = r"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' width='10%' height='0%'></center>"
# img_f_name = logo_file.replace("\\","/")
# # with io.open('file_name.html','r') as f:
# with io.open(img_f_name,'r') as f:
# # emailtext = f.read()
# emailtext = img_f_name
# # attachment = 'attachment_file_name.png'
# attachment = img_f_name
# attachment = logo_file
# fp = open(attachment, 'rb')
# img = MIMEImage(fp.read())
# fp.close()
# img.add_header('Content-ID', '<{}>'.format(attachment))
# msg.attach(img)
# 파일 첨부
files = list()
for i in range(self.listwidget21.count()):
files.append(self.listwidget21.item(i).text())
for f in files:
part = MIMEBase('application', "octet-stream")
part.set_payload(open(f,"rb").read())
encode_base64(part)
part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(f))
msg.attach(part)
# 메일 서버를 이용하여 메일을 발송합니다.
# server.sendmail(msg_from, msg["To"].split(",") + msg["Cc"].split(","), msg.as_string())
self.server.sendmail(msg['From'], msg['To'], msg.as_string())
# self.server.quit()
def fn_test(self):
# 메일 서버를 설정합니다.
# server = smtplib.SMTP('smtp.com', port_number)
# server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# self.server = smtplib.SMTP_SSL('smtp.kakao.com')
# server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# 로그인이 필요하면 로그인 설정
# self.server.login(secret.kakao_id, secret.kakao_pw)
# 보내는 사람, 받는 사람 설정
msg_from = 'miero@kakao.com'
self.fn_send("밀1", self.df_table_02.loc["밀1"][0])
self.server.quit()
self.fn_print_name("밀1", self.df_table_02.loc["밀1"][0])
def fn_run(self):
# 메일 서버를 설정합니다.
# server = smtplib.SMTP('smtp.com', port_number)
# server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# server = smtplib.SMTP_SSL('smtp.kakao.com')
# server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# 로그인이 필요하면 로그인 설정
# server.login(secret.kakao_id, secret.kakao_pw)
# 보내는 사람, 받는 사람 설정
msg_from = 'miero@kakao.com'
# self.fn_send("밀1", self.df_table_02.loc["밀1"][0])
# self.fn_print_name("밀1", self.df_table_02.loc["밀1"][0])
for idx in self.idx_list:
# print(idx)
# print(self.df_table_02.loc[idx][0])
# print(idx, table_02.loc[idx][0])
self.fn_send(idx, self.df_table_02.loc[idx][0])
self.fn_print_name(idx, self.df_table_02.loc[idx][0])
self.server.quit()
if __name__ == '__main__':
# don't auto scale when drag app to a different monitor.
# QGuiApplication.setHighDpiScaleFactorRoundingPolicy(Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
excel_file_path = '급여1.xlsx'
worksheet_name = '4대급여'
emailsheet_name = '이메일'
app = QApplication(sys.argv)
app.setStyleSheet('''
QWidget {
font-size: 17px;
}
''')
myApp = MyApp()
myApp.show()
try:
sys.exit(app.exec())
except SystemExit:
print('Closing Window...')
====================
pay09.py--------------------
from operator import index
from unittest import result
from xml.dom.minidom import Document
from PyQt5.QtWidgets import QApplication, QWidget, QTableWidget, QTableWidgetItem, QPushButton, \
QHeaderView, QHBoxLayout, QVBoxLayout, QGridLayout, QAbstractScrollArea, QLabel, QListWidget, \
QFileDialog, QMessageBox, QTextEdit, QAbstractItemView
from PyQt5.QtCore import Qt
# from PyQt5 import QtGui
from PyQt5.QtGui import QTextCursor
import sys
import pandas as pd # pip install pandas
import os
import smtplib
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
# 출처: https://nowonbun.tistory.com/684 [명월 일지:티스토리]
from email import encoders
from email.encoders import encode_base64
import io
import secret
import xlwings as xw
class MyApp(QWidget):
def __init__(self):
super().__init__()
self.window_width, self.window_height = 800, 600
self.resize(self.window_width, self.window_height)
self.setWindowTitle('pay')
self.server = smtplib.SMTP_SSL('smtp.kakao.com')
self.server.login(secret.kakao_id, secret.kakao_pw)
self.msg_from = 'miero@kakao.com'
##### layout_main #####
layout_main = QHBoxLayout()
self.setLayout(layout_main)
##### layout_1 #####
layout_1 = QVBoxLayout()
label11 = QLabel('직원 메일')
# self.button = QPushButton('&Load Data')
# self.button.clicked.connect(lambda _, xl_path=excel_file_path, sheet_name=worksheet_name: self.loadExcelData(xl_path, sheet_name))
# layout_v.addWidget(self.button)
layout_1.addWidget(label11)
self.table = QTableWidget()
self.table.setFixedWidth(310)
layout_1.addWidget(self.table)
layout_main.addLayout(layout_1)
##### layout_2 #####
layout_2 = QGridLayout()
label21 = QLabel('첨부파일')
layout_2.addWidget(label21, 0, 0, 1, 1)
self.listwidget21 = QListWidget()
self.listwidget21.setFixedWidth(300)
self.listwidget21.setSelectionMode(QAbstractItemView.ExtendedSelection)
layout_2.addWidget(self.listwidget21, 1, 0, 5, 1)
self.btn_file_add = QPushButton('파일 추가') # sendlist
# self.btn_file_add.setMinimumHeight(80)
layout_2.addWidget(self.btn_file_add, 1, 2, 1, 1)
self.btn_file_add.clicked.connect(self.fn_fileadd)
self.btn_file_del = QPushButton('파일 삭제')
layout_2.addWidget(self.btn_file_del, 2, 2, 1, 1)
self.btn_file_del.clicked.connect(self.fn_filedel)
label21 = QLabel('본문 (HTML형식)')
layout_2.addWidget(label21, 6, 0, 1, 1)
self.textedit22 = QTextEdit()
self.textedit22.setFixedWidth(300)
self.textedit22.setAcceptRichText(False)
layout_2.addWidget(self.textedit22, 7, 0, 5, 1)
self.btn_send = QPushButton("보내기")
layout_2.addWidget(self.btn_send, 7, 2, 1, 1)
self.btn_send.clicked.connect(self.fn_test) #@@@@@@@@@@@@@@@@@@@@@@@@@@
layout_main.addLayout(layout_2)
# html 파일이 존재하면
filename = 'html0.txt'
if os.path.isfile(filename) == True:
source_text = open(filename,'r', encoding="UTF-8").read()
# self.textedit22.setText(source_text) # TextEdit에 RichText 형식의 글을 입력합니다.
self.textedit22.setPlainText(source_text) # TextEdit에 PlainText 형식의 글을 새로 입력합니다.
# table_data = self.loadExcelData(excel_file_path, worksheet_name)
# print(table_data.keys())
df_table = self.loadExcelData(excel_file_path, worksheet_name)
# print(table_df["성명"][0])
self.df_table_02 = df_table.set_index("성명")
self.idx_name_list = self.df_table_02.index.to_list()
# print(index)
# for i in table_02["이메일"]:
def loadExcelData(self, excel_file_dir, worksheet_name):
df_work_sheet = pd.read_excel(excel_file_path, worksheet_name)
df_email_sheet = pd.read_excel(excel_file_path, emailsheet_name)
df_table = df_work_sheet.merge(df_email_sheet, how='left')
df_table_mail = df_table[['성명','이메일']]
res = df_table_mail
# res = df_table_mail.to_dict()
# self.table.setRowCount(df.shape[0])
# self.table.setColumnCount(df.shape[1])
self.table.setRowCount(df_table_mail.shape[0])
self.table.setColumnCount(df_table_mail.shape[1])
# self.table.setHorizontalHeaderLabels(df.columns)
self.table.setHorizontalHeaderLabels(df_table_mail.columns)
header = self.table.horizontalHeader()
# header.setSectionResizeMode(0, QHeaderView.Stretch)
# header.setSectionResizeMode(0, QHeaderView.ResizeToContents)
header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
# returns pandas array object
# for row in df.iterrows():
for row in df_table_mail.iterrows():
values = row[1]
for col_index, value in enumerate(values):
if isinstance(value, (float, int)):
value = '{0:0,.0f}'.format(value)
tableItem = QTableWidgetItem(str(value))
if value == "nan":
tableItem.setBackground(Qt.red)
self.table.setItem(row[0], col_index, tableItem)
self.table.setColumnWidth(2, 310)
return res
def fn_fileadd(self):
# f_name = QFileDialog.getOpenFileName(None, '열기', '', "All Files(*.*)")
f_names = QFileDialog.getOpenFileNames(None, '열기', '', "All Files(*.*)")
# txtPath = f_name[0]
filelist = f_names[0]
if filelist:
for f_name in filelist:
# ext = os.path.splitext(f_name[0])[1]
ext = os.path.splitext(f_name)[1] # 확장자 확인
# if f_names[0]:
icnt = 0
for i in range(self.listwidget21.count()):
# if str(self.listwidget21.item(i).text()) == txtPath.replace("/","\\") or str(self.listwidget21.item(i).text()) == txtPath:
if str(self.listwidget21.item(i).text()) == f_name.replace("/","\\") or str(self.listwidget21.item(i).text()) == f_name:
icnt = 1
break
if icnt != 1:
f_path = f_name
if ext == '.exe':
QMessageBox.about(self,'파일 형식 확인','exe파일은 전송할 수 없습니다.')
pass
else:
cnt = self.listwidget21.count() +1
# self.listwidget21.insertItem(cnt, os.path.basename(txtPath))
# self.listwidget21.insertItem(cnt, txtPath)
# f_path = f_names[0]
# print(f_path)
self.listwidget21.insertItem(cnt, f_path)
# self.listwidget21.insertItem(cnt, f_path.replace("/","\\"))
def fn_filedel(self):
currentrow = self.listwidget21.currentRow()
self.listwidget21.takeItem(currentrow) # currentrowRight번째 항목을 삭제합니다
self.listwidget21.clearSelection()
def fn_html_save(self):
if len(self.textedit22.toPlainText())>0:
# print(len(self.textedit.toPlainText()))
# S__File = QFileDialog.getSaveFileName(None,'문자 파일저장','/', "Text Files (*.txt)")
# S__File = QFileDialog.getSaveFileName(None,'문자 파일저장','html0', "Text Files (*.txt)")
S__File = os.path.join(os.getcwd(),'html0.txt')
# This will let you access the test in your QTextEdit
Text = self.textedit22.toPlainText()
# document = self.textedit22.document()
# cursor = QTextCursor(document)
# p1 = cursor.position() # return int
# cursor.insertImage(r"C:\Users\newstep\Pictures\number1.jpg")
# This will prevent you from an error if pressed cancel on file dialog.
# if S__File[0]:
if S__File:
# Finally this will Save your file to the path selected.
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
file.write(Text)
# txtPath = S__File[0]
# icnt = 0
# for i in range(self.listwidget31.count()):
# if str(self.listwidget31.item(i).text()) == txtPath.replace("/","\\"):
# icnt = 1
# break
# if icnt != 1:
# cnt = self.listwidget31.count() +1
# self.listwidget31.insertItem(cnt, os.path.basename(txtPath))
# self.listwidget31.insertItem(cnt, txtPath)
else:
QMessageBox.about(self,'메시지 입력 확인','메시지를 입력하셔야 합니다.')
def fn_print_name(self, name, email):
# f_name_pre = r"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' width='50%' height='0%'></center>"
# f_name = f_name_pre.replace("\\","/")
# with io.open('file_name.html','r') as f:
# with io.open(f_name,'r') as f:
# # emailtext = f.read()
# emailtext = f_name
# attachment = 'attachment_file_name.png'
# attachment = f_name
# print(name, self.df_table_02.loc[name][0])
# print(name, email)
if len(self.textedit22.toPlainText())>0:
S__File = os.path.join(os.getcwd(),'html0.txt')
# print(len(self.textedit22.toPlainText()))
# print(S__File)
pretext = f'{name} 님<br/><br/>'
# pretext += f'당신의 이메일은 {email} 입니다.<br/>'
contents = self.textedit22.toPlainText()
# nexttext = f'<br/><img src="cid:{attachment}" >'
nexttext = f"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' width='50%' height='0%'></center>"
# document = self.textedit22.document()
# cursor = QTextCursor(document)
# p1 = cursor.position() # return int
# cursor.insertImage(f_name)
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
# file.write(pretext)
file.write(contents)
# file.write(nexttext)
# print(contents)
# msgText = MIMEText(contents, 'html')
print(name,email,"전송완료")
def fn_pdf_create(self, idx_name):
#####################################
# xlwings
self.current_pdf_path = os.getcwd()+"\pdf"
fname = "급여1.xlsx"
# for n in self.target_name_list:
name = idx_name
df_data = pd.read_excel(fname, sheet_name='4대급여')
df_data = df_data.fillna(0)
df_employee = pd.read_excel(fname, sheet_name='직원현황')
idx_df_data = df_data.index[df_data['성명']==name].tolist()[0]
# print("4대급여 인덱스 :",idx_df_data)
normal = df_data.loc[idx_df_data,['기본급']][0]
overtime = df_data.loc[idx_df_data,['연장수당']][0]
holiday = df_data.loc[idx_df_data,['휴일수당']][0]
holidayovertime = df_data.loc[idx_df_data,['휴일연장수당']][0]
extra = df_data.loc[idx_df_data,['추가수당']][0]
meals = df_data.loc[idx_df_data,['식대']][0]
bonus = df_data.loc[idx_df_data,['상여금']][0]
normal_calculation = df_data.loc[idx_df_data,['기']][0]
overtime_calculation = df_data.loc[idx_df_data,['연']][0]
holiday_calculation = df_data.loc[idx_df_data,['휴']][0]
holidayovertime_calculation = df_data.loc[idx_df_data,['휴연']][0]
extra_calculation = df_data.loc[idx_df_data,['추']][0]
nationalpension = df_data.loc[idx_df_data,['국민연금']][0]
healthinsurance = df_data.loc[idx_df_data,['건강보험']][0]
longtermcareinsurance = df_data.loc[idx_df_data,['장기요양보험']][0]
employmentinsurance = df_data.loc[idx_df_data,['고용보험']][0]
healthsettlement = df_data.loc[idx_df_data,['정산건강']][0]
longtermcaresettlement = df_data.loc[idx_df_data,['정산장기요양']][0]
advancepayment = df_data.loc[idx_df_data,['선지급']][0]
etc = df_data.loc[idx_df_data,['기타']][0]
incometax = df_data.loc[idx_df_data,['소득세']][0]
localincometax = df_data.loc[idx_df_data,['지방소득세']][0]
idx_df_employee = df_employee.index[df_employee['성명']==name].tolist()[0]
# print("직원현황 인덱스 :",idx_df_employee)
jobposition = df_employee.loc[idx_df_employee,['직위']][0]
department = df_employee.loc[idx_df_employee,['부서']][0]
birthday = df_employee.loc[idx_df_employee,['생일']][0]
# 엑셀 인스턴스 생성
app = xw.App(visible=False)
book = xw.Book(fname)
sh_paystub = book.sheets('급여명세서사대보험')
sh_paystub["B4"].value = name
sh_paystub["D4"].value = jobposition
sh_paystub["B5"].value = department
sh_paystub["D5"].value = birthday
sh_paystub["B8"].value = normal
sh_paystub["B9"].value = overtime
sh_paystub["B10"].value = holiday
sh_paystub["B11"].value = holidayovertime
sh_paystub["B12"].value = extra
sh_paystub["B13"].value = meals
sh_paystub["D8"].value = nationalpension
sh_paystub["D9"].value = healthinsurance
sh_paystub["D10"].value = longtermcareinsurance
sh_paystub["D11"].value = employmentinsurance
sh_paystub["D12"].value = healthsettlement
sh_paystub["D13"].value = longtermcaresettlement
sh_paystub["D14"].value = advancepayment
sh_paystub["D15"].value = etc
sh_paystub["D16"].value = incometax
sh_paystub["D17"].value = localincometax
sh_paystub["B23"].value = normal_calculation
sh_paystub["B24"].value = overtime_calculation
sh_paystub["B25"].value = holiday_calculation
sh_paystub["B26"].value = holidayovertime_calculation
sh_paystub["B27"].value = extra_calculation
sh_paystub["D23"].value = normal
sh_paystub["D24"].value = overtime
sh_paystub["D25"].value = holiday
sh_paystub["D26"].value = holidayovertime
sh_paystub["D27"].value = extra
# pdf 로 저장하기
# current_path = os.getcwd() # 현재 작업중인 폴더에 저장하기
# 절대경로로 파일 위치 입력
pdf_file = os.path.join(self.current_pdf_path, f"2022년08월급여명세서-{name}.pdf")
# PDF 로 저장할 시트 선택하기(본 예제에서는 첫 번째 시트 선택하기)
# report_sheet = book.sheets[1]
report_sheet = sh_paystub
# PDF 로 저장하기
# report_sheet.ExportAsFixedFormat(0, pdf_path)
report_sheet.api.ExportAsFixedFormat(0, pdf_file)
book.save()
app.kill()
#####################################
def fn_send(self, name, email_i):
# # 메일 서버를 설정합니다.
# # server = smtplib.SMTP('smtp.com', port_number)
# # server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# server = smtplib.SMTP_SSL('smtp.kakao.com')
# # server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# # 로그인이 필요하면 로그인 설정
# server.login(secret.kakao_id, secret.kakao_pw)
# # 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
# msg_to = email_i
# cc = 'b@b.com, c@c.com'
# cc = ''
# print(name,email_i)
# 메세지 구성
msg = MIMEBase('multipart','mixed')
msg['Subject'] = f'2022년08월급여명세서-{name}'
msg['From'] = self.msg_from
msg['To'] = email_i
msg['Cc'] = ""
# 메일 본문 작성
# # html 로 되어있던 파일을 불러 오고 거기에 파일을 붙여서 보냅니다.
# msgText = MIMEText('<h1>%s</h1><hr>, <img src="cid:%s" >' % (emailtext, attachment), 'html')
# contents = '<h1>%s</h1>'
# contents += '<hr>'
# contents += '<img src="cid:%s" >'
# msgText = MIMEText(contents % (emailtext, attachment), 'html')
# contents = f'<h1>{emailtext}</h1>'
# contents += f'<h2>{msg_to} 님 메일이 도착했습니다.</h2>'
# contents += '<hr>'
# contents += f'<img src="cid:{attachment}" >'
# msgText = MIMEText(contents, 'html')
# pretext = f'수신: {name}<br/>'
# pretext += '발신: 주식회사 밀앤아이, 주식회사 헴펠 대표이사<br/>'
# pretext += '<br/>'
# msgpreText = MIMEText(pretext, 'html')
# msg.attach(msgpreText)
contents = self.textedit22.toPlainText()
con_before = self.textedit22.toPlainText()
# 문자치환 f-string 사용하여 변수 적용하기
contents = con_before.replace("{성명}",f'수신: {name}')
msgText = MIMEText(contents, 'html')
# 메세지를 메일에 붙여 줍니다.
msg.attach(msgText)
# 메일 제일 밑에 로고그림 붙여 줍니다.
# logo_file = "logo.jpg"
# img_f_name = logo_file.replace("\\","/")
# logo_file = r"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' width='10%' height='0%'></center>"
# img_f_name = logo_file.replace("\\","/")
# # with io.open('file_name.html','r') as f:
# with io.open(img_f_name,'r') as f:
# # emailtext = f.read()
# emailtext = img_f_name
# # attachment = 'attachment_file_name.png'
# attachment = img_f_name
# attachment = logo_file
# fp = open(attachment, 'rb')
# img = MIMEImage(fp.read())
# fp.close()
# img.add_header('Content-ID', '<{}>'.format(attachment))
# msg.attach(img)
# 파일첨부
files = list()
pdf_file_name = f"2022년08월급여명세서-{name}.pdf"
pdf_file = os.path.join(self.current_pdf_path, pdf_file_name)
if os.path.isfile(pdf_file):
binary_pdf = open(pdf_file, 'rb')
payload = MIMEBase('application', 'octate-stream', Name=pdf_file_name)
payload.set_payload((binary_pdf).read())
encoders.encode_base64(payload)
payload.add_header('Content-Decomposition', 'attachment', filename=pdf_file_name)
msg.attach(payload)
for i in range(self.listwidget21.count()):
files.append(self.listwidget21.item(i).text())
# print(files)
for f in files:
part = MIMEBase('application', "octet-stream")
part.set_payload(open(f,"rb").read())
encode_base64(part)
part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(f))
msg.attach(part)
# 메일 서버를 이용하여 메일을 발송합니다.
# server.sendmail(msg_from, msg["To"].split(",") + msg["Cc"].split(","), msg.as_string())
self.server.sendmail(msg['From'], msg['To'], msg.as_string())
# self.server.quit()
def fn_test(self):
# 메일 서버를 설정합니다.
# server = smtplib.SMTP('smtp.com', port_number)
# server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# self.server = smtplib.SMTP_SSL('smtp.kakao.com')
# server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# 로그인이 필요하면 로그인 설정
# self.server.login(secret.kakao_id, secret.kakao_pw)
# 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
self.fn_pdf_create("밀1")
self.fn_send("밀1", self.df_table_02.loc["밀1"][0])
self.server.quit()
self.fn_print_name("밀1", self.df_table_02.loc["밀1"][0])
def fn_run(self):
# 메일 서버를 설정합니다.
# server = smtplib.SMTP('smtp.com', port_number)
# server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# server = smtplib.SMTP_SSL('smtp.kakao.com')
# server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# 로그인이 필요하면 로그인 설정
# server.login(secret.kakao_id, secret.kakao_pw)
# 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
# self.fn_send("밀1", self.df_table_02.loc["밀1"][0])
# self.fn_print_name("밀1", self.df_table_02.loc["밀1"][0])
for idx_name in self.idx_name_list:
# print(idx)
# print(self.df_table_02.loc[idx][0])
# print(idx, table_02.loc[idx][0])
self.fn_pdf_create(idx_name)
self.fn_send(idx_name, self.df_table_02.loc[idx_name][0])
self.fn_print_name(idx_name, self.df_table_02.loc[idx_name][0])
self.server.quit()
if __name__ == '__main__':
# don't auto scale when drag app to a different monitor.
# QGuiApplication.setHighDpiScaleFactorRoundingPolicy(Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
excel_file_path = '급여1.xlsx'
worksheet_name = '4대급여'
emailsheet_name = '이메일'
app = QApplication(sys.argv)
app.setStyleSheet('''
QWidget {
font-size: 17px;
}
''')
myApp = MyApp()
myApp.show()
try:
sys.exit(app.exec())
except SystemExit:
print('Closing Window...')
====================
pay10.py--------------------
# from operator import index
# from unittest import result
# from xml.dom.minidom import Document
from PyQt5.QtWidgets import QApplication, QWidget, QTableWidget, QTableWidgetItem, QPushButton, \
QHeaderView, QHBoxLayout, QVBoxLayout, QGridLayout, QAbstractScrollArea, QLabel, QListWidget, \
QFileDialog, QMessageBox, QTextEdit, QAbstractItemView
from PyQt5.QtCore import Qt
# from PyQt5 import QtGui
from PyQt5.QtGui import QTextCursor
import sys
import pandas as pd # pip install pandas
import os
import io
import secret
import xlwings as xw
import smtplib
from email.encoders import encode_base64
from email.header import Header
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText # 메일의 본문 내용을 만드는 모듈 내용을 base64형식으로 변환
from email.utils import formatdate
from email.mime.application import MIMEApplication # 메일의 첨부 파일을 base64 형식으로 변환
from email.mime.image import MIMEImage # 메일의 이미지 파일을 base64 형식으로 변환
# 출처: https://nowonbun.tistory.com/684 [명월 일지:티스토리]
from email import encoders
from email.encoders import encode_base64
class MyApp(QWidget):
def __init__(self):
super().__init__()
self.window_width, self.window_height = 800, 600
self.resize(self.window_width, self.window_height)
self.setWindowTitle('pay')
# self.server = smtplib.SMTP_SSL('smtp.kakao.com')
# self.server.login(secret.kakao_id, secret.kakao_pw)
# self.msg_from = 'miero@kakao.com'
##### layout_main #####
layout_main = QHBoxLayout()
self.setLayout(layout_main)
##### layout_1 #####
layout_1 = QVBoxLayout()
label11 = QLabel('직원 메일')
# self.button = QPushButton('&Load Data')
# self.button.clicked.connect(lambda _, xl_path=excel_file_path, sheet_name=worksheet_name: self.loadExcelData(xl_path, sheet_name))
# layout_v.addWidget(self.button)
layout_1.addWidget(label11)
self.table = QTableWidget()
self.table.setFixedWidth(310)
layout_1.addWidget(self.table)
layout_main.addLayout(layout_1)
##### layout_2 #####
layout_2 = QGridLayout()
label21 = QLabel('첨부파일')
layout_2.addWidget(label21, 0, 0, 1, 1)
self.listwidget21 = QListWidget()
self.listwidget21.setFixedWidth(300)
self.listwidget21.setSelectionMode(QAbstractItemView.ExtendedSelection)
layout_2.addWidget(self.listwidget21, 1, 0, 5, 1)
self.btn_file_add = QPushButton('파일 추가') # sendlist
# self.btn_file_add.setMinimumHeight(80)
layout_2.addWidget(self.btn_file_add, 1, 2, 1, 1)
self.btn_file_add.clicked.connect(self.fn_fileadd)
self.btn_file_del = QPushButton('파일 삭제')
layout_2.addWidget(self.btn_file_del, 2, 2, 1, 1)
self.btn_file_del.clicked.connect(self.fn_filedel)
label21 = QLabel('본문 (HTML형식)')
layout_2.addWidget(label21, 6, 0, 1, 1)
self.textedit22 = QTextEdit()
self.textedit22.setFixedWidth(300)
self.textedit22.setAcceptRichText(False)
layout_2.addWidget(self.textedit22, 7, 0, 5, 1)
self.btn_send = QPushButton("보내기")
layout_2.addWidget(self.btn_send, 7, 2, 1, 1)
self.btn_send.clicked.connect(self.fn_test) #@@@@@@@@@@@@@@@@@@@@@@@@@@
layout_main.addLayout(layout_2)
# html 파일이 존재하면
filename = 'html0.txt'
if os.path.isfile(filename) == True:
source_text = open(filename,'r', encoding="UTF-8").read()
# self.textedit22.setText(source_text) # TextEdit에 RichText 형식의 글을 입력합니다.
self.textedit22.setPlainText(source_text) # TextEdit에 PlainText 형식의 글을 새로 입력합니다.
# table_data = self.loadExcelData(excel_file_path, worksheet_name)
# print(table_data.keys())
df_table = self.loadExcelData(excel_file_path, worksheet_name)
# print(table_df["성명"][0])
self.df_table_02 = df_table.set_index("성명")
self.idx_name_list = self.df_table_02.index.to_list()
# print(index)
# for i in table_02["이메일"]:
def loadExcelData(self, excel_file_dir, worksheet_name):
df_work_sheet = pd.read_excel(excel_file_path, worksheet_name)
df_email_sheet = pd.read_excel(excel_file_path, emailsheet_name)
df_table = df_work_sheet.merge(df_email_sheet, how='left')
df_table_mail = df_table[['성명','이메일']]
res = df_table_mail
# res = df_table_mail.to_dict()
# self.table.setRowCount(df.shape[0])
# self.table.setColumnCount(df.shape[1])
self.table.setRowCount(df_table_mail.shape[0])
self.table.setColumnCount(df_table_mail.shape[1])
# self.table.setHorizontalHeaderLabels(df.columns)
self.table.setHorizontalHeaderLabels(df_table_mail.columns)
header = self.table.horizontalHeader()
# header.setSectionResizeMode(0, QHeaderView.Stretch)
# header.setSectionResizeMode(0, QHeaderView.ResizeToContents)
header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
# returns pandas array object
# for row in df.iterrows():
for row in df_table_mail.iterrows():
values = row[1]
for col_index, value in enumerate(values):
if isinstance(value, (float, int)):
value = '{0:0,.0f}'.format(value)
tableItem = QTableWidgetItem(str(value))
if value == "nan":
tableItem.setBackground(Qt.red)
self.table.setItem(row[0], col_index, tableItem)
self.table.setColumnWidth(2, 310)
return res
def fn_fileadd(self):
# f_name = QFileDialog.getOpenFileName(None, '열기', '', "All Files(*.*)")
f_names = QFileDialog.getOpenFileNames(None, '열기', '', "All Files(*.*)")
# txtPath = f_name[0]
filelist = f_names[0]
if filelist:
for f_name in filelist:
# ext = os.path.splitext(f_name[0])[1]
ext = os.path.splitext(f_name)[1] # 확장자 확인
# if f_names[0]:
icnt = 0
for i in range(self.listwidget21.count()):
# if str(self.listwidget21.item(i).text()) == txtPath.replace("/","\\") or str(self.listwidget21.item(i).text()) == txtPath:
if str(self.listwidget21.item(i).text()) == f_name.replace("/","\\") or str(self.listwidget21.item(i).text()) == f_name:
icnt = 1
break
if icnt != 1:
f_path = f_name
if ext == '.exe':
QMessageBox.about(self,'파일 형식 확인','exe파일은 전송할 수 없습니다.')
pass
else:
cnt = self.listwidget21.count() +1
# self.listwidget21.insertItem(cnt, os.path.basename(txtPath))
# self.listwidget21.insertItem(cnt, txtPath)
# f_path = f_names[0]
# print(f_path)
self.listwidget21.insertItem(cnt, f_path)
# self.listwidget21.insertItem(cnt, f_path.replace("/","\\"))
def fn_filedel(self):
currentrow = self.listwidget21.currentRow()
self.listwidget21.takeItem(currentrow) # currentrowRight번째 항목을 삭제합니다
self.listwidget21.clearSelection()
def fn_html_save(self):
if len(self.textedit22.toPlainText())>0:
# print(len(self.textedit.toPlainText()))
# S__File = QFileDialog.getSaveFileName(None,'문자 파일저장','/', "Text Files (*.txt)")
# S__File = QFileDialog.getSaveFileName(None,'문자 파일저장','html0', "Text Files (*.txt)")
S__File = os.path.join(os.getcwd(),'html0.txt')
# This will let you access the test in your QTextEdit
Text = self.textedit22.toPlainText()
# document = self.textedit22.document()
# cursor = QTextCursor(document)
# p1 = cursor.position() # return int
# cursor.insertImage(r"C:\Users\newstep\Pictures\number1.jpg")
# This will prevent you from an error if pressed cancel on file dialog.
# if S__File[0]:
if S__File:
# Finally this will Save your file to the path selected.
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
file.write(Text)
# txtPath = S__File[0]
# icnt = 0
# for i in range(self.listwidget31.count()):
# if str(self.listwidget31.item(i).text()) == txtPath.replace("/","\\"):
# icnt = 1
# break
# if icnt != 1:
# cnt = self.listwidget31.count() +1
# self.listwidget31.insertItem(cnt, os.path.basename(txtPath))
# self.listwidget31.insertItem(cnt, txtPath)
else:
QMessageBox.about(self,'메시지 입력 확인','메시지를 입력하셔야 합니다.')
def fn_print_name(self, name, email):
# f_name_pre = r"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' width='50%' height='0%'></center>"
# f_name = f_name_pre.replace("\\","/")
# with io.open('file_name.html','r') as f:
# with io.open(f_name,'r') as f:
# # emailtext = f.read()
# emailtext = f_name
# attachment = 'attachment_file_name.png'
# attachment = f_name
# print(name, self.df_table_02.loc[name][0])
# print(name, email)
if len(self.textedit22.toPlainText())>0:
S__File = os.path.join(os.getcwd(),'html0.txt')
# print(len(self.textedit22.toPlainText()))
# print(S__File)
pretext = f'{name} 님<br/><br/>'
# pretext += f'당신의 이메일은 {email} 입니다.<br/>'
contents = self.textedit22.toPlainText()
# nexttext = f'<br/><img src="cid:{attachment}" >'
nexttext = f"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' id='millstudio logo' width='10%' height='0%'></center>"
# document = self.textedit22.document()
# cursor = QTextCursor(document)
# p1 = cursor.position() # return int
# cursor.insertImage(f_name)
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
# file.write(pretext)
file.write(contents)
# file.write(nexttext)
# print(contents)
# msgText = MIMEText(contents, 'html')
print(name,email,"전송완료")
def fn_DeleteAllFiles(self,filePath):
if os.path.exists(filePath):
for file in os.scandir(filePath):
os.remove(file.path)
return 'Remove All File'
else:
return 'Directory Not Found'
def fn_pdf_create(self, idx_name):
#####################################
# xlwings
self.current_pdf_path = os.getcwd()+"\pdf"
fname = "급여1.xlsx"
# for n in self.target_name_list:
name = idx_name
df_data = pd.read_excel(fname, sheet_name='4대급여')
df_data = df_data.fillna(0)
df_employee = pd.read_excel(fname, sheet_name='직원현황')
idx_df_data = df_data.index[df_data['성명']==name].tolist()[0]
# print("4대급여 인덱스 :",idx_df_data)
normal = df_data.loc[idx_df_data,['기본급']][0]
overtime = df_data.loc[idx_df_data,['연장수당']][0]
holiday = df_data.loc[idx_df_data,['휴일수당']][0]
holidayovertime = df_data.loc[idx_df_data,['휴일연장수당']][0]
extra = df_data.loc[idx_df_data,['추가수당']][0]
meals = df_data.loc[idx_df_data,['식대']][0]
bonus = df_data.loc[idx_df_data,['상여금']][0]
normal_calculation = df_data.loc[idx_df_data,['기']][0]
overtime_calculation = df_data.loc[idx_df_data,['연']][0]
holiday_calculation = df_data.loc[idx_df_data,['휴']][0]
holidayovertime_calculation = df_data.loc[idx_df_data,['휴연']][0]
extra_calculation = df_data.loc[idx_df_data,['추']][0]
nationalpension = df_data.loc[idx_df_data,['국민연금']][0]
healthinsurance = df_data.loc[idx_df_data,['건강보험']][0]
longtermcareinsurance = df_data.loc[idx_df_data,['장기요양보험']][0]
employmentinsurance = df_data.loc[idx_df_data,['고용보험']][0]
healthsettlement = df_data.loc[idx_df_data,['정산건강']][0]
longtermcaresettlement = df_data.loc[idx_df_data,['정산장기요양']][0]
advancepayment = df_data.loc[idx_df_data,['선지급']][0]
etc = df_data.loc[idx_df_data,['기타']][0]
incometax = df_data.loc[idx_df_data,['소득세']][0]
localincometax = df_data.loc[idx_df_data,['지방소득세']][0]
idx_df_employee = df_employee.index[df_employee['성명']==name].tolist()[0]
# print("직원현황 인덱스 :",idx_df_employee)
jobposition = df_employee.loc[idx_df_employee,['직위']][0]
department = df_employee.loc[idx_df_employee,['부서']][0]
birthday = df_employee.loc[idx_df_employee,['생일']][0]
# 엑셀 인스턴스 생성
app = xw.App(visible=False)
book = xw.Book(fname)
sh_paystub = book.sheets('급여명세서사대보험')
sh_paystub["B4"].value = name
sh_paystub["D4"].value = jobposition
sh_paystub["B5"].value = department
sh_paystub["D5"].value = birthday
sh_paystub["B8"].value = normal
sh_paystub["B9"].value = overtime
sh_paystub["B10"].value = holiday
sh_paystub["B11"].value = holidayovertime
sh_paystub["B12"].value = extra
sh_paystub["B13"].value = meals
sh_paystub["D8"].value = nationalpension
sh_paystub["D9"].value = healthinsurance
sh_paystub["D10"].value = longtermcareinsurance
sh_paystub["D11"].value = employmentinsurance
sh_paystub["D12"].value = healthsettlement
sh_paystub["D13"].value = longtermcaresettlement
sh_paystub["D14"].value = advancepayment
sh_paystub["D15"].value = etc
sh_paystub["D16"].value = incometax
sh_paystub["D17"].value = localincometax
sh_paystub["B23"].value = normal_calculation
sh_paystub["B24"].value = overtime_calculation
sh_paystub["B25"].value = holiday_calculation
sh_paystub["B26"].value = holidayovertime_calculation
sh_paystub["B27"].value = extra_calculation
sh_paystub["D23"].value = normal
sh_paystub["D24"].value = overtime
sh_paystub["D25"].value = holiday
sh_paystub["D26"].value = holidayovertime
sh_paystub["D27"].value = extra
# pdf 로 저장하기
# current_path = os.getcwd() # 현재 작업중인 폴더에 저장하기
# 절대경로로 파일 위치 입력
pdf_file = os.path.join(self.current_pdf_path, f"2022년08월급여명세서-{name}.pdf")
# PDF 로 저장할 시트 선택하기(본 예제에서는 첫 번째 시트 선택하기)
# report_sheet = book.sheets[1]
report_sheet = sh_paystub
# PDF 로 저장하기
# report_sheet.ExportAsFixedFormat(0, pdf_path)
report_sheet.api.ExportAsFixedFormat(0, pdf_file)
book.save()
app.kill()
#####################################
def fn_send(self, name, email_i):
# # 메일 서버를 설정합니다.
self.server = smtplib.SMTP_SSL('smtp.kakao.com')
self.server.login(secret.kakao_id, secret.kakao_pw)
self.msg_from = 'miero@kakao.com'
# # server = smtplib.SMTP('smtp.com', port_number)
# # server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# server = smtplib.SMTP_SSL('smtp.kakao.com')
# # server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# # 로그인이 필요하면 로그인 설정
# server.login(secret.kakao_id, secret.kakao_pw)
# # 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
# msg_to = email_i
# cc = 'b@b.com, c@c.com'
# cc = ''
# print(name,email_i)
# 메세지 구성
# msg = MIMEBase('multipart','mixed')
msg = MIMEMultipart()
msg['From'] = self.msg_from
msg['To'] = email_i
msg['Date'] = formatdate(localtime=True)
# msg['Subject'] = f'2022년08월급여명세서-{name}'
msg['Subject'] = Header(s=f'2022년08월급여명세서-{name}', charset='utf-8')
# msg['Cc'] = ""
# 메일 본문 작성
# # html 로 되어있던 파일을 불러 오고 거기에 파일을 붙여서 보냅니다.
# msgText = MIMEText('<h1>%s</h1><hr>, <img src="cid:%s" >' % (emailtext, attachment), 'html')
# contents = '<h1>%s</h1>'
# contents += '<hr>'
# contents += '<img src="cid:%s" >'
# msgText = MIMEText(contents % (emailtext, attachment), 'html')
# contents = f'<h1>{emailtext}</h1>'
# contents += f'<h2>{msg_to} 님 메일이 도착했습니다.</h2>'
# contents += '<hr>'
# contents += f'<img src="cid:{attachment}" >'
# msgText = MIMEText(contents, 'html')
# pretext = f'수신: {name}<br/>'
# pretext += '발신: 주식회사 밀앤아이, 주식회사 헴펠 대표이사<br/>'
# pretext += '<br/>'
# msgpreText = MIMEText(pretext, 'html')
# msg.attach(msgpreText)
# contents = self.textedit22.toPlainText()
contents_before = self.textedit22.toPlainText()
# 문자치환 f-string 사용하여 변수 적용하기
contents = contents_before.replace("{성명}",f'수신: {name}')
# msgText = MIMEText(contents, 'plain')
msgText = MIMEText(contents, 'html')
# msgText = MIMEText(contents, _charset='utf-8')
# 메세지를 메일에 붙여 줍니다.
msg.attach(msgText)
# 메일 제일 밑에 로고그림 붙여 줍니다.
# logo_file = "logo.jpg"
# img_f_name = logo_file.replace("\\","/")
# logo_file = r"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' width='10%' height='0%'></center>"
# img_f_name = logo_file.replace("\\","/")
# # with io.open('file_name.html','r') as f:
# with io.open(img_f_name,'r') as f:
# # emailtext = f.read()
# emailtext = img_f_name
# # attachment = 'attachment_file_name.png'
# attachment = img_f_name
# attachment = logo_file
# fp = open(attachment, 'rb')
# img = MIMEImage(fp.read())
# fp.close()
# img.add_header('Content-ID', '<{}>'.format(attachment))
# msg.attach(img)
# 파일첨부
files = list()
pdf_file_name = f"2022년08월급여명세서-{name}.pdf"
pdf_file = os.path.join(os.getcwd()+"\pdf", pdf_file_name)
files.append(pdf_file)
# if os.path.isfile(pdf_file):
# binary_pdf = open(pdf_file, 'rb')
# payload = MIMEBase('application', 'octate-stream', Name=pdf_file_name)
# payload.set_payload((binary_pdf).read())
# encoders.encode_base64(payload)
# payload.add_header('Content-Decomposition', 'attachment', filename=pdf_file_name)
# msg.attach(payload)
for i in range(self.listwidget21.count()):
files.append(self.listwidget21.item(i).text())
# print(files)
for f in files:
# print(f)
part = MIMEBase('application', "octet-stream")
part.set_payload(open(f,"rb").read())
encoders.encode_base64(part)
fstr_name = os.path.basename(f)
# part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(f))
part.add_header('Content-Disposition',"attachment", filename= fstr_name, charset='utf-8')
# [출처] 파이썬에서 지메일 보내기(w/첨부파일) 한글파일도 가능|작성자 데이터공방
# Header(s=f'2022년08월급여명세서-{name}', charset='utf-8')
msg.attach(part)
# 메일 서버를 이용하여 메일을 발송합니다.
# server.sendmail(msg_from, msg["To"].split(",") + msg["Cc"].split(","), msg.as_string())
self.server.sendmail(msg['From'], msg['To'], msg.as_string())
# self.server.quit()
def fn_test(self):
# 메일 서버를 설정합니다.
# server = smtplib.SMTP('smtp.com', port_number)
# server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# self.server = smtplib.SMTP_SSL('smtp.kakao.com')
# server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# 로그인이 필요하면 로그인 설정
# self.server.login(secret.kakao_id, secret.kakao_pw)
# 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
self.fn_DeleteAllFiles(os.getcwd()+"\pdf")
self.fn_pdf_create("정용만")
# self.fn_pdf_create("정용만")
self.fn_send("정용만", self.df_table_02.loc["정용만"][0])
self.server.quit()
self.fn_print_name("정용만", self.df_table_02.loc["정용만"][0])
def fn_run(self):
# 메일 서버를 설정합니다.
# server = smtplib.SMTP('smtp.com', port_number)
# server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# server = smtplib.SMTP_SSL('smtp.kakao.com')
# server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# 로그인이 필요하면 로그인 설정
# server.login(secret.kakao_id, secret.kakao_pw)
# 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
# self.fn_send("정용만", self.df_table_02.loc["정용만"][0])
# self.fn_print_name("정용만", self.df_table_02.loc["정용만"][0])
for idx_name in self.idx_name_list:
# print(idx)
# print(self.df_table_02.loc[idx][0])
# print(idx, table_02.loc[idx][0])
self.fn_DeleteAllFiles(os.getcwd()+"\pdf")
self.fn_pdf_create(idx_name)
self.fn_send(idx_name, self.df_table_02.loc[idx_name][0])
self.fn_print_name(idx_name, self.df_table_02.loc[idx_name][0])
self.server.quit()
if __name__ == '__main__':
# don't auto scale when drag app to a different monitor.
# QGuiApplication.setHighDpiScaleFactorRoundingPolicy(Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
excel_file_path = '급여1.xlsx'
worksheet_name = '4대급여'
emailsheet_name = '이메일'
app = QApplication(sys.argv)
app.setStyleSheet('''
QWidget {
font-size: 17px;
}
''')
myApp = MyApp()
myApp.show()
try:
sys.exit(app.exec())
except SystemExit:
print('Closing Window...')
====================
pay11.py--------------------
# from operator import index
# from unittest import result
# from xml.dom.minidom import Document
from PyQt5.QtWidgets import QApplication, QWidget, QTableWidget, QTableWidgetItem, QPushButton, \
QHeaderView, QHBoxLayout, QVBoxLayout, QGridLayout, QAbstractScrollArea, QLabel, QListWidget, \
QFileDialog, QMessageBox, QTextEdit, QAbstractItemView, QLineEdit
from PyQt5.QtCore import Qt
# from PyQt5 import QtGui
from PyQt5.QtGui import QTextCursor
import sys
import pandas as pd # pip install pandas
import os
import io
import secret
import xlwings as xw
import smtplib
from email.encoders import encode_base64
from email.header import Header
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText # 메일의 본문 내용을 만드는 모듈 내용을 base64형식으로 변환
from email.utils import formatdate
from email.mime.application import MIMEApplication # 메일의 첨부 파일을 base64 형식으로 변환
from email.mime.image import MIMEImage # 메일의 이미지 파일을 base64 형식으로 변환
# 출처: https://nowonbun.tistory.com/684 [명월 일지:티스토리]
from email import encoders
from email.encoders import encode_base64
class MyApp(QWidget):
def __init__(self):
super().__init__()
self.window_width, self.window_height = 800, 600
self.resize(self.window_width, self.window_height)
self.setWindowTitle('pay')
# self.server = smtplib.SMTP_SSL('smtp.kakao.com')
# self.server.login(secret.kakao_id, secret.kakao_pw)
# self.msg_from = 'miero@kakao.com'
##### layout_main #####
layout_main = QHBoxLayout()
self.setLayout(layout_main)
##### layout_1 #####
layout_1 = QVBoxLayout()
label11 = QLabel('직원 메일')
# self.button = QPushButton('&Load Data')
# self.button.clicked.connect(lambda _, xl_path=excel_file_path, sheet_name=worksheet_name: self.loadExcelData(xl_path, sheet_name))
# layout_v.addWidget(self.button)
layout_1.addWidget(label11)
self.table = QTableWidget()
self.table.setFixedWidth(350)
layout_1.addWidget(self.table)
layout_main.addLayout(layout_1)
##### layout_2 #####
layout_2 = QGridLayout()
label21 = QLabel('이메일 제목')
layout_2.addWidget(label21, 0, 0)
self.lineedit21 = QLineEdit()
layout_2.addWidget(self.lineedit21, 1, 0, 1, 2)
label22 = QLabel('첨부파일')
layout_2.addWidget(label22, 2, 0)
self.listwidget22 = QListWidget()
# self.listwidget22.setFixedWidth(300)
self.listwidget22.setSelectionMode(QAbstractItemView.ExtendedSelection)
layout_2.addWidget(self.listwidget22, 3, 0, 5, 1)
self.btn_file_add = QPushButton('파일 추가') # sendlist
# self.btn_file_add.setMinimumHeight(80)
layout_2.addWidget(self.btn_file_add, 3, 1, 1, 1)
self.btn_file_add.clicked.connect(self.fn_fileadd)
self.btn_file_del = QPushButton('파일 삭제')
layout_2.addWidget(self.btn_file_del, 4, 1, 1, 1)
self.btn_file_del.clicked.connect(self.fn_filedel)
label21 = QLabel('본문 (HTML형식)')
layout_2.addWidget(label21, 8, 0)
self.textedit23 = QTextEdit()
self.textedit23.setFixedWidth(400)
self.textedit23.setAcceptRichText(False)
layout_2.addWidget(self.textedit23, 9, 0, 3, 1)
self.btn_send = QPushButton("보내기")
self.btn_send.setMaximumHeight(500) # gridlayout button size
layout_2.addWidget(self.btn_send, 9, 1, 3, 1)
self.btn_send.clicked.connect(self.fn_test) #@@@@@@@@@@@@@@@@@@@@@@@@@@
layout_main.addLayout(layout_2)
# subject0 파일이 존재하면
filename_subject = 'subject0.txt'
if os.path.isfile(filename_subject) == True:
source_text = open(filename_subject,'r', encoding="UTF-8").read()
# self.lineedit21.setText(source_text) # TextEdit에 RichText 형식의 글을 입력합니다.
self.lineedit21.setText(source_text) # TextEdit에 PlainText 형식의 글을 새로 입력합니다.
# html0 파일이 존재하면
filename_html = 'html0.txt'
if os.path.isfile(filename_html) == True:
source_text = open(filename_html,'r', encoding="UTF-8").read()
# self.textedit23.setText(source_text) # TextEdit에 RichText 형식의 글을 입력합니다.
self.textedit23.setPlainText(source_text) # TextEdit에 PlainText 형식의 글을 새로 입력합니다.
# table_data = self.loadExcelData(excel_file_path, worksheet_name)
# print(table_data.keys())
df_table = self.loadExcelData(excel_file_path, worksheet_name)
# print(table_df["성명"][0])
self.df_table_02 = df_table.set_index("성명")
self.idx_name_list = self.df_table_02.index.to_list()
# print(index)
# for i in table_02["이메일"]:
def loadExcelData(self, excel_file_dir, worksheet_name):
df_work_sheet = pd.read_excel(excel_file_path, worksheet_name)
df_email_sheet = pd.read_excel(excel_file_path, emailsheet_name)
df_table = df_work_sheet.merge(df_email_sheet, how='left')
df_table_mail = df_table[['성명','이메일']]
res = df_table_mail
# res = df_table_mail.to_dict()
# self.table.setRowCount(df.shape[0])
# self.table.setColumnCount(df.shape[1])
self.table.setRowCount(df_table_mail.shape[0])
self.table.setColumnCount(df_table_mail.shape[1])
# self.table.setHorizontalHeaderLabels(df.columns)
self.table.setHorizontalHeaderLabels(df_table_mail.columns)
header = self.table.horizontalHeader()
# header.setSectionResizeMode(0, QHeaderView.Stretch)
# header.setSectionResizeMode(0, QHeaderView.ResizeToContents)
header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
# returns pandas array object
# for row in df.iterrows():
for row in df_table_mail.iterrows():
values = row[1]
for col_index, value in enumerate(values):
if isinstance(value, (float, int)):
value = '{0:0,.0f}'.format(value)
tableItem = QTableWidgetItem(str(value))
if value == "nan":
tableItem.setBackground(Qt.red)
self.table.setItem(row[0], col_index, tableItem)
self.table.setColumnWidth(2, 310)
return res
def fn_fileadd(self):
# f_name = QFileDialog.getOpenFileName(None, '열기', '', "All Files(*.*)")
f_names = QFileDialog.getOpenFileNames(None, '열기', '', "All Files(*.*)")
# txtPath = f_name[0]
filelist = f_names[0]
if filelist:
for f_name in filelist:
# ext = os.path.splitext(f_name[0])[1]
ext = os.path.splitext(f_name)[1] # 확장자 확인
# if f_names[0]:
icnt = 0
for i in range(self.listwidget22.count()):
# if str(self.listwidget22.item(i).text()) == txtPath.replace("/","\\") or str(self.listwidget22.item(i).text()) == txtPath:
if str(self.listwidget22.item(i).text()) == f_name.replace("/","\\") or str(self.listwidget22.item(i).text()) == f_name:
icnt = 1
break
if icnt != 1:
f_path = f_name
if ext == '.exe':
QMessageBox.about(self,'파일 형식 확인','exe파일은 전송할 수 없습니다.')
pass
else:
cnt = self.listwidget22.count() +1
# self.listwidget22.insertItem(cnt, os.path.basename(txtPath))
# self.listwidget22.insertItem(cnt, txtPath)
# f_path = f_names[0]
# print(f_path)
self.listwidget22.insertItem(cnt, f_path)
# self.listwidget22.insertItem(cnt, f_path.replace("/","\\"))
def fn_filedel(self):
currentrow = self.listwidget22.currentRow()
self.listwidget22.takeItem(currentrow) # currentrowRight번째 항목을 삭제합니다
self.listwidget22.clearSelection()
def fn_subject_save(self):
if len(self.lineedit21.text())>0:
S__File = os.path.join(os.getcwd(),'subject0.txt')
Text = self.lineedit21.text()
if S__File:
# Finally this will Save your file to the path selected.
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
file.write(Text)
else:
QMessageBox.about(self,'제목 입력 확인','제목을 입력하십시요.')
def fn_html_save(self):
if len(self.textedit23.toPlainText())>0:
# print(len(self.textedit.toPlainText()))
# S__File = QFileDialog.getSaveFileName(None,'문자 파일저장','/', "Text Files (*.txt)")
# S__File = QFileDialog.getSaveFileName(None,'문자 파일저장','html0', "Text Files (*.txt)")
S__File = os.path.join(os.getcwd(),'html0.txt')
# This will let you access the test in your QTextEdit
Text = self.textedit23.toPlainText()
# document = self.textedit23.document()
# cursor = QTextCursor(document)
# p1 = cursor.position() # return int
# cursor.insertImage(r"C:\Users\newstep\Pictures\number1.jpg")
# This will prevent you from an error if pressed cancel on file dialog.
# if S__File[0]:
if S__File:
# Finally this will Save your file to the path selected.
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
file.write(Text)
# txtPath = S__File[0]
# icnt = 0
# for i in range(self.listwidget31.count()):
# if str(self.listwidget31.item(i).text()) == txtPath.replace("/","\\"):
# icnt = 1
# break
# if icnt != 1:
# cnt = self.listwidget31.count() +1
# self.listwidget31.insertItem(cnt, os.path.basename(txtPath))
# self.listwidget31.insertItem(cnt, txtPath)
else:
QMessageBox.about(self,'메시지 입력 확인','메시지를 입력하셔야 합니다.')
def fn_print_name(self, name, email):
# f_name_pre = r"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' width='50%' height='0%'></center>"
# f_name = f_name_pre.replace("\\","/")
# with io.open('file_name.html','r') as f:
# with io.open(f_name,'r') as f:
# # emailtext = f.read()
# emailtext = f_name
# attachment = 'attachment_file_name.png'
# attachment = f_name
# print(name, self.df_table_02.loc[name][0])
# print(name, email)
if len(self.textedit23.toPlainText())>0:
S__File = os.path.join(os.getcwd(),'html0.txt')
# print(len(self.textedit23.toPlainText()))
# print(S__File)
pretext = f'{name} 님<br/><br/>'
# pretext += f'당신의 이메일은 {email} 입니다.<br/>'
contents = self.textedit23.toPlainText()
# nexttext = f'<br/><img src="cid:{attachment}" >'
nexttext = f"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' id='millstudio logo' width='10%' height='0%'></center>"
# document = self.textedit23.document()
# cursor = QTextCursor(document)
# p1 = cursor.position() # return int
# cursor.insertImage(f_name)
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
# file.write(pretext)
file.write(contents)
# file.write(nexttext)
# print(contents)
# msgText = MIMEText(contents, 'html')
print(name,email,"전송완료")
def fn_DeleteAllFiles(self,filePath):
if os.path.exists(filePath):
for file in os.scandir(filePath):
os.remove(file.path)
return '폴더 내 모든 파일 지우기 완료'
else:
return '폴더가 없습니다.'
def fn_pdf_create(self, idx_name):
#####################################
# xlwings
self.current_pdf_path = os.getcwd()+"\pdf"
fname = "급여1.xlsx"
# for n in self.target_name_list:
name = idx_name
df_data = pd.read_excel(fname, sheet_name='4대급여')
df_data = df_data.fillna(0)
df_employee = pd.read_excel(fname, sheet_name='직원현황')
idx_df_data = df_data.index[df_data['성명']==name].tolist()[0]
# print("4대급여 인덱스 :",idx_df_data)
normal = df_data.loc[idx_df_data,['기본급']][0]
overtime = df_data.loc[idx_df_data,['연장수당']][0]
holiday = df_data.loc[idx_df_data,['휴일수당']][0]
holidayovertime = df_data.loc[idx_df_data,['휴일연장수당']][0]
extra = df_data.loc[idx_df_data,['추가수당']][0]
meals = df_data.loc[idx_df_data,['식대']][0]
bonus = df_data.loc[idx_df_data,['상여금']][0]
normal_calculation = df_data.loc[idx_df_data,['기']][0]
overtime_calculation = df_data.loc[idx_df_data,['연']][0]
holiday_calculation = df_data.loc[idx_df_data,['휴']][0]
holidayovertime_calculation = df_data.loc[idx_df_data,['휴연']][0]
extra_calculation = df_data.loc[idx_df_data,['추']][0]
nationalpension = df_data.loc[idx_df_data,['국민연금']][0]
healthinsurance = df_data.loc[idx_df_data,['건강보험']][0]
longtermcareinsurance = df_data.loc[idx_df_data,['장기요양보험']][0]
employmentinsurance = df_data.loc[idx_df_data,['고용보험']][0]
healthsettlement = df_data.loc[idx_df_data,['정산건강']][0]
longtermcaresettlement = df_data.loc[idx_df_data,['정산장기요양']][0]
advancepayment = df_data.loc[idx_df_data,['선지급']][0]
etc = df_data.loc[idx_df_data,['기타']][0]
incometax = df_data.loc[idx_df_data,['소득세']][0]
localincometax = df_data.loc[idx_df_data,['지방소득세']][0]
idx_df_employee = df_employee.index[df_employee['성명']==name].tolist()[0]
# print("직원현황 인덱스 :",idx_df_employee)
jobposition = df_employee.loc[idx_df_employee,['직위']][0]
department = df_employee.loc[idx_df_employee,['부서']][0]
birthday = df_employee.loc[idx_df_employee,['생일']][0]
# 엑셀 인스턴스 생성
app = xw.App(visible=False)
book = xw.Book(fname)
sh_paystub = book.sheets('급여명세서사대보험')
sh_paystub["B4"].value = name
sh_paystub["D4"].value = jobposition
sh_paystub["B5"].value = department
sh_paystub["D5"].value = birthday
sh_paystub["B8"].value = normal
sh_paystub["B9"].value = overtime
sh_paystub["B10"].value = holiday
sh_paystub["B11"].value = holidayovertime
sh_paystub["B12"].value = extra
sh_paystub["B13"].value = meals
sh_paystub["D8"].value = nationalpension
sh_paystub["D9"].value = healthinsurance
sh_paystub["D10"].value = longtermcareinsurance
sh_paystub["D11"].value = employmentinsurance
sh_paystub["D12"].value = healthsettlement
sh_paystub["D13"].value = longtermcaresettlement
sh_paystub["D14"].value = advancepayment
sh_paystub["D15"].value = etc
sh_paystub["D16"].value = incometax
sh_paystub["D17"].value = localincometax
sh_paystub["B23"].value = normal_calculation
sh_paystub["B24"].value = overtime_calculation
sh_paystub["B25"].value = holiday_calculation
sh_paystub["B26"].value = holidayovertime_calculation
sh_paystub["B27"].value = extra_calculation
sh_paystub["D23"].value = normal
sh_paystub["D24"].value = overtime
sh_paystub["D25"].value = holiday
sh_paystub["D26"].value = holidayovertime
sh_paystub["D27"].value = extra
if len(self.lineedit21.text())==0:
book.save()
app.kill()
return
# print(len(self.lineedit21.text()))
# pdf 로 저장하기
# current_path = os.getcwd() # 현재 작업중인 폴더에 저장하기
# 절대경로로 파일 위치 입력
subject_before = self.lineedit21.text()
# 문자치환 f-string 사용하여 변수 적용하기
subject = subject_before.replace("{성명}",f'{name}')
pdf_file = os.path.join(self.current_pdf_path, f"{subject}.pdf")
# PDF 로 저장할 시트 선택하기(본 예제에서는 첫 번째 시트 선택하기)
# report_sheet = book.sheets[1]
report_sheet = sh_paystub
# PDF 로 저장하기
# report_sheet.ExportAsFixedFormat(0, pdf_path)
report_sheet.api.ExportAsFixedFormat(0, pdf_file)
book.save()
app.kill()
#####################################
def fn_send(self, name, email_i):
# # 메일 서버를 설정합니다.
self.server = smtplib.SMTP_SSL('smtp.kakao.com')
self.server.login(secret.kakao_id, secret.kakao_pw)
self.msg_from = 'miero@kakao.com'
# # server = smtplib.SMTP('smtp.com', port_number)
# # server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# server = smtplib.SMTP_SSL('smtp.kakao.com')
# # server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# # 로그인이 필요하면 로그인 설정
# server.login(secret.kakao_id, secret.kakao_pw)
# # 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
# msg_to = email_i
# cc = 'b@b.com, c@c.com'
# cc = ''
# print(name,email_i)
# 메세지 구성
# msg = MIMEBase('multipart','mixed')
msg = MIMEMultipart()
msg['From'] = self.msg_from
msg['To'] = email_i
msg['Date'] = formatdate(localtime=True)
# msg['Subject'] = f'2022년08월급여명세서-{name}'
subject_before = self.lineedit21.text()
# 문자치환 f-string 사용하여 변수 적용하기
subject = subject_before.replace("{성명}",f'{name}')
msg['Subject'] = Header(s=subject, charset='utf-8')
# msg['Subject'] = Header(s=f'2022년08월급여명세서-{name}', charset='utf-8')
# msg['Cc'] = ""
# 메일 본문 작성
# # html 로 되어있던 파일을 불러 오고 거기에 파일을 붙여서 보냅니다.
# msgText = MIMEText('<h1>%s</h1><hr>, <img src="cid:%s" >' % (emailtext, attachment), 'html')
# contents = '<h1>%s</h1>'
# contents += '<hr>'
# contents += '<img src="cid:%s" >'
# msgText = MIMEText(contents % (emailtext, attachment), 'html')
# contents = f'<h1>{emailtext}</h1>'
# contents += f'<h2>{msg_to} 님 메일이 도착했습니다.</h2>'
# contents += '<hr>'
# contents += f'<img src="cid:{attachment}" >'
# msgText = MIMEText(contents, 'html')
# pretext = f'수신: {name}<br/>'
# pretext += '발신: 주식회사 밀앤아이, 주식회사 헴펠 대표이사<br/>'
# pretext += '<br/>'
# msgpreText = MIMEText(pretext, 'html')
# msg.attach(msgpreText)
# contents = self.textedit23.toPlainText()
contents_before = self.textedit23.toPlainText()
# 문자치환 f-string 사용하여 변수 적용하기
contents = contents_before.replace("{성명}",f'수신: {name}')
# msgText = MIMEText(contents, 'plain')
msgText = MIMEText(contents, 'html')
# msgText = MIMEText(contents, _charset='utf-8')
# 메세지를 메일에 붙여 줍니다.
msg.attach(msgText)
# 메일 제일 밑에 로고그림 붙여 줍니다.
# logo_file = "logo.jpg"
# img_f_name = logo_file.replace("\\","/")
# logo_file = r"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' width='10%' height='0%'></center>"
# img_f_name = logo_file.replace("\\","/")
# # with io.open('file_name.html','r') as f:
# with io.open(img_f_name,'r') as f:
# # emailtext = f.read()
# emailtext = img_f_name
# # attachment = 'attachment_file_name.png'
# attachment = img_f_name
# attachment = logo_file
# fp = open(attachment, 'rb')
# img = MIMEImage(fp.read())
# fp.close()
# img.add_header('Content-ID', '<{}>'.format(attachment))
# msg.attach(img)
# 파일첨부
files = list()
pdf_file_name = f"2022년08월급여명세서-{name}.pdf"
pdf_file = os.path.join(os.getcwd()+"\pdf", pdf_file_name)
files.append(pdf_file)
# if os.path.isfile(pdf_file):
# binary_pdf = open(pdf_file, 'rb')
# payload = MIMEBase('application', 'octate-stream', Name=pdf_file_name)
# payload.set_payload((binary_pdf).read())
# encoders.encode_base64(payload)
# payload.add_header('Content-Decomposition', 'attachment', filename=pdf_file_name)
# msg.attach(payload)
for i in range(self.listwidget22.count()):
files.append(self.listwidget22.item(i).text())
# print(files)
for f in files:
# print(f)
part = MIMEBase('application', "octet-stream")
part.set_payload(open(f,"rb").read())
encoders.encode_base64(part)
fstr_name = os.path.basename(f)
# part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(f))
part.add_header('Content-Disposition',"attachment", filename= fstr_name, charset='utf-8')
# [출처] 파이썬에서 지메일 보내기(w/첨부파일) 한글파일도 가능|작성자 데이터공방
# Header(s=f'2022년08월급여명세서-{name}', charset='utf-8')
msg.attach(part)
# 메일 서버를 이용하여 메일을 발송합니다.
# server.sendmail(msg_from, msg["To"].split(",") + msg["Cc"].split(","), msg.as_string())
self.server.sendmail(msg['From'], msg['To'], msg.as_string())
# self.server.quit()
def fn_test(self):
try:
# 메일 서버를 설정합니다.
# server = smtplib.SMTP('smtp.com', port_number)
# server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# self.server = smtplib.SMTP_SSL('smtp.kakao.com')
# server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# 로그인이 필요하면 로그인 설정
# self.server.login(secret.kakao_id, secret.kakao_pw)
# 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
self.fn_subject_save()
self.fn_html_save()
self.fn_DeleteAllFiles(os.getcwd()+"\pdf")
self.fn_pdf_create("정용만")
# self.fn_pdf_create("정용만")
self.fn_send("정용만", self.df_table_02.loc["정용만"][0])
self.server.quit()
self.fn_print_name("정용만", self.df_table_02.loc["정용만"][0])
except: # 예외가 발생했을 때 실행됨
print('예외가 발생했습니다.')
def fn_run(self):
try:
# 메일 서버를 설정합니다.
# server = smtplib.SMTP('smtp.com', port_number)
# server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# server = smtplib.SMTP_SSL('smtp.kakao.com')
# server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# 로그인이 필요하면 로그인 설정
# server.login(secret.kakao_id, secret.kakao_pw)
# 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
self.fn_subject_save()
self.fn_html_save()
# self.fn_send("정용만", self.df_table_02.loc["정용만"][0])
# self.fn_print_name("정용만", self.df_table_02.loc["정용만"][0])
for idx_name in self.idx_name_list:
# print(idx)
# print(self.df_table_02.loc[idx][0])
# print(idx, table_02.loc[idx][0])
self.fn_DeleteAllFiles(os.getcwd()+"\pdf")
self.fn_pdf_create(idx_name)
self.fn_send(idx_name, self.df_table_02.loc[idx_name][0])
self.fn_print_name(idx_name, self.df_table_02.loc[idx_name][0])
self.server.quit()
except: # 예외가 발생했을 때 실행됨
print('예외가 발생했습니다.')
if __name__ == '__main__':
# don't auto scale when drag app to a different monitor.
# QGuiApplication.setHighDpiScaleFactorRoundingPolicy(Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
excel_file_path = '급여1.xlsx'
worksheet_name = '4대급여'
emailsheet_name = '이메일'
app = QApplication(sys.argv)
app.setStyleSheet('''
QWidget {
font-size: 17px;
}
''')
myApp = MyApp()
myApp.show()
try:
sys.exit(app.exec())
except SystemExit:
print('Closing Window...')
====================
pay12.py--------------------
# from operator import index
# from unittest import result
# from xml.dom.minidom import Document
from PyQt5.QtWidgets import QApplication, QWidget, QTableWidget, QTableWidgetItem, QPushButton, \
QHeaderView, QHBoxLayout, QVBoxLayout, QGridLayout, QAbstractScrollArea, QLabel, QListWidget, \
QFileDialog, QMessageBox, QTextEdit, QAbstractItemView, QLineEdit, QGroupBox, QRadioButton
from PyQt5.QtCore import Qt
# from PyQt5 import QtGui
from PyQt5.QtGui import QTextCursor
import sys
import pandas as pd # pip install pandas
import os
import io
import secret
import xlwings as xw
import smtplib
from email.encoders import encode_base64
from email.header import Header
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText # 메일의 본문 내용을 만드는 모듈 내용을 base64형식으로 변환
from email.utils import formatdate
from email.mime.application import MIMEApplication # 메일의 첨부 파일을 base64 형식으로 변환
from email.mime.image import MIMEImage # 메일의 이미지 파일을 base64 형식으로 변환
# 출처: https://nowonbun.tistory.com/684 [명월 일지:티스토리]
from email import encoders
from email.encoders import encode_base64
class MyApp(QWidget):
def __init__(self):
super().__init__()
self.window_width, self.window_height = 800, 600
self.resize(self.window_width, self.window_height)
self.setWindowTitle('pay')
# self.server = smtplib.SMTP_SSL('smtp.kakao.com')
# self.server.login(secret.kakao_id, secret.kakao_pw)
# self.msg_from = 'miero@kakao.com'
##### layout_main #####
layout_main = QHBoxLayout()
self.setLayout(layout_main)
##### layout_1 #####
layout_1 = QVBoxLayout()
label11 = QLabel('직원 메일')
# self.button = QPushButton('&Load Data')
# self.button.clicked.connect(lambda _, xl_path=excel_file_path, sheet_name=worksheet_name: self.loadExcelData(xl_path, sheet_name))
# layout_v.addWidget(self.button)
layout_1.addWidget(label11)
self.table = QTableWidget()
self.table.setFixedWidth(350)
layout_1.addWidget(self.table)
layout_main.addLayout(layout_1)
##### layout_2 #####
layout_2 = QGridLayout()
label21 = QLabel('이메일 제목')
layout_2.addWidget(label21, 0, 0)
self.lineedit21 = QLineEdit()
layout_2.addWidget(self.lineedit21, 1, 0, 1, 2)
label22 = QLabel('첨부파일')
layout_2.addWidget(label22, 2, 0)
self.listwidget22 = QListWidget()
# self.listwidget22.setFixedWidth(300)
# self.listwidget22.setSelectionMode(QAbstractItemView.ExtendedSelection)
layout_2.addWidget(self.listwidget22, 3, 0, 5, 1)
self.btn_file_add = QPushButton('파일 추가') # sendlist
# self.btn_file_add.setMinimumHeight(80)
layout_2.addWidget(self.btn_file_add, 3, 1, 1, 1)
self.btn_file_add.clicked.connect(self.fn_fileadd)
self.btn_file_del = QPushButton('파일 삭제')
layout_2.addWidget(self.btn_file_del, 4, 1, 1, 1)
self.btn_file_del.clicked.connect(self.fn_filedel)
# label21 = QLabel('본문 (HTML형식)')
# layout_2.addWidget(label21, 8, 0)
# radio_1 ~ 4 버튼을 그룹으로 설정
groupBoxBottom = QGroupBox("본문 보기형식 선택")
layout_2.addWidget(groupBoxBottom, 8, 0)
hBox = QHBoxLayout()
groupBoxBottom.setLayout(hBox)
self.radioBtn1 = QRadioButton("HTML")
self.radioBtn1.setChecked(True)
self.radioBtn1.clicked.connect(self.fn_radio_select)
hBox.addWidget(self.radioBtn1)
self.radioBtn2 = QRadioButton("미리보기")
self.radioBtn2.clicked.connect(self.fn_radio_select)
hBox.addWidget(self.radioBtn2)
self.textedit23 = QTextEdit()
# self.textedit23.setFixedWidth(400)
# self.textedit23.setAcceptRichText(False)
layout_2.addWidget(self.textedit23, 10, 0, 3, 1)
self.textedit23.show()
self.textedit24 = QTextEdit()
layout_2.addWidget(self.textedit24, 10, 0, 3, 1)
self.textedit24.hide()
self.btn_send = QPushButton("보내기")
self.btn_send.setMaximumHeight(500) # gridlayout button size
layout_2.addWidget(self.btn_send, 10, 1, 3, 1)
self.btn_send.clicked.connect(self.fn_test) #@@@@@@@@@@@@@@@@@@@@@@@@@@
layout_main.addLayout(layout_2)
# subject0 파일이 존재하면
filename_subject = 'subject0.txt'
if os.path.isfile(filename_subject) == True:
source_text = open(filename_subject,'r', encoding="UTF-8").read()
# self.lineedit21.setText(source_text) # TextEdit에 RichText 형식의 글을 입력합니다.
self.lineedit21.setText(source_text) # TextEdit에 PlainText 형식의 글을 새로 입력합니다.
# html0 파일이 존재하면
filename_html = 'html0.txt'
if os.path.isfile(filename_html) == True:
source_text = open(filename_html,'r', encoding="UTF-8").read()
# self.textedit23.setText(source_text) # TextEdit에 RichText 형식의 글을 입력합니다.
self.textedit23.setPlainText(source_text) # TextEdit에 PlainText 형식의 글을 새로 입력합니다.
# self.textedit24.setHtml(source_text) # TextEdit에 PlainText 형식의 글을 새로 입력합니다.
# table_data = self.loadExcelData(excel_file_path, worksheet_name)
# print(table_data.keys())
df_table = self.loadExcelData(excel_file_path, worksheet_name)
# print(table_df["성명"][0])
self.df_table_02 = df_table.set_index("성명")
self.idx_name_list = self.df_table_02.index.to_list()
# print(index)
# for i in table_02["이메일"]:
def fn_radio_select(self):
# QRadioButton1 클릭 여부 표시
if self.radioBtn1.isChecked():
self.textedit23.show()
self.textedit24.hide()
self.hidden = False
# self.btn_send.setText('보내기')
elif self.radioBtn2.isChecked():
self.fn_html_save()
self.textedit23.hide()
self.textedit24.show()
self.hidden = True
# self.btn_send.setText('미리보기')
def loadExcelData(self, excel_file_dir, worksheet_name):
df_work_sheet = pd.read_excel(excel_file_path, worksheet_name)
df_email_sheet = pd.read_excel(excel_file_path, emailsheet_name)
df_table = df_work_sheet.merge(df_email_sheet, how='left')
df_table_mail = df_table[['성명','이메일']]
res = df_table_mail
# res = df_table_mail.to_dict()
# self.table.setRowCount(df.shape[0])
# self.table.setColumnCount(df.shape[1])
self.table.setRowCount(df_table_mail.shape[0])
self.table.setColumnCount(df_table_mail.shape[1])
# self.table.setHorizontalHeaderLabels(df.columns)
self.table.setHorizontalHeaderLabels(df_table_mail.columns)
header = self.table.horizontalHeader()
# header.setSectionResizeMode(0, QHeaderView.Stretch)
# header.setSectionResizeMode(0, QHeaderView.ResizeToContents)
header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
# returns pandas array object
# for row in df.iterrows():
for row in df_table_mail.iterrows():
values = row[1]
for col_index, value in enumerate(values):
if isinstance(value, (float, int)):
value = '{0:0,.0f}'.format(value)
tableItem = QTableWidgetItem(str(value))
if value == "nan":
tableItem.setBackground(Qt.red)
self.table.setItem(row[0], col_index, tableItem)
self.table.setColumnWidth(2, 310)
return res
def fn_fileadd(self):
# f_name = QFileDialog.getOpenFileName(None, '열기', '', "All Files(*.*)")
f_names = QFileDialog.getOpenFileNames(None, '열기', '', "All Files(*.*)")
# txtPath = f_name[0]
filelist = f_names[0]
if filelist:
for f_name in filelist:
# ext = os.path.splitext(f_name[0])[1]
ext = os.path.splitext(f_name)[1] # 확장자 확인
# if f_names[0]:
icnt = 0
for i in range(self.listwidget22.count()):
# if str(self.listwidget22.item(i).text()) == txtPath.replace("/","\\") or str(self.listwidget22.item(i).text()) == txtPath:
if str(self.listwidget22.item(i).text()) == f_name.replace("/","\\") or str(self.listwidget22.item(i).text()) == f_name:
icnt = 1
break
if icnt != 1:
f_path = f_name
if ext == '.exe':
QMessageBox.about(self,'파일 형식 확인','exe파일은 전송할 수 없습니다.')
pass
else:
cnt = self.listwidget22.count() +1
# self.listwidget22.insertItem(cnt, os.path.basename(txtPath))
# self.listwidget22.insertItem(cnt, txtPath)
# f_path = f_names[0]
# print(f_path)
self.listwidget22.insertItem(cnt, f_path)
# self.listwidget22.insertItem(cnt, f_path.replace("/","\\"))
def fn_filedel(self):
currentrow = self.listwidget22.currentRow()
self.listwidget22.takeItem(currentrow) # currentrowRight번째 항목을 삭제합니다
self.listwidget22.clearSelection()
def fn_subject_save(self):
if len(self.lineedit21.text())>0:
S__File = os.path.join(os.getcwd(),'subject0.txt')
Text = self.lineedit21.text()
if S__File:
# Finally this will Save your file to the path selected.
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
file.write(Text)
else:
QMessageBox.about(self,'제목 입력 확인','제목을 입력하십시요.')
def fn_html_save(self):
if len(self.textedit23.toPlainText())>0:
# print(len(self.textedit.toPlainText()))
# S__File = QFileDialog.getSaveFileName(None,'문자 파일저장','/', "Text Files (*.txt)")
# S__File = QFileDialog.getSaveFileName(None,'문자 파일저장','html0', "Text Files (*.txt)")
S__File = os.path.join(os.getcwd(),'html0.txt')
# This will let you access the test in your QTextEdit
Text = self.textedit23.toPlainText()
self.textedit24.setHtml(Text)
# document = self.textedit23.document()
# cursor = QTextCursor(document)
# p1 = cursor.position() # return int
# cursor.insertImage(r"C:\Users\newstep\Pictures\number1.jpg")
# This will prevent you from an error if pressed cancel on file dialog.
# if S__File[0]:
if S__File:
# Finally this will Save your file to the path selected.
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
file.write(Text)
# txtPath = S__File[0]
# icnt = 0
# for i in range(self.listwidget31.count()):
# if str(self.listwidget31.item(i).text()) == txtPath.replace("/","\\"):
# icnt = 1
# break
# if icnt != 1:
# cnt = self.listwidget31.count() +1
# self.listwidget31.insertItem(cnt, os.path.basename(txtPath))
# self.listwidget31.insertItem(cnt, txtPath)
else:
QMessageBox.about(self,'메시지 입력 확인','메시지를 입력하셔야 합니다.')
def fn_print_name(self, name, email):
# f_name_pre = r"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' width='50%' height='0%'></center>"
# f_name = f_name_pre.replace("\\","/")
# with io.open('file_name.html','r') as f:
# with io.open(f_name,'r') as f:
# # emailtext = f.read()
# emailtext = f_name
# attachment = 'attachment_file_name.png'
# attachment = f_name
# print(name, self.df_table_02.loc[name][0])
# print(name, email)
if len(self.textedit23.toPlainText())>0:
S__File = os.path.join(os.getcwd(),'html0.txt')
# print(len(self.textedit23.toPlainText()))
# print(S__File)
# pretext = f'{name} 님<br/><br/>'
# pretext += f'당신의 이메일은 {email} 입니다.<br/>'
contents = self.textedit23.toPlainText()
# nexttext = f'<br/><img src="cid:{attachment}" >'
# nexttext = f"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' id='millstudio logo' width='10%' height='0%'></center>"
# document = self.textedit23.document()
# cursor = QTextCursor(document)
# p1 = cursor.position() # return int
# cursor.insertImage(f_name)
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
# file.write(pretext)
file.write(contents)
# file.write(nexttext)
# print(contents)
# msgText = MIMEText(contents, 'html')
print(name,email,"전송완료")
def fn_DeleteAllFiles(self,filePath):
if os.path.exists(filePath):
for file in os.scandir(filePath):
os.remove(file.path)
return '폴더 내 모든 파일 지우기 완료'
else:
return '폴더가 없습니다.'
def fn_pdf_create(self, idx_name):
#####################################
# xlwings
self.current_pdf_path = os.getcwd()+"\pdf"
fname = "급여1.xlsx"
# for n in self.target_name_list:
name = idx_name
df_data = pd.read_excel(fname, sheet_name='4대급여')
df_data = df_data.fillna(0)
df_employee = pd.read_excel(fname, sheet_name='직원현황')
idx_df_data = df_data.index[df_data['성명']==name].tolist()[0]
# print("4대급여 인덱스 :",idx_df_data)
normal = df_data.loc[idx_df_data,['기본급']][0]
overtime = df_data.loc[idx_df_data,['연장수당']][0]
holiday = df_data.loc[idx_df_data,['휴일수당']][0]
holidayovertime = df_data.loc[idx_df_data,['휴일연장수당']][0]
extra = df_data.loc[idx_df_data,['추가수당']][0]
meals = df_data.loc[idx_df_data,['식대']][0]
bonus = df_data.loc[idx_df_data,['상여금']][0]
normal_calculation = df_data.loc[idx_df_data,['기']][0]
overtime_calculation = df_data.loc[idx_df_data,['연']][0]
holiday_calculation = df_data.loc[idx_df_data,['휴']][0]
holidayovertime_calculation = df_data.loc[idx_df_data,['휴연']][0]
extra_calculation = df_data.loc[idx_df_data,['추']][0]
nationalpension = df_data.loc[idx_df_data,['국민연금']][0]
healthinsurance = df_data.loc[idx_df_data,['건강보험']][0]
longtermcareinsurance = df_data.loc[idx_df_data,['장기요양보험']][0]
employmentinsurance = df_data.loc[idx_df_data,['고용보험']][0]
healthsettlement = df_data.loc[idx_df_data,['정산건강']][0]
longtermcaresettlement = df_data.loc[idx_df_data,['정산장기요양']][0]
advancepayment = df_data.loc[idx_df_data,['선지급']][0]
etc = df_data.loc[idx_df_data,['기타']][0]
incometax = df_data.loc[idx_df_data,['소득세']][0]
localincometax = df_data.loc[idx_df_data,['지방소득세']][0]
idx_df_employee = df_employee.index[df_employee['성명']==name].tolist()[0]
# print("직원현황 인덱스 :",idx_df_employee)
jobposition = df_employee.loc[idx_df_employee,['직위']][0]
department = df_employee.loc[idx_df_employee,['부서']][0]
birthday = df_employee.loc[idx_df_employee,['생일']][0]
# 엑셀 인스턴스 생성
app = xw.App(visible=False)
book = xw.Book(fname)
sh_paystub = book.sheets('급여명세서사대보험')
sh_paystub["B4"].value = name
sh_paystub["D4"].value = jobposition
sh_paystub["B5"].value = department
sh_paystub["D5"].value = birthday
sh_paystub["B8"].value = normal
sh_paystub["B9"].value = overtime
sh_paystub["B10"].value = holiday
sh_paystub["B11"].value = holidayovertime
sh_paystub["B12"].value = extra
sh_paystub["B13"].value = meals
sh_paystub["D8"].value = nationalpension
sh_paystub["D9"].value = healthinsurance
sh_paystub["D10"].value = longtermcareinsurance
sh_paystub["D11"].value = employmentinsurance
sh_paystub["D12"].value = healthsettlement
sh_paystub["D13"].value = longtermcaresettlement
sh_paystub["D14"].value = advancepayment
sh_paystub["D15"].value = etc
sh_paystub["D16"].value = incometax
sh_paystub["D17"].value = localincometax
sh_paystub["B23"].value = normal_calculation
sh_paystub["B24"].value = overtime_calculation
sh_paystub["B25"].value = holiday_calculation
sh_paystub["B26"].value = holidayovertime_calculation
sh_paystub["B27"].value = extra_calculation
sh_paystub["D23"].value = normal
sh_paystub["D24"].value = overtime
sh_paystub["D25"].value = holiday
sh_paystub["D26"].value = holidayovertime
sh_paystub["D27"].value = extra
if len(self.lineedit21.text())==0:
book.save()
app.kill()
return
# print(len(self.lineedit21.text()))
# pdf 로 저장하기
# current_path = os.getcwd() # 현재 작업중인 폴더에 저장하기
# 절대경로로 파일 위치 입력
subject_before = self.lineedit21.text()
# 문자치환 f-string 사용하여 변수 적용하기
subject = subject_before.replace("{성명}",f'{name}')
pdf_file = os.path.join(self.current_pdf_path, f"{subject}.pdf")
# PDF 로 저장할 시트 선택하기(본 예제에서는 첫 번째 시트 선택하기)
# report_sheet = book.sheets[1]
report_sheet = sh_paystub
# PDF 로 저장하기
# report_sheet.ExportAsFixedFormat(0, pdf_path)
report_sheet.api.ExportAsFixedFormat(0, pdf_file)
book.save()
app.kill()
#####################################
def fn_send(self, name, email_i):
# # 메일 서버를 설정합니다.
self.server = smtplib.SMTP_SSL('smtp.kakao.com')
self.server.login(secret.kakao_id, secret.kakao_pw)
self.msg_from = 'miero@kakao.com'
# # server = smtplib.SMTP('smtp.com', port_number)
# # server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# server = smtplib.SMTP_SSL('smtp.kakao.com')
# # server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# # 로그인이 필요하면 로그인 설정
# server.login(secret.kakao_id, secret.kakao_pw)
# # 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
# msg_to = email_i
# cc = 'b@b.com, c@c.com'
# cc = ''
# print(name,email_i)
# 메세지 구성
# msg = MIMEBase('multipart','mixed')
msg = MIMEMultipart()
msg['From'] = self.msg_from
msg['To'] = email_i
msg['Date'] = formatdate(localtime=True)
# msg['Subject'] = f'2022년08월급여명세서-{name}'
subject_before = self.lineedit21.text()
# 문자치환 f-string 사용하여 변수 적용하기
subject = subject_before.replace("{성명}",f'{name}')
msg['Subject'] = Header(s=subject, charset='utf-8')
# msg['Subject'] = Header(s=f'2022년08월급여명세서-{name}', charset='utf-8')
# msg['Cc'] = ""
# 메일 본문 작성
# # html 로 되어있던 파일을 불러 오고 거기에 파일을 붙여서 보냅니다.
# msgText = MIMEText('<h1>%s</h1><hr>, <img src="cid:%s" >' % (emailtext, attachment), 'html')
# contents = '<h1>%s</h1>'
# contents += '<hr>'
# contents += '<img src="cid:%s" >'
# msgText = MIMEText(contents % (emailtext, attachment), 'html')
# contents = f'<h1>{emailtext}</h1>'
# contents += f'<h2>{msg_to} 님 메일이 도착했습니다.</h2>'
# contents += '<hr>'
# contents += f'<img src="cid:{attachment}" >'
# msgText = MIMEText(contents, 'html')
# pretext = f'수신: {name}<br/>'
# pretext += '발신: 주식회사 밀앤아이, 주식회사 헴펠 대표이사<br/>'
# pretext += '<br/>'
# msgpreText = MIMEText(pretext, 'html')
# msg.attach(msgpreText)
# contents = self.textedit23.toPlainText()
contents_before = self.textedit23.toPlainText()
# 문자치환 f-string 사용하여 변수 적용하기
contents = contents_before.replace("{성명}",f'수신: {name}')
# msgText = MIMEText(contents, 'plain')
msgText = MIMEText(contents, 'html')
# msgText = MIMEText(contents, _charset='utf-8')
# 메세지를 메일에 붙여 줍니다.
msg.attach(msgText)
# 메일 제일 밑에 로고그림 붙여 줍니다.
# logo_file = "logo.jpg"
# img_f_name = logo_file.replace("\\","/")
# logo_file = r"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' width='10%' height='0%'></center>"
# img_f_name = logo_file.replace("\\","/")
# # with io.open('file_name.html','r') as f:
# with io.open(img_f_name,'r') as f:
# # emailtext = f.read()
# emailtext = img_f_name
# # attachment = 'attachment_file_name.png'
# attachment = img_f_name
# attachment = logo_file
# fp = open(attachment, 'rb')
# img = MIMEImage(fp.read())
# fp.close()
# img.add_header('Content-ID', '<{}>'.format(attachment))
# msg.attach(img)
# 파일첨부
files = list()
pdf_file_name = f"{subject}.pdf"
pdf_file = os.path.join(os.getcwd()+"\pdf", pdf_file_name)
files.append(pdf_file)
# if os.path.isfile(pdf_file):
# binary_pdf = open(pdf_file, 'rb')
# payload = MIMEBase('application', 'octate-stream', Name=pdf_file_name)
# payload.set_payload((binary_pdf).read())
# encoders.encode_base64(payload)
# payload.add_header('Content-Decomposition', 'attachment', filename=pdf_file_name)
# msg.attach(payload)
for i in range(self.listwidget22.count()):
files.append(self.listwidget22.item(i).text())
# print(files)
for f in files:
# print(f)
part = MIMEBase('application', "octet-stream")
part.set_payload(open(f,"rb").read())
encoders.encode_base64(part)
fstr_name = os.path.basename(f)
# part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(f))
part.add_header('Content-Disposition',"attachment", filename= fstr_name, charset='utf-8')
# [출처] 파이썬에서 지메일 보내기(w/첨부파일) 한글파일도 가능|작성자 데이터공방
# Header(s=f'2022년08월급여명세서-{name}', charset='utf-8')
msg.attach(part)
# 메일 서버를 이용하여 메일을 발송합니다.
# server.sendmail(msg_from, msg["To"].split(",") + msg["Cc"].split(","), msg.as_string())
self.server.sendmail(msg['From'], msg['To'], msg.as_string())
# self.server.quit()
def fn_test(self):
try:
# 메일 서버를 설정합니다.
# server = smtplib.SMTP('smtp.com', port_number)
# server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# self.server = smtplib.SMTP_SSL('smtp.kakao.com')
# server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# 로그인이 필요하면 로그인 설정
# self.server.login(secret.kakao_id, secret.kakao_pw)
# 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
self.fn_subject_save()
self.fn_html_save()
self.fn_DeleteAllFiles(os.getcwd()+"\pdf")
self.fn_pdf_create("정용만")
# self.fn_pdf_create("정용만")
self.fn_send("정용만", self.df_table_02.loc["정용만"][0])
self.server.quit()
self.fn_print_name("정용만", self.df_table_02.loc["정용만"][0])
except: # 예외가 발생했을 때 실행됨
print('예외가 발생했습니다.')
def fn_run(self):
try:
# 메일 서버를 설정합니다.
# server = smtplib.SMTP('smtp.com', port_number)
# server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# server = smtplib.SMTP_SSL('smtp.kakao.com')
# server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# 로그인이 필요하면 로그인 설정
# server.login(secret.kakao_id, secret.kakao_pw)
# 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
self.fn_subject_save()
self.fn_html_save()
# self.fn_send("정용만", self.df_table_02.loc["정용만"][0])
# self.fn_print_name("정용만", self.df_table_02.loc["정용만"][0])
for idx_name in self.idx_name_list:
# print(idx)
# print(self.df_table_02.loc[idx][0])
# print(idx, table_02.loc[idx][0])
self.fn_DeleteAllFiles(os.getcwd()+"\pdf")
self.fn_pdf_create(idx_name)
self.fn_send(idx_name, self.df_table_02.loc[idx_name][0])
self.fn_print_name(idx_name, self.df_table_02.loc[idx_name][0])
self.server.quit()
except: # 예외가 발생했을 때 실행됨
print('예외가 발생했습니다.')
if __name__ == '__main__':
# don't auto scale when drag app to a different monitor.
# QGuiApplication.setHighDpiScaleFactorRoundingPolicy(Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
excel_file_path = '급여1.xlsx'
worksheet_name = '4대급여'
emailsheet_name = '이메일'
app = QApplication(sys.argv)
app.setStyleSheet('''
QWidget {
font-size: 17px;
}
''')
myApp = MyApp()
myApp.show()
try:
sys.exit(app.exec())
except SystemExit:
print('Closing Window...')
====================
pay13.py--------------------
# from operator import index
# from unittest import result
# from xml.dom.minidom import Document
from PyQt5.QtWidgets import QApplication, QWidget, QTableWidget, QTableWidgetItem, QPushButton, \
QHeaderView, QHBoxLayout, QVBoxLayout, QGridLayout, QAbstractScrollArea, QLabel, QListWidget, \
QFileDialog, QMessageBox, QTextEdit, QAbstractItemView, QLineEdit, QGroupBox, QRadioButton
from PyQt5.QtCore import Qt
# from PyQt5 import QtGui
from PyQt5.QtGui import QTextCursor
import sys
import pandas as pd # pip install pandas
import os
import io
import secret
import xlwings as xw
import smtplib
from email.encoders import encode_base64
from email.header import Header
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText # 메일의 본문 내용을 만드는 모듈 내용을 base64형식으로 변환
from email.utils import formatdate
from email.mime.application import MIMEApplication # 메일의 첨부 파일을 base64 형식으로 변환
from email.mime.image import MIMEImage # 메일의 이미지 파일을 base64 형식으로 변환
# 출처: https://nowonbun.tistory.com/684 [명월 일지:티스토리]
from email import encoders
from email.encoders import encode_base64
class MyApp(QWidget):
def __init__(self):
super().__init__()
self.window_width, self.window_height = 1100, 600
self.resize(self.window_width, self.window_height)
self.setWindowTitle('pay')
# self.server = smtplib.SMTP_SSL('smtp.kakao.com')
# self.server.login(secret.kakao_id, secret.kakao_pw)
# self.msg_from = 'miero@kakao.com'
##### layout_main #####
layout_main = QHBoxLayout()
self.setLayout(layout_main)
##### layout_1 #####
layout_1 = QVBoxLayout()
label11 = QLabel('직원 메일')
# self.button = QPushButton('&Load Data')
# self.button.clicked.connect(lambda _, xl_path=excel_file_path, sheet_name=worksheet_name: self.loadExcelData(xl_path, sheet_name))
# layout_v.addWidget(self.button)
layout_1.addWidget(label11)
self.table = QTableWidget()
self.table.setFixedWidth(350)
layout_1.addWidget(self.table)
layout_main.addLayout(layout_1)
##### layout_2 #####
layout_2 = QGridLayout()
label21 = QLabel('이메일 제목')
layout_2.addWidget(label21, 0, 0)
self.lineedit21 = QLineEdit()
layout_2.addWidget(self.lineedit21, 1, 0, 1, 2)
label22 = QLabel('첨부파일')
layout_2.addWidget(label22, 2, 0)
self.listwidget22 = QListWidget()
# self.listwidget22.setFixedWidth(300)
# self.listwidget22.setSelectionMode(QAbstractItemView.ExtendedSelection)
layout_2.addWidget(self.listwidget22, 3, 0, 5, 1)
self.btn_file_add = QPushButton('파일 추가') # sendlist
# self.btn_file_add.setMinimumHeight(80)
layout_2.addWidget(self.btn_file_add, 3, 1, 1, 1)
self.btn_file_add.clicked.connect(self.fn_fileadd)
self.btn_file_del = QPushButton('파일 삭제')
layout_2.addWidget(self.btn_file_del, 4, 1, 1, 1)
self.btn_file_del.clicked.connect(self.fn_filedel)
# label21 = QLabel('본문 (HTML형식)')
# layout_2.addWidget(label21, 8, 0)
# radio_1 ~ 4 버튼을 그룹으로 설정
groupBoxBottom = QGroupBox("본문 보기형식 선택")
layout_2.addWidget(groupBoxBottom, 8, 0)
hBox = QHBoxLayout()
groupBoxBottom.setLayout(hBox)
self.radioBtn1 = QRadioButton("HTML")
self.radioBtn1.setChecked(True)
self.radioBtn1.clicked.connect(self.fn_radio_select)
hBox.addWidget(self.radioBtn1)
self.radioBtn2 = QRadioButton("미리보기")
self.radioBtn2.clicked.connect(self.fn_radio_select)
hBox.addWidget(self.radioBtn2)
self.textedit23 = QTextEdit()
# self.textedit23.setFixedWidth(400)
# self.textedit23.setAcceptRichText(False)
layout_2.addWidget(self.textedit23, 10, 0, 3, 1)
self.textedit23.show()
self.textedit24 = QTextEdit()
layout_2.addWidget(self.textedit24, 10, 0, 3, 1)
self.textedit24.hide()
self.btn_send = QPushButton("보내기")
self.btn_send.setMaximumHeight(500) # gridlayout button size
layout_2.addWidget(self.btn_send, 10, 1, 3, 1)
self.btn_send.clicked.connect(self.fn_run) #@@@@@@@@@@@@@@@@@@@@@@@@@@
layout_main.addLayout(layout_2)
##### layout_3 #####
layout_3 = QVBoxLayout()
label31 = QLabel('발송 결과')
layout_3.addWidget(label31)
self.listwidget32 = QListWidget()
# self.listwidget32.setMinimumWidth(self.listwidget32.sizeHintForColumn(0))
# self.listwidget32.setWidth(10)
layout_3.addWidget(self.listwidget32)
layout_main.addLayout(layout_3)
# subject0 파일이 존재하면
filename_subject = 'subject0.txt'
if os.path.isfile(filename_subject) == True:
source_text = open(filename_subject,'r', encoding="UTF-8").read()
# self.lineedit21.setText(source_text) # TextEdit에 RichText 형식의 글을 입력합니다.
self.lineedit21.setText(source_text) # TextEdit에 PlainText 형식의 글을 새로 입력합니다.
# html0 파일이 존재하면
filename_html = 'html0.txt'
if os.path.isfile(filename_html) == True:
source_text = open(filename_html,'r', encoding="UTF-8").read()
# self.textedit23.setText(source_text) # TextEdit에 RichText 형식의 글을 입력합니다.
self.textedit23.setPlainText(source_text) # TextEdit에 PlainText 형식의 글을 새로 입력합니다.
# self.textedit24.setHtml(source_text) # TextEdit에 PlainText 형식의 글을 새로 입력합니다.
# table_data = self.loadExcelData(excel_file_path, worksheet_name)
# print(table_data.keys())
df_table = self.loadExcelData(excel_file_path, worksheet_name)
# print(table_df["성명"][0])
self.df_table_02 = df_table.set_index("성명")
self.idx_name_list = self.df_table_02.index.to_list()
# print(index)
# for i in table_02["이메일"]:
def fn_radio_select(self):
# QRadioButton1 클릭 여부 표시
if self.radioBtn1.isChecked():
self.textedit23.show()
self.textedit24.hide()
self.hidden = False
# self.btn_send.setText('보내기')
elif self.radioBtn2.isChecked():
self.fn_html_save()
self.textedit23.hide()
self.textedit24.show()
self.hidden = True
# self.btn_send.setText('미리보기')
def loadExcelData(self, excel_file_dir, worksheet_name):
df_work_sheet = pd.read_excel(excel_file_path, worksheet_name)
df_email_sheet = pd.read_excel(excel_file_path, emailsheet_name)
df_table = df_work_sheet.merge(df_email_sheet, how='left')
df_table_mail = df_table[['성명','이메일']]
res = df_table_mail
# res = df_table_mail.to_dict()
# self.table.setRowCount(df.shape[0])
# self.table.setColumnCount(df.shape[1])
self.table.setRowCount(df_table_mail.shape[0])
self.table.setColumnCount(df_table_mail.shape[1])
# self.table.setHorizontalHeaderLabels(df.columns)
self.table.setHorizontalHeaderLabels(df_table_mail.columns)
header = self.table.horizontalHeader()
# header.setSectionResizeMode(0, QHeaderView.Stretch)
# header.setSectionResizeMode(0, QHeaderView.ResizeToContents)
header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
# returns pandas array object
# for row in df.iterrows():
for row in df_table_mail.iterrows():
values = row[1]
for col_index, value in enumerate(values):
if isinstance(value, (float, int)):
value = '{0:0,.0f}'.format(value)
tableItem = QTableWidgetItem(str(value))
if value == "nan":
tableItem.setBackground(Qt.red)
self.table.setItem(row[0], col_index, tableItem)
self.table.setColumnWidth(2, 310)
return res
def fn_fileadd(self):
# f_name = QFileDialog.getOpenFileName(None, '열기', '', "All Files(*.*)")
f_names = QFileDialog.getOpenFileNames(None, '열기', '', "All Files(*.*)")
# txtPath = f_name[0]
filelist = f_names[0]
if filelist:
for f_name in filelist:
# ext = os.path.splitext(f_name[0])[1]
ext = os.path.splitext(f_name)[1] # 확장자 확인
# if f_names[0]:
icnt = 0
for i in range(self.listwidget22.count()):
# if str(self.listwidget22.item(i).text()) == txtPath.replace("/","\\") or str(self.listwidget22.item(i).text()) == txtPath:
if str(self.listwidget22.item(i).text()) == f_name.replace("/","\\") or str(self.listwidget22.item(i).text()) == f_name:
icnt = 1
break
if icnt != 1:
f_path = f_name
if ext == '.exe':
QMessageBox.about(self,'파일 형식 확인','exe파일은 전송할 수 없습니다.')
pass
else:
cnt = self.listwidget22.count() +1
# self.listwidget22.insertItem(cnt, os.path.basename(txtPath))
# self.listwidget22.insertItem(cnt, txtPath)
# f_path = f_names[0]
# print(f_path)
self.listwidget22.insertItem(cnt, f_path)
# self.listwidget22.insertItem(cnt, f_path.replace("/","\\"))
def fn_filedel(self):
currentrow = self.listwidget22.currentRow()
self.listwidget22.takeItem(currentrow) # currentrowRight번째 항목을 삭제합니다
self.listwidget22.clearSelection()
def fn_subject_save(self):
if len(self.lineedit21.text())>0:
S__File = os.path.join(os.getcwd(),'subject0.txt')
Text = self.lineedit21.text()
if S__File:
# Finally this will Save your file to the path selected.
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
file.write(Text)
else:
QMessageBox.about(self,'제목 입력 확인','제목을 입력하십시요.')
def fn_html_save(self):
if len(self.textedit23.toPlainText())>0:
# print(len(self.textedit.toPlainText()))
# S__File = QFileDialog.getSaveFileName(None,'문자 파일저장','/', "Text Files (*.txt)")
# S__File = QFileDialog.getSaveFileName(None,'문자 파일저장','html0', "Text Files (*.txt)")
S__File = os.path.join(os.getcwd(),'html0.txt')
# This will let you access the test in your QTextEdit
Text = self.textedit23.toPlainText()
self.textedit24.setHtml(Text)
# document = self.textedit23.document()
# cursor = QTextCursor(document)
# p1 = cursor.position() # return int
# cursor.insertImage(r"C:\Users\newstep\Pictures\number1.jpg")
# This will prevent you from an error if pressed cancel on file dialog.
# if S__File[0]:
if S__File:
# Finally this will Save your file to the path selected.
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
file.write(Text)
# txtPath = S__File[0]
# icnt = 0
# for i in range(self.listwidget31.count()):
# if str(self.listwidget31.item(i).text()) == txtPath.replace("/","\\"):
# icnt = 1
# break
# if icnt != 1:
# cnt = self.listwidget31.count() +1
# self.listwidget31.insertItem(cnt, os.path.basename(txtPath))
# self.listwidget31.insertItem(cnt, txtPath)
else:
QMessageBox.about(self,'메시지 입력 확인','메시지를 입력하셔야 합니다.')
def fn_print_name(self, name, email):
# f_name_pre = r"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' width='50%' height='0%'></center>"
# f_name = f_name_pre.replace("\\","/")
# with io.open('file_name.html','r') as f:
# with io.open(f_name,'r') as f:
# # emailtext = f.read()
# emailtext = f_name
# attachment = 'attachment_file_name.png'
# attachment = f_name
# print(name, self.df_table_02.loc[name][0])
# print(name, email)
if len(self.textedit23.toPlainText())>0:
S__File = os.path.join(os.getcwd(),'html0.txt')
# print(len(self.textedit23.toPlainText()))
# print(S__File)
# pretext = f'{name} 님<br/><br/>'
# pretext += f'당신의 이메일은 {email} 입니다.<br/>'
contents = self.textedit23.toPlainText()
# nexttext = f'<br/><img src="cid:{attachment}" >'
# nexttext = f"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' id='millstudio logo' width='10%' height='0%'></center>"
# document = self.textedit23.document()
# cursor = QTextCursor(document)
# p1 = cursor.position() # return int
# cursor.insertImage(f_name)
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
# file.write(pretext)
file.write(contents)
# file.write(nexttext)
# print(contents)
# msgText = MIMEText(contents, 'html')
print(name, email, "전송완료")
self.fn_result_window(name, email)
def fn_DeleteAllFiles(self,filePath):
if os.path.exists(filePath):
for file in os.scandir(filePath):
os.remove(file.path)
return '폴더 내 모든 파일 지우기 완료'
else:
return '폴더가 없습니다.'
def fn_pdf_create(self, idx_name):
#####################################
# xlwings
self.current_pdf_path = os.getcwd()+"\pdf"
fname = "급여1.xlsx"
# for n in self.target_name_list:
name = idx_name
df_data = pd.read_excel(fname, sheet_name='4대급여')
df_data = df_data.fillna(0)
df_employee = pd.read_excel(fname, sheet_name='직원현황')
idx_df_data = df_data.index[df_data['성명']==name].tolist()[0]
# print("4대급여 인덱스 :",idx_df_data)
normal = df_data.loc[idx_df_data,['기본급']][0]
overtime = df_data.loc[idx_df_data,['연장수당']][0]
holiday = df_data.loc[idx_df_data,['휴일수당']][0]
holidayovertime = df_data.loc[idx_df_data,['휴일연장수당']][0]
extra = df_data.loc[idx_df_data,['추가수당']][0]
meals = df_data.loc[idx_df_data,['식대']][0]
bonus = df_data.loc[idx_df_data,['상여금']][0]
normal_calculation = df_data.loc[idx_df_data,['기']][0]
overtime_calculation = df_data.loc[idx_df_data,['연']][0]
holiday_calculation = df_data.loc[idx_df_data,['휴']][0]
holidayovertime_calculation = df_data.loc[idx_df_data,['휴연']][0]
extra_calculation = df_data.loc[idx_df_data,['추']][0]
nationalpension = df_data.loc[idx_df_data,['국민연금']][0]
healthinsurance = df_data.loc[idx_df_data,['건강보험']][0]
longtermcareinsurance = df_data.loc[idx_df_data,['장기요양보험']][0]
employmentinsurance = df_data.loc[idx_df_data,['고용보험']][0]
healthsettlement = df_data.loc[idx_df_data,['정산건강']][0]
longtermcaresettlement = df_data.loc[idx_df_data,['정산장기요양']][0]
advancepayment = df_data.loc[idx_df_data,['선지급']][0]
etc = df_data.loc[idx_df_data,['기타']][0]
incometax = df_data.loc[idx_df_data,['소득세']][0]
localincometax = df_data.loc[idx_df_data,['지방소득세']][0]
idx_df_employee = df_employee.index[df_employee['성명']==name].tolist()[0]
# print("직원현황 인덱스 :",idx_df_employee)
jobposition = df_employee.loc[idx_df_employee,['직위']][0]
department = df_employee.loc[idx_df_employee,['부서']][0]
birthday = df_employee.loc[idx_df_employee,['생일']][0]
# 엑셀 인스턴스 생성
app = xw.App(visible=False)
book = xw.Book(fname)
sh_paystub = book.sheets('급여명세서사대보험')
sh_paystub["B4"].value = name
sh_paystub["D4"].value = jobposition
sh_paystub["B5"].value = department
sh_paystub["D5"].value = birthday
sh_paystub["B8"].value = normal
sh_paystub["B9"].value = overtime
sh_paystub["B10"].value = holiday
sh_paystub["B11"].value = holidayovertime
sh_paystub["B12"].value = extra
sh_paystub["B13"].value = meals
sh_paystub["D8"].value = nationalpension
sh_paystub["D9"].value = healthinsurance
sh_paystub["D10"].value = longtermcareinsurance
sh_paystub["D11"].value = employmentinsurance
sh_paystub["D12"].value = healthsettlement
sh_paystub["D13"].value = longtermcaresettlement
sh_paystub["D14"].value = advancepayment
sh_paystub["D15"].value = etc
sh_paystub["D16"].value = incometax
sh_paystub["D17"].value = localincometax
sh_paystub["B23"].value = normal_calculation
sh_paystub["B24"].value = overtime_calculation
sh_paystub["B25"].value = holiday_calculation
sh_paystub["B26"].value = holidayovertime_calculation
sh_paystub["B27"].value = extra_calculation
sh_paystub["D23"].value = normal
sh_paystub["D24"].value = overtime
sh_paystub["D25"].value = holiday
sh_paystub["D26"].value = holidayovertime
sh_paystub["D27"].value = extra
if len(self.lineedit21.text())==0:
book.save()
app.kill()
return
# print(len(self.lineedit21.text()))
# pdf 로 저장하기
# current_path = os.getcwd() # 현재 작업중인 폴더에 저장하기
# 절대경로로 파일 위치 입력
subject_before = self.lineedit21.text()
# 문자치환 f-string 사용하여 변수 적용하기
subject = subject_before.replace("{성명}",f'{name}')
pdf_file = os.path.join(self.current_pdf_path, f"{subject}.pdf")
# PDF 로 저장할 시트 선택하기(본 예제에서는 첫 번째 시트 선택하기)
# report_sheet = book.sheets[1]
report_sheet = sh_paystub
# PDF 로 저장하기
# report_sheet.ExportAsFixedFormat(0, pdf_path)
report_sheet.api.ExportAsFixedFormat(0, pdf_file)
book.save()
app.kill()
#####################################
def fn_send(self, name, email_i):
# # 메일 서버를 설정합니다.
self.server = smtplib.SMTP_SSL('smtp.kakao.com')
self.server.login(secret.kakao_id, secret.kakao_pw)
self.msg_from = 'miero@kakao.com'
# # server = smtplib.SMTP('smtp.com', port_number)
# # server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# server = smtplib.SMTP_SSL('smtp.kakao.com')
# # server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# # 로그인이 필요하면 로그인 설정
# server.login(secret.kakao_id, secret.kakao_pw)
# # 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
# msg_to = email_i
# cc = 'b@b.com, c@c.com'
# cc = ''
# print(name,email_i)
# 메세지 구성
# msg = MIMEBase('multipart','mixed')
msg = MIMEMultipart()
msg['From'] = self.msg_from
msg['To'] = email_i
msg['Date'] = formatdate(localtime=True)
# msg['Subject'] = f'2022년08월급여명세서-{name}'
subject_before = self.lineedit21.text()
# 문자치환 f-string 사용하여 변수 적용하기
subject = subject_before.replace("{성명}",f'{name}')
msg['Subject'] = Header(s=subject, charset='utf-8')
# msg['Subject'] = Header(s=f'2022년08월급여명세서-{name}', charset='utf-8')
# msg['Cc'] = ""
# 메일 본문 작성
# # html 로 되어있던 파일을 불러 오고 거기에 파일을 붙여서 보냅니다.
# msgText = MIMEText('<h1>%s</h1><hr>, <img src="cid:%s" >' % (emailtext, attachment), 'html')
# contents = '<h1>%s</h1>'
# contents += '<hr>'
# contents += '<img src="cid:%s" >'
# msgText = MIMEText(contents % (emailtext, attachment), 'html')
# contents = f'<h1>{emailtext}</h1>'
# contents += f'<h2>{msg_to} 님 메일이 도착했습니다.</h2>'
# contents += '<hr>'
# contents += f'<img src="cid:{attachment}" >'
# msgText = MIMEText(contents, 'html')
# pretext = f'수신: {name}<br/>'
# pretext += '발신: 주식회사 밀앤아이, 주식회사 헴펠 대표이사<br/>'
# pretext += '<br/>'
# msgpreText = MIMEText(pretext, 'html')
# msg.attach(msgpreText)
# contents = self.textedit23.toPlainText()
contents_before = self.textedit23.toPlainText()
# 문자치환 f-string 사용하여 변수 적용하기
contents = contents_before.replace("{성명}",f'수신: {name}')
# msgText = MIMEText(contents, 'plain')
msgText = MIMEText(contents, 'html')
# msgText = MIMEText(contents, _charset='utf-8')
# 메세지를 메일에 붙여 줍니다.
msg.attach(msgText)
# 메일 제일 밑에 로고그림 붙여 줍니다.
# logo_file = "logo.jpg"
# img_f_name = logo_file.replace("\\","/")
# logo_file = r"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' width='10%' height='0%'></center>"
# img_f_name = logo_file.replace("\\","/")
# # with io.open('file_name.html','r') as f:
# with io.open(img_f_name,'r') as f:
# # emailtext = f.read()
# emailtext = img_f_name
# # attachment = 'attachment_file_name.png'
# attachment = img_f_name
# attachment = logo_file
# fp = open(attachment, 'rb')
# img = MIMEImage(fp.read())
# fp.close()
# img.add_header('Content-ID', '<{}>'.format(attachment))
# msg.attach(img)
# 파일첨부
files = list()
pdf_file_name = f"{subject}.pdf"
pdf_file = os.path.join(os.getcwd()+"\pdf", pdf_file_name)
files.append(pdf_file)
# if os.path.isfile(pdf_file):
# binary_pdf = open(pdf_file, 'rb')
# payload = MIMEBase('application', 'octate-stream', Name=pdf_file_name)
# payload.set_payload((binary_pdf).read())
# encoders.encode_base64(payload)
# payload.add_header('Content-Decomposition', 'attachment', filename=pdf_file_name)
# msg.attach(payload)
for i in range(self.listwidget22.count()):
files.append(self.listwidget22.item(i).text())
# print(files)
for f in files:
# print(f)
part = MIMEBase('application', "octet-stream")
part.set_payload(open(f,"rb").read())
encoders.encode_base64(part)
fstr_name = os.path.basename(f)
# part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(f))
part.add_header('Content-Disposition',"attachment", filename= fstr_name, charset='utf-8')
# [출처] 파이썬에서 지메일 보내기(w/첨부파일) 한글파일도 가능|작성자 데이터공방
# Header(s=f'2022년08월급여명세서-{name}', charset='utf-8')
msg.attach(part)
# 메일 서버를 이용하여 메일을 발송합니다.
# server.sendmail(msg_from, msg["To"].split(",") + msg["Cc"].split(","), msg.as_string())
self.server.sendmail(msg['From'], msg['To'], msg.as_string())
# self.server.quit()
def fn_result_window(self, name, email):
self.listwidget32.clear()
cnt = self.listwidget32.count() +1
# print(cnt, name, email, "전송완료")
# self.listwidget32.insertItem(cnt,name&email&"전송완료")
self.listwidget32.insertItem(cnt, f'{name}-{email}-전송완료')
def fn_test(self):
try:
# 메일 서버를 설정합니다.
# server = smtplib.SMTP('smtp.com', port_number)
# server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# self.server = smtplib.SMTP_SSL('smtp.kakao.com')
# server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# 로그인이 필요하면 로그인 설정
# self.server.login(secret.kakao_id, secret.kakao_pw)
# 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
self.listwidget32.clear()
cnt = 0
self.fn_subject_save()
self.fn_html_save()
self.fn_DeleteAllFiles(os.getcwd()+"\pdf")
self.fn_pdf_create("정용만")
# self.fn_pdf_create("정용만")
self.fn_send("정용만", self.df_table_02.loc["정용만"][0])
self.server.quit()
self.fn_print_name("정용만", self.df_table_02.loc["정용만"][0])
except: # 예외가 발생했을 때 실행됨
print('예외가 발생했습니다.')
self.listwidget32.insertItem(cnt, f'{"정용만"}-{self.df_table_02.loc["정용만"][0]}-실패')
def fn_run(self):
try:
# 메일 서버를 설정합니다.
# server = smtplib.SMTP('smtp.com', port_number)
# server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# server = smtplib.SMTP_SSL('smtp.kakao.com')
# server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# 로그인이 필요하면 로그인 설정
# server.login(secret.kakao_id, secret.kakao_pw)
# 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
self.listwidget32.clear()
cnt = 0
self.fn_subject_save()
self.fn_html_save()
# self.fn_send("정용만", self.df_table_02.loc["정용만"][0])
# self.fn_print_name("정용만", self.df_table_02.loc["정용만"][0])
for idx_name in self.idx_name_list:
# print(idx)
# print(self.df_table_02.loc[idx][0])
# print(idx, table_02.loc[idx][0])
self.fn_DeleteAllFiles(os.getcwd()+"\pdf")
self.fn_pdf_create(idx_name)
self.fn_send(idx_name, self.df_table_02.loc[idx_name][0])
self.listwidget32.insertItem(cnt, f'{idx_name}-{self.df_table_02.loc[idx_name][0]}-전송완료')
self.fn_print_name(idx_name, self.df_table_02.loc[idx_name][0])
self.server.quit()
except: # 예외가 발생했을 때 실행됨
print('예외가 발생했습니다.')
self.listwidget32.insertItem(cnt, f'{idx_name}-{self.df_table_02.loc[idx_name][0]}-실패')
if __name__ == '__main__':
# don't auto scale when drag app to a different monitor.
# QGuiApplication.setHighDpiScaleFactorRoundingPolicy(Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
excel_file_path = '급여1.xlsx'
worksheet_name = '4대급여'
emailsheet_name = '이메일'
app = QApplication(sys.argv)
app.setStyleSheet('''
QWidget {
font-size: 17px;
}
''')
myApp = MyApp()
myApp.show()
try:
sys.exit(app.exec())
except SystemExit:
print('Closing Window...')
====================
pay14.py--------------------
# from operator import index
# from unittest import result
# from xml.dom.minidom import Document
from PyQt5.QtWidgets import QApplication, QWidget, QTableWidget, QTableWidgetItem, QPushButton, \
QHeaderView, QHBoxLayout, QVBoxLayout, QGridLayout, QAbstractScrollArea, QLabel, QListWidget, \
QFileDialog, QMessageBox, QTextEdit, QAbstractItemView, QLineEdit, QGroupBox, QRadioButton
from PyQt5.QtCore import Qt
# from PyQt5 import QtGui
from PyQt5.QtGui import QTextCursor
import sys
import pandas as pd # pip install pandas
import os
import io
import secret
import xlwings as xw
import smtplib
from email.encoders import encode_base64
from email.header import Header
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText # 메일의 본문 내용을 만드는 모듈 내용을 base64형식으로 변환
from email.utils import formatdate
from email.mime.application import MIMEApplication # 메일의 첨부 파일을 base64 형식으로 변환
from email.mime.image import MIMEImage # 메일의 이미지 파일을 base64 형식으로 변환
# 출처: https://nowonbun.tistory.com/684 [명월 일지:티스토리]
from email import encoders
from email.encoders import encode_base64
class MyApp(QWidget):
def __init__(self):
super().__init__()
self.window_width, self.window_height = 1150, 600
self.resize(self.window_width, self.window_height)
self.setWindowTitle('pay')
# self.server = smtplib.SMTP_SSL('smtp.kakao.com')
# self.server.login(secret.kakao_id, secret.kakao_pw)
# self.msg_from = 'miero@kakao.com'
##### layout_main #####
layout_main = QHBoxLayout()
self.setLayout(layout_main)
##### layout_1 #####
layout_1 = QVBoxLayout()
label11 = QLabel('직원 메일')
# self.button = QPushButton('&Load Data')
# self.button.clicked.connect(lambda _, xl_path=excel_file_path, sheet_name=worksheet_name: self.loadExcelData(xl_path, sheet_name))
# layout_v.addWidget(self.button)
layout_1.addWidget(label11)
self.table = QTableWidget()
self.table.setFixedWidth(350)
layout_1.addWidget(self.table)
layout_main.addLayout(layout_1)
##### layout_2 #####
layout_2 = QGridLayout()
label21 = QLabel('이메일 제목')
layout_2.addWidget(label21, 0, 0)
self.lineedit21 = QLineEdit()
layout_2.addWidget(self.lineedit21, 1, 0, 1, 2)
label22 = QLabel('첨부파일')
layout_2.addWidget(label22, 2, 0)
self.listwidget22 = QListWidget()
# self.listwidget22.setFixedWidth(300)
self.listwidget22.setMinimumWidth(400)
# self.listwidget22.setSelectionMode(QAbstractItemView.ExtendedSelection)
layout_2.addWidget(self.listwidget22, 3, 0, 5, 1)
self.btn_file_add = QPushButton('파일 추가') # sendlist
# self.btn_file_add.setMinimumHeight(80)
layout_2.addWidget(self.btn_file_add, 3, 1, 1, 1)
self.btn_file_add.clicked.connect(self.fn_fileadd)
self.btn_file_del = QPushButton('파일 삭제')
layout_2.addWidget(self.btn_file_del, 4, 1, 1, 1)
self.btn_file_del.clicked.connect(self.fn_filedel)
# label21 = QLabel('본문 (HTML형식)')
# layout_2.addWidget(label21, 8, 0)
# radio_1 ~ 4 버튼을 그룹으로 설정
groupBoxBottom = QGroupBox("본문 보기형식 선택")
layout_2.addWidget(groupBoxBottom, 8, 0)
hBox = QHBoxLayout()
groupBoxBottom.setLayout(hBox)
self.radioBtn1 = QRadioButton("HTML")
self.radioBtn1.setChecked(True)
self.radioBtn1.clicked.connect(self.fn_radio_select)
hBox.addWidget(self.radioBtn1)
self.radioBtn2 = QRadioButton("미리보기")
self.radioBtn2.clicked.connect(self.fn_radio_select)
hBox.addWidget(self.radioBtn2)
self.textedit23 = QTextEdit()
# self.textedit23.setFixedWidth(400)
# self.textedit23.setAcceptRichText(False)
layout_2.addWidget(self.textedit23, 10, 0, 3, 1)
self.textedit23.show()
self.textedit24 = QTextEdit()
layout_2.addWidget(self.textedit24, 10, 0, 3, 1)
self.textedit24.hide()
self.btn_send = QPushButton("보내기")
self.btn_send.setMaximumHeight(500) # gridlayout button size
layout_2.addWidget(self.btn_send, 10, 1, 3, 1)
self.btn_send.clicked.connect(self.fn_run) #@@@@@@@@@@@@@@@@@@@@@@@@@@
layout_main.addLayout(layout_2)
##### layout_3 #####
layout_3 = QVBoxLayout()
label31 = QLabel('발송 결과')
layout_3.addWidget(label31)
self.listwidget32 = QListWidget()
# self.listwidget32.setMinimumWidth(self.listwidget32.sizeHintForColumn(0))
# self.listwidget32.setWidth(10)
layout_3.addWidget(self.listwidget32)
layout_main.addLayout(layout_3)
# subject0 파일이 존재하면
filename_subject = 'subject0.txt'
if os.path.isfile(filename_subject) == True:
source_text = open(filename_subject,'r', encoding="UTF-8").read()
# self.lineedit21.setText(source_text) # TextEdit에 RichText 형식의 글을 입력합니다.
self.lineedit21.setText(source_text) # TextEdit에 PlainText 형식의 글을 새로 입력합니다.
# html0 파일이 존재하면
filename_html = 'html0.txt'
if os.path.isfile(filename_html) == True:
source_text = open(filename_html,'r', encoding="UTF-8").read()
# self.textedit23.setText(source_text) # TextEdit에 RichText 형식의 글을 입력합니다.
self.textedit23.setPlainText(source_text) # TextEdit에 PlainText 형식의 글을 새로 입력합니다.
# self.textedit24.setHtml(source_text) # TextEdit에 PlainText 형식의 글을 새로 입력합니다.
# table_data = self.loadExcelData(excel_file_path, worksheet_name)
# print(table_data.keys())
df_table = self.loadExcelData(excel_file_path, worksheet_name)
# print(table_df["성명"][0])
self.df_table_02 = df_table.set_index("성명")
self.idx_name_list = self.df_table_02.index.to_list()
# print(index)
# for i in table_02["이메일"]:
def fn_radio_select(self):
# QRadioButton1 클릭 여부 표시
if self.radioBtn1.isChecked():
self.textedit23.show()
self.textedit24.hide()
self.hidden = False
# self.btn_send.setText('보내기')
elif self.radioBtn2.isChecked():
self.fn_html_save()
self.textedit23.hide()
self.textedit24.show()
self.hidden = True
# self.btn_send.setText('미리보기')
def loadExcelData(self, excel_file_dir, worksheet_name):
df_work_sheet = pd.read_excel(excel_file_path, worksheet_name)
df_email_sheet = pd.read_excel(excel_file_path, emailsheet_name)
df_table = df_work_sheet.merge(df_email_sheet, how='left')
df_table_mail = df_table[['성명','이메일']]
res = df_table_mail
# res = df_table_mail.to_dict()
# self.table.setRowCount(df.shape[0])
# self.table.setColumnCount(df.shape[1])
self.table.setRowCount(df_table_mail.shape[0])
self.table.setColumnCount(df_table_mail.shape[1])
# self.table.setHorizontalHeaderLabels(df.columns)
self.table.setHorizontalHeaderLabels(df_table_mail.columns)
header = self.table.horizontalHeader()
# header.setSectionResizeMode(0, QHeaderView.Stretch)
# header.setSectionResizeMode(0, QHeaderView.ResizeToContents)
header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
# returns pandas array object
# for row in df.iterrows():
for row in df_table_mail.iterrows():
values = row[1]
for col_index, value in enumerate(values):
if isinstance(value, (float, int)):
value = '{0:0,.0f}'.format(value)
tableItem = QTableWidgetItem(str(value))
if value == "nan":
tableItem.setBackground(Qt.red)
self.table.setItem(row[0], col_index, tableItem)
self.table.setColumnWidth(2, 310)
return res
def fn_fileadd(self):
# f_name = QFileDialog.getOpenFileName(None, '열기', '', "All Files(*.*)")
f_names = QFileDialog.getOpenFileNames(None, '열기', '', "All Files(*.*)")
# txtPath = f_name[0]
filelist = f_names[0]
if filelist:
for f_name in filelist:
# ext = os.path.splitext(f_name[0])[1]
ext = os.path.splitext(f_name)[1] # 확장자 확인
# if f_names[0]:
icnt = 0
for i in range(self.listwidget22.count()):
# if str(self.listwidget22.item(i).text()) == txtPath.replace("/","\\") or str(self.listwidget22.item(i).text()) == txtPath:
if str(self.listwidget22.item(i).text()) == f_name.replace("/","\\") or str(self.listwidget22.item(i).text()) == f_name:
icnt = 1
break
if icnt != 1:
f_path = f_name
if ext == '.exe':
QMessageBox.about(self,'파일 형식 확인','exe파일은 전송할 수 없습니다.')
pass
else:
cnt = self.listwidget22.count() +1
# self.listwidget22.insertItem(cnt, os.path.basename(txtPath))
# self.listwidget22.insertItem(cnt, txtPath)
# f_path = f_names[0]
# print(f_path)
self.listwidget22.insertItem(cnt, f_path)
# self.listwidget22.insertItem(cnt, f_path.replace("/","\\"))
def fn_filedel(self):
currentrow = self.listwidget22.currentRow()
self.listwidget22.takeItem(currentrow) # currentrowRight번째 항목을 삭제합니다
self.listwidget22.clearSelection()
def fn_subject_save(self):
if len(self.lineedit21.text())>0:
S__File = os.path.join(os.getcwd(),'subject0.txt')
Text = self.lineedit21.text()
if S__File:
# Finally this will Save your file to the path selected.
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
file.write(Text)
def fn_html_save(self):
if len(self.textedit23.toPlainText())>0:
# print(len(self.textedit.toPlainText()))
# S__File = QFileDialog.getSaveFileName(None,'문자 파일저장','/', "Text Files (*.txt)")
# S__File = QFileDialog.getSaveFileName(None,'문자 파일저장','html0', "Text Files (*.txt)")
S__File = os.path.join(os.getcwd(),'html0.txt')
# This will let you access the test in your QTextEdit
Text = self.textedit23.toPlainText()
self.textedit24.setHtml(Text)
# document = self.textedit23.document()
# cursor = QTextCursor(document)
# p1 = cursor.position() # return int
# cursor.insertImage(r"C:\Users\newstep\Pictures\number1.jpg")
# This will prevent you from an error if pressed cancel on file dialog.
# if S__File[0]:
if S__File:
# Finally this will Save your file to the path selected.
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
file.write(Text)
# txtPath = S__File[0]
# icnt = 0
# for i in range(self.listwidget31.count()):
# if str(self.listwidget31.item(i).text()) == txtPath.replace("/","\\"):
# icnt = 1
# break
# if icnt != 1:
# cnt = self.listwidget31.count() +1
# self.listwidget31.insertItem(cnt, os.path.basename(txtPath))
# self.listwidget31.insertItem(cnt, txtPath)
else:
QMessageBox.about(self,'메시지 입력 확인','메시지를 입력하셔야 합니다.')
def fn_print_name(self, name, email):
# f_name_pre = r"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' width='50%' height='0%'></center>"
# f_name = f_name_pre.replace("\\","/")
# with io.open('file_name.html','r') as f:
# with io.open(f_name,'r') as f:
# # emailtext = f.read()
# emailtext = f_name
# attachment = 'attachment_file_name.png'
# attachment = f_name
# print(name, self.df_table_02.loc[name][0])
# print(name, email)
if len(self.textedit23.toPlainText())>0:
S__File = os.path.join(os.getcwd(),'html0.txt')
# print(len(self.textedit23.toPlainText()))
# print(S__File)
# pretext = f'{name} 님<br/><br/>'
# pretext += f'당신의 이메일은 {email} 입니다.<br/>'
contents = self.textedit23.toPlainText()
# nexttext = f'<br/><img src="cid:{attachment}" >'
# nexttext = f"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' id='millstudio logo' width='10%' height='0%'></center>"
# document = self.textedit23.document()
# cursor = QTextCursor(document)
# p1 = cursor.position() # return int
# cursor.insertImage(f_name)
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
# file.write(pretext)
file.write(contents)
# file.write(nexttext)
# print(contents)
# msgText = MIMEText(contents, 'html')
print(name, email, "전송완료")
# self.fn_result_window(name, email)
def fn_DeleteAllFiles(self,filePath):
if os.path.exists(filePath):
for file in os.scandir(filePath):
os.remove(file.path)
return '폴더 내 모든 파일 지우기 완료'
else:
return '폴더가 없습니다.'
def fn_pdf_create(self, idx_name):
#####################################
# xlwings
self.current_pdf_path = os.getcwd()+"\pdf"
fname = "급여1.xlsx"
# for n in self.target_name_list:
name = idx_name
df_data = pd.read_excel(fname, sheet_name='4대급여')
df_data = df_data.fillna(0)
df_employee = pd.read_excel(fname, sheet_name='직원현황')
idx_df_data = df_data.index[df_data['성명']==name].tolist()[0]
# print("4대급여 인덱스 :",idx_df_data)
normal = df_data.loc[idx_df_data,['기본급']][0]
overtime = df_data.loc[idx_df_data,['연장수당']][0]
holiday = df_data.loc[idx_df_data,['휴일수당']][0]
holidayovertime = df_data.loc[idx_df_data,['휴일연장수당']][0]
extra = df_data.loc[idx_df_data,['추가수당']][0]
meals = df_data.loc[idx_df_data,['식대']][0]
bonus = df_data.loc[idx_df_data,['상여금']][0]
normal_calculation = df_data.loc[idx_df_data,['기']][0]
overtime_calculation = df_data.loc[idx_df_data,['연']][0]
holiday_calculation = df_data.loc[idx_df_data,['휴']][0]
holidayovertime_calculation = df_data.loc[idx_df_data,['휴연']][0]
extra_calculation = df_data.loc[idx_df_data,['추']][0]
nationalpension = df_data.loc[idx_df_data,['국민연금']][0]
healthinsurance = df_data.loc[idx_df_data,['건강보험']][0]
longtermcareinsurance = df_data.loc[idx_df_data,['장기요양보험']][0]
employmentinsurance = df_data.loc[idx_df_data,['고용보험']][0]
healthsettlement = df_data.loc[idx_df_data,['정산건강']][0]
longtermcaresettlement = df_data.loc[idx_df_data,['정산장기요양']][0]
advancepayment = df_data.loc[idx_df_data,['선지급']][0]
etc = df_data.loc[idx_df_data,['기타']][0]
incometax = df_data.loc[idx_df_data,['소득세']][0]
localincometax = df_data.loc[idx_df_data,['지방소득세']][0]
idx_df_employee = df_employee.index[df_employee['성명']==name].tolist()[0]
# print("직원현황 인덱스 :",idx_df_employee)
jobposition = df_employee.loc[idx_df_employee,['직위']][0]
department = df_employee.loc[idx_df_employee,['부서']][0]
birthday = df_employee.loc[idx_df_employee,['생일']][0]
# 엑셀 인스턴스 생성
app = xw.App(visible=False)
book = xw.Book(fname)
sh_paystub = book.sheets('급여명세서사대보험')
sh_paystub["B4"].value = name
sh_paystub["D4"].value = jobposition
sh_paystub["B5"].value = department
sh_paystub["D5"].value = birthday
sh_paystub["B8"].value = normal
sh_paystub["B9"].value = overtime
sh_paystub["B10"].value = holiday
sh_paystub["B11"].value = holidayovertime
sh_paystub["B12"].value = extra
sh_paystub["B13"].value = meals
sh_paystub["D8"].value = nationalpension
sh_paystub["D9"].value = healthinsurance
sh_paystub["D10"].value = longtermcareinsurance
sh_paystub["D11"].value = employmentinsurance
sh_paystub["D12"].value = healthsettlement
sh_paystub["D13"].value = longtermcaresettlement
sh_paystub["D14"].value = advancepayment
sh_paystub["D15"].value = etc
sh_paystub["D16"].value = incometax
sh_paystub["D17"].value = localincometax
sh_paystub["B23"].value = normal_calculation
sh_paystub["B24"].value = overtime_calculation
sh_paystub["B25"].value = holiday_calculation
sh_paystub["B26"].value = holidayovertime_calculation
sh_paystub["B27"].value = extra_calculation
sh_paystub["D23"].value = normal
sh_paystub["D24"].value = overtime
sh_paystub["D25"].value = holiday
sh_paystub["D26"].value = holidayovertime
sh_paystub["D27"].value = extra
if len(self.lineedit21.text())==0:
book.save()
app.kill()
return
# print(len(self.lineedit21.text()))
# pdf 로 저장하기
# current_path = os.getcwd() # 현재 작업중인 폴더에 저장하기
# 절대경로로 파일 위치 입력
subject_before = self.lineedit21.text()
# 문자치환 f-string 사용하여 변수 적용하기
subject = subject_before.replace("{성명}",f'{name}')
pdf_file = os.path.join(self.current_pdf_path, f"{subject}.pdf")
# PDF 로 저장할 시트 선택하기(본 예제에서는 첫 번째 시트 선택하기)
# report_sheet = book.sheets[1]
report_sheet = sh_paystub
# PDF 로 저장하기
# report_sheet.ExportAsFixedFormat(0, pdf_path)
report_sheet.api.ExportAsFixedFormat(0, pdf_file)
book.save()
app.kill()
#####################################
def fn_send(self, name, email_i):
# # 메일 서버를 설정합니다.
self.server = smtplib.SMTP_SSL('smtp.kakao.com')
self.server.login(secret.kakao_id, secret.kakao_pw)
self.msg_from = 'miero@kakao.com'
# # server = smtplib.SMTP('smtp.com', port_number)
# # server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# server = smtplib.SMTP_SSL('smtp.kakao.com')
# # server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# # 로그인이 필요하면 로그인 설정
# server.login(secret.kakao_id, secret.kakao_pw)
# # 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
# msg_to = email_i
# cc = 'b@b.com, c@c.com'
# cc = ''
# print(name,email_i)
# 메세지 구성
# msg = MIMEBase('multipart','mixed')
msg = MIMEMultipart()
msg['From'] = self.msg_from
msg['To'] = email_i
msg['Date'] = formatdate(localtime=True)
# msg['Subject'] = f'2022년08월급여명세서-{name}'
subject_before = self.lineedit21.text()
# 문자치환 f-string 사용하여 변수 적용하기
subject = subject_before.replace("{성명}",f'{name}')
msg['Subject'] = Header(s=subject, charset='utf-8')
# msg['Subject'] = Header(s=f'2022년08월급여명세서-{name}', charset='utf-8')
# msg['Cc'] = ""
# 메일 본문 작성
# # html 로 되어있던 파일을 불러 오고 거기에 파일을 붙여서 보냅니다.
# msgText = MIMEText('<h1>%s</h1><hr>, <img src="cid:%s" >' % (emailtext, attachment), 'html')
# contents = '<h1>%s</h1>'
# contents += '<hr>'
# contents += '<img src="cid:%s" >'
# msgText = MIMEText(contents % (emailtext, attachment), 'html')
# contents = f'<h1>{emailtext}</h1>'
# contents += f'<h2>{msg_to} 님 메일이 도착했습니다.</h2>'
# contents += '<hr>'
# contents += f'<img src="cid:{attachment}" >'
# msgText = MIMEText(contents, 'html')
# pretext = f'수신: {name}<br/>'
# pretext += '발신: 주식회사 밀앤아이, 주식회사 헴펠 대표이사<br/>'
# pretext += '<br/>'
# msgpreText = MIMEText(pretext, 'html')
# msg.attach(msgpreText)
# contents = self.textedit23.toPlainText()
contents_before = self.textedit23.toPlainText()
# 문자치환 f-string 사용하여 변수 적용하기
contents = contents_before.replace("{성명}",f'수신: {name}')
# msgText = MIMEText(contents, 'plain')
msgText = MIMEText(contents, 'html')
# msgText = MIMEText(contents, _charset='utf-8')
# 메세지를 메일에 붙여 줍니다.
msg.attach(msgText)
# 메일 제일 밑에 로고그림 붙여 줍니다.
# logo_file = "logo.jpg"
# img_f_name = logo_file.replace("\\","/")
# logo_file = r"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' width='10%' height='0%'></center>"
# img_f_name = logo_file.replace("\\","/")
# # with io.open('file_name.html','r') as f:
# with io.open(img_f_name,'r') as f:
# # emailtext = f.read()
# emailtext = img_f_name
# # attachment = 'attachment_file_name.png'
# attachment = img_f_name
# attachment = logo_file
# fp = open(attachment, 'rb')
# img = MIMEImage(fp.read())
# fp.close()
# img.add_header('Content-ID', '<{}>'.format(attachment))
# msg.attach(img)
# 파일첨부
files = list()
pdf_file_name = f"{subject}.pdf"
pdf_file = os.path.join(os.getcwd()+"\pdf", pdf_file_name)
files.append(pdf_file)
# if os.path.isfile(pdf_file):
# binary_pdf = open(pdf_file, 'rb')
# payload = MIMEBase('application', 'octate-stream', Name=pdf_file_name)
# payload.set_payload((binary_pdf).read())
# encoders.encode_base64(payload)
# payload.add_header('Content-Decomposition', 'attachment', filename=pdf_file_name)
# msg.attach(payload)
for i in range(self.listwidget22.count()):
files.append(self.listwidget22.item(i).text())
# print(files)
for f in files:
# print(f)
part = MIMEBase('application', "octet-stream")
part.set_payload(open(f,"rb").read())
encoders.encode_base64(part)
fstr_name = os.path.basename(f)
# part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(f))
part.add_header('Content-Disposition',"attachment", filename= fstr_name, charset='utf-8')
# [출처] 파이썬에서 지메일 보내기(w/첨부파일) 한글파일도 가능|작성자 데이터공방
# Header(s=f'2022년08월급여명세서-{name}', charset='utf-8')
msg.attach(part)
# 메일 서버를 이용하여 메일을 발송합니다.
# server.sendmail(msg_from, msg["To"].split(",") + msg["Cc"].split(","), msg.as_string())
self.server.sendmail(msg['From'], msg['To'], msg.as_string())
# self.server.quit()
def fn_result_window(self, name, email):
self.listwidget32.clear()
cnt = self.listwidget32.count() +1
# print(cnt, name, email, "전송완료")
# self.listwidget32.insertItem(cnt,name&email&"전송완료")
self.listwidget32.insertItem(cnt, f'{name}-{email}-전송완료')
def fn_test(self):
# try:
# 메일 서버를 설정합니다.
# server = smtplib.SMTP('smtp.com', port_number)
# server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# self.server = smtplib.SMTP_SSL('smtp.kakao.com')
# server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# 로그인이 필요하면 로그인 설정
# self.server.login(secret.kakao_id, secret.kakao_pw)
# 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
self.listwidget32.clear()
cnt = 0
if len(self.lineedit21.text()) == 0:
QMessageBox.about(self,'제목 입력 확인','제목을 입력하십시요.')
return
self.fn_subject_save()
self.fn_html_save()
self.fn_DeleteAllFiles(os.getcwd()+"\pdf")
self.fn_pdf_create("밀1")
# self.fn_pdf_create("밀1")
self.fn_send("밀1", self.df_table_02.loc["밀1"][0])
self.server.quit()
self.fn_print_name("밀1", self.df_table_02.loc["밀1"][0])
# except: # 예외가 발생했을 때 실행됨
# print('예외가 발생했습니다.')
# self.listwidget32.insertItem(cnt, f'{"밀1"}-{self.df_table_02.loc["밀1"][0]}-실패')
def fn_run(self):
# 메일 서버를 설정합니다.
# server = smtplib.SMTP('smtp.com', port_number)
# server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# server = smtplib.SMTP_SSL('smtp.kakao.com')
# server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# 로그인이 필요하면 로그인 설정
# server.login(secret.kakao_id, secret.kakao_pw)
# 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
self.listwidget32.clear()
cnt = 0
if len(self.lineedit21.text()) == 0:
QMessageBox.about(self,'제목 입력 확인','제목을 입력하십시요.')
return
self.fn_subject_save()
self.fn_html_save()
# self.fn_send("밀1", self.df_table_02.loc["밀1"][0])
# self.fn_print_name("밀1", self.df_table_02.loc["밀1"][0])
for idx_name in self.idx_name_list:
# print(idx)
# print(self.df_table_02.loc[idx][0])
# print(idx, table_02.loc[idx][0])
self.fn_DeleteAllFiles(os.getcwd()+"\pdf")
self.fn_pdf_create(idx_name)
try:
if self.df_table_02.loc[idx_name][0] != "nan":
self.fn_send(idx_name, self.df_table_02.loc[idx_name][0])
cnt += 1
self.listwidget32.insertItem(cnt, f'{idx_name}-{self.df_table_02.loc[idx_name][0]}-전송완료')
except:
cnt += 1
self.listwidget32.insertItem(cnt, f'{idx_name}-{self.df_table_02.loc[idx_name][0]}-실패')
self.listwidget32.item(cnt-1).setBackground(Qt.red)
# if self.df_table_02.loc[idx_name][0] == "nan":
# print(self.listwidget32.)
# self.listwidget32.item(cnt).setBackground(Qt.red)
# print("예외가 발생했습니다.-fn_run",cnt,self.df_table_02.loc[idx_name][0])
# self.fn_print_name(idx_name, self.df_table_02.loc[idx_name][0])
self.server.quit()
# print('예외가 발생했습니다.')
# self.listwidget32.insertItem(cnt, f'{idx_name}-{self.df_table_02.loc[idx_name][0]}-실패')
if __name__ == '__main__':
# don't auto scale when drag app to a different monitor.
# QGuiApplication.setHighDpiScaleFactorRoundingPolicy(Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
excel_file_path = '급여1.xlsx'
worksheet_name = '4대급여'
emailsheet_name = '이메일'
app = QApplication(sys.argv)
app.setStyleSheet('''
QWidget {
font-size: 17px;
}
''')
myApp = MyApp()
myApp.show()
try:
sys.exit(app.exec())
except SystemExit:
print('Closing Window...')
====================
pay15.py--------------------
# from operator import index
# from unittest import result
# from xml.dom.minidom import Document
from PyQt5.QtWidgets import QApplication, QWidget, QTableWidget, QTableWidgetItem, QPushButton, \
QHeaderView, QHBoxLayout, QVBoxLayout, QGridLayout, QAbstractScrollArea, QLabel, QListWidget, \
QFileDialog, QMessageBox, QTextEdit, QAbstractItemView, QLineEdit, QGroupBox, QRadioButton
from PyQt5.QtCore import Qt
# from PyQt5 import QtGui
from PyQt5.QtGui import QTextCursor
import sys
import pandas as pd # pip install pandas
import os
import io
import secret
import xlwings as xw
import smtplib
from email.encoders import encode_base64
from email.header import Header
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText # 메일의 본문 내용을 만드는 모듈 내용을 base64형식으로 변환
from email.utils import formatdate
from email.mime.application import MIMEApplication # 메일의 첨부 파일을 base64 형식으로 변환
from email.mime.image import MIMEImage # 메일의 이미지 파일을 base64 형식으로 변환
# 출처: https://nowonbun.tistory.com/684 [명월 일지:티스토리]
from email import encoders
from email.encoders import encode_base64
class MyApp(QWidget):
def __init__(self):
super().__init__()
self.window_width, self.window_height = 1150, 600
self.resize(self.window_width, self.window_height)
self.setWindowTitle('pay')
# self.server = smtplib.SMTP_SSL('smtp.kakao.com')
# self.server.login(secret.kakao_id, secret.kakao_pw)
# self.msg_from = 'miero@kakao.com'
##### layout_main #####
layout_main = QHBoxLayout()
self.setLayout(layout_main)
##### layout_1 #####
layout_1 = QVBoxLayout()
label11 = QLabel('직원 메일')
# self.button = QPushButton('&Load Data')
# self.button.clicked.connect(lambda _, xl_path=excel_file_path, sheet_name=worksheet_name: self.loadExcelData(xl_path, sheet_name))
# layout_v.addWidget(self.button)
layout_1.addWidget(label11)
self.table = QTableWidget()
self.table.setFixedWidth(350)
layout_1.addWidget(self.table)
layout_main.addLayout(layout_1)
##### layout_2 #####
layout_2 = QGridLayout()
label21 = QLabel('이메일 제목')
layout_2.addWidget(label21, 0, 0)
self.lineedit21 = QLineEdit()
layout_2.addWidget(self.lineedit21, 1, 0, 1, 2)
label22 = QLabel('첨부파일')
layout_2.addWidget(label22, 2, 0)
self.listwidget22 = QListWidget()
# self.listwidget22.setFixedWidth(300)
self.listwidget22.setMinimumWidth(400)
# self.listwidget22.setSelectionMode(QAbstractItemView.ExtendedSelection)
layout_2.addWidget(self.listwidget22, 3, 0, 5, 1)
self.btn_file_add = QPushButton('파일 추가') # sendlist
# self.btn_file_add.setMinimumHeight(80)
layout_2.addWidget(self.btn_file_add, 3, 1, 1, 1)
self.btn_file_add.clicked.connect(self.fn_fileadd)
self.btn_file_del = QPushButton('파일 삭제')
layout_2.addWidget(self.btn_file_del, 4, 1, 1, 1)
self.btn_file_del.clicked.connect(self.fn_filedel)
# label21 = QLabel('본문 (HTML형식)')
# layout_2.addWidget(label21, 8, 0)
# radio_1 ~ 4 버튼을 그룹으로 설정
groupBoxBottom1 = QGroupBox("테스트 메일 보내기")
layout_2.addWidget(groupBoxBottom1, 8, 0, 1, 2)
hBox1 = QHBoxLayout()
groupBoxBottom1.setLayout(hBox1)
self.label23 = QLabel("성명")
hBox1.addWidget(self.label23)
self.lineedit23 = QLineEdit("밀1")
hBox1.addWidget(self.lineedit23)
self.pushbutton23 = QPushButton("테스트 보내기")
self.pushbutton23.clicked.connect(self.fn_test)
hBox1.addWidget(self.pushbutton23)
groupBoxBottom2 = QGroupBox("본문 보기형식 선택")
layout_2.addWidget(groupBoxBottom2, 9, 0)
hBox2 = QHBoxLayout()
groupBoxBottom2.setLayout(hBox2)
self.radioBtn1 = QRadioButton("HTML")
self.radioBtn1.setChecked(True)
self.radioBtn1.clicked.connect(self.fn_radio_select)
hBox2.addWidget(self.radioBtn1)
self.radioBtn2 = QRadioButton("미리보기")
self.radioBtn2.clicked.connect(self.fn_radio_select)
hBox2.addWidget(self.radioBtn2)
self.textedit23 = QTextEdit()
# self.textedit23.setFixedWidth(400)
# self.textedit23.setAcceptRichText(False)
layout_2.addWidget(self.textedit23, 11, 0, 3, 1)
self.textedit23.show()
self.textedit24 = QTextEdit()
layout_2.addWidget(self.textedit24, 11, 0, 3, 1)
self.textedit24.hide()
self.btn_send = QPushButton("보내기")
self.btn_send.setMaximumHeight(500) # gridlayout button size
layout_2.addWidget(self.btn_send, 11, 1, 3, 1)
self.btn_send.clicked.connect(self.fn_run) #@@@@@@@@@@@@@@@@@@@@@@@@@@
layout_main.addLayout(layout_2)
##### layout_3 #####
layout_3 = QVBoxLayout()
label31 = QLabel('발송 결과')
layout_3.addWidget(label31)
self.listwidget32 = QListWidget()
# self.listwidget32.setMinimumWidth(self.listwidget32.sizeHintForColumn(0))
# self.listwidget32.setWidth(10)
layout_3.addWidget(self.listwidget32)
layout_main.addLayout(layout_3)
# subject0 파일이 존재하면
filename_subject = 'subject0.txt'
if os.path.isfile(filename_subject) == True:
source_text = open(filename_subject,'r', encoding="UTF-8").read()
# self.lineedit21.setText(source_text) # TextEdit에 RichText 형식의 글을 입력합니다.
self.lineedit21.setText(source_text) # TextEdit에 PlainText 형식의 글을 새로 입력합니다.
# html0 파일이 존재하면
filename_html = 'html0.txt'
if os.path.isfile(filename_html) == True:
source_text = open(filename_html,'r', encoding="UTF-8").read()
# self.textedit23.setText(source_text) # TextEdit에 RichText 형식의 글을 입력합니다.
self.textedit23.setPlainText(source_text) # TextEdit에 PlainText 형식의 글을 새로 입력합니다.
# self.textedit24.setHtml(source_text) # TextEdit에 PlainText 형식의 글을 새로 입력합니다.
# table_data = self.loadExcelData(excel_file_path, worksheet_name)
# print(table_data.keys())
df_table = self.loadExcelData(excel_file_path, worksheet_name)
# print(table_df["성명"][0])
self.df_table_02 = df_table.set_index("성명")
self.idx_name_list = self.df_table_02.index.to_list()
# print(index)
# for i in table_02["이메일"]:
def fn_radio_select(self):
# QRadioButton1 클릭 여부 표시
if self.radioBtn1.isChecked():
self.textedit23.show()
self.textedit24.hide()
self.hidden = False
# self.btn_send.setText('보내기')
elif self.radioBtn2.isChecked():
self.fn_html_save()
self.textedit23.hide()
self.textedit24.show()
self.hidden = True
# self.btn_send.setText('미리보기')
def loadExcelData(self, excel_file_dir, worksheet_name):
df_work_sheet = pd.read_excel(excel_file_path, worksheet_name)
df_email_sheet = pd.read_excel(excel_file_path, emailsheet_name)
df_table = df_work_sheet.merge(df_email_sheet, how='left')
df_table_mail = df_table[['성명','이메일']]
res = df_table_mail
# res = df_table_mail.to_dict()
# self.table.setRowCount(df.shape[0])
# self.table.setColumnCount(df.shape[1])
self.table.setRowCount(df_table_mail.shape[0])
self.table.setColumnCount(df_table_mail.shape[1])
# self.table.setHorizontalHeaderLabels(df.columns)
self.table.setHorizontalHeaderLabels(df_table_mail.columns)
header = self.table.horizontalHeader()
# header.setSectionResizeMode(0, QHeaderView.Stretch)
# header.setSectionResizeMode(0, QHeaderView.ResizeToContents)
header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
# returns pandas array object
# for row in df.iterrows():
for row in df_table_mail.iterrows():
values = row[1]
for col_index, value in enumerate(values):
if isinstance(value, (float, int)):
value = '{0:0,.0f}'.format(value)
tableItem = QTableWidgetItem(str(value))
if value == "nan":
tableItem.setBackground(Qt.red)
self.table.setItem(row[0], col_index, tableItem)
self.table.setColumnWidth(2, 310)
return res
def fn_fileadd(self):
# f_name = QFileDialog.getOpenFileName(None, '열기', '', "All Files(*.*)")
f_names = QFileDialog.getOpenFileNames(None, '열기', '', "All Files(*.*)")
# txtPath = f_name[0]
filelist = f_names[0]
if filelist:
for f_name in filelist:
# ext = os.path.splitext(f_name[0])[1]
ext = os.path.splitext(f_name)[1] # 확장자 확인
# if f_names[0]:
icnt = 0
for i in range(self.listwidget22.count()):
# if str(self.listwidget22.item(i).text()) == txtPath.replace("/","\\") or str(self.listwidget22.item(i).text()) == txtPath:
if str(self.listwidget22.item(i).text()) == f_name.replace("/","\\") or str(self.listwidget22.item(i).text()) == f_name:
icnt = 1
break
if icnt != 1:
f_path = f_name
if ext == '.exe':
QMessageBox.about(self,'파일 형식 확인','exe파일은 전송할 수 없습니다.')
pass
else:
cnt = self.listwidget22.count() +1
# self.listwidget22.insertItem(cnt, os.path.basename(txtPath))
# self.listwidget22.insertItem(cnt, txtPath)
# f_path = f_names[0]
# print(f_path)
self.listwidget22.insertItem(cnt, f_path)
# self.listwidget22.insertItem(cnt, f_path.replace("/","\\"))
def fn_filedel(self):
currentrow = self.listwidget22.currentRow()
self.listwidget22.takeItem(currentrow) # currentrowRight번째 항목을 삭제합니다
self.listwidget22.clearSelection()
def fn_subject_save(self):
if len(self.lineedit21.text())>0:
S__File = os.path.join(os.getcwd(),'subject0.txt')
Text = self.lineedit21.text()
if S__File:
# Finally this will Save your file to the path selected.
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
file.write(Text)
def fn_html_save(self):
if len(self.textedit23.toPlainText())>0:
# print(len(self.textedit.toPlainText()))
# S__File = QFileDialog.getSaveFileName(None,'문자 파일저장','/', "Text Files (*.txt)")
# S__File = QFileDialog.getSaveFileName(None,'문자 파일저장','html0', "Text Files (*.txt)")
S__File = os.path.join(os.getcwd(),'html0.txt')
# This will let you access the test in your QTextEdit
Text = self.textedit23.toPlainText()
self.textedit24.setHtml(Text)
# document = self.textedit23.document()
# cursor = QTextCursor(document)
# p1 = cursor.position() # return int
# cursor.insertImage(r"C:\Users\newstep\Pictures\number1.jpg")
# This will prevent you from an error if pressed cancel on file dialog.
# if S__File[0]:
if S__File:
# Finally this will Save your file to the path selected.
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
file.write(Text)
# txtPath = S__File[0]
# icnt = 0
# for i in range(self.listwidget31.count()):
# if str(self.listwidget31.item(i).text()) == txtPath.replace("/","\\"):
# icnt = 1
# break
# if icnt != 1:
# cnt = self.listwidget31.count() +1
# self.listwidget31.insertItem(cnt, os.path.basename(txtPath))
# self.listwidget31.insertItem(cnt, txtPath)
else:
QMessageBox.about(self,'메시지 입력 확인','메시지를 입력하셔야 합니다.')
def fn_print_name(self, name, email):
# f_name_pre = r"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' width='50%' height='0%'></center>"
# f_name = f_name_pre.replace("\\","/")
# with io.open('file_name.html','r') as f:
# with io.open(f_name,'r') as f:
# # emailtext = f.read()
# emailtext = f_name
# attachment = 'attachment_file_name.png'
# attachment = f_name
# print(name, self.df_table_02.loc[name][0])
# print(name, email)
if len(self.textedit23.toPlainText())>0:
S__File = os.path.join(os.getcwd(),'html0.txt')
# print(len(self.textedit23.toPlainText()))
# print(S__File)
# pretext = f'{name} 님<br/><br/>'
# pretext += f'당신의 이메일은 {email} 입니다.<br/>'
contents = self.textedit23.toPlainText()
# nexttext = f'<br/><img src="cid:{attachment}" >'
# nexttext = f"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' id='millstudio logo' width='10%' height='0%'></center>"
# document = self.textedit23.document()
# cursor = QTextCursor(document)
# p1 = cursor.position() # return int
# cursor.insertImage(f_name)
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
# file.write(pretext)
file.write(contents)
# file.write(nexttext)
# print(contents)
# msgText = MIMEText(contents, 'html')
print(name, email, "전송완료")
# self.fn_result_window(name, email)
def fn_DeleteAllFiles(self,filePath):
if os.path.exists(filePath):
for file in os.scandir(filePath):
os.remove(file.path)
return '폴더 내 모든 파일 지우기 완료'
else:
return '폴더가 없습니다.'
def fn_pdf_create(self, idx_name):
#####################################
# xlwings
self.current_pdf_path = os.getcwd()+"\pdf"
fname = "급여1.xlsx"
# for n in self.target_name_list:
name = idx_name
df_data = pd.read_excel(fname, sheet_name='4대급여')
df_data = df_data.fillna(0)
df_employee = pd.read_excel(fname, sheet_name='직원현황')
idx_df_data = df_data.index[df_data['성명']==name].tolist()[0]
# print("4대급여 인덱스 :",idx_df_data)
normal = df_data.loc[idx_df_data,['기본급']][0]
overtime = df_data.loc[idx_df_data,['연장수당']][0]
holiday = df_data.loc[idx_df_data,['휴일수당']][0]
holidayovertime = df_data.loc[idx_df_data,['휴일연장수당']][0]
extra = df_data.loc[idx_df_data,['추가수당']][0]
meals = df_data.loc[idx_df_data,['식대']][0]
bonus = df_data.loc[idx_df_data,['상여금']][0]
normal_calculation = df_data.loc[idx_df_data,['기']][0]
overtime_calculation = df_data.loc[idx_df_data,['연']][0]
holiday_calculation = df_data.loc[idx_df_data,['휴']][0]
holidayovertime_calculation = df_data.loc[idx_df_data,['휴연']][0]
extra_calculation = df_data.loc[idx_df_data,['추']][0]
nationalpension = df_data.loc[idx_df_data,['국민연금']][0]
healthinsurance = df_data.loc[idx_df_data,['건강보험']][0]
longtermcareinsurance = df_data.loc[idx_df_data,['장기요양보험']][0]
employmentinsurance = df_data.loc[idx_df_data,['고용보험']][0]
healthsettlement = df_data.loc[idx_df_data,['정산건강']][0]
longtermcaresettlement = df_data.loc[idx_df_data,['정산장기요양']][0]
advancepayment = df_data.loc[idx_df_data,['선지급']][0]
etc = df_data.loc[idx_df_data,['기타']][0]
incometax = df_data.loc[idx_df_data,['소득세']][0]
localincometax = df_data.loc[idx_df_data,['지방소득세']][0]
idx_df_employee = df_employee.index[df_employee['성명']==name].tolist()[0]
# print("직원현황 인덱스 :",idx_df_employee)
jobposition = df_employee.loc[idx_df_employee,['직위']][0]
department = df_employee.loc[idx_df_employee,['부서']][0]
birthday = df_employee.loc[idx_df_employee,['생일']][0]
# 엑셀 인스턴스 생성
app = xw.App(visible=False)
book = xw.Book(fname)
sh_paystub = book.sheets('급여명세서사대보험')
sh_paystub["B4"].value = name
sh_paystub["D4"].value = jobposition
sh_paystub["B5"].value = department
sh_paystub["D5"].value = birthday
sh_paystub["B8"].value = normal
sh_paystub["B9"].value = overtime
sh_paystub["B10"].value = holiday
sh_paystub["B11"].value = holidayovertime
sh_paystub["B12"].value = extra
sh_paystub["B13"].value = meals
sh_paystub["D8"].value = nationalpension
sh_paystub["D9"].value = healthinsurance
sh_paystub["D10"].value = longtermcareinsurance
sh_paystub["D11"].value = employmentinsurance
sh_paystub["D12"].value = healthsettlement
sh_paystub["D13"].value = longtermcaresettlement
sh_paystub["D14"].value = advancepayment
sh_paystub["D15"].value = etc
sh_paystub["D16"].value = incometax
sh_paystub["D17"].value = localincometax
sh_paystub["B23"].value = normal_calculation
sh_paystub["B24"].value = overtime_calculation
sh_paystub["B25"].value = holiday_calculation
sh_paystub["B26"].value = holidayovertime_calculation
sh_paystub["B27"].value = extra_calculation
sh_paystub["D23"].value = normal
sh_paystub["D24"].value = overtime
sh_paystub["D25"].value = holiday
sh_paystub["D26"].value = holidayovertime
sh_paystub["D27"].value = extra
if len(self.lineedit21.text())==0:
book.save()
app.kill()
return
# print(len(self.lineedit21.text()))
# pdf 로 저장하기
# current_path = os.getcwd() # 현재 작업중인 폴더에 저장하기
# 절대경로로 파일 위치 입력
subject_before = self.lineedit21.text()
# 문자치환 f-string 사용하여 변수 적용하기
subject = subject_before.replace("{성명}",f'{name}')
pdf_file = os.path.join(self.current_pdf_path, f"{subject}.pdf")
# PDF 로 저장할 시트 선택하기(본 예제에서는 첫 번째 시트 선택하기)
# report_sheet = book.sheets[1]
report_sheet = sh_paystub
# PDF 로 저장하기
# report_sheet.ExportAsFixedFormat(0, pdf_path)
report_sheet.api.ExportAsFixedFormat(0, pdf_file)
book.save()
app.kill()
#####################################
def fn_send(self, name, email_i):
# # 메일 서버를 설정합니다.
self.server = smtplib.SMTP_SSL('smtp.kakao.com')
self.server.login(secret.kakao_id, secret.kakao_pw)
self.msg_from = 'miero@kakao.com'
# # server = smtplib.SMTP('smtp.com', port_number)
# # server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# server = smtplib.SMTP_SSL('smtp.kakao.com')
# # server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# # 로그인이 필요하면 로그인 설정
# server.login(secret.kakao_id, secret.kakao_pw)
# # 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
# msg_to = email_i
# cc = 'b@b.com, c@c.com'
# cc = ''
# print(name,email_i)
# 메세지 구성
# msg = MIMEBase('multipart','mixed')
msg = MIMEMultipart()
msg['From'] = self.msg_from
msg['To'] = email_i
msg['Date'] = formatdate(localtime=True)
# msg['Subject'] = f'2022년08월급여명세서-{name}'
subject_before = self.lineedit21.text()
# 문자치환 f-string 사용하여 변수 적용하기
subject = subject_before.replace("{성명}",f'{name}')
msg['Subject'] = Header(s=subject, charset='utf-8')
# msg['Subject'] = Header(s=f'2022년08월급여명세서-{name}', charset='utf-8')
# msg['Cc'] = ""
# 메일 본문 작성
# # html 로 되어있던 파일을 불러 오고 거기에 파일을 붙여서 보냅니다.
# msgText = MIMEText('<h1>%s</h1><hr>, <img src="cid:%s" >' % (emailtext, attachment), 'html')
# contents = '<h1>%s</h1>'
# contents += '<hr>'
# contents += '<img src="cid:%s" >'
# msgText = MIMEText(contents % (emailtext, attachment), 'html')
# contents = f'<h1>{emailtext}</h1>'
# contents += f'<h2>{msg_to} 님 메일이 도착했습니다.</h2>'
# contents += '<hr>'
# contents += f'<img src="cid:{attachment}" >'
# msgText = MIMEText(contents, 'html')
# pretext = f'수신: {name}<br/>'
# pretext += '발신: 주식회사 밀앤아이, 주식회사 헴펠 대표이사<br/>'
# pretext += '<br/>'
# msgpreText = MIMEText(pretext, 'html')
# msg.attach(msgpreText)
# contents = self.textedit23.toPlainText()
contents_before = self.textedit23.toPlainText()
# 문자치환 f-string 사용하여 변수 적용하기
contents = contents_before.replace("{성명}",f'수신: {name}')
# msgText = MIMEText(contents, 'plain')
msgText = MIMEText(contents, 'html')
# msgText = MIMEText(contents, _charset='utf-8')
# 메세지를 메일에 붙여 줍니다.
msg.attach(msgText)
# 메일 제일 밑에 로고그림 붙여 줍니다.
# logo_file = "logo.jpg"
# img_f_name = logo_file.replace("\\","/")
# logo_file = r"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' width='10%' height='0%'></center>"
# img_f_name = logo_file.replace("\\","/")
# # with io.open('file_name.html','r') as f:
# with io.open(img_f_name,'r') as f:
# # emailtext = f.read()
# emailtext = img_f_name
# # attachment = 'attachment_file_name.png'
# attachment = img_f_name
# attachment = logo_file
# fp = open(attachment, 'rb')
# img = MIMEImage(fp.read())
# fp.close()
# img.add_header('Content-ID', '<{}>'.format(attachment))
# msg.attach(img)
# 파일첨부
files = list()
pdf_file_name = f"{subject}.pdf"
pdf_file = os.path.join(os.getcwd()+"\pdf", pdf_file_name)
files.append(pdf_file)
# if os.path.isfile(pdf_file):
# binary_pdf = open(pdf_file, 'rb')
# payload = MIMEBase('application', 'octate-stream', Name=pdf_file_name)
# payload.set_payload((binary_pdf).read())
# encoders.encode_base64(payload)
# payload.add_header('Content-Decomposition', 'attachment', filename=pdf_file_name)
# msg.attach(payload)
for i in range(self.listwidget22.count()):
files.append(self.listwidget22.item(i).text())
# print(files)
for f in files:
# print(f)
part = MIMEBase('application', "octet-stream")
part.set_payload(open(f,"rb").read())
encoders.encode_base64(part)
fstr_name = os.path.basename(f)
# part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(f))
part.add_header('Content-Disposition',"attachment", filename= fstr_name, charset='utf-8')
# [출처] 파이썬에서 지메일 보내기(w/첨부파일) 한글파일도 가능|작성자 데이터공방
# Header(s=f'2022년08월급여명세서-{name}', charset='utf-8')
msg.attach(part)
# 메일 서버를 이용하여 메일을 발송합니다.
# server.sendmail(msg_from, msg["To"].split(",") + msg["Cc"].split(","), msg.as_string())
self.server.sendmail(msg['From'], msg['To'], msg.as_string())
# self.server.quit()
def fn_result_window(self, name, email):
self.listwidget32.clear()
cnt = self.listwidget32.count() +1
# print(cnt, name, email, "전송완료")
# self.listwidget32.insertItem(cnt,name&email&"전송완료")
self.listwidget32.insertItem(cnt, f'{name}-{email}-전송완료')
def fn_test(self):
# try:
# 메일 서버를 설정합니다.
# server = smtplib.SMTP('smtp.com', port_number)
# server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# self.server = smtplib.SMTP_SSL('smtp.kakao.com')
# server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# 로그인이 필요하면 로그인 설정
# self.server.login(secret.kakao_id, secret.kakao_pw)
# 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
self.listwidget32.clear()
cnt = 0
if len(self.lineedit21.text()) == 0:
QMessageBox.about(self,'제목 입력 확인','제목을 입력하십시요.')
return
self.fn_subject_save()
self.fn_html_save()
self.fn_DeleteAllFiles(os.getcwd()+"\pdf")
self.fn_pdf_create(self.lineedit23.text())
try:
if self.df_table_02.loc[self.lineedit23.text()][0] != "nan":
self.fn_send(self.lineedit23.text(), self.df_table_02.loc[self.lineedit23.text()][0])
cnt += 1
self.listwidget32.insertItem(cnt, f'{self.lineedit23.text()}-{self.df_table_02.loc[self.lineedit23.text()][0]}-전송완료')
except:
cnt += 1
self.listwidget32.insertItem(cnt, f'{self.lineedit23.text()}-{self.df_table_02.loc[self.lineedit23.text()][0]}-실패')
self.listwidget32.item(cnt-1).setBackground(Qt.red)
# self.fn_pdf_create("밀1")
# self.fn_send(self.lineedit23.text(), self.df_table_02.loc[self.lineedit23.text()][0])
# cnt += 1
# self.listwidget32.insertItem(cnt, f'{self.lineedit23.text()}-{self.df_table_02.loc[self.lineedit23.text()][0]}-전송완료')
self.server.quit()
# self.fn_print_name(self.lineedit23.text(), self.df_table_02.loc[self.lineedit23.text()][0])
# except: # 예외가 발생했을 때 실행됨
# print('예외가 발생했습니다.')
# self.listwidget32.insertItem(cnt, f'{"밀1"}-{self.df_table_02.loc["밀1"][0]}-실패')
def fn_run(self):
# 메일 서버를 설정합니다.
# server = smtplib.SMTP('smtp.com', port_number)
# server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# server = smtplib.SMTP_SSL('smtp.kakao.com')
# server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# 로그인이 필요하면 로그인 설정
# server.login(secret.kakao_id, secret.kakao_pw)
# 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
self.listwidget32.clear()
cnt = 0
if len(self.lineedit21.text()) == 0:
QMessageBox.about(self,'제목 입력 확인','제목을 입력하십시요.')
return
self.fn_subject_save()
self.fn_html_save()
# self.fn_send("밀1", self.df_table_02.loc["밀1"][0])
# self.fn_print_name("밀1", self.df_table_02.loc["밀1"][0])
for idx_name in self.idx_name_list:
# print(idx)
# print(self.df_table_02.loc[idx][0])
# print(idx, table_02.loc[idx][0])
self.fn_DeleteAllFiles(os.getcwd()+"\pdf")
self.fn_pdf_create(idx_name)
try:
if self.df_table_02.loc[idx_name][0] != "nan":
self.fn_send(idx_name, self.df_table_02.loc[idx_name][0])
cnt += 1
self.listwidget32.insertItem(cnt, f'{idx_name}-{self.df_table_02.loc[idx_name][0]}-전송완료')
except:
cnt += 1
self.listwidget32.insertItem(cnt, f'{idx_name}-{self.df_table_02.loc[idx_name][0]}-실패')
self.listwidget32.item(cnt-1).setBackground(Qt.red)
# if self.df_table_02.loc[idx_name][0] == "nan":
# print(self.listwidget32.)
# self.listwidget32.item(cnt).setBackground(Qt.red)
# print("예외가 발생했습니다.-fn_run",cnt,self.df_table_02.loc[idx_name][0])
# self.fn_print_name(idx_name, self.df_table_02.loc[idx_name][0])
self.server.quit()
# print('예외가 발생했습니다.')
# self.listwidget32.insertItem(cnt, f'{idx_name}-{self.df_table_02.loc[idx_name][0]}-실패')
if __name__ == '__main__':
# don't auto scale when drag app to a different monitor.
# QGuiApplication.setHighDpiScaleFactorRoundingPolicy(Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
excel_file_path = '급여1.xlsx'
worksheet_name = '4대급여'
emailsheet_name = '이메일'
app = QApplication(sys.argv)
app.setStyleSheet('''
QWidget {
font-size: 17px;
}
''')
myApp = MyApp()
myApp.show()
try:
sys.exit(app.exec())
except SystemExit:
print('Closing Window...')
====================
pay16.py--------------------
# from operator import index
# from unittest import result
# from xml.dom.minidom import Document
from PyQt5.QtWidgets import QApplication, QWidget, QTableWidget, QTableWidgetItem, QPushButton, \
QHeaderView, QHBoxLayout, QVBoxLayout, QGridLayout, QAbstractScrollArea, QLabel, QListWidget, \
QFileDialog, QMessageBox, QTextEdit, QAbstractItemView, QLineEdit, QGroupBox, QRadioButton
from PyQt5.QtCore import Qt
# from PyQt5 import QtGui
from PyQt5.QtGui import QTextCursor
import sys
import pandas as pd # pip install pandas
import os
import io
import secret
import xlwings as xw
import smtplib
from email.encoders import encode_base64
from email.header import Header
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText # 메일의 본문 내용을 만드는 모듈 내용을 base64형식으로 변환
from email.utils import formatdate
from email.mime.application import MIMEApplication # 메일의 첨부 파일을 base64 형식으로 변환
from email.mime.image import MIMEImage # 메일의 이미지 파일을 base64 형식으로 변환
# 출처: https://nowonbun.tistory.com/684 [명월 일지:티스토리]
from email import encoders
from email.encoders import encode_base64
class MyApp(QWidget):
def __init__(self):
super().__init__()
self.window_width, self.window_height = 1150, 600
self.resize(self.window_width, self.window_height)
self.setWindowTitle('pay')
# self.server = smtplib.SMTP_SSL('smtp.kakao.com')
# self.server.login(secret.kakao_id, secret.kakao_pw)
# self.msg_from = 'miero@kakao.com'
##### layout_main #####
layout_main = QHBoxLayout()
self.setLayout(layout_main)
##### layout_1 #####
layout_1 = QVBoxLayout()
vBox11 = QVBoxLayout()
groupBoxLogin11 = QGroupBox("로그인 정보")
groupBoxLogin11.setLayout(vBox11)
layout_1.addWidget(groupBoxLogin11)
self.label11 = QLabel("이메일계정")
vBox11.addWidget(self.label11)
self.lineedit11 = QLineEdit("miero@kakao.com")
vBox11.addWidget(self.lineedit11)
self.label12 = QLabel("패스워드")
vBox11.addWidget(self.label12)
self.lineedit12 = QLineEdit()
self.lineedit12.setEchoMode(QLineEdit.Password)
# self.lineedit12.show()
vBox11.addWidget(self.lineedit12)
label13 = QLabel('직원 메일')
# self.button = QPushButton('&Load Data')
# self.button.clicked.connect(lambda _, xl_path=excel_file_path, sheet_name=worksheet_name: self.loadExcelData(xl_path, sheet_name))
# layout_v.addWidget(self.button)
layout_1.addWidget(label13)
self.table = QTableWidget()
self.table.setFixedWidth(350)
layout_1.addWidget(self.table)
layout_main.addLayout(layout_1)
##### layout_2 #####
layout_2 = QGridLayout()
label21 = QLabel('이메일 제목')
layout_2.addWidget(label21, 0, 0)
self.lineedit21 = QLineEdit()
layout_2.addWidget(self.lineedit21, 1, 0, 1, 2)
label22 = QLabel('첨부파일')
layout_2.addWidget(label22, 2, 0)
self.listwidget22 = QListWidget()
# self.listwidget22.setFixedWidth(300)
self.listwidget22.setMinimumWidth(400)
# self.listwidget22.setSelectionMode(QAbstractItemView.ExtendedSelection)
layout_2.addWidget(self.listwidget22, 3, 0, 3, 1)
self.btn_file_add = QPushButton('파일 추가') # sendlist
# self.btn_file_add.setMinimumHeight(80)
layout_2.addWidget(self.btn_file_add, 3, 1, 1, 1)
self.btn_file_add.clicked.connect(self.fn_fileadd)
self.btn_file_del = QPushButton('파일 삭제')
layout_2.addWidget(self.btn_file_del, 4, 1, 1, 1)
self.btn_file_del.clicked.connect(self.fn_filedel)
# label21 = QLabel('본문 (HTML형식)')
# layout_2.addWidget(label21, 8, 0)
# radio_1 ~ 4 버튼을 그룹으로 설정
groupBoxMid = QGroupBox("테스트 메일 보내기")
layout_2.addWidget(groupBoxMid, 6, 0, 1, 2)
hBox1 = QHBoxLayout()
groupBoxMid.setLayout(hBox1)
self.label23 = QLabel("성명")
hBox1.addWidget(self.label23)
self.lineedit23 = QLineEdit("밀1")
hBox1.addWidget(self.lineedit23)
self.pushbutton23 = QPushButton("테스트 보내기")
self.pushbutton23.clicked.connect(self.fn_test)
hBox1.addWidget(self.pushbutton23)
groupBoxBottom = QGroupBox("본문 보기형식 선택")
layout_2.addWidget(groupBoxBottom, 7, 0, 1, 2)
hBox2 = QHBoxLayout()
groupBoxBottom.setLayout(hBox2)
self.radioBtn1 = QRadioButton("HTML")
self.radioBtn1.setChecked(True)
self.radioBtn1.clicked.connect(self.fn_radio_select)
hBox2.addWidget(self.radioBtn1)
self.radioBtn2 = QRadioButton("미리보기")
self.radioBtn2.clicked.connect(self.fn_radio_select)
hBox2.addWidget(self.radioBtn2)
self.textedit23 = QTextEdit()
# self.textedit23.setFixedWidth(400)
# self.textedit23.setAcceptRichText(False)
layout_2.addWidget(self.textedit23, 8, 0, 4, 1)
self.textedit23.show()
self.textedit24 = QTextEdit()
layout_2.addWidget(self.textedit24, 8, 0, 4, 1)
self.textedit24.hide()
self.btn_send = QPushButton("보내기")
self.btn_send.setMaximumHeight(500) # gridlayout button size
layout_2.addWidget(self.btn_send, 8, 1, 4, 1)
self.btn_send.clicked.connect(self.fn_run) #@@@@@@@@@@@@@@@@@@@@@@@@@@
layout_main.addLayout(layout_2)
##### layout_3 #####
layout_3 = QVBoxLayout()
label31 = QLabel('발송 결과')
layout_3.addWidget(label31)
self.listwidget32 = QListWidget()
# self.listwidget32.setMinimumWidth(self.listwidget32.sizeHintForColumn(0))
# self.listwidget32.setWidth(10)
layout_3.addWidget(self.listwidget32)
layout_main.addLayout(layout_3)
# subject0 파일이 존재하면
filename_subject = 'subject0.txt'
if os.path.isfile(filename_subject) == True:
source_text = open(filename_subject,'r', encoding="UTF-8").read()
# self.lineedit21.setText(source_text) # TextEdit에 RichText 형식의 글을 입력합니다.
self.lineedit21.setText(source_text) # TextEdit에 PlainText 형식의 글을 새로 입력합니다.
# html0 파일이 존재하면
filename_html = 'html0.txt'
if os.path.isfile(filename_html) == True:
source_text = open(filename_html,'r', encoding="UTF-8").read()
# self.textedit23.setText(source_text) # TextEdit에 RichText 형식의 글을 입력합니다.
self.textedit23.setPlainText(source_text) # TextEdit에 PlainText 형식의 글을 새로 입력합니다.
# self.textedit24.setHtml(source_text) # TextEdit에 PlainText 형식의 글을 새로 입력합니다.
# table_data = self.loadExcelData(excel_file_path, worksheet_name)
# print(table_data.keys())
df_table = self.loadExcelData(excel_file_path, worksheet_name)
# print(table_df["성명"][0])
self.df_table_02 = df_table.set_index("성명")
self.idx_name_list = self.df_table_02.index.to_list()
# print(index)
# for i in table_02["이메일"]:
def fn_radio_select(self):
# QRadioButton1 클릭 여부 표시
if self.radioBtn1.isChecked():
self.textedit23.show()
self.textedit24.hide()
self.hidden = False
# self.btn_send.setText('보내기')
elif self.radioBtn2.isChecked():
self.fn_html_save()
self.textedit23.hide()
self.textedit24.show()
self.hidden = True
# self.btn_send.setText('미리보기')
def loadExcelData(self, excel_file_dir, worksheet_name):
df_work_sheet = pd.read_excel(excel_file_path, worksheet_name)
df_email_sheet = pd.read_excel(excel_file_path, emailsheet_name)
df_table = df_work_sheet.merge(df_email_sheet, how='left')
df_table_mail = df_table[['성명','이메일']]
res = df_table_mail
# res = df_table_mail.to_dict()
# self.table.setRowCount(df.shape[0])
# self.table.setColumnCount(df.shape[1])
self.table.setRowCount(df_table_mail.shape[0])
self.table.setColumnCount(df_table_mail.shape[1])
# self.table.setHorizontalHeaderLabels(df.columns)
self.table.setHorizontalHeaderLabels(df_table_mail.columns)
header = self.table.horizontalHeader()
# header.setSectionResizeMode(0, QHeaderView.Stretch)
# header.setSectionResizeMode(0, QHeaderView.ResizeToContents)
header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
# returns pandas array object
# for row in df.iterrows():
for row in df_table_mail.iterrows():
values = row[1]
for col_index, value in enumerate(values):
if isinstance(value, (float, int)):
value = '{0:0,.0f}'.format(value)
tableItem = QTableWidgetItem(str(value))
if value == "nan":
tableItem.setBackground(Qt.red)
self.table.setItem(row[0], col_index, tableItem)
self.table.setColumnWidth(2, 310)
return res
def fn_fileadd(self):
# f_name = QFileDialog.getOpenFileName(None, '열기', '', "All Files(*.*)")
f_names = QFileDialog.getOpenFileNames(None, '열기', '', "All Files(*.*)")
# txtPath = f_name[0]
filelist = f_names[0]
if filelist:
for f_name in filelist:
# ext = os.path.splitext(f_name[0])[1]
ext = os.path.splitext(f_name)[1] # 확장자 확인
# if f_names[0]:
icnt = 0
for i in range(self.listwidget22.count()):
# if str(self.listwidget22.item(i).text()) == txtPath.replace("/","\\") or str(self.listwidget22.item(i).text()) == txtPath:
if str(self.listwidget22.item(i).text()) == f_name.replace("/","\\") or str(self.listwidget22.item(i).text()) == f_name:
icnt = 1
break
if icnt != 1:
f_path = f_name
if ext == '.exe':
QMessageBox.about(self,'파일 형식 확인','exe파일은 전송할 수 없습니다.')
pass
else:
cnt = self.listwidget22.count() +1
# self.listwidget22.insertItem(cnt, os.path.basename(txtPath))
# self.listwidget22.insertItem(cnt, txtPath)
# f_path = f_names[0]
# print(f_path)
self.listwidget22.insertItem(cnt, f_path)
# self.listwidget22.insertItem(cnt, f_path.replace("/","\\"))
def fn_filedel(self):
currentrow = self.listwidget22.currentRow()
self.listwidget22.takeItem(currentrow) # currentrowRight번째 항목을 삭제합니다
self.listwidget22.clearSelection()
def fn_subject_save(self):
if len(self.lineedit21.text())>0:
S__File = os.path.join(os.getcwd(),'subject0.txt')
Text = self.lineedit21.text()
if S__File:
# Finally this will Save your file to the path selected.
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
file.write(Text)
def fn_html_save(self):
if len(self.textedit23.toPlainText())>0:
# print(len(self.textedit.toPlainText()))
# S__File = QFileDialog.getSaveFileName(None,'문자 파일저장','/', "Text Files (*.txt)")
# S__File = QFileDialog.getSaveFileName(None,'문자 파일저장','html0', "Text Files (*.txt)")
S__File = os.path.join(os.getcwd(),'html0.txt')
# This will let you access the test in your QTextEdit
Text = self.textedit23.toPlainText()
self.textedit24.setHtml(Text)
# document = self.textedit23.document()
# cursor = QTextCursor(document)
# p1 = cursor.position() # return int
# cursor.insertImage(r"C:\Users\newstep\Pictures\number1.jpg")
# This will prevent you from an error if pressed cancel on file dialog.
# if S__File[0]:
if S__File:
# Finally this will Save your file to the path selected.
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
file.write(Text)
# txtPath = S__File[0]
# icnt = 0
# for i in range(self.listwidget31.count()):
# if str(self.listwidget31.item(i).text()) == txtPath.replace("/","\\"):
# icnt = 1
# break
# if icnt != 1:
# cnt = self.listwidget31.count() +1
# self.listwidget31.insertItem(cnt, os.path.basename(txtPath))
# self.listwidget31.insertItem(cnt, txtPath)
else:
QMessageBox.about(self,'메시지 입력 확인','메시지를 입력하셔야 합니다.')
def fn_print_name(self, name, email):
# f_name_pre = r"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' width='50%' height='0%'></center>"
# f_name = f_name_pre.replace("\\","/")
# with io.open('file_name.html','r') as f:
# with io.open(f_name,'r') as f:
# # emailtext = f.read()
# emailtext = f_name
# attachment = 'attachment_file_name.png'
# attachment = f_name
# print(name, self.df_table_02.loc[name][0])
# print(name, email)
if len(self.textedit23.toPlainText())>0:
S__File = os.path.join(os.getcwd(),'html0.txt')
# print(len(self.textedit23.toPlainText()))
# print(S__File)
# pretext = f'{name} 님<br/><br/>'
# pretext += f'당신의 이메일은 {email} 입니다.<br/>'
contents = self.textedit23.toPlainText()
# nexttext = f'<br/><img src="cid:{attachment}" >'
# nexttext = f"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' id='millstudio logo' width='10%' height='0%'></center>"
# document = self.textedit23.document()
# cursor = QTextCursor(document)
# p1 = cursor.position() # return int
# cursor.insertImage(f_name)
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
# file.write(pretext)
file.write(contents)
# file.write(nexttext)
# print(contents)
# msgText = MIMEText(contents, 'html')
print(name, email, "전송완료")
# self.fn_result_window(name, email)
def fn_DeleteAllFiles(self,filePath):
if os.path.exists(filePath):
for file in os.scandir(filePath):
os.remove(file.path)
return '폴더 내 모든 파일 지우기 완료'
else:
return '폴더가 없습니다.'
def fn_pdf_create(self, idx_name):
#####################################
# xlwings
self.current_pdf_path = os.getcwd()+"\pdf"
fname = "급여1.xlsx"
# for n in self.target_name_list:
name = idx_name
df_data = pd.read_excel(fname, sheet_name='4대급여')
df_data = df_data.fillna(0)
df_employee = pd.read_excel(fname, sheet_name='직원현황')
idx_df_data = df_data.index[df_data['성명']==name].tolist()[0]
# print("4대급여 인덱스 :",idx_df_data)
normal = df_data.loc[idx_df_data,['기본급']][0]
overtime = df_data.loc[idx_df_data,['연장수당']][0]
holiday = df_data.loc[idx_df_data,['휴일수당']][0]
holidayovertime = df_data.loc[idx_df_data,['휴일연장수당']][0]
extra = df_data.loc[idx_df_data,['추가수당']][0]
meals = df_data.loc[idx_df_data,['식대']][0]
bonus = df_data.loc[idx_df_data,['상여금']][0]
normal_calculation = df_data.loc[idx_df_data,['기']][0]
overtime_calculation = df_data.loc[idx_df_data,['연']][0]
holiday_calculation = df_data.loc[idx_df_data,['휴']][0]
holidayovertime_calculation = df_data.loc[idx_df_data,['휴연']][0]
extra_calculation = df_data.loc[idx_df_data,['추']][0]
nationalpension = df_data.loc[idx_df_data,['국민연금']][0]
healthinsurance = df_data.loc[idx_df_data,['건강보험']][0]
longtermcareinsurance = df_data.loc[idx_df_data,['장기요양보험']][0]
employmentinsurance = df_data.loc[idx_df_data,['고용보험']][0]
healthsettlement = df_data.loc[idx_df_data,['정산건강']][0]
longtermcaresettlement = df_data.loc[idx_df_data,['정산장기요양']][0]
advancepayment = df_data.loc[idx_df_data,['선지급']][0]
etc = df_data.loc[idx_df_data,['기타']][0]
incometax = df_data.loc[idx_df_data,['소득세']][0]
localincometax = df_data.loc[idx_df_data,['지방소득세']][0]
idx_df_employee = df_employee.index[df_employee['성명']==name].tolist()[0]
# print("직원현황 인덱스 :",idx_df_employee)
jobposition = df_employee.loc[idx_df_employee,['직위']][0]
department = df_employee.loc[idx_df_employee,['부서']][0]
birthday = df_employee.loc[idx_df_employee,['생일']][0]
# 엑셀 인스턴스 생성
app = xw.App(visible=False)
book = xw.Book(fname)
sh_paystub = book.sheets('급여명세서사대보험')
sh_paystub["B4"].value = name
sh_paystub["D4"].value = jobposition
sh_paystub["B5"].value = department
sh_paystub["D5"].value = birthday
sh_paystub["B8"].value = normal
sh_paystub["B9"].value = overtime
sh_paystub["B10"].value = holiday
sh_paystub["B11"].value = holidayovertime
sh_paystub["B12"].value = extra
sh_paystub["B13"].value = meals
sh_paystub["D8"].value = nationalpension
sh_paystub["D9"].value = healthinsurance
sh_paystub["D10"].value = longtermcareinsurance
sh_paystub["D11"].value = employmentinsurance
sh_paystub["D12"].value = healthsettlement
sh_paystub["D13"].value = longtermcaresettlement
sh_paystub["D14"].value = advancepayment
sh_paystub["D15"].value = etc
sh_paystub["D16"].value = incometax
sh_paystub["D17"].value = localincometax
sh_paystub["B23"].value = normal_calculation
sh_paystub["B24"].value = overtime_calculation
sh_paystub["B25"].value = holiday_calculation
sh_paystub["B26"].value = holidayovertime_calculation
sh_paystub["B27"].value = extra_calculation
sh_paystub["D23"].value = normal
sh_paystub["D24"].value = overtime
sh_paystub["D25"].value = holiday
sh_paystub["D26"].value = holidayovertime
sh_paystub["D27"].value = extra
if len(self.lineedit21.text())==0:
book.save()
app.kill()
return
# print(len(self.lineedit21.text()))
# pdf 로 저장하기
# current_path = os.getcwd() # 현재 작업중인 폴더에 저장하기
# 절대경로로 파일 위치 입력
subject_before = self.lineedit21.text()
# 문자치환 f-string 사용하여 변수 적용하기
subject = subject_before.replace("{성명}",f'{name}')
pdf_file = os.path.join(self.current_pdf_path, f"{subject}.pdf")
# PDF 로 저장할 시트 선택하기(본 예제에서는 첫 번째 시트 선택하기)
# report_sheet = book.sheets[1]
report_sheet = sh_paystub
# PDF 로 저장하기
# report_sheet.ExportAsFixedFormat(0, pdf_path)
report_sheet.api.ExportAsFixedFormat(0, pdf_file)
book.save()
app.kill()
#####################################
def fn_send(self, name, email_i):
# # 메일 서버를 설정합니다.
account_id = self.lineedit11.text().split("@")[0]
emailserver = self.lineedit11.text().split("@")[1]
# self.server = smtplib.SMTP_SSL('smtp.kakao.com')
smtp_server = 'smtp.'+ emailserver
# print(account_id)
self.server = smtplib.SMTP_SSL(smtp_server)
# self.server.login(secret.kakao_id, secret.kakao_pw)
self.server.login(account_id, self.lineedit12.text())
# self.msg_from = 'miero@kakao.com'
self.msg_from = self.lineedit11.text()
# # server = smtplib.SMTP('smtp.com', port_number)
# # server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# server = smtplib.SMTP_SSL('smtp.kakao.com')
# # server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# # 로그인이 필요하면 로그인 설정
# server.login(secret.kakao_id, secret.kakao_pw)
# # 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
# msg_to = email_i
# cc = 'b@b.com, c@c.com'
# cc = ''
# print(name,email_i)
# 메세지 구성
# msg = MIMEBase('multipart','mixed')
msg = MIMEMultipart()
msg['From'] = self.msg_from
msg['To'] = email_i
msg['Date'] = formatdate(localtime=True)
# msg['Subject'] = f'2022년08월급여명세서-{name}'
subject_before = self.lineedit21.text()
# 문자치환 f-string 사용하여 변수 적용하기
subject = subject_before.replace("{성명}",f'{name}')
msg['Subject'] = Header(s=subject, charset='utf-8')
# msg['Subject'] = Header(s=f'2022년08월급여명세서-{name}', charset='utf-8')
# msg['Cc'] = ""
# 메일 본문 작성
# # html 로 되어있던 파일을 불러 오고 거기에 파일을 붙여서 보냅니다.
# msgText = MIMEText('<h1>%s</h1><hr>, <img src="cid:%s" >' % (emailtext, attachment), 'html')
# contents = '<h1>%s</h1>'
# contents += '<hr>'
# contents += '<img src="cid:%s" >'
# msgText = MIMEText(contents % (emailtext, attachment), 'html')
# contents = f'<h1>{emailtext}</h1>'
# contents += f'<h2>{msg_to} 님 메일이 도착했습니다.</h2>'
# contents += '<hr>'
# contents += f'<img src="cid:{attachment}" >'
# msgText = MIMEText(contents, 'html')
# pretext = f'수신: {name}<br/>'
# pretext += '발신: 주식회사 밀앤아이, 주식회사 헴펠 대표이사<br/>'
# pretext += '<br/>'
# msgpreText = MIMEText(pretext, 'html')
# msg.attach(msgpreText)
# contents = self.textedit23.toPlainText()
contents_before = self.textedit23.toPlainText()
# 문자치환 f-string 사용하여 변수 적용하기
contents = contents_before.replace("{성명}",f'수신: {name}')
# msgText = MIMEText(contents, 'plain')
msgText = MIMEText(contents, 'html')
# msgText = MIMEText(contents, _charset='utf-8')
# 메세지를 메일에 붙여 줍니다.
msg.attach(msgText)
# 메일 제일 밑에 로고그림 붙여 줍니다.
# logo_file = "logo.jpg"
# img_f_name = logo_file.replace("\\","/")
# logo_file = r"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' width='10%' height='0%'></center>"
# img_f_name = logo_file.replace("\\","/")
# # with io.open('file_name.html','r') as f:
# with io.open(img_f_name,'r') as f:
# # emailtext = f.read()
# emailtext = img_f_name
# # attachment = 'attachment_file_name.png'
# attachment = img_f_name
# attachment = logo_file
# fp = open(attachment, 'rb')
# img = MIMEImage(fp.read())
# fp.close()
# img.add_header('Content-ID', '<{}>'.format(attachment))
# msg.attach(img)
# 파일첨부
files = list()
pdf_file_name = f"{subject}.pdf"
pdf_file = os.path.join(os.getcwd()+"\pdf", pdf_file_name)
files.append(pdf_file)
# if os.path.isfile(pdf_file):
# binary_pdf = open(pdf_file, 'rb')
# payload = MIMEBase('application', 'octate-stream', Name=pdf_file_name)
# payload.set_payload((binary_pdf).read())
# encoders.encode_base64(payload)
# payload.add_header('Content-Decomposition', 'attachment', filename=pdf_file_name)
# msg.attach(payload)
for i in range(self.listwidget22.count()):
files.append(self.listwidget22.item(i).text())
# print(files)
for f in files:
# print(f)
part = MIMEBase('application', "octet-stream")
part.set_payload(open(f,"rb").read())
encoders.encode_base64(part)
fstr_name = os.path.basename(f)
# part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(f))
part.add_header('Content-Disposition',"attachment", filename= fstr_name, charset='utf-8')
# [출처] 파이썬에서 지메일 보내기(w/첨부파일) 한글파일도 가능|작성자 데이터공방
# Header(s=f'2022년08월급여명세서-{name}', charset='utf-8')
msg.attach(part)
# 메일 서버를 이용하여 메일을 발송합니다.
# server.sendmail(msg_from, msg["To"].split(",") + msg["Cc"].split(","), msg.as_string())
self.server.sendmail(msg['From'], msg['To'], msg.as_string())
# self.server.quit()
def fn_result_window(self, name, email):
self.listwidget32.clear()
cnt = self.listwidget32.count() +1
# print(cnt, name, email, "전송완료")
# self.listwidget32.insertItem(cnt,name&email&"전송완료")
self.listwidget32.insertItem(cnt, f'{name}-{email}-전송완료')
def fn_test(self):
# try:
# 메일 서버를 설정합니다.
# server = smtplib.SMTP('smtp.com', port_number)
# server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# self.server = smtplib.SMTP_SSL('smtp.kakao.com')
# server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# 로그인이 필요하면 로그인 설정
# self.server.login(secret.kakao_id, secret.kakao_pw)
# 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
if len(self.lineedit11.text()) == 0:
QMessageBox.about(self,'이메일계정 확인','이메일계정을 입력하십시요.')
return
if len(self.lineedit12.text()) == 0:
QMessageBox.about(self,'비밀번호 확인','비밀번호를 입력하십시요.')
return
self.listwidget32.clear()
cnt = 0
if len(self.lineedit21.text()) == 0:
QMessageBox.about(self,'제목 입력 확인','제목을 입력하십시요.')
return
self.fn_subject_save()
self.fn_html_save()
self.fn_DeleteAllFiles(os.getcwd()+"\pdf")
self.fn_pdf_create(self.lineedit23.text())
try:
if self.df_table_02.loc[self.lineedit23.text()][0] != "nan":
self.fn_send(self.lineedit23.text(), self.df_table_02.loc[self.lineedit23.text()][0])
cnt += 1
self.listwidget32.insertItem(cnt, f'{self.lineedit23.text()}-{self.df_table_02.loc[self.lineedit23.text()][0]}-전송완료')
except:
cnt += 1
self.listwidget32.insertItem(cnt, f'{self.lineedit23.text()}-{self.df_table_02.loc[self.lineedit23.text()][0]}-실패')
self.listwidget32.item(cnt-1).setBackground(Qt.red)
# self.fn_pdf_create("밀1")
# self.fn_send(self.lineedit23.text(), self.df_table_02.loc[self.lineedit23.text()][0])
# cnt += 1
# self.listwidget32.insertItem(cnt, f'{self.lineedit23.text()}-{self.df_table_02.loc[self.lineedit23.text()][0]}-전송완료')
self.server.quit()
# self.fn_print_name(self.lineedit23.text(), self.df_table_02.loc[self.lineedit23.text()][0])
# except: # 예외가 발생했을 때 실행됨
# print('예외가 발생했습니다.')
# self.listwidget32.insertItem(cnt, f'{"밀1"}-{self.df_table_02.loc["밀1"][0]}-실패')
def fn_run(self):
# 메일 서버를 설정합니다.
# server = smtplib.SMTP('smtp.com', port_number)
# server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# server = smtplib.SMTP_SSL('smtp.kakao.com')
# server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# 로그인이 필요하면 로그인 설정
# server.login(secret.kakao_id, secret.kakao_pw)
# 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
self.listwidget32.clear()
if len(self.lineedit11.text()) == 0:
QMessageBox.about(self,'이메일계정 확인','이메일계정을 입력하십시요.')
return
if len(self.lineedit12.text()) == 0:
QMessageBox.about(self,'비밀번호 확인','비밀번호를 입력하십시요.')
return
cnt = 0
if len(self.lineedit21.text()) == 0:
QMessageBox.about(self,'제목 입력 확인','제목을 입력하십시요.')
return
self.fn_subject_save()
self.fn_html_save()
# self.fn_send("밀1", self.df_table_02.loc["밀1"][0])
# self.fn_print_name("밀1", self.df_table_02.loc["밀1"][0])
for idx_name in self.idx_name_list:
# print(idx)
# print(self.df_table_02.loc[idx][0])
# print(idx, table_02.loc[idx][0])
self.fn_DeleteAllFiles(os.getcwd()+"\pdf")
self.fn_pdf_create(idx_name)
try:
if self.df_table_02.loc[idx_name][0] != "nan":
self.fn_send(idx_name, self.df_table_02.loc[idx_name][0])
cnt += 1
self.listwidget32.insertItem(cnt, f'{idx_name}-{self.df_table_02.loc[idx_name][0]}-전송완료')
except:
cnt += 1
self.listwidget32.insertItem(cnt, f'{idx_name}-{self.df_table_02.loc[idx_name][0]}-실패')
self.listwidget32.item(cnt-1).setBackground(Qt.red)
# if self.df_table_02.loc[idx_name][0] == "nan":
# print(self.listwidget32.)
# self.listwidget32.item(cnt).setBackground(Qt.red)
# print("예외가 발생했습니다.-fn_run",cnt,self.df_table_02.loc[idx_name][0])
# self.fn_print_name(idx_name, self.df_table_02.loc[idx_name][0])
self.server.quit()
# print('예외가 발생했습니다.')
# self.listwidget32.insertItem(cnt, f'{idx_name}-{self.df_table_02.loc[idx_name][0]}-실패')
if __name__ == '__main__':
# don't auto scale when drag app to a different monitor.
# QGuiApplication.setHighDpiScaleFactorRoundingPolicy(Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
excel_file_path = '급여1.xlsx'
worksheet_name = '4대급여'
emailsheet_name = '이메일'
app = QApplication(sys.argv)
app.setStyleSheet('''
QWidget {
font-size: 17px;
}
''')
myApp = MyApp()
myApp.show()
try:
sys.exit(app.exec())
except SystemExit:
print('Closing Window...')
====================
pay17.py--------------------
# from operator import index
# from unittest import result
# from xml.dom.minidom import Document
from PyQt5.QtWidgets import QApplication, QWidget, QTableWidget, QTableWidgetItem, QPushButton, \
QHeaderView, QHBoxLayout, QVBoxLayout, QGridLayout, QAbstractScrollArea, QLabel, QListWidget, \
QFileDialog, QMessageBox, QTextEdit, QAbstractItemView, QLineEdit, QGroupBox, QRadioButton
from PyQt5.QtCore import Qt
# from PyQt5 import QtGui
from PyQt5.QtGui import QTextCursor
import sys
import pandas as pd # pip install pandas
import os
import io
import secret
import xlwings as xw
import re
import smtplib
from email.encoders import encode_base64
from email.header import Header
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText # 메일의 본문 내용을 만드는 모듈 내용을 base64형식으로 변환
from email.utils import formatdate
from email.mime.application import MIMEApplication # 메일의 첨부 파일을 base64 형식으로 변환
from email.mime.image import MIMEImage # 메일의 이미지 파일을 base64 형식으로 변환
# 출처: https://nowonbun.tistory.com/684 [명월 일지:티스토리]
from email import encoders
from email.encoders import encode_base64
class MyApp(QWidget):
def __init__(self):
super().__init__()
self.window_width, self.window_height = 1150, 600
self.resize(self.window_width, self.window_height)
self.setWindowTitle('pay')
# self.server = smtplib.SMTP_SSL('smtp.kakao.com')
# self.server.login(secret.kakao_id, secret.kakao_pw)
# self.msg_from = 'miero@kakao.com'
##### layout_main #####
layout_main = QHBoxLayout()
self.setLayout(layout_main)
##### layout_1 #####
layout_1 = QVBoxLayout()
vBox11 = QVBoxLayout()
groupBoxLogin11 = QGroupBox("로그인 정보")
groupBoxLogin11.setLayout(vBox11)
layout_1.addWidget(groupBoxLogin11)
self.label11 = QLabel("이메일계정")
vBox11.addWidget(self.label11)
self.lineedit11 = QLineEdit("miero@kakao.com")
vBox11.addWidget(self.lineedit11)
self.label12 = QLabel("패스워드")
vBox11.addWidget(self.label12)
self.lineedit12 = QLineEdit()
self.lineedit12.setEchoMode(QLineEdit.Password)
# self.lineedit12.show()
vBox11.addWidget(self.lineedit12)
label13 = QLabel('직원 메일')
# self.button = QPushButton('&Load Data')
# self.button.clicked.connect(lambda _, xl_path=excel_file_path, sheet_name=worksheet_name: self.loadExcelData(xl_path, sheet_name))
# layout_v.addWidget(self.button)
layout_1.addWidget(label13)
self.table = QTableWidget()
self.table.setFixedWidth(350)
layout_1.addWidget(self.table)
layout_main.addLayout(layout_1)
##### layout_2 #####
layout_2 = QGridLayout()
label21 = QLabel('이메일 제목')
layout_2.addWidget(label21, 0, 0)
self.lineedit21 = QLineEdit()
layout_2.addWidget(self.lineedit21, 1, 0, 1, 2)
label22 = QLabel('첨부파일')
layout_2.addWidget(label22, 2, 0)
self.listwidget22 = QListWidget()
# self.listwidget22.setFixedWidth(300)
self.listwidget22.setMinimumWidth(400)
# self.listwidget22.setSelectionMode(QAbstractItemView.ExtendedSelection)
layout_2.addWidget(self.listwidget22, 3, 0, 3, 1)
self.btn_file_add = QPushButton('파일 추가') # sendlist
# self.btn_file_add.setMinimumHeight(80)
layout_2.addWidget(self.btn_file_add, 3, 1, 1, 1)
self.btn_file_add.clicked.connect(self.fn_fileadd)
self.btn_file_del = QPushButton('파일 삭제')
layout_2.addWidget(self.btn_file_del, 4, 1, 1, 1)
self.btn_file_del.clicked.connect(self.fn_filedel)
# label21 = QLabel('본문 (HTML형식)')
# layout_2.addWidget(label21, 8, 0)
# radio_1 ~ 4 버튼을 그룹으로 설정
groupBoxMid = QGroupBox("테스트 메일 보내기")
layout_2.addWidget(groupBoxMid, 6, 0, 1, 2)
hBox1 = QHBoxLayout()
groupBoxMid.setLayout(hBox1)
self.label23 = QLabel("성명")
hBox1.addWidget(self.label23)
self.lineedit23 = QLineEdit("밀1")
hBox1.addWidget(self.lineedit23)
self.pushbutton23 = QPushButton("테스트 보내기")
self.pushbutton23.clicked.connect(self.fn_test)
hBox1.addWidget(self.pushbutton23)
groupBoxBottom = QGroupBox("본문 보기형식 선택")
layout_2.addWidget(groupBoxBottom, 7, 0, 1, 2)
hBox2 = QHBoxLayout()
groupBoxBottom.setLayout(hBox2)
self.radioBtn1 = QRadioButton("HTML")
self.radioBtn1.setChecked(True)
self.radioBtn1.clicked.connect(self.fn_radio_select)
hBox2.addWidget(self.radioBtn1)
self.radioBtn2 = QRadioButton("미리보기")
self.radioBtn2.clicked.connect(self.fn_radio_select)
hBox2.addWidget(self.radioBtn2)
self.textedit23 = QTextEdit()
# self.textedit23.setFixedWidth(400)
# self.textedit23.setAcceptRichText(False)
layout_2.addWidget(self.textedit23, 8, 0, 4, 1)
self.textedit23.show()
self.textedit24 = QTextEdit()
layout_2.addWidget(self.textedit24, 8, 0, 4, 1)
self.textedit24.hide()
self.btn_send = QPushButton("보내기")
self.btn_send.setMaximumHeight(500) # gridlayout button size
layout_2.addWidget(self.btn_send, 8, 1, 4, 1)
self.btn_send.clicked.connect(self.fn_run) #@@@@@@@@@@@@@@@@@@@@@@@@@@
layout_main.addLayout(layout_2)
##### layout_3 #####
layout_3 = QVBoxLayout()
label31 = QLabel('발송 결과')
layout_3.addWidget(label31)
self.listwidget32 = QListWidget()
# self.listwidget32.setMinimumWidth(self.listwidget32.sizeHintForColumn(0))
# self.listwidget32.setWidth(10)
layout_3.addWidget(self.listwidget32)
layout_main.addLayout(layout_3)
# subject0 파일이 존재하면
filename_subject = 'subject0.txt'
if os.path.isfile(filename_subject) == True:
source_text = open(filename_subject,'r', encoding="UTF-8").read()
# self.lineedit21.setText(source_text) # TextEdit에 RichText 형식의 글을 입력합니다.
self.lineedit21.setText(source_text) # TextEdit에 PlainText 형식의 글을 새로 입력합니다.
# html0 파일이 존재하면
filename_html = 'html0.txt'
if os.path.isfile(filename_html) == True:
source_text = open(filename_html,'r', encoding="UTF-8").read()
# self.textedit23.setText(source_text) # TextEdit에 RichText 형식의 글을 입력합니다.
self.textedit23.setPlainText(source_text) # TextEdit에 PlainText 형식의 글을 새로 입력합니다.
# self.textedit24.setHtml(source_text) # TextEdit에 PlainText 형식의 글을 새로 입력합니다.
# table_data = self.loadExcelData(excel_file_path, worksheet_name)
# print(table_data.keys())
df_table = self.loadExcelData(excel_file_path, worksheet_name)
# print(table_df["성명"][0])
self.df_table_02 = df_table.set_index("성명")
self.idx_name_list = self.df_table_02.index.to_list()
# print(index)
# for i in table_02["이메일"]:
def fn_radio_select(self):
# QRadioButton1 클릭 여부 표시
if self.radioBtn1.isChecked():
self.textedit23.show()
self.textedit24.hide()
self.hidden = False
# self.btn_send.setText('보내기')
elif self.radioBtn2.isChecked():
self.fn_html_save()
self.textedit23.hide()
self.textedit24.show()
self.hidden = True
# self.btn_send.setText('미리보기')
def loadExcelData(self, excel_file_dir, worksheet_name):
df_work_sheet = pd.read_excel(excel_file_path, worksheet_name)
df_email_sheet = pd.read_excel(excel_file_path, emailsheet_name)
df_table = df_work_sheet.merge(df_email_sheet, how='left')
df_table_mail = df_table[['성명','이메일']]
res = df_table_mail
# res = df_table_mail.to_dict()
# self.table.setRowCount(df.shape[0])
# self.table.setColumnCount(df.shape[1])
self.table.setRowCount(df_table_mail.shape[0])
self.table.setColumnCount(df_table_mail.shape[1])
# self.table.setHorizontalHeaderLabels(df.columns)
self.table.setHorizontalHeaderLabels(df_table_mail.columns)
header = self.table.horizontalHeader()
# header.setSectionResizeMode(0, QHeaderView.Stretch)
# header.setSectionResizeMode(0, QHeaderView.ResizeToContents)
header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
# returns pandas array object
# for row in df.iterrows():
for row in df_table_mail.iterrows():
values = row[1]
for col_index, value in enumerate(values):
if isinstance(value, (float, int)):
value = '{0:0,.0f}'.format(value)
tableItem = QTableWidgetItem(str(value))
if value == "nan":
tableItem.setBackground(Qt.red)
self.table.setItem(row[0], col_index, tableItem)
self.table.setColumnWidth(2, 310)
return res
def fn_fileadd(self):
# f_name = QFileDialog.getOpenFileName(None, '열기', '', "All Files(*.*)")
f_names = QFileDialog.getOpenFileNames(None, '열기', '', "All Files(*.*)")
# txtPath = f_name[0]
filelist = f_names[0]
if filelist:
for f_name in filelist:
# ext = os.path.splitext(f_name[0])[1]
ext = os.path.splitext(f_name)[1] # 확장자 확인
# if f_names[0]:
icnt = 0
for i in range(self.listwidget22.count()):
# if str(self.listwidget22.item(i).text()) == txtPath.replace("/","\\") or str(self.listwidget22.item(i).text()) == txtPath:
if str(self.listwidget22.item(i).text()) == f_name.replace("/","\\") or str(self.listwidget22.item(i).text()) == f_name:
icnt = 1
break
if icnt != 1:
f_path = f_name
if ext == '.exe':
QMessageBox.about(self,'파일 형식 확인','exe파일은 전송할 수 없습니다.')
pass
else:
cnt = self.listwidget22.count() +1
# self.listwidget22.insertItem(cnt, os.path.basename(txtPath))
# self.listwidget22.insertItem(cnt, txtPath)
# f_path = f_names[0]
# print(f_path)
self.listwidget22.insertItem(cnt, f_path)
# self.listwidget22.insertItem(cnt, f_path.replace("/","\\"))
def fn_filedel(self):
currentrow = self.listwidget22.currentRow()
self.listwidget22.takeItem(currentrow) # currentrowRight번째 항목을 삭제합니다
self.listwidget22.clearSelection()
def fn_subject_save(self):
if len(self.lineedit21.text())>0:
S__File = os.path.join(os.getcwd(),'subject0.txt')
Text = self.lineedit21.text()
if S__File:
# Finally this will Save your file to the path selected.
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
file.write(Text)
def fn_html_save(self):
if len(self.textedit23.toPlainText())>0:
# print(len(self.textedit.toPlainText()))
# S__File = QFileDialog.getSaveFileName(None,'문자 파일저장','/', "Text Files (*.txt)")
# S__File = QFileDialog.getSaveFileName(None,'문자 파일저장','html0', "Text Files (*.txt)")
S__File = os.path.join(os.getcwd(),'html0.txt')
# This will let you access the test in your QTextEdit
Text = self.textedit23.toPlainText()
self.textedit24.setHtml(Text)
# document = self.textedit23.document()
# cursor = QTextCursor(document)
# p1 = cursor.position() # return int
# cursor.insertImage(r"C:\Users\newstep\Pictures\number1.jpg")
# This will prevent you from an error if pressed cancel on file dialog.
# if S__File[0]:
if S__File:
# Finally this will Save your file to the path selected.
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
file.write(Text)
# txtPath = S__File[0]
# icnt = 0
# for i in range(self.listwidget31.count()):
# if str(self.listwidget31.item(i).text()) == txtPath.replace("/","\\"):
# icnt = 1
# break
# if icnt != 1:
# cnt = self.listwidget31.count() +1
# self.listwidget31.insertItem(cnt, os.path.basename(txtPath))
# self.listwidget31.insertItem(cnt, txtPath)
else:
QMessageBox.about(self,'메시지 입력 확인','메시지를 입력하셔야 합니다.')
def fn_print_name(self, name, email):
# f_name_pre = r"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' width='50%' height='0%'></center>"
# f_name = f_name_pre.replace("\\","/")
# with io.open('file_name.html','r') as f:
# with io.open(f_name,'r') as f:
# # emailtext = f.read()
# emailtext = f_name
# attachment = 'attachment_file_name.png'
# attachment = f_name
# print(name, self.df_table_02.loc[name][0])
# print(name, email)
if len(self.textedit23.toPlainText())>0:
S__File = os.path.join(os.getcwd(),'html0.txt')
# print(len(self.textedit23.toPlainText()))
# print(S__File)
# pretext = f'{name} 님<br/><br/>'
# pretext += f'당신의 이메일은 {email} 입니다.<br/>'
contents = self.textedit23.toPlainText()
# nexttext = f'<br/><img src="cid:{attachment}" >'
# nexttext = f"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' id='millstudio logo' width='10%' height='0%'></center>"
# document = self.textedit23.document()
# cursor = QTextCursor(document)
# p1 = cursor.position() # return int
# cursor.insertImage(f_name)
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
# file.write(pretext)
file.write(contents)
# file.write(nexttext)
# print(contents)
# msgText = MIMEText(contents, 'html')
print(name, email, "전송완료")
# self.fn_result_window(name, email)
def fn_DeleteAllFiles(self,filePath):
if os.path.exists(filePath):
for file in os.scandir(filePath):
os.remove(file.path)
return '폴더 내 모든 파일 지우기 완료'
else:
return '폴더가 없습니다.'
def fn_pdf_create(self, idx_name):
#####################################
# xlwings
self.current_pdf_path = os.getcwd()+"\pdf"
fname = "급여1.xlsx"
# for n in self.target_name_list:
name = idx_name
df_data = pd.read_excel(fname, sheet_name='4대급여')
df_data = df_data.fillna(0)
df_employee = pd.read_excel(fname, sheet_name='직원현황')
idx_df_data = df_data.index[df_data['성명']==name].tolist()[0]
# print("4대급여 인덱스 :",idx_df_data)
normal = df_data.loc[idx_df_data,['기본급']][0]
overtime = df_data.loc[idx_df_data,['연장수당']][0]
holiday = df_data.loc[idx_df_data,['휴일수당']][0]
holidayovertime = df_data.loc[idx_df_data,['휴일연장수당']][0]
extra = df_data.loc[idx_df_data,['추가수당']][0]
meals = df_data.loc[idx_df_data,['식대']][0]
bonus = df_data.loc[idx_df_data,['상여금']][0]
normal_calculation = df_data.loc[idx_df_data,['기']][0]
overtime_calculation = df_data.loc[idx_df_data,['연']][0]
holiday_calculation = df_data.loc[idx_df_data,['휴']][0]
holidayovertime_calculation = df_data.loc[idx_df_data,['휴연']][0]
extra_calculation = df_data.loc[idx_df_data,['추']][0]
nationalpension = df_data.loc[idx_df_data,['국민연금']][0]
healthinsurance = df_data.loc[idx_df_data,['건강보험']][0]
longtermcareinsurance = df_data.loc[idx_df_data,['장기요양보험']][0]
employmentinsurance = df_data.loc[idx_df_data,['고용보험']][0]
healthsettlement = df_data.loc[idx_df_data,['정산건강']][0]
longtermcaresettlement = df_data.loc[idx_df_data,['정산장기요양']][0]
advancepayment = df_data.loc[idx_df_data,['선지급']][0]
etc = df_data.loc[idx_df_data,['기타']][0]
incometax = df_data.loc[idx_df_data,['소득세']][0]
localincometax = df_data.loc[idx_df_data,['지방소득세']][0]
idx_df_employee = df_employee.index[df_employee['성명']==name].tolist()[0]
# print("직원현황 인덱스 :",idx_df_employee)
jobposition = df_employee.loc[idx_df_employee,['직위']][0]
department = df_employee.loc[idx_df_employee,['부서']][0]
birthday = df_employee.loc[idx_df_employee,['생일']][0]
# 엑셀 인스턴스 생성
app = xw.App(visible=False)
book = xw.Book(fname)
sh_paystub = book.sheets('급여명세서사대보험')
sh_paystub["B4"].value = name
sh_paystub["D4"].value = jobposition
sh_paystub["B5"].value = department
sh_paystub["D5"].value = birthday
sh_paystub["B8"].value = normal
sh_paystub["B9"].value = overtime
sh_paystub["B10"].value = holiday
sh_paystub["B11"].value = holidayovertime
sh_paystub["B12"].value = extra
sh_paystub["B13"].value = meals
sh_paystub["D8"].value = nationalpension
sh_paystub["D9"].value = healthinsurance
sh_paystub["D10"].value = longtermcareinsurance
sh_paystub["D11"].value = employmentinsurance
sh_paystub["D12"].value = healthsettlement
sh_paystub["D13"].value = longtermcaresettlement
sh_paystub["D14"].value = advancepayment
sh_paystub["D15"].value = etc
sh_paystub["D16"].value = incometax
sh_paystub["D17"].value = localincometax
sh_paystub["B23"].value = normal_calculation
sh_paystub["B24"].value = overtime_calculation
sh_paystub["B25"].value = holiday_calculation
sh_paystub["B26"].value = holidayovertime_calculation
sh_paystub["B27"].value = extra_calculation
sh_paystub["D23"].value = normal
sh_paystub["D24"].value = overtime
sh_paystub["D25"].value = holiday
sh_paystub["D26"].value = holidayovertime
sh_paystub["D27"].value = extra
if len(self.lineedit21.text())==0:
book.save()
app.kill()
return
# print(len(self.lineedit21.text()))
# pdf 로 저장하기
# current_path = os.getcwd() # 현재 작업중인 폴더에 저장하기
# 절대경로로 파일 위치 입력
subject_before = self.lineedit21.text()
# 문자치환 f-string 사용하여 변수 적용하기
subject = subject_before.replace("{성명}",f'{name}')
pdf_file = os.path.join(self.current_pdf_path, f"{subject}.pdf")
# PDF 로 저장할 시트 선택하기(본 예제에서는 첫 번째 시트 선택하기)
# report_sheet = book.sheets[1]
report_sheet = sh_paystub
# PDF 로 저장하기
# report_sheet.ExportAsFixedFormat(0, pdf_path)
report_sheet.api.ExportAsFixedFormat(0, pdf_file)
book.save()
app.kill()
#####################################
def fn_send(self, name, email_i):
# # 메일 서버를 설정합니다.
account_id = self.lineedit11.text().split("@")[0]
emailserver = self.lineedit11.text().split("@")[1]
# self.server = smtplib.SMTP_SSL('smtp.kakao.com')
smtp_server = 'smtp.'+ emailserver
# print(account_id)
self.server = smtplib.SMTP_SSL(smtp_server)
# self.server.login(secret.kakao_id, secret.kakao_pw)
self.server.login(account_id, self.lineedit12.text())
# self.msg_from = 'miero@kakao.com'
self.msg_from = self.lineedit11.text()
# # server = smtplib.SMTP('smtp.com', port_number)
# # server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# server = smtplib.SMTP_SSL('smtp.kakao.com')
# # server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# # 로그인이 필요하면 로그인 설정
# server.login(secret.kakao_id, secret.kakao_pw)
# # 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
# msg_to = email_i
# cc = 'b@b.com, c@c.com'
# cc = ''
# print(name,email_i)
# 메세지 구성
# msg = MIMEBase('multipart','mixed')
msg = MIMEMultipart()
msg['From'] = self.msg_from
msg['To'] = email_i
msg['Date'] = formatdate(localtime=True)
# msg['Subject'] = f'2022년08월급여명세서-{name}'
subject_before = self.lineedit21.text()
# 문자치환 f-string 사용하여 변수 적용하기
subject = subject_before.replace("{성명}",f'{name}')
msg['Subject'] = Header(s=subject, charset='utf-8')
# msg['Subject'] = Header(s=f'2022년08월급여명세서-{name}', charset='utf-8')
# msg['Cc'] = ""
# 메일 본문 작성
# # html 로 되어있던 파일을 불러 오고 거기에 파일을 붙여서 보냅니다.
# msgText = MIMEText('<h1>%s</h1><hr>, <img src="cid:%s" >' % (emailtext, attachment), 'html')
# contents = '<h1>%s</h1>'
# contents += '<hr>'
# contents += '<img src="cid:%s" >'
# msgText = MIMEText(contents % (emailtext, attachment), 'html')
# contents = f'<h1>{emailtext}</h1>'
# contents += f'<h2>{msg_to} 님 메일이 도착했습니다.</h2>'
# contents += '<hr>'
# contents += f'<img src="cid:{attachment}" >'
# msgText = MIMEText(contents, 'html')
# pretext = f'수신: {name}<br/>'
# pretext += '발신: 주식회사 밀앤아이, 주식회사 헴펠 대표이사<br/>'
# pretext += '<br/>'
# msgpreText = MIMEText(pretext, 'html')
# msg.attach(msgpreText)
# contents = self.textedit23.toPlainText()
contents_before = self.textedit23.toPlainText()
# 문자치환 f-string 사용하여 변수 적용하기
contents = contents_before.replace("{성명}",f'수신: {name}')
# msgText = MIMEText(contents, 'plain')
msgText = MIMEText(contents, 'html')
# msgText = MIMEText(contents, _charset='utf-8')
# 메세지를 메일에 붙여 줍니다.
msg.attach(msgText)
# 메일 제일 밑에 로고그림 붙여 줍니다.
# logo_file = "logo.jpg"
# img_f_name = logo_file.replace("\\","/")
# logo_file = r"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' width='10%' height='0%'></center>"
# img_f_name = logo_file.replace("\\","/")
# # with io.open('file_name.html','r') as f:
# with io.open(img_f_name,'r') as f:
# # emailtext = f.read()
# emailtext = img_f_name
# # attachment = 'attachment_file_name.png'
# attachment = img_f_name
# attachment = logo_file
# fp = open(attachment, 'rb')
# img = MIMEImage(fp.read())
# fp.close()
# img.add_header('Content-ID', '<{}>'.format(attachment))
# msg.attach(img)
# 파일첨부
files = list()
pdf_file_name = f"{subject}.pdf"
pdf_file = os.path.join(os.getcwd()+"\pdf", pdf_file_name)
files.append(pdf_file)
# if os.path.isfile(pdf_file):
# binary_pdf = open(pdf_file, 'rb')
# payload = MIMEBase('application', 'octate-stream', Name=pdf_file_name)
# payload.set_payload((binary_pdf).read())
# encoders.encode_base64(payload)
# payload.add_header('Content-Decomposition', 'attachment', filename=pdf_file_name)
# msg.attach(payload)
for i in range(self.listwidget22.count()):
files.append(self.listwidget22.item(i).text())
# print(files)
for f in files:
# print(f)
part = MIMEBase('application', "octet-stream")
part.set_payload(open(f,"rb").read())
encoders.encode_base64(part)
fstr_name = os.path.basename(f)
# part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(f))
part.add_header('Content-Disposition',"attachment", filename= fstr_name, charset='utf-8')
# [출처] 파이썬에서 지메일 보내기(w/첨부파일) 한글파일도 가능|작성자 데이터공방
# Header(s=f'2022년08월급여명세서-{name}', charset='utf-8')
msg.attach(part)
# 메일 서버를 이용하여 메일을 발송합니다.
# server.sendmail(msg_from, msg["To"].split(",") + msg["Cc"].split(","), msg.as_string())
self.server.sendmail(msg['From'], msg['To'], msg.as_string())
# self.server.quit()
def fn_result_window(self, name, email):
self.listwidget32.clear()
cnt = self.listwidget32.count() +1
# print(cnt, name, email, "전송완료")
# self.listwidget32.insertItem(cnt,name&email&"전송완료")
self.listwidget32.insertItem(cnt, f'{name}-{email}-전송완료')
def fn_test(self):
# try:
# 메일 서버를 설정합니다.
# server = smtplib.SMTP('smtp.com', port_number)
# server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# self.server = smtplib.SMTP_SSL('smtp.kakao.com')
# server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# 로그인이 필요하면 로그인 설정
# self.server.login(secret.kakao_id, secret.kakao_pw)
# 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
self.listwidget32.clear()
if len(self.lineedit11.text()) == 0:
QMessageBox.about(self,'이메일계정 확인','이메일계정을 입력하십시요.')
return
p = re.compile('^[a-zA-Z0-9+-_.]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$')
if p.match(self.lineedit11.text()) == None:
# print(p.match(self.lineedit11.text()) != None)
QMessageBox.about(self,'이메일 형식 확인','올바른 이메일 형식이 아닙니다.')
return
if len(self.lineedit12.text()) == 0:
QMessageBox.about(self,'비밀번호 확인','비밀번호를 입력하십시요.')
return
cnt = 0
if len(self.lineedit21.text()) == 0:
QMessageBox.about(self,'제목 입력 확인','제목을 입력하십시요.')
return
self.fn_subject_save()
self.fn_html_save()
self.fn_DeleteAllFiles(os.getcwd()+"\pdf")
self.fn_pdf_create(self.lineedit23.text())
try:
if self.df_table_02.loc[self.lineedit23.text()][0] != "nan":
self.fn_send(self.lineedit23.text(), self.df_table_02.loc[self.lineedit23.text()][0])
cnt += 1
self.listwidget32.insertItem(cnt, f'{self.lineedit23.text()}-{self.df_table_02.loc[self.lineedit23.text()][0]}-전송완료')
except:
cnt += 1
self.listwidget32.insertItem(cnt, f'{self.lineedit23.text()}-{self.df_table_02.loc[self.lineedit23.text()][0]}-실패')
self.listwidget32.item(cnt-1).setBackground(Qt.red)
# self.fn_pdf_create("밀1")
# self.fn_send(self.lineedit23.text(), self.df_table_02.loc[self.lineedit23.text()][0])
# cnt += 1
# self.listwidget32.insertItem(cnt, f'{self.lineedit23.text()}-{self.df_table_02.loc[self.lineedit23.text()][0]}-전송완료')
self.server.quit()
# self.fn_print_name(self.lineedit23.text(), self.df_table_02.loc[self.lineedit23.text()][0])
# except: # 예외가 발생했을 때 실행됨
# print('예외가 발생했습니다.')
# self.listwidget32.insertItem(cnt, f'{"밀1"}-{self.df_table_02.loc["밀1"][0]}-실패')
def fn_run(self):
# 메일 서버를 설정합니다.
# server = smtplib.SMTP('smtp.com', port_number)
# server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# server = smtplib.SMTP_SSL('smtp.kakao.com')
# server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# 로그인이 필요하면 로그인 설정
# server.login(secret.kakao_id, secret.kakao_pw)
# 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
self.listwidget32.clear()
if len(self.lineedit11.text()) == 0:
QMessageBox.about(self,'이메일계정 확인','이메일계정을 입력하십시요.')
return
p = re.compile('^[a-zA-Z0-9+-_.]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$')
if p.match(self.lineedit11.text()) == None:
# print(p.match(self.lineedit11.text()) != None)
QMessageBox.about(self,'이메일 형식 확인','올바른 이메일 형식이 아닙니다.')
return
if len(self.lineedit12.text()) == 0:
QMessageBox.about(self,'비밀번호 확인','비밀번호를 입력하십시요.')
return
cnt = 0
if len(self.lineedit21.text()) == 0:
QMessageBox.about(self,'제목 입력 확인','제목을 입력하십시요.')
return
self.fn_subject_save()
self.fn_html_save()
# self.fn_send("밀1", self.df_table_02.loc["밀1"][0])
# self.fn_print_name("밀1", self.df_table_02.loc["밀1"][0])
for idx_name in self.idx_name_list:
# print(idx)
# print(self.df_table_02.loc[idx][0])
# print(idx, table_02.loc[idx][0])
self.fn_DeleteAllFiles(os.getcwd()+"\pdf")
self.fn_pdf_create(idx_name)
try:
if self.df_table_02.loc[idx_name][0] != "nan":
self.fn_send(idx_name, self.df_table_02.loc[idx_name][0])
cnt += 1
self.listwidget32.insertItem(cnt, f'{idx_name}-{self.df_table_02.loc[idx_name][0]}-전송완료')
except:
cnt += 1
self.listwidget32.insertItem(cnt, f'{idx_name}-{self.df_table_02.loc[idx_name][0]}-실패')
self.listwidget32.item(cnt-1).setBackground(Qt.red)
# if self.df_table_02.loc[idx_name][0] == "nan":
# print(self.listwidget32.)
# self.listwidget32.item(cnt).setBackground(Qt.red)
# print("예외가 발생했습니다.-fn_run",cnt,self.df_table_02.loc[idx_name][0])
# self.fn_print_name(idx_name, self.df_table_02.loc[idx_name][0])
self.server.quit()
# print('예외가 발생했습니다.')
# self.listwidget32.insertItem(cnt, f'{idx_name}-{self.df_table_02.loc[idx_name][0]}-실패')
if __name__ == '__main__':
# don't auto scale when drag app to a different monitor.
# QGuiApplication.setHighDpiScaleFactorRoundingPolicy(Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
excel_file_path = '급여1.xlsx'
worksheet_name = '4대급여'
emailsheet_name = '이메일'
app = QApplication(sys.argv)
app.setStyleSheet('''
QWidget {
font-size: 17px;
}
''')
myApp = MyApp()
myApp.show()
try:
sys.exit(app.exec())
except SystemExit:
print('Closing Window...')
====================
pay18.py--------------------
# from operator import index
# from unittest import result
# from xml.dom.minidom import Document
from PyQt5.QtWidgets import QApplication, QWidget, QTableWidget, QTableWidgetItem, QPushButton, \
QHeaderView, QHBoxLayout, QVBoxLayout, QGridLayout, QAbstractScrollArea, QLabel, QListWidget, \
QFileDialog, QMessageBox, QTextEdit, QAbstractItemView, QLineEdit, QGroupBox, QRadioButton
from PyQt5.QtCore import Qt
# from PyQt5 import QtGui
from PyQt5.QtGui import QTextCursor
import sys
import pandas as pd # pip install pandas
import os
import io
import secret
import xlwings as xw
import re
import smtplib
from email.encoders import encode_base64
from email.header import Header
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText # 메일의 본문 내용을 만드는 모듈 내용을 base64형식으로 변환
from email.utils import formatdate
from email.mime.application import MIMEApplication # 메일의 첨부 파일을 base64 형식으로 변환
from email.mime.image import MIMEImage # 메일의 이미지 파일을 base64 형식으로 변환
# 출처: https://nowonbun.tistory.com/684 [명월 일지:티스토리]
from email import encoders
from email.encoders import encode_base64
class MyApp(QWidget):
def __init__(self):
super().__init__()
self.window_width, self.window_height = 1150, 600
self.resize(self.window_width, self.window_height)
self.setWindowTitle('pay')
# self.server = smtplib.SMTP_SSL('smtp.kakao.com')
# self.server.login(secret.kakao_id, secret.kakao_pw)
# self.msg_from = 'miero@kakao.com'
##### layout_main #####
layout_main = QHBoxLayout()
self.setLayout(layout_main)
##### layout_1 #####
layout_1 = QVBoxLayout()
vBox11 = QVBoxLayout()
groupBoxLogin11 = QGroupBox("로그인 정보")
groupBoxLogin11.setLayout(vBox11)
layout_1.addWidget(groupBoxLogin11)
self.label11 = QLabel("이메일계정")
vBox11.addWidget(self.label11)
self.lineedit11 = QLineEdit("miero@kakao.com")
vBox11.addWidget(self.lineedit11)
self.label12 = QLabel("패스워드")
vBox11.addWidget(self.label12)
self.lineedit12 = QLineEdit()
self.lineedit12.setEchoMode(QLineEdit.Password)
# self.lineedit12.show()
vBox11.addWidget(self.lineedit12)
label13 = QLabel('직원 메일')
# self.button = QPushButton('&Load Data')
# self.button.clicked.connect(lambda _, xl_path=excel_file_path, sheet_name=worksheet_name: self.loadExcelData(xl_path, sheet_name))
# layout_v.addWidget(self.button)
layout_1.addWidget(label13)
self.table = QTableWidget()
self.table.setFixedWidth(350)
layout_1.addWidget(self.table)
layout_main.addLayout(layout_1)
##### layout_2 #####
layout_2 = QGridLayout()
label21 = QLabel('이메일 제목')
layout_2.addWidget(label21, 0, 0)
self.lineedit21 = QLineEdit()
layout_2.addWidget(self.lineedit21, 1, 0, 1, 2)
label22 = QLabel('첨부파일')
layout_2.addWidget(label22, 2, 0)
self.listwidget22 = QListWidget()
# self.listwidget22.setFixedWidth(300)
self.listwidget22.setMinimumWidth(400)
# self.listwidget22.setSelectionMode(QAbstractItemView.ExtendedSelection)
layout_2.addWidget(self.listwidget22, 3, 0, 3, 1)
self.btn_file_add = QPushButton('파일 추가') # sendlist
# self.btn_file_add.setMinimumHeight(80)
layout_2.addWidget(self.btn_file_add, 3, 1, 1, 1)
self.btn_file_add.clicked.connect(self.fn_fileadd)
self.btn_file_del = QPushButton('파일 삭제')
layout_2.addWidget(self.btn_file_del, 4, 1, 1, 1)
self.btn_file_del.clicked.connect(self.fn_filedel)
# label21 = QLabel('본문 (HTML형식)')
# layout_2.addWidget(label21, 8, 0)
# radio_1 ~ 4 버튼을 그룹으로 설정
groupBoxMid = QGroupBox("테스트 메일 보내기")
layout_2.addWidget(groupBoxMid, 6, 0, 1, 2)
hBox1 = QHBoxLayout()
groupBoxMid.setLayout(hBox1)
self.label23 = QLabel("성명")
hBox1.addWidget(self.label23)
self.lineedit23 = QLineEdit("정용만") # 이름기본값
hBox1.addWidget(self.lineedit23)
self.pushbutton23 = QPushButton("테스트 보내기")
self.pushbutton23.clicked.connect(self.fn_test)
hBox1.addWidget(self.pushbutton23)
groupBoxBottom = QGroupBox("본문 보기형식 선택")
layout_2.addWidget(groupBoxBottom, 7, 0, 1, 2)
hBox2 = QHBoxLayout()
groupBoxBottom.setLayout(hBox2)
self.radioBtn1 = QRadioButton("HTML")
self.radioBtn1.setChecked(True)
self.radioBtn1.clicked.connect(self.fn_radio_select)
hBox2.addWidget(self.radioBtn1)
self.radioBtn2 = QRadioButton("미리보기")
self.radioBtn2.clicked.connect(self.fn_radio_select)
hBox2.addWidget(self.radioBtn2)
self.textedit23 = QTextEdit()
# self.textedit23.setFixedWidth(400)
# self.textedit23.setAcceptRichText(False)
layout_2.addWidget(self.textedit23, 8, 0, 4, 1)
self.textedit23.show()
self.textedit24 = QTextEdit()
layout_2.addWidget(self.textedit24, 8, 0, 4, 1)
self.textedit24.hide()
self.btn_send = QPushButton("보내기")
self.btn_send.setMaximumHeight(500) # gridlayout button size
layout_2.addWidget(self.btn_send, 8, 1, 4, 1)
self.btn_send.clicked.connect(self.fn_run) #@@@@@@@@@@@@@@@@@@@@@@@@@@
layout_main.addLayout(layout_2)
##### layout_3 #####
layout_3 = QVBoxLayout()
label31 = QLabel('발송 결과')
layout_3.addWidget(label31)
self.listwidget32 = QListWidget()
# self.listwidget32.setMinimumWidth(self.listwidget32.sizeHintForColumn(0))
# self.listwidget32.setWidth(10)
layout_3.addWidget(self.listwidget32)
layout_main.addLayout(layout_3)
# subject0 파일이 존재하면
filename_subject = 'subject0.txt'
if os.path.isfile(filename_subject) == True:
source_text = open(filename_subject,'r', encoding="UTF-8").read()
# self.lineedit21.setText(source_text) # TextEdit에 RichText 형식의 글을 입력합니다.
self.lineedit21.setText(source_text) # TextEdit에 PlainText 형식의 글을 새로 입력합니다.
# html0 파일이 존재하면
filename_html = 'html0.txt'
if os.path.isfile(filename_html) == True:
source_text = open(filename_html,'r', encoding="UTF-8").read()
# self.textedit23.setText(source_text) # TextEdit에 RichText 형식의 글을 입력합니다.
self.textedit23.setPlainText(source_text) # TextEdit에 PlainText 형식의 글을 새로 입력합니다.
# self.textedit24.setHtml(source_text) # TextEdit에 PlainText 형식의 글을 새로 입력합니다.
# table_data = self.loadExcelData(excel_file_path, worksheet_name)
# print(table_data.keys())
df_table = self.loadExcelData(excel_file_path, worksheet_name)
# print(table_df["성명"][0])
self.df_table_02 = df_table.set_index("성명")
self.idx_name_list = self.df_table_02.index.to_list()
# print(index)
# for i in table_02["이메일"]:
def fn_radio_select(self):
# QRadioButton1 클릭 여부 표시
if self.radioBtn1.isChecked():
self.textedit23.show()
self.textedit24.hide()
self.hidden = False
# self.btn_send.setText('보내기')
elif self.radioBtn2.isChecked():
self.fn_html_save()
self.textedit23.hide()
self.textedit24.show()
self.hidden = True
# self.btn_send.setText('미리보기')
def loadExcelData(self, excel_file_dir, worksheet_name):
df_work_sheet = pd.read_excel(excel_file_path, worksheet_name)
df_email_sheet = pd.read_excel(excel_file_path, emailsheet_name)
df_table = df_work_sheet.merge(df_email_sheet, how='left')
df_table_mail = df_table[['성명','이메일']]
res = df_table_mail
# res = df_table_mail.to_dict()
# self.table.setRowCount(df.shape[0])
# self.table.setColumnCount(df.shape[1])
self.table.setRowCount(df_table_mail.shape[0])
self.table.setColumnCount(df_table_mail.shape[1])
# self.table.setHorizontalHeaderLabels(df.columns)
self.table.setHorizontalHeaderLabels(df_table_mail.columns)
header = self.table.horizontalHeader()
# header.setSectionResizeMode(0, QHeaderView.Stretch)
# header.setSectionResizeMode(0, QHeaderView.ResizeToContents)
header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
# returns pandas array object
# for row in df.iterrows():
for row in df_table_mail.iterrows():
values = row[1]
for col_index, value in enumerate(values):
if isinstance(value, (float, int)):
value = '{0:0,.0f}'.format(value)
tableItem = QTableWidgetItem(str(value))
if value == "nan":
tableItem.setBackground(Qt.red)
self.table.setItem(row[0], col_index, tableItem)
self.table.setColumnWidth(2, 310)
return res
def fn_fileadd(self):
# f_name = QFileDialog.getOpenFileName(None, '열기', '', "All Files(*.*)")
f_names = QFileDialog.getOpenFileNames(None, '열기', '', "All Files(*.*)")
# txtPath = f_name[0]
filelist = f_names[0]
if filelist:
for f_name in filelist:
# ext = os.path.splitext(f_name[0])[1]
ext = os.path.splitext(f_name)[1] # 확장자 확인
# if f_names[0]:
icnt = 0
for i in range(self.listwidget22.count()):
# if str(self.listwidget22.item(i).text()) == txtPath.replace("/","\\") or str(self.listwidget22.item(i).text()) == txtPath:
if str(self.listwidget22.item(i).text()) == f_name.replace("/","\\") or str(self.listwidget22.item(i).text()) == f_name:
icnt = 1
break
if icnt != 1:
f_path = f_name
if ext == '.exe':
QMessageBox.about(self,'파일 형식 확인','exe파일은 전송할 수 없습니다.')
pass
else:
cnt = self.listwidget22.count() +1
# self.listwidget22.insertItem(cnt, os.path.basename(txtPath))
# self.listwidget22.insertItem(cnt, txtPath)
# f_path = f_names[0]
# print(f_path)
self.listwidget22.insertItem(cnt, f_path)
# self.listwidget22.insertItem(cnt, f_path.replace("/","\\"))
def fn_filedel(self):
currentrow = self.listwidget22.currentRow()
self.listwidget22.takeItem(currentrow) # currentrowRight번째 항목을 삭제합니다
self.listwidget22.clearSelection()
def fn_subject_save(self):
if len(self.lineedit21.text())>0:
S__File = os.path.join(os.getcwd(),'subject0.txt')
Text = self.lineedit21.text()
if S__File:
# Finally this will Save your file to the path selected.
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
file.write(Text)
def fn_html_save(self):
if len(self.textedit23.toPlainText())>0:
# print(len(self.textedit.toPlainText()))
# S__File = QFileDialog.getSaveFileName(None,'문자 파일저장','/', "Text Files (*.txt)")
# S__File = QFileDialog.getSaveFileName(None,'문자 파일저장','html0', "Text Files (*.txt)")
S__File = os.path.join(os.getcwd(),'html0.txt')
# This will let you access the test in your QTextEdit
Text = self.textedit23.toPlainText()
self.textedit24.setHtml(Text)
# document = self.textedit23.document()
# cursor = QTextCursor(document)
# p1 = cursor.position() # return int
# cursor.insertImage(r"C:\Users\newstep\Pictures\number1.jpg")
# This will prevent you from an error if pressed cancel on file dialog.
# if S__File[0]:
if S__File:
# Finally this will Save your file to the path selected.
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
file.write(Text)
# txtPath = S__File[0]
# icnt = 0
# for i in range(self.listwidget31.count()):
# if str(self.listwidget31.item(i).text()) == txtPath.replace("/","\\"):
# icnt = 1
# break
# if icnt != 1:
# cnt = self.listwidget31.count() +1
# self.listwidget31.insertItem(cnt, os.path.basename(txtPath))
# self.listwidget31.insertItem(cnt, txtPath)
else:
QMessageBox.about(self,'메시지 입력 확인','메시지를 입력하셔야 합니다.')
def fn_print_name(self, name, email):
# f_name_pre = r"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' width='50%' height='0%'></center>"
# f_name = f_name_pre.replace("\\","/")
# with io.open('file_name.html','r') as f:
# with io.open(f_name,'r') as f:
# # emailtext = f.read()
# emailtext = f_name
# attachment = 'attachment_file_name.png'
# attachment = f_name
# print(name, self.df_table_02.loc[name][0])
# print(name, email)
if len(self.textedit23.toPlainText())>0:
S__File = os.path.join(os.getcwd(),'html0.txt')
# print(len(self.textedit23.toPlainText()))
# print(S__File)
# pretext = f'{name} 님<br/><br/>'
# pretext += f'당신의 이메일은 {email} 입니다.<br/>'
contents = self.textedit23.toPlainText()
# nexttext = f'<br/><img src="cid:{attachment}" >'
# nexttext = f"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' id='millstudio logo' width='10%' height='0%'></center>"
# document = self.textedit23.document()
# cursor = QTextCursor(document)
# p1 = cursor.position() # return int
# cursor.insertImage(f_name)
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
# file.write(pretext)
file.write(contents)
# file.write(nexttext)
# print(contents)
# msgText = MIMEText(contents, 'html')
print(name, email, "전송완료")
# self.fn_result_window(name, email)
def fn_DeleteAllFiles(self,filePath):
if os.path.exists(filePath):
for file in os.scandir(filePath):
os.remove(file.path)
return '폴더 내 모든 파일 지우기 완료'
else:
return '폴더가 없습니다.'
def fn_pdf_create(self, idx_name):
#####################################
# xlwings
self.current_pdf_path = os.getcwd()+"\pdf"
fname = "급여1.xlsx"
# for n in self.target_name_list:
name = idx_name
df_data = pd.read_excel(fname, sheet_name='4대급여')
df_data = df_data.fillna(0)
df_employee = pd.read_excel(fname, sheet_name='직원현황')
idx_df_data = df_data.index[df_data['성명']==name].tolist()[0]
# print("4대급여 인덱스 :",idx_df_data)
normal = df_data.loc[idx_df_data,['기본급']][0]
overtime = df_data.loc[idx_df_data,['연장수당']][0]
holiday = df_data.loc[idx_df_data,['휴일수당']][0]
holidayovertime = df_data.loc[idx_df_data,['휴일연장수당']][0]
extra = df_data.loc[idx_df_data,['추가수당']][0]
meals = df_data.loc[idx_df_data,['식대']][0]
bonus = df_data.loc[idx_df_data,['상여금']][0]
normal_calculation = df_data.loc[idx_df_data,['기']][0]
overtime_calculation = df_data.loc[idx_df_data,['연']][0]
holiday_calculation = df_data.loc[idx_df_data,['휴']][0]
holidayovertime_calculation = df_data.loc[idx_df_data,['휴연']][0]
extra_calculation = df_data.loc[idx_df_data,['추']][0]
nationalpension = df_data.loc[idx_df_data,['국민연금']][0]
healthinsurance = df_data.loc[idx_df_data,['건강보험']][0]
longtermcareinsurance = df_data.loc[idx_df_data,['장기요양보험']][0]
employmentinsurance = df_data.loc[idx_df_data,['고용보험']][0]
healthsettlement = df_data.loc[idx_df_data,['정산건강']][0]
longtermcaresettlement = df_data.loc[idx_df_data,['정산장기요양']][0]
advancepayment = df_data.loc[idx_df_data,['선지급']][0]
etc = df_data.loc[idx_df_data,['기타']][0]
incometax = df_data.loc[idx_df_data,['소득세']][0]
localincometax = df_data.loc[idx_df_data,['지방소득세']][0]
idx_df_employee = df_employee.index[df_employee['성명']==name].tolist()[0]
# print("직원현황 인덱스 :",idx_df_employee)
jobposition = df_employee.loc[idx_df_employee,['직위']][0]
department = df_employee.loc[idx_df_employee,['부서']][0]
birthday = df_employee.loc[idx_df_employee,['생일']][0]
# 엑셀 인스턴스 생성
app = xw.App(visible=False)
book = xw.Book(fname)
sh_paystub = book.sheets('급여명세서사대보험')
sh_paystub["B4"].value = name
sh_paystub["D4"].value = jobposition
sh_paystub["B5"].value = department
sh_paystub["D5"].value = birthday
sh_paystub["B8"].value = normal
sh_paystub["B9"].value = overtime
sh_paystub["B10"].value = holiday
sh_paystub["B11"].value = holidayovertime
sh_paystub["B12"].value = extra
sh_paystub["B13"].value = meals
sh_paystub["D8"].value = nationalpension
sh_paystub["D9"].value = healthinsurance
sh_paystub["D10"].value = longtermcareinsurance
sh_paystub["D11"].value = employmentinsurance
sh_paystub["D12"].value = healthsettlement
sh_paystub["D13"].value = longtermcaresettlement
sh_paystub["D14"].value = advancepayment
sh_paystub["D15"].value = etc
sh_paystub["D16"].value = incometax
sh_paystub["D17"].value = localincometax
sh_paystub["B23"].value = normal_calculation
sh_paystub["B24"].value = overtime_calculation
sh_paystub["B25"].value = holiday_calculation
sh_paystub["B26"].value = holidayovertime_calculation
sh_paystub["B27"].value = extra_calculation
sh_paystub["D23"].value = normal
sh_paystub["D24"].value = overtime
sh_paystub["D25"].value = holiday
sh_paystub["D26"].value = holidayovertime
sh_paystub["D27"].value = extra
# rng = sh_paystub.range("D35")
# sh_paystub.pictures.add(r'B:\python\vscode\excel\millstudio_logo.png', left=rng.left, top=rng.top)
if len(self.lineedit21.text())==0:
book.save()
# app.kill()
return
# print(len(self.lineedit21.text()))
# pdf 로 저장하기
# current_path = os.getcwd() # 현재 작업중인 폴더에 저장하기
# 절대경로로 파일 위치 입력
subject_before = self.lineedit21.text()
# 문자치환 f-string 사용하여 변수 적용하기
subject = subject_before.replace("{성명}",f'{name}')
pdf_file = os.path.join(self.current_pdf_path, f"{subject}.pdf")
# PDF 로 저장할 시트 선택하기(본 예제에서는 첫 번째 시트 선택하기)
# report_sheet = book.sheets[1]
report_sheet = sh_paystub
# PDF 로 저장하기
# report_sheet.ExportAsFixedFormat(0, pdf_path)
report_sheet.api.ExportAsFixedFormat(0, pdf_file)
book.save()
# app.kill()
#####################################
def fn_send(self, name, email_i):
# # 메일 서버를 설정합니다.
account_id = self.lineedit11.text().split("@")[0]
emailserver = self.lineedit11.text().split("@")[1]
# self.server = smtplib.SMTP_SSL('smtp.kakao.com')
smtp_server = 'smtp.'+ emailserver
# print(account_id)
self.server = smtplib.SMTP_SSL(smtp_server)
# self.server.login(secret.kakao_id, secret.kakao_pw)
self.server.login(account_id, self.lineedit12.text())
# self.msg_from = 'miero@kakao.com'
self.msg_from = self.lineedit11.text()
# # server = smtplib.SMTP('smtp.com', port_number)
# # server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# server = smtplib.SMTP_SSL('smtp.kakao.com')
# # server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# # 로그인이 필요하면 로그인 설정
# server.login(secret.kakao_id, secret.kakao_pw)
# # 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
# msg_to = email_i
# cc = 'b@b.com, c@c.com'
# cc = ''
# print(name,email_i)
# 메세지 구성
# msg = MIMEBase('multipart','mixed')
msg = MIMEMultipart()
msg['From'] = self.msg_from
msg['To'] = email_i
msg['Date'] = formatdate(localtime=True)
# msg['Subject'] = f'2022년08월급여명세서-{name}'
subject_before = self.lineedit21.text()
# 문자치환 f-string 사용하여 변수 적용하기
subject = subject_before.replace("{성명}",f'{name}')
msg['Subject'] = Header(s=subject, charset='utf-8')
# msg['Subject'] = Header(s=f'2022년08월급여명세서-{name}', charset='utf-8')
# msg['Cc'] = ""
# 메일 본문 작성
# # html 로 되어있던 파일을 불러 오고 거기에 파일을 붙여서 보냅니다.
# msgText = MIMEText('<h1>%s</h1><hr>, <img src="cid:%s" >' % (emailtext, attachment), 'html')
# contents = '<h1>%s</h1>'
# contents += '<hr>'
# contents += '<img src="cid:%s" >'
# msgText = MIMEText(contents % (emailtext, attachment), 'html')
# contents = f'<h1>{emailtext}</h1>'
# contents += f'<h2>{msg_to} 님 메일이 도착했습니다.</h2>'
# contents += '<hr>'
# contents += f'<img src="cid:{attachment}" >'
# msgText = MIMEText(contents, 'html')
# pretext = f'수신: {name}<br/>'
# pretext += '발신: 주식회사 밀앤아이, 주식회사 헴펠 대표이사<br/>'
# pretext += '<br/>'
# msgpreText = MIMEText(pretext, 'html')
# msg.attach(msgpreText)
# contents = self.textedit23.toPlainText()
contents_before = self.textedit23.toPlainText()
# 문자치환 f-string 사용하여 변수 적용하기
contents = contents_before.replace("{성명}",f'수신: {name}')
# msgText = MIMEText(contents, 'plain')
msgText = MIMEText(contents, 'html')
# msgText = MIMEText(contents, _charset='utf-8')
# 메세지를 메일에 붙여 줍니다.
msg.attach(msgText)
# 메일 제일 밑에 로고그림 붙여 줍니다.
# logo_file = "logo.jpg"
# img_f_name = logo_file.replace("\\","/")
# logo_file = r"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' width='10%' height='0%'></center>"
# img_f_name = logo_file.replace("\\","/")
# # with io.open('file_name.html','r') as f:
# with io.open(img_f_name,'r') as f:
# # emailtext = f.read()
# emailtext = img_f_name
# # attachment = 'attachment_file_name.png'
# attachment = img_f_name
# attachment = logo_file
# fp = open(attachment, 'rb')
# img = MIMEImage(fp.read())
# fp.close()
# img.add_header('Content-ID', '<{}>'.format(attachment))
# msg.attach(img)
# 파일첨부
files = list()
pdf_file_name = f"{subject}.pdf"
pdf_file = os.path.join(os.getcwd()+"\pdf", pdf_file_name)
files.append(pdf_file)
# if os.path.isfile(pdf_file):
# binary_pdf = open(pdf_file, 'rb')
# payload = MIMEBase('application', 'octate-stream', Name=pdf_file_name)
# payload.set_payload((binary_pdf).read())
# encoders.encode_base64(payload)
# payload.add_header('Content-Decomposition', 'attachment', filename=pdf_file_name)
# msg.attach(payload)
for i in range(self.listwidget22.count()):
files.append(self.listwidget22.item(i).text())
# print(files)
for f in files:
# print(f)
part = MIMEBase('application', "octet-stream")
part.set_payload(open(f,"rb").read())
encoders.encode_base64(part)
fstr_name = os.path.basename(f)
# part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(f))
part.add_header('Content-Disposition',"attachment", filename= fstr_name, charset='utf-8')
# [출처] 파이썬에서 지메일 보내기(w/첨부파일) 한글파일도 가능|작성자 데이터공방
# Header(s=f'2022년08월급여명세서-{name}', charset='utf-8')
msg.attach(part)
# 메일 서버를 이용하여 메일을 발송합니다.
# server.sendmail(msg_from, msg["To"].split(",") + msg["Cc"].split(","), msg.as_string())
self.server.sendmail(msg['From'], msg['To'], msg.as_string())
# self.server.quit()
def fn_result_window(self, name, email):
self.listwidget32.clear()
cnt = self.listwidget32.count() +1
# print(cnt, name, email, "전송완료")
# self.listwidget32.insertItem(cnt,name&email&"전송완료")
self.listwidget32.insertItem(cnt, f'{name}-{email}-전송완료')
def fn_test(self):
# try:
# 메일 서버를 설정합니다.
# server = smtplib.SMTP('smtp.com', port_number)
# server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# self.server = smtplib.SMTP_SSL('smtp.kakao.com')
# server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# 로그인이 필요하면 로그인 설정
# self.server.login(secret.kakao_id, secret.kakao_pw)
# 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
self.listwidget32.clear()
if len(self.lineedit11.text()) == 0:
QMessageBox.about(self,'이메일계정 확인','이메일계정을 입력하십시요.')
return
p = re.compile('^[a-zA-Z0-9+-_.]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$')
if p.match(self.lineedit11.text()) == None:
# print(p.match(self.lineedit11.text()) != None)
QMessageBox.about(self,'이메일 형식 확인','올바른 이메일 형식이 아닙니다.')
return
if len(self.lineedit12.text()) == 0:
QMessageBox.about(self,'비밀번호 확인','비밀번호를 입력하십시요.')
return
cnt = 0
if len(self.lineedit21.text()) == 0:
QMessageBox.about(self,'제목 입력 확인','제목을 입력하십시요.')
return
self.fn_subject_save()
self.fn_html_save()
self.fn_DeleteAllFiles(os.getcwd()+"\pdf")
self.fn_pdf_create(self.lineedit23.text())
try:
if self.df_table_02.loc[self.lineedit23.text()][0] != "nan":
self.fn_send(self.lineedit23.text(), self.df_table_02.loc[self.lineedit23.text()][0])
cnt += 1
self.listwidget32.insertItem(cnt, f'{self.lineedit23.text()}-{self.df_table_02.loc[self.lineedit23.text()][0]}-전송완료')
except:
cnt += 1
self.listwidget32.insertItem(cnt, f'{self.lineedit23.text()}-{self.df_table_02.loc[self.lineedit23.text()][0]}-실패')
self.listwidget32.item(cnt-1).setBackground(Qt.red)
# self.fn_pdf_create("밀1")
# self.fn_send(self.lineedit23.text(), self.df_table_02.loc[self.lineedit23.text()][0])
# cnt += 1
# self.listwidget32.insertItem(cnt, f'{self.lineedit23.text()}-{self.df_table_02.loc[self.lineedit23.text()][0]}-전송완료')
self.server.quit()
# self.fn_print_name(self.lineedit23.text(), self.df_table_02.loc[self.lineedit23.text()][0])
# except: # 예외가 발생했을 때 실행됨
# print('예외가 발생했습니다.')
# self.listwidget32.insertItem(cnt, f'{"밀1"}-{self.df_table_02.loc["밀1"][0]}-실패')
def fn_run(self):
# 메일 서버를 설정합니다.
# server = smtplib.SMTP('smtp.com', port_number)
# server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# server = smtplib.SMTP_SSL('smtp.kakao.com')
# server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# 로그인이 필요하면 로그인 설정
# server.login(secret.kakao_id, secret.kakao_pw)
# 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
self.listwidget32.clear()
if len(self.lineedit11.text()) == 0:
QMessageBox.about(self,'이메일계정 확인','이메일계정을 입력하십시요.')
return
p = re.compile('^[a-zA-Z0-9+-_.]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$')
if p.match(self.lineedit11.text()) == None:
# print(p.match(self.lineedit11.text()) != None)
QMessageBox.about(self,'이메일 형식 확인','올바른 이메일 형식이 아닙니다.')
return
if len(self.lineedit12.text()) == 0:
QMessageBox.about(self,'비밀번호 확인','비밀번호를 입력하십시요.')
return
cnt = 0
if len(self.lineedit21.text()) == 0:
QMessageBox.about(self,'제목 입력 확인','제목을 입력하십시요.')
return
self.fn_subject_save()
self.fn_html_save()
# self.fn_send("밀1", self.df_table_02.loc["밀1"][0])
# self.fn_print_name("밀1", self.df_table_02.loc["밀1"][0])
for idx_name in self.idx_name_list:
# print(idx)
# print(self.df_table_02.loc[idx][0])
# print(idx, table_02.loc[idx][0])
self.fn_DeleteAllFiles(os.getcwd()+"\pdf")
self.fn_pdf_create(idx_name)
try:
if self.df_table_02.loc[idx_name][0] != "nan":
self.fn_send(idx_name, self.df_table_02.loc[idx_name][0])
cnt += 1
self.listwidget32.insertItem(cnt, f'{idx_name}-{self.df_table_02.loc[idx_name][0]}-전송완료')
except:
cnt += 1
self.listwidget32.insertItem(cnt, f'{idx_name}-{self.df_table_02.loc[idx_name][0]}-실패')
self.listwidget32.item(cnt-1).setBackground(Qt.red)
# if self.df_table_02.loc[idx_name][0] == "nan":
# print(self.listwidget32.)
# self.listwidget32.item(cnt).setBackground(Qt.red)
# print("예외가 발생했습니다.-fn_run",cnt,self.df_table_02.loc[idx_name][0])
# self.fn_print_name(idx_name, self.df_table_02.loc[idx_name][0])
self.server.quit()
# print('예외가 발생했습니다.')
# self.listwidget32.insertItem(cnt, f'{idx_name}-{self.df_table_02.loc[idx_name][0]}-실패')
if __name__ == '__main__':
# don't auto scale when drag app to a different monitor.
# QGuiApplication.setHighDpiScaleFactorRoundingPolicy(Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
excel_file_path = '급여1.xlsx'
worksheet_name = '4대급여'
emailsheet_name = '이메일'
app = QApplication(sys.argv)
app.setStyleSheet('''
QWidget {
font-size: 17px;
}
''')
myApp = MyApp()
myApp.show()
try:
sys.exit(app.exec())
except SystemExit:
print('Closing Window...')
====================
pay19.py--------------------
# from operator import index
# from unittest import result
# from xml.dom.minidom import Document
from PyQt5.QtWidgets import QApplication, QWidget, QTableWidget, QTableWidgetItem, QPushButton, \
QHeaderView, QHBoxLayout, QVBoxLayout, QGridLayout, QAbstractScrollArea, QLabel, QListWidget, \
QFileDialog, QMessageBox, QTextEdit, QAbstractItemView, QLineEdit, QGroupBox, QRadioButton
from PyQt5.QtCore import Qt
# from PyQt5 import QtGui
from PyQt5.QtGui import QTextCursor
import sys
import pandas as pd # pip install pandas
import os
import io
import secret
import xlwings as xw
import re
import smtplib
from email.encoders import encode_base64
from email.header import Header
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText # 메일의 본문 내용을 만드는 모듈 내용을 base64형식으로 변환
from email.utils import formatdate
from email.mime.application import MIMEApplication # 메일의 첨부 파일을 base64 형식으로 변환
from email.mime.image import MIMEImage # 메일의 이미지 파일을 base64 형식으로 변환
# 출처: https://nowonbun.tistory.com/684 [명월 일지:티스토리]
from email import encoders
from email.encoders import encode_base64
class MyApp(QWidget):
def __init__(self):
super().__init__()
self.window_width, self.window_height = 1150, 600
self.resize(self.window_width, self.window_height)
self.setWindowTitle('pay')
# self.server = smtplib.SMTP_SSL('smtp.kakao.com')
# self.server.login(secret.kakao_id, secret.kakao_pw)
# self.msg_from = 'miero@kakao.com'
##### layout_main #####
layout_main = QHBoxLayout()
self.setLayout(layout_main)
##### layout_1 #####
layout_1 = QVBoxLayout()
vBox11 = QVBoxLayout()
groupBoxLogin11 = QGroupBox("로그인 정보")
groupBoxLogin11.setLayout(vBox11)
layout_1.addWidget(groupBoxLogin11)
self.label11 = QLabel("이메일계정")
vBox11.addWidget(self.label11)
self.lineedit11 = QLineEdit("miero@kakao.com")
vBox11.addWidget(self.lineedit11)
self.label12 = QLabel("패스워드")
vBox11.addWidget(self.label12)
self.lineedit12 = QLineEdit()
self.lineedit12.setEchoMode(QLineEdit.Password)
# self.lineedit12.show()
vBox11.addWidget(self.lineedit12)
label13 = QLabel('직원 메일')
# self.button = QPushButton('&Load Data')
# self.button.clicked.connect(lambda _, xl_path=excel_file_path, sheet_name=worksheet_name: self.loadExcelData(xl_path, sheet_name))
# layout_v.addWidget(self.button)
layout_1.addWidget(label13)
self.table = QTableWidget()
self.table.setFixedWidth(350)
layout_1.addWidget(self.table)
layout_main.addLayout(layout_1)
##### layout_2 #####
layout_2 = QGridLayout()
label21 = QLabel('이메일 제목')
layout_2.addWidget(label21, 0, 0)
self.lineedit21 = QLineEdit()
layout_2.addWidget(self.lineedit21, 1, 0, 1, 2)
label22 = QLabel('첨부파일')
layout_2.addWidget(label22, 2, 0)
self.listwidget22 = QListWidget()
# self.listwidget22.setFixedWidth(300)
self.listwidget22.setMinimumWidth(400)
# self.listwidget22.setSelectionMode(QAbstractItemView.ExtendedSelection)
layout_2.addWidget(self.listwidget22, 3, 0, 3, 1)
self.btn_file_add = QPushButton('파일 추가') # sendlist
# self.btn_file_add.setMinimumHeight(80)
layout_2.addWidget(self.btn_file_add, 3, 1, 1, 1)
self.btn_file_add.clicked.connect(self.fn_fileadd)
self.btn_file_del = QPushButton('파일 삭제')
layout_2.addWidget(self.btn_file_del, 4, 1, 1, 1)
self.btn_file_del.clicked.connect(self.fn_filedel)
# label21 = QLabel('본문 (HTML형식)')
# layout_2.addWidget(label21, 8, 0)
# radio_1 ~ 4 버튼을 그룹으로 설정
groupBoxMid = QGroupBox("테스트 메일 보내기")
layout_2.addWidget(groupBoxMid, 6, 0, 1, 2)
hBox1 = QHBoxLayout()
groupBoxMid.setLayout(hBox1)
self.label23 = QLabel("성명")
hBox1.addWidget(self.label23)
self.lineedit23 = QLineEdit("정용만") # 이름기본값
hBox1.addWidget(self.lineedit23)
self.pushbutton23 = QPushButton("테스트 보내기")
self.pushbutton23.clicked.connect(self.fn_test)
hBox1.addWidget(self.pushbutton23)
groupBoxBottom = QGroupBox("본문 보기형식 선택")
layout_2.addWidget(groupBoxBottom, 7, 0, 1, 2)
hBox2 = QHBoxLayout()
groupBoxBottom.setLayout(hBox2)
self.radioBtn1 = QRadioButton("HTML")
self.radioBtn1.setChecked(True)
self.radioBtn1.clicked.connect(self.fn_radio_select)
hBox2.addWidget(self.radioBtn1)
self.radioBtn2 = QRadioButton("미리보기")
self.radioBtn2.clicked.connect(self.fn_radio_select)
hBox2.addWidget(self.radioBtn2)
self.textedit23 = QTextEdit()
# self.textedit23.setFixedWidth(400)
# self.textedit23.setAcceptRichText(False)
layout_2.addWidget(self.textedit23, 8, 0, 4, 1)
self.textedit23.show()
self.textedit24 = QTextEdit()
layout_2.addWidget(self.textedit24, 8, 0, 4, 1)
self.textedit24.hide()
self.btn_send = QPushButton("보내기")
self.btn_send.setMaximumHeight(500) # gridlayout button size
layout_2.addWidget(self.btn_send, 8, 1, 4, 1)
self.btn_send.clicked.connect(self.fn_run) #@@@@@@@@@@@@@@@@@@@@@@@@@@
layout_main.addLayout(layout_2)
##### layout_3 #####
layout_3 = QVBoxLayout()
label31 = QLabel('발송 결과')
layout_3.addWidget(label31)
self.listwidget32 = QListWidget()
# self.listwidget32.setMinimumWidth(self.listwidget32.sizeHintForColumn(0))
# self.listwidget32.setWidth(10)
layout_3.addWidget(self.listwidget32)
layout_main.addLayout(layout_3)
# subject0 파일이 존재하면
filename_subject = 'subject0.txt'
if os.path.isfile(filename_subject) == True:
source_text = open(filename_subject,'r', encoding="UTF-8").read()
# self.lineedit21.setText(source_text) # TextEdit에 RichText 형식의 글을 입력합니다.
self.lineedit21.setText(source_text) # TextEdit에 PlainText 형식의 글을 새로 입력합니다.
# html0 파일이 존재하면
filename_html = 'html0.txt'
if os.path.isfile(filename_html) == True:
source_text = open(filename_html,'r', encoding="UTF-8").read()
# self.textedit23.setText(source_text) # TextEdit에 RichText 형식의 글을 입력합니다.
self.textedit23.setPlainText(source_text) # TextEdit에 PlainText 형식의 글을 새로 입력합니다.
# self.textedit24.setHtml(source_text) # TextEdit에 PlainText 형식의 글을 새로 입력합니다.
# table_data = self.loadExcelData(excel_file_path, worksheet_name)
# print(table_data.keys())
df_table = self.loadExcelData(excel_file_path, worksheet_name)
# print(table_df["성명"][0])
self.df_table_02 = df_table.set_index("성명")
self.idx_name_list = self.df_table_02.index.to_list()
# print(index)
# for i in table_02["이메일"]:
def fn_radio_select(self):
# QRadioButton1 클릭 여부 표시
if self.radioBtn1.isChecked():
self.textedit23.show()
self.textedit24.hide()
self.hidden = False
# self.btn_send.setText('보내기')
elif self.radioBtn2.isChecked():
self.fn_html_save()
self.textedit23.hide()
self.textedit24.show()
self.hidden = True
# self.btn_send.setText('미리보기')
def loadExcelData(self, excel_file_dir, worksheet_name):
df_work_sheet = pd.read_excel(excel_file_path, worksheet_name)
df_email_sheet = pd.read_excel(excel_file_path, emailsheet_name)
df_table = df_work_sheet.merge(df_email_sheet, how='left')
df_table_mail = df_table[['성명','이메일']]
res = df_table_mail
# res = df_table_mail.to_dict()
# self.table.setRowCount(df.shape[0])
# self.table.setColumnCount(df.shape[1])
self.table.setRowCount(df_table_mail.shape[0])
self.table.setColumnCount(df_table_mail.shape[1])
# self.table.setHorizontalHeaderLabels(df.columns)
self.table.setHorizontalHeaderLabels(df_table_mail.columns)
header = self.table.horizontalHeader()
# header.setSectionResizeMode(0, QHeaderView.Stretch)
# header.setSectionResizeMode(0, QHeaderView.ResizeToContents)
header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
# returns pandas array object
# for row in df.iterrows():
for row in df_table_mail.iterrows():
values = row[1]
for col_index, value in enumerate(values):
if isinstance(value, (float, int)):
value = '{0:0,.0f}'.format(value)
tableItem = QTableWidgetItem(str(value))
if value == "nan":
tableItem.setBackground(Qt.red)
self.table.setItem(row[0], col_index, tableItem)
self.table.setColumnWidth(2, 310)
return res
def fn_fileadd(self):
# f_name = QFileDialog.getOpenFileName(None, '열기', '', "All Files(*.*)")
f_names = QFileDialog.getOpenFileNames(None, '열기', '', "All Files(*.*)")
# txtPath = f_name[0]
filelist = f_names[0]
if filelist:
for f_name in filelist:
# ext = os.path.splitext(f_name[0])[1]
ext = os.path.splitext(f_name)[1] # 확장자 확인
# if f_names[0]:
icnt = 0
for i in range(self.listwidget22.count()):
# if str(self.listwidget22.item(i).text()) == txtPath.replace("/","\\") or str(self.listwidget22.item(i).text()) == txtPath:
if str(self.listwidget22.item(i).text()) == f_name.replace("/","\\") or str(self.listwidget22.item(i).text()) == f_name:
icnt = 1
break
if icnt != 1:
f_path = f_name
if ext == '.exe':
QMessageBox.about(self,'파일 형식 확인','exe파일은 전송할 수 없습니다.')
pass
else:
cnt = self.listwidget22.count() +1
# self.listwidget22.insertItem(cnt, os.path.basename(txtPath))
# self.listwidget22.insertItem(cnt, txtPath)
# f_path = f_names[0]
# print(f_path)
self.listwidget22.insertItem(cnt, f_path)
# self.listwidget22.insertItem(cnt, f_path.replace("/","\\"))
def fn_filedel(self):
currentrow = self.listwidget22.currentRow()
self.listwidget22.takeItem(currentrow) # currentrowRight번째 항목을 삭제합니다
self.listwidget22.clearSelection()
def fn_subject_save(self):
if len(self.lineedit21.text())>0:
S__File = os.path.join(os.getcwd(),'subject0.txt')
Text = self.lineedit21.text()
if S__File:
# Finally this will Save your file to the path selected.
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
file.write(Text)
def fn_html_save(self):
if len(self.textedit23.toPlainText())>0:
# print(len(self.textedit.toPlainText()))
# S__File = QFileDialog.getSaveFileName(None,'문자 파일저장','/', "Text Files (*.txt)")
# S__File = QFileDialog.getSaveFileName(None,'문자 파일저장','html0', "Text Files (*.txt)")
S__File = os.path.join(os.getcwd(),'html0.txt')
# This will let you access the test in your QTextEdit
Text = self.textedit23.toPlainText()
self.textedit24.setHtml(Text)
# document = self.textedit23.document()
# cursor = QTextCursor(document)
# p1 = cursor.position() # return int
# cursor.insertImage(r"C:\Users\newstep\Pictures\number1.jpg")
# This will prevent you from an error if pressed cancel on file dialog.
# if S__File[0]:
if S__File:
# Finally this will Save your file to the path selected.
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
file.write(Text)
# txtPath = S__File[0]
# icnt = 0
# for i in range(self.listwidget31.count()):
# if str(self.listwidget31.item(i).text()) == txtPath.replace("/","\\"):
# icnt = 1
# break
# if icnt != 1:
# cnt = self.listwidget31.count() +1
# self.listwidget31.insertItem(cnt, os.path.basename(txtPath))
# self.listwidget31.insertItem(cnt, txtPath)
else:
QMessageBox.about(self,'메시지 입력 확인','메시지를 입력하셔야 합니다.')
def fn_print_name(self, name, email):
# f_name_pre = r"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' width='50%' height='0%'></center>"
# f_name = f_name_pre.replace("\\","/")
# with io.open('file_name.html','r') as f:
# with io.open(f_name,'r') as f:
# # emailtext = f.read()
# emailtext = f_name
# attachment = 'attachment_file_name.png'
# attachment = f_name
# print(name, self.df_table_02.loc[name][0])
# print(name, email)
if len(self.textedit23.toPlainText())>0:
S__File = os.path.join(os.getcwd(),'html0.txt')
# print(len(self.textedit23.toPlainText()))
# print(S__File)
# pretext = f'{name} 님<br/><br/>'
# pretext += f'당신의 이메일은 {email} 입니다.<br/>'
contents = self.textedit23.toPlainText()
# nexttext = f'<br/><img src="cid:{attachment}" >'
# nexttext = f"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' id='millstudio logo' width='10%' height='0%'></center>"
# document = self.textedit23.document()
# cursor = QTextCursor(document)
# p1 = cursor.position() # return int
# cursor.insertImage(f_name)
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
# file.write(pretext)
file.write(contents)
# file.write(nexttext)
# print(contents)
# msgText = MIMEText(contents, 'html')
print(name, email, "전송완료")
# self.fn_result_window(name, email)
def fn_DeleteAllFiles(self,filePath):
if os.path.exists(filePath):
for file in os.scandir(filePath):
os.remove(file.path)
return '폴더 내 모든 파일 지우기 완료'
else:
return '폴더가 없습니다.'
def fn_pdf_create(self, idx_name):
#####################################
# xlwings
self.current_pdf_path = os.getcwd()+"\pdf"
fname = "급여1.xlsx"
# for n in self.target_name_list:
name = idx_name
df_data = pd.read_excel(fname, sheet_name='4대급여')
df_data = df_data.fillna(0)
df_employee = pd.read_excel(fname, sheet_name='직원현황')
idx_df_data = df_data.index[df_data['성명']==name].tolist()[0]
# print("4대급여 인덱스 :",idx_df_data)
normal = df_data.loc[idx_df_data,['기본급']][0]
overtime = df_data.loc[idx_df_data,['연장수당']][0]
holiday = df_data.loc[idx_df_data,['휴일수당']][0]
holidayovertime = df_data.loc[idx_df_data,['휴일연장수당']][0]
extra = df_data.loc[idx_df_data,['추가수당']][0]
meals = df_data.loc[idx_df_data,['식대']][0]
bonus = df_data.loc[idx_df_data,['상여금']][0]
normal_calculation = df_data.loc[idx_df_data,['기']][0]
overtime_calculation = df_data.loc[idx_df_data,['연']][0]
holiday_calculation = df_data.loc[idx_df_data,['휴']][0]
holidayovertime_calculation = df_data.loc[idx_df_data,['휴연']][0]
extra_calculation = df_data.loc[idx_df_data,['추']][0]
nationalpension = df_data.loc[idx_df_data,['국민연금']][0]
healthinsurance = df_data.loc[idx_df_data,['건강보험']][0]
longtermcareinsurance = df_data.loc[idx_df_data,['장기요양보험']][0]
employmentinsurance = df_data.loc[idx_df_data,['고용보험']][0]
healthsettlement = df_data.loc[idx_df_data,['정산건강']][0]
longtermcaresettlement = df_data.loc[idx_df_data,['정산장기요양']][0]
advancepayment = df_data.loc[idx_df_data,['선지급']][0]
etc = df_data.loc[idx_df_data,['기타']][0]
incometax = df_data.loc[idx_df_data,['소득세']][0]
localincometax = df_data.loc[idx_df_data,['지방소득세']][0]
idx_df_employee = df_employee.index[df_employee['성명']==name].tolist()[0]
# print("직원현황 인덱스 :",idx_df_employee)
jobposition = df_employee.loc[idx_df_employee,['직위']][0]
department = df_employee.loc[idx_df_employee,['부서']][0]
birthday = df_employee.loc[idx_df_employee,['생일']][0]
# 엑셀 인스턴스 생성
app = xw.App(visible=False)
book = xw.Book(fname)
sh_paystub = book.sheets('급여명세서사대보험')
sh_paystub["B4"].value = name
sh_paystub["D4"].value = jobposition
sh_paystub["B5"].value = department
sh_paystub["D5"].value = birthday
sh_paystub["B8"].value = normal
sh_paystub["B9"].value = overtime
sh_paystub["B10"].value = holiday
sh_paystub["B11"].value = holidayovertime
sh_paystub["B12"].value = extra
sh_paystub["B13"].value = meals
sh_paystub["D8"].value = nationalpension
sh_paystub["D9"].value = healthinsurance
sh_paystub["D10"].value = longtermcareinsurance
sh_paystub["D11"].value = employmentinsurance
sh_paystub["D12"].value = healthsettlement
sh_paystub["D13"].value = longtermcaresettlement
sh_paystub["D14"].value = advancepayment
sh_paystub["D15"].value = etc
sh_paystub["D16"].value = incometax
sh_paystub["D17"].value = localincometax
sh_paystub["B23"].value = normal_calculation
sh_paystub["B24"].value = overtime_calculation
sh_paystub["B25"].value = holiday_calculation
sh_paystub["B26"].value = holidayovertime_calculation
sh_paystub["B27"].value = extra_calculation
sh_paystub["D23"].value = normal
sh_paystub["D24"].value = overtime
sh_paystub["D25"].value = holiday
sh_paystub["D26"].value = holidayovertime
sh_paystub["D27"].value = extra
# rng = sh_paystub.range("D35")
# sh_paystub.pictures.add(r'B:\python\vscode\excel\millstudio_logo.png', left=rng.left, top=rng.top)
if len(self.lineedit21.text())==0:
book.save()
# app.kill()
return
# print(len(self.lineedit21.text()))
# pdf 로 저장하기
# current_path = os.getcwd() # 현재 작업중인 폴더에 저장하기
# 절대경로로 파일 위치 입력
subject_before = self.lineedit21.text()
# 문자치환 f-string 사용하여 변수 적용하기
subject = subject_before.replace("{성명}",f'{name}')
pdf_file = os.path.join(self.current_pdf_path, f"{subject}.pdf")
# PDF 로 저장할 시트 선택하기(본 예제에서는 첫 번째 시트 선택하기)
# report_sheet = book.sheets[1]
report_sheet = sh_paystub
# PDF 로 저장하기
# report_sheet.ExportAsFixedFormat(0, pdf_path)
report_sheet.api.ExportAsFixedFormat(0, pdf_file)
book.save()
# app.kill()
#####################################
def fn_send(self, name, email_i):
# # 메일 서버를 설정합니다.
account_id = self.lineedit11.text().split("@")[0]
emailserver = self.lineedit11.text().split("@")[1]
# self.server = smtplib.SMTP_SSL('smtp.kakao.com')
smtp_server = 'smtp.'+ emailserver
# print(account_id)
self.server = smtplib.SMTP_SSL(smtp_server)
# self.server.login(secret.kakao_id, secret.kakao_pw)
self.server.login(account_id, self.lineedit12.text())
# self.msg_from = 'miero@kakao.com'
self.msg_from = self.lineedit11.text()
# # server = smtplib.SMTP('smtp.com', port_number)
# # server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# server = smtplib.SMTP_SSL('smtp.kakao.com')
# # server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# # 로그인이 필요하면 로그인 설정
# server.login(secret.kakao_id, secret.kakao_pw)
# # 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
# msg_to = email_i
# cc = 'b@b.com, c@c.com'
# cc = ''
# print(name,email_i)
# 메세지 구성
# msg = MIMEBase('multipart','mixed')
msg = MIMEMultipart()
msg['From'] = self.msg_from
msg['To'] = email_i
msg['Date'] = formatdate(localtime=True)
# msg['Subject'] = f'2022년08월급여명세서-{name}'
subject_before = self.lineedit21.text()
# 문자치환 f-string 사용하여 변수 적용하기
subject = subject_before.replace("{성명}",f'{name}')
msg['Subject'] = Header(s=subject, charset='utf-8')
# msg['Subject'] = Header(s=f'2022년08월급여명세서-{name}', charset='utf-8')
# msg['Cc'] = ""
# 메일 본문 작성
# # html 로 되어있던 파일을 불러 오고 거기에 파일을 붙여서 보냅니다.
# msgText = MIMEText('<h1>%s</h1><hr>, <img src="cid:%s" >' % (emailtext, attachment), 'html')
# contents = '<h1>%s</h1>'
# contents += '<hr>'
# contents += '<img src="cid:%s" >'
# msgText = MIMEText(contents % (emailtext, attachment), 'html')
# contents = f'<h1>{emailtext}</h1>'
# contents += f'<h2>{msg_to} 님 메일이 도착했습니다.</h2>'
# contents += '<hr>'
# contents += f'<img src="cid:{attachment}" >'
# msgText = MIMEText(contents, 'html')
# pretext = f'수신: {name}<br/>'
# pretext += '발신: 주식회사 밀앤아이, 주식회사 헴펠 대표이사<br/>'
# pretext += '<br/>'
# msgpreText = MIMEText(pretext, 'html')
# msg.attach(msgpreText)
# contents = self.textedit23.toPlainText()
contents_before = self.textedit23.toPlainText()
# 문자치환 f-string 사용하여 변수 적용하기
contents = contents_before.replace("{성명}",f'수신: {name}')
# msgText = MIMEText(contents, 'plain')
msgText = MIMEText(contents, 'html')
# msgText = MIMEText(contents, _charset='utf-8')
# 메세지를 메일에 붙여 줍니다.
msg.attach(msgText)
# 메일 제일 밑에 로고그림 붙여 줍니다.
# logo_file = "logo.jpg"
# img_f_name = logo_file.replace("\\","/")
# logo_file = r"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' width='10%' height='0%'></center>"
# img_f_name = logo_file.replace("\\","/")
# # with io.open('file_name.html','r') as f:
# with io.open(img_f_name,'r') as f:
# # emailtext = f.read()
# emailtext = img_f_name
# # attachment = 'attachment_file_name.png'
# attachment = img_f_name
# attachment = logo_file
# fp = open(attachment, 'rb')
# img = MIMEImage(fp.read())
# fp.close()
# img.add_header('Content-ID', '<{}>'.format(attachment))
# msg.attach(img)
# 파일첨부
files = list()
pdf_file_name = f"{subject}.pdf"
pdf_file = os.path.join(os.getcwd()+"\pdf", pdf_file_name)
files.append(pdf_file)
# if os.path.isfile(pdf_file):
# binary_pdf = open(pdf_file, 'rb')
# payload = MIMEBase('application', 'octate-stream', Name=pdf_file_name)
# payload.set_payload((binary_pdf).read())
# encoders.encode_base64(payload)
# payload.add_header('Content-Decomposition', 'attachment', filename=pdf_file_name)
# msg.attach(payload)
for i in range(self.listwidget22.count()):
files.append(self.listwidget22.item(i).text())
# print(files)
for f in files:
# print(f)
part = MIMEBase('application', "octet-stream")
part.set_payload(open(f,"rb").read())
encoders.encode_base64(part)
fstr_name = os.path.basename(f)
# part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(f))
part.add_header('Content-Disposition',"attachment", filename= fstr_name, charset='utf-8')
# [출처] 파이썬에서 지메일 보내기(w/첨부파일) 한글파일도 가능|작성자 데이터공방
# Header(s=f'2022년08월급여명세서-{name}', charset='utf-8')
msg.attach(part)
# 메일 서버를 이용하여 메일을 발송합니다.
# server.sendmail(msg_from, msg["To"].split(",") + msg["Cc"].split(","), msg.as_string())
self.server.sendmail(msg['From'], msg['To'], msg.as_string())
# self.server.quit()
# def fn_result_window(self, name, email):
# self.listwidget32.clear()
# cnt = self.listwidget32.count() +1
# # print(cnt, name, email, "전송완료")
# # self.listwidget32.insertItem(cnt,name&email&"전송완료")
# self.listwidget32.insertItem(cnt, f'{name}-{email}-전송완료')
def fn_test(self):
# try:
# 메일 서버를 설정합니다.
# server = smtplib.SMTP('smtp.com', port_number)
# server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# self.server = smtplib.SMTP_SSL('smtp.kakao.com')
# server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# 로그인이 필요하면 로그인 설정
# self.server.login(secret.kakao_id, secret.kakao_pw)
# 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
self.listwidget32.clear()
if len(self.lineedit11.text()) == 0:
QMessageBox.about(self,'이메일계정 확인','이메일계정을 입력하십시요.')
return
p = re.compile('^[a-zA-Z0-9+-_.]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$')
if p.match(self.lineedit11.text()) == None:
# print(p.match(self.lineedit11.text()) != None)
QMessageBox.about(self,'이메일 형식 확인','올바른 이메일 형식이 아닙니다.')
return
if len(self.lineedit12.text()) == 0:
QMessageBox.about(self,'비밀번호 확인','비밀번호를 입력하십시요.')
return
cnt = 0
if len(self.lineedit21.text()) == 0:
QMessageBox.about(self,'제목 입력 확인','제목을 입력하십시요.')
return
self.fn_subject_save()
self.fn_html_save()
self.fn_DeleteAllFiles(os.getcwd()+"\pdf")
self.fn_pdf_create(self.lineedit23.text())
try:
if self.df_table_02.loc[self.lineedit23.text()][0] != "nan":
self.fn_send(self.lineedit23.text(), self.df_table_02.loc[self.lineedit23.text()][0])
cnt += 1
# self.listwidget32.insertItem(cnt, f'{self.lineedit23.text()}-{self.df_table_02.loc[self.lineedit23.text()][0]}-전송완료')
self.listwidget32.addItem(f'{self.lineedit23.text()}-{self.df_table_02.loc[self.lineedit23.text()][0]}-전송완료')
except:
cnt += 1
# self.listwidget32.insertItem(cnt, f'{self.lineedit23.text()}-{self.df_table_02.loc[self.lineedit23.text()][0]}-실패')
# self.listwidget32.item(cnt-1).setBackground(Qt.red)
self.listwidget32.addItem(f'{self.lineedit23.text()}-{self.df_table_02.loc[self.lineedit23.text()][0]}-실패')
self.listwidget32.item(cnt-1).setBackground(Qt.red)
# self.fn_pdf_create("밀1")
# self.fn_send(self.lineedit23.text(), self.df_table_02.loc[self.lineedit23.text()][0])
# cnt += 1
# self.listwidget32.insertItem(cnt, f'{self.lineedit23.text()}-{self.df_table_02.loc[self.lineedit23.text()][0]}-전송완료')
self.server.quit()
# self.fn_print_name(self.lineedit23.text(), self.df_table_02.loc[self.lineedit23.text()][0])
# except: # 예외가 발생했을 때 실행됨
# print('예외가 발생했습니다.')
# self.listwidget32.insertItem(cnt, f'{"밀1"}-{self.df_table_02.loc["밀1"][0]}-실패')
def fn_run(self):
# 메일 서버를 설정합니다.
# server = smtplib.SMTP('smtp.com', port_number)
# server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# server = smtplib.SMTP_SSL('smtp.kakao.com')
# server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# 로그인이 필요하면 로그인 설정
# server.login(secret.kakao_id, secret.kakao_pw)
# 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
self.listwidget32.clear()
if len(self.lineedit11.text()) == 0:
QMessageBox.about(self,'이메일계정 확인','이메일계정을 입력하십시요.')
return
p = re.compile('^[a-zA-Z0-9+-_.]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$')
if p.match(self.lineedit11.text()) == None:
# print(p.match(self.lineedit11.text()) != None)
QMessageBox.about(self,'이메일 형식 확인','올바른 이메일 형식이 아닙니다.')
return
if len(self.lineedit12.text()) == 0:
QMessageBox.about(self,'비밀번호 확인','비밀번호를 입력하십시요.')
return
cnt = 0
if len(self.lineedit21.text()) == 0:
QMessageBox.about(self,'제목 입력 확인','제목을 입력하십시요.')
return
self.fn_subject_save()
self.fn_html_save()
# self.fn_send("밀1", self.df_table_02.loc["밀1"][0])
# self.fn_print_name("밀1", self.df_table_02.loc["밀1"][0])
for idx_name in self.idx_name_list:
# print(idx)
# print(self.df_table_02.loc[idx][0])
# print(idx, table_02.loc[idx][0])
self.fn_DeleteAllFiles(os.getcwd()+"\pdf")
self.fn_pdf_create(idx_name)
try:
if self.df_table_02.loc[idx_name][0] != "nan":
self.fn_send(idx_name, self.df_table_02.loc[idx_name][0])
cnt += 1
self.listwidget32.insertItem(cnt, f'{idx_name}-{self.df_table_02.loc[idx_name][0]}-전송완료')
except:
cnt += 1
self.listwidget32.insertItem(cnt, f'{idx_name}-{self.df_table_02.loc[idx_name][0]}-실패')
self.listwidget32.item(cnt-1).setBackground(Qt.red)
# if self.df_table_02.loc[idx_name][0] == "nan":
# print(self.listwidget32.)
# self.listwidget32.item(cnt).setBackground(Qt.red)
# print("예외가 발생했습니다.-fn_run",cnt,self.df_table_02.loc[idx_name][0])
# self.fn_print_name(idx_name, self.df_table_02.loc[idx_name][0])
self.server.quit()
# print('예외가 발생했습니다.')
# self.listwidget32.insertItem(cnt, f'{idx_name}-{self.df_table_02.loc[idx_name][0]}-실패')
if __name__ == '__main__':
# don't auto scale when drag app to a different monitor.
# QGuiApplication.setHighDpiScaleFactorRoundingPolicy(Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
excel_file_path = '급여1.xlsx'
worksheet_name = '4대급여'
emailsheet_name = '이메일'
app = QApplication(sys.argv)
app.setStyleSheet('''
QWidget {
font-size: 17px;
}
''')
myApp = MyApp()
myApp.show()
try:
sys.exit(app.exec())
except SystemExit:
print('Closing Window...')
====================
pay20.py--------------------
# from operator import index
# from unittest import result
# from xml.dom.minidom import Document
from PyQt5.QtWidgets import QApplication, QWidget, QTableWidget, QTableWidgetItem, QPushButton, \
QHeaderView, QHBoxLayout, QVBoxLayout, QGridLayout, QAbstractScrollArea, QLabel, QListWidget, \
QFileDialog, QMessageBox, QTextEdit, QAbstractItemView, QLineEdit, QGroupBox, QRadioButton
from PyQt5.QtCore import Qt
# from PyQt5 import QtGui
from PyQt5.QtGui import QTextCursor
import sys
import pandas as pd # pip install pandas
import os
import io
import secret
import xlwings as xw
import re
import smtplib
from email.encoders import encode_base64
from email.header import Header
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText # 메일의 본문 내용을 만드는 모듈 내용을 base64형식으로 변환
from email.utils import formatdate
from email.mime.application import MIMEApplication # 메일의 첨부 파일을 base64 형식으로 변환
from email.mime.image import MIMEImage # 메일의 이미지 파일을 base64 형식으로 변환
# 출처: https://nowonbun.tistory.com/684 [명월 일지:티스토리]
from email import encoders
from email.encoders import encode_base64
class MyApp(QWidget):
def __init__(self):
super().__init__()
self.window_width, self.window_height = 1150, 600
self.resize(self.window_width, self.window_height)
self.setWindowTitle('pay')
# self.server = smtplib.SMTP_SSL('smtp.kakao.com')
# self.server.login(secret.kakao_id, secret.kakao_pw)
# self.msg_from = 'miero@kakao.com'
##### layout_main #####
layout_main = QHBoxLayout()
self.setLayout(layout_main)
##### layout_1 #####
layout_1 = QVBoxLayout()
vBox11 = QVBoxLayout()
groupBoxLogin11 = QGroupBox("로그인 정보")
groupBoxLogin11.setLayout(vBox11)
layout_1.addWidget(groupBoxLogin11)
self.label11 = QLabel("이메일계정")
vBox11.addWidget(self.label11)
self.lineedit11 = QLineEdit("miero@kakao.com")
vBox11.addWidget(self.lineedit11)
self.label12 = QLabel("패스워드")
vBox11.addWidget(self.label12)
self.lineedit12 = QLineEdit()
self.lineedit12.setEchoMode(QLineEdit.Password)
# self.lineedit12.show()
vBox11.addWidget(self.lineedit12)
label13 = QLabel('직원 메일')
# self.button = QPushButton('&Load Data')
# self.button.clicked.connect(lambda _, xl_path=excel_file_path, sheet_name=worksheet_name: self.loadExcelData(xl_path, sheet_name))
# layout_v.addWidget(self.button)
layout_1.addWidget(label13)
self.table = QTableWidget()
self.table.setFixedWidth(350)
layout_1.addWidget(self.table)
layout_main.addLayout(layout_1)
##### layout_2 #####
layout_2 = QGridLayout()
label21 = QLabel('이메일 제목')
layout_2.addWidget(label21, 0, 0)
self.lineedit21 = QLineEdit()
layout_2.addWidget(self.lineedit21, 1, 0, 1, 2)
label22 = QLabel('첨부파일')
layout_2.addWidget(label22, 2, 0)
self.listwidget22 = QListWidget()
# self.listwidget22.setFixedWidth(300)
self.listwidget22.setMinimumWidth(400)
# self.listwidget22.setSelectionMode(QAbstractItemView.ExtendedSelection)
layout_2.addWidget(self.listwidget22, 3, 0, 3, 1)
self.btn_file_add = QPushButton('파일 추가') # sendlist
# self.btn_file_add.setMinimumHeight(80)
layout_2.addWidget(self.btn_file_add, 3, 1, 1, 1)
self.btn_file_add.clicked.connect(self.fn_fileadd)
self.btn_file_del = QPushButton('파일 삭제')
layout_2.addWidget(self.btn_file_del, 4, 1, 1, 1)
self.btn_file_del.clicked.connect(self.fn_filedel)
# label21 = QLabel('본문 (HTML형식)')
# layout_2.addWidget(label21, 8, 0)
# radio_1 ~ 4 버튼을 그룹으로 설정
groupBoxMid = QGroupBox("테스트 메일 보내기")
layout_2.addWidget(groupBoxMid, 6, 0, 1, 2)
hBox1 = QHBoxLayout()
groupBoxMid.setLayout(hBox1)
self.label23 = QLabel("성명")
hBox1.addWidget(self.label23)
self.lineedit23 = QLineEdit("정용만") # 이름기본값
hBox1.addWidget(self.lineedit23)
self.pushbutton23 = QPushButton("테스트 보내기")
self.pushbutton23.clicked.connect(self.fn_test)
hBox1.addWidget(self.pushbutton23)
groupBoxBottom = QGroupBox("본문 보기형식 선택")
layout_2.addWidget(groupBoxBottom, 7, 0, 1, 2)
hBox2 = QHBoxLayout()
groupBoxBottom.setLayout(hBox2)
self.radioBtn1 = QRadioButton("HTML")
self.radioBtn1.setChecked(True)
self.radioBtn1.clicked.connect(self.fn_radio_select)
hBox2.addWidget(self.radioBtn1)
self.radioBtn2 = QRadioButton("미리보기")
self.radioBtn2.clicked.connect(self.fn_radio_select)
hBox2.addWidget(self.radioBtn2)
self.textedit23 = QTextEdit()
# self.textedit23.setFixedWidth(400)
# self.textedit23.setAcceptRichText(False)
layout_2.addWidget(self.textedit23, 8, 0, 4, 1)
self.textedit23.show()
self.textedit24 = QTextEdit()
layout_2.addWidget(self.textedit24, 8, 0, 4, 1)
self.textedit24.hide()
self.btn_send = QPushButton("보내기")
self.btn_send.setMaximumHeight(500) # gridlayout button size
layout_2.addWidget(self.btn_send, 8, 1, 4, 1)
self.btn_send.clicked.connect(self.fn_run) #@@@@@@@@@@@@@@@@@@@@@@@@@@
layout_main.addLayout(layout_2)
##### layout_3 #####
layout_3 = QVBoxLayout()
label31 = QLabel('발송 결과')
layout_3.addWidget(label31)
self.listwidget32 = QListWidget()
# self.listwidget32.setMinimumWidth(self.listwidget32.sizeHintForColumn(0))
# self.listwidget32.setWidth(10)
layout_3.addWidget(self.listwidget32)
layout_main.addLayout(layout_3)
# subject0 파일이 존재하면
filename_subject = 'subject0.txt'
if os.path.isfile(filename_subject) == True:
source_text = open(filename_subject,'r', encoding="UTF-8").read()
# self.lineedit21.setText(source_text) # TextEdit에 RichText 형식의 글을 입력합니다.
self.lineedit21.setText(source_text) # TextEdit에 PlainText 형식의 글을 새로 입력합니다.
# html0 파일이 존재하면
filename_html = 'html0.txt'
if os.path.isfile(filename_html) == True:
source_text = open(filename_html,'r', encoding="UTF-8").read()
# self.textedit23.setText(source_text) # TextEdit에 RichText 형식의 글을 입력합니다.
self.textedit23.setPlainText(source_text) # TextEdit에 PlainText 형식의 글을 새로 입력합니다.
# self.textedit24.setHtml(source_text) # TextEdit에 PlainText 형식의 글을 새로 입력합니다.
# table_data = self.loadExcelData(excel_file_path, worksheet_name)
# print(table_data.keys())
df_table = self.loadExcelData(excel_file_path, worksheet_name)
# print(table_df["성명"][0])
self.df_table_02 = df_table.set_index("성명")
self.idx_name_list = self.df_table_02.index.to_list()
# print(index)
# for i in table_02["이메일"]:
def fn_radio_select(self):
# QRadioButton1 클릭 여부 표시
if self.radioBtn1.isChecked():
self.textedit23.show()
self.textedit24.hide()
self.hidden = False
# self.btn_send.setText('보내기')
elif self.radioBtn2.isChecked():
self.fn_html_save()
self.textedit23.hide()
self.textedit24.show()
self.hidden = True
# self.btn_send.setText('미리보기')
def loadExcelData(self, excel_file_dir, worksheet_name):
df_work_sheet = pd.read_excel(excel_file_path, worksheet_name)
df_email_sheet = pd.read_excel(excel_file_path, emailsheet_name)
df_table = df_work_sheet.merge(df_email_sheet, how='left')
df_table_mail = df_table[['성명','이메일']]
res = df_table_mail
# res = df_table_mail.to_dict()
# self.table.setRowCount(df.shape[0])
# self.table.setColumnCount(df.shape[1])
self.table.setRowCount(df_table_mail.shape[0])
self.table.setColumnCount(df_table_mail.shape[1])
# self.table.setHorizontalHeaderLabels(df.columns)
self.table.setHorizontalHeaderLabels(df_table_mail.columns)
header = self.table.horizontalHeader()
# header.setSectionResizeMode(0, QHeaderView.Stretch)
# header.setSectionResizeMode(0, QHeaderView.ResizeToContents)
header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
# returns pandas array object
# for row in df.iterrows():
for row in df_table_mail.iterrows():
values = row[1]
for col_index, value in enumerate(values):
if isinstance(value, (float, int)):
value = '{0:0,.0f}'.format(value)
tableItem = QTableWidgetItem(str(value))
if value == "nan":
tableItem.setBackground(Qt.red)
self.table.setItem(row[0], col_index, tableItem)
self.table.setColumnWidth(2, 310)
return res
def fn_fileadd(self):
# f_name = QFileDialog.getOpenFileName(None, '열기', '', "All Files(*.*)")
f_names = QFileDialog.getOpenFileNames(None, '열기', '', "All Files(*.*)")
# txtPath = f_name[0]
filelist = f_names[0]
if filelist:
for f_name in filelist:
# ext = os.path.splitext(f_name[0])[1]
ext = os.path.splitext(f_name)[1] # 확장자 확인
# if f_names[0]:
icnt = 0
for i in range(self.listwidget22.count()):
# if str(self.listwidget22.item(i).text()) == txtPath.replace("/","\\") or str(self.listwidget22.item(i).text()) == txtPath:
if str(self.listwidget22.item(i).text()) == f_name.replace("/","\\") or str(self.listwidget22.item(i).text()) == f_name:
icnt = 1
break
if icnt != 1:
f_path = f_name
if ext == '.exe':
QMessageBox.about(self,'파일 형식 확인','exe파일은 전송할 수 없습니다.')
pass
else:
cnt = self.listwidget22.count() +1
# self.listwidget22.insertItem(cnt, os.path.basename(txtPath))
# self.listwidget22.insertItem(cnt, txtPath)
# f_path = f_names[0]
# print(f_path)
self.listwidget22.insertItem(cnt, f_path)
# self.listwidget22.insertItem(cnt, f_path.replace("/","\\"))
def fn_filedel(self):
currentrow = self.listwidget22.currentRow()
self.listwidget22.takeItem(currentrow) # currentrowRight번째 항목을 삭제합니다
self.listwidget22.clearSelection()
def fn_subject_save(self):
if len(self.lineedit21.text())>0:
S__File = os.path.join(os.getcwd(),'subject0.txt')
Text = self.lineedit21.text()
if S__File:
# Finally this will Save your file to the path selected.
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
file.write(Text)
def fn_html_save(self):
if len(self.textedit23.toPlainText())>0:
# print(len(self.textedit.toPlainText()))
# S__File = QFileDialog.getSaveFileName(None,'문자 파일저장','/', "Text Files (*.txt)")
# S__File = QFileDialog.getSaveFileName(None,'문자 파일저장','html0', "Text Files (*.txt)")
S__File = os.path.join(os.getcwd(),'html0.txt')
# This will let you access the test in your QTextEdit
Text = self.textedit23.toPlainText()
self.textedit24.setHtml(Text)
# document = self.textedit23.document()
# cursor = QTextCursor(document)
# p1 = cursor.position() # return int
# cursor.insertImage(r"C:\Users\newstep\Pictures\number1.jpg")
# This will prevent you from an error if pressed cancel on file dialog.
# if S__File[0]:
if S__File:
# Finally this will Save your file to the path selected.
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
file.write(Text)
# txtPath = S__File[0]
# icnt = 0
# for i in range(self.listwidget31.count()):
# if str(self.listwidget31.item(i).text()) == txtPath.replace("/","\\"):
# icnt = 1
# break
# if icnt != 1:
# cnt = self.listwidget31.count() +1
# self.listwidget31.insertItem(cnt, os.path.basename(txtPath))
# self.listwidget31.insertItem(cnt, txtPath)
else:
QMessageBox.about(self,'메시지 입력 확인','메시지를 입력하셔야 합니다.')
def fn_print_name(self, name, email):
# f_name_pre = r"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' width='50%' height='0%'></center>"
# f_name = f_name_pre.replace("\\","/")
# with io.open('file_name.html','r') as f:
# with io.open(f_name,'r') as f:
# # emailtext = f.read()
# emailtext = f_name
# attachment = 'attachment_file_name.png'
# attachment = f_name
# print(name, self.df_table_02.loc[name][0])
# print(name, email)
if len(self.textedit23.toPlainText())>0:
S__File = os.path.join(os.getcwd(),'html0.txt')
# print(len(self.textedit23.toPlainText()))
# print(S__File)
# pretext = f'{name} 님<br/><br/>'
# pretext += f'당신의 이메일은 {email} 입니다.<br/>'
contents = self.textedit23.toPlainText()
# nexttext = f'<br/><img src="cid:{attachment}" >'
# nexttext = f"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' id='millstudio logo' width='10%' height='0%'></center>"
# document = self.textedit23.document()
# cursor = QTextCursor(document)
# p1 = cursor.position() # return int
# cursor.insertImage(f_name)
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
# file.write(pretext)
file.write(contents)
# file.write(nexttext)
# print(contents)
# msgText = MIMEText(contents, 'html')
print(name, email, "전송완료")
# self.fn_result_window(name, email)
def fn_DeleteAllFiles(self,filePath):
if os.path.exists(filePath):
for file in os.scandir(filePath):
os.remove(file.path)
return '폴더 내 모든 파일 지우기 완료'
else:
return '폴더가 없습니다.'
def fn_pdf_create(self, idx_name):
#####################################
# xlwings
self.current_pdf_path = os.getcwd()+"\pdf"
fname = "급여1.xlsx"
# for n in self.target_name_list:
name = idx_name
df_data = pd.read_excel(fname, sheet_name='4대급여')
df_data = df_data.fillna(0)
df_employee = pd.read_excel(fname, sheet_name='직원현황')
idx_df_data = df_data.index[df_data['성명']==name].tolist()[0]
# print("4대급여 인덱스 :",idx_df_data)
normal = df_data.loc[idx_df_data,['기본급']][0]
overtime = df_data.loc[idx_df_data,['연장수당']][0]
holiday = df_data.loc[idx_df_data,['휴일수당']][0]
holidayovertime = df_data.loc[idx_df_data,['휴일연장수당']][0]
extra = df_data.loc[idx_df_data,['추가수당']][0]
meals = df_data.loc[idx_df_data,['식대']][0]
bonus = df_data.loc[idx_df_data,['상여금']][0]
normal_calculation = df_data.loc[idx_df_data,['기']][0]
overtime_calculation = df_data.loc[idx_df_data,['연']][0]
holiday_calculation = df_data.loc[idx_df_data,['휴']][0]
holidayovertime_calculation = df_data.loc[idx_df_data,['휴연']][0]
extra_calculation = df_data.loc[idx_df_data,['추']][0]
nationalpension = df_data.loc[idx_df_data,['국민연금']][0]
healthinsurance = df_data.loc[idx_df_data,['건강보험']][0]
longtermcareinsurance = df_data.loc[idx_df_data,['장기요양보험']][0]
employmentinsurance = df_data.loc[idx_df_data,['고용보험']][0]
healthsettlement = df_data.loc[idx_df_data,['정산건강']][0]
longtermcaresettlement = df_data.loc[idx_df_data,['정산장기요양']][0]
advancepayment = df_data.loc[idx_df_data,['선지급']][0]
etc = df_data.loc[idx_df_data,['기타']][0]
incometax = df_data.loc[idx_df_data,['소득세']][0]
localincometax = df_data.loc[idx_df_data,['지방소득세']][0]
idx_df_employee = df_employee.index[df_employee['성명']==name].tolist()[0]
# print("직원현황 인덱스 :",idx_df_employee)
jobposition = df_employee.loc[idx_df_employee,['직위']][0]
department = df_employee.loc[idx_df_employee,['부서']][0]
birthday = df_employee.loc[idx_df_employee,['생일']][0]
# 엑셀 인스턴스 생성
self.app = xw.App(visible=False)
book = xw.Book(fname)
sh_paystub = book.sheets('급여명세서사대보험')
sh_paystub["B4"].value = name
sh_paystub["D4"].value = jobposition
sh_paystub["B5"].value = department
sh_paystub["D5"].value = birthday
sh_paystub["B8"].value = normal
sh_paystub["B9"].value = overtime
sh_paystub["B10"].value = holiday
sh_paystub["B11"].value = holidayovertime
sh_paystub["B12"].value = extra
sh_paystub["B13"].value = meals
sh_paystub["D8"].value = nationalpension
sh_paystub["D9"].value = healthinsurance
sh_paystub["D10"].value = longtermcareinsurance
sh_paystub["D11"].value = employmentinsurance
sh_paystub["D12"].value = healthsettlement
sh_paystub["D13"].value = longtermcaresettlement
sh_paystub["D14"].value = advancepayment
sh_paystub["D15"].value = etc
sh_paystub["D16"].value = incometax
sh_paystub["D17"].value = localincometax
sh_paystub["B23"].value = normal_calculation
sh_paystub["B24"].value = overtime_calculation
sh_paystub["B25"].value = holiday_calculation
sh_paystub["B26"].value = holidayovertime_calculation
sh_paystub["B27"].value = extra_calculation
sh_paystub["D23"].value = normal
sh_paystub["D24"].value = overtime
sh_paystub["D25"].value = holiday
sh_paystub["D26"].value = holidayovertime
sh_paystub["D27"].value = extra
# rng = sh_paystub.range("D35")
# sh_paystub.pictures.add(r'B:\python\vscode\excel\millstudio_logo.png', left=rng.left, top=rng.top)
if len(self.lineedit21.text())==0:
book.save()
# app.kill()
return
# print(len(self.lineedit21.text()))
# pdf 로 저장하기
# current_path = os.getcwd() # 현재 작업중인 폴더에 저장하기
# 절대경로로 파일 위치 입력
subject_before = self.lineedit21.text()
# 문자치환 f-string 사용하여 변수 적용하기
subject = subject_before.replace("{성명}",f'{name}')
pdf_file = os.path.join(self.current_pdf_path, f"{subject}.pdf")
# PDF 로 저장할 시트 선택하기(본 예제에서는 첫 번째 시트 선택하기)
# report_sheet = book.sheets[1]
report_sheet = sh_paystub
# PDF 로 저장하기
# report_sheet.ExportAsFixedFormat(0, pdf_path)
report_sheet.api.ExportAsFixedFormat(0, pdf_file)
book.save()
# app.kill()
#####################################
def fn_send(self, name, email_i):
# # 메일 서버를 설정합니다.
account_id = self.lineedit11.text().split("@")[0]
emailserver = self.lineedit11.text().split("@")[1]
# self.server = smtplib.SMTP_SSL('smtp.kakao.com')
smtp_server = 'smtp.'+ emailserver
# print(account_id)
self.server = smtplib.SMTP_SSL(smtp_server)
# self.server.login(secret.kakao_id, secret.kakao_pw)
self.server.login(account_id, self.lineedit12.text())
# self.msg_from = 'miero@kakao.com'
self.msg_from = self.lineedit11.text()
# # server = smtplib.SMTP('smtp.com', port_number)
# # server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# server = smtplib.SMTP_SSL('smtp.kakao.com')
# # server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# # 로그인이 필요하면 로그인 설정
# server.login(secret.kakao_id, secret.kakao_pw)
# # 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
# msg_to = email_i
# cc = 'b@b.com, c@c.com'
# cc = ''
# print(name,email_i)
# 메세지 구성
# msg = MIMEBase('multipart','mixed')
msg = MIMEMultipart()
msg['From'] = self.msg_from
msg['To'] = email_i
msg['Date'] = formatdate(localtime=True)
# msg['Subject'] = f'2022년08월급여명세서-{name}'
subject_before = self.lineedit21.text()
# 문자치환 f-string 사용하여 변수 적용하기
subject = subject_before.replace("{성명}",f'{name}')
msg['Subject'] = Header(s=subject, charset='utf-8')
# msg['Subject'] = Header(s=f'2022년08월급여명세서-{name}', charset='utf-8')
# msg['Cc'] = ""
# 메일 본문 작성
# # html 로 되어있던 파일을 불러 오고 거기에 파일을 붙여서 보냅니다.
# msgText = MIMEText('<h1>%s</h1><hr>, <img src="cid:%s" >' % (emailtext, attachment), 'html')
# contents = '<h1>%s</h1>'
# contents += '<hr>'
# contents += '<img src="cid:%s" >'
# msgText = MIMEText(contents % (emailtext, attachment), 'html')
# contents = f'<h1>{emailtext}</h1>'
# contents += f'<h2>{msg_to} 님 메일이 도착했습니다.</h2>'
# contents += '<hr>'
# contents += f'<img src="cid:{attachment}" >'
# msgText = MIMEText(contents, 'html')
# pretext = f'수신: {name}<br/>'
# pretext += '발신: 주식회사 밀앤아이, 주식회사 헴펠 대표이사<br/>'
# pretext += '<br/>'
# msgpreText = MIMEText(pretext, 'html')
# msg.attach(msgpreText)
# contents = self.textedit23.toPlainText()
contents_before = self.textedit23.toPlainText()
# 문자치환 f-string 사용하여 변수 적용하기
contents = contents_before.replace("{성명}",f'수신: {name}')
# msgText = MIMEText(contents, 'plain')
msgText = MIMEText(contents, 'html')
# msgText = MIMEText(contents, _charset='utf-8')
# 메세지를 메일에 붙여 줍니다.
msg.attach(msgText)
# 메일 제일 밑에 로고그림 붙여 줍니다.
# logo_file = "logo.jpg"
# img_f_name = logo_file.replace("\\","/")
# logo_file = r"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' width='10%' height='0%'></center>"
# img_f_name = logo_file.replace("\\","/")
# # with io.open('file_name.html','r') as f:
# with io.open(img_f_name,'r') as f:
# # emailtext = f.read()
# emailtext = img_f_name
# # attachment = 'attachment_file_name.png'
# attachment = img_f_name
# attachment = logo_file
# fp = open(attachment, 'rb')
# img = MIMEImage(fp.read())
# fp.close()
# img.add_header('Content-ID', '<{}>'.format(attachment))
# msg.attach(img)
# 파일첨부
files = list()
pdf_file_name = f"{subject}.pdf"
pdf_file = os.path.join(os.getcwd()+"\pdf", pdf_file_name)
files.append(pdf_file)
# if os.path.isfile(pdf_file):
# binary_pdf = open(pdf_file, 'rb')
# payload = MIMEBase('application', 'octate-stream', Name=pdf_file_name)
# payload.set_payload((binary_pdf).read())
# encoders.encode_base64(payload)
# payload.add_header('Content-Decomposition', 'attachment', filename=pdf_file_name)
# msg.attach(payload)
for i in range(self.listwidget22.count()):
files.append(self.listwidget22.item(i).text())
# print(files)
for f in files:
# print(f)
part = MIMEBase('application', "octet-stream")
part.set_payload(open(f,"rb").read())
encoders.encode_base64(part)
fstr_name = os.path.basename(f)
# part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(f))
part.add_header('Content-Disposition',"attachment", filename= fstr_name, charset='utf-8')
# [출처] 파이썬에서 지메일 보내기(w/첨부파일) 한글파일도 가능|작성자 데이터공방
# Header(s=f'2022년08월급여명세서-{name}', charset='utf-8')
msg.attach(part)
# 메일 서버를 이용하여 메일을 발송합니다.
# server.sendmail(msg_from, msg["To"].split(",") + msg["Cc"].split(","), msg.as_string())
self.server.sendmail(msg['From'], msg['To'], msg.as_string())
# self.server.quit()
# def fn_result_window(self, name, email):
# self.listwidget32.clear()
# cnt = self.listwidget32.count() +1
# # print(cnt, name, email, "전송완료")
# # self.listwidget32.insertItem(cnt,name&email&"전송완료")
# self.listwidget32.insertItem(cnt, f'{name}-{email}-전송완료')
def fn_test(self):
# try:
# 메일 서버를 설정합니다.
# server = smtplib.SMTP('smtp.com', port_number)
# server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# self.server = smtplib.SMTP_SSL('smtp.kakao.com')
# server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# 로그인이 필요하면 로그인 설정
# self.server.login(secret.kakao_id, secret.kakao_pw)
# 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
self.listwidget32.clear()
if len(self.lineedit11.text()) == 0:
QMessageBox.about(self,'이메일계정 확인','이메일계정을 입력하십시요.')
return
p = re.compile('^[a-zA-Z0-9+-_.]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$')
if p.match(self.lineedit11.text()) == None:
# print(p.match(self.lineedit11.text()) != None)
QMessageBox.about(self,'이메일 형식 확인','올바른 이메일 형식이 아닙니다.')
return
if len(self.lineedit12.text()) == 0:
QMessageBox.about(self,'비밀번호 확인','비밀번호를 입력하십시요.')
return
cnt = 0
if len(self.lineedit21.text()) == 0:
QMessageBox.about(self,'제목 입력 확인','제목을 입력하십시요.')
return
self.fn_subject_save()
self.fn_html_save()
self.fn_DeleteAllFiles(os.getcwd()+"\pdf")
self.fn_pdf_create(self.lineedit23.text())
try:
if self.df_table_02.loc[self.lineedit23.text()][0] != "nan":
self.fn_send(self.lineedit23.text(), self.df_table_02.loc[self.lineedit23.text()][0])
cnt += 1
# self.listwidget32.insertItem(cnt, f'{self.lineedit23.text()}-{self.df_table_02.loc[self.lineedit23.text()][0]}-전송완료')
self.listwidget32.addItem(f'{self.lineedit23.text()}-{self.df_table_02.loc[self.lineedit23.text()][0]}-전송완료')
except:
cnt += 1
# self.listwidget32.insertItem(cnt, f'{self.lineedit23.text()}-{self.df_table_02.loc[self.lineedit23.text()][0]}-실패')
# self.listwidget32.item(cnt-1).setBackground(Qt.red)
self.listwidget32.addItem(f'{self.lineedit23.text()}-{self.df_table_02.loc[self.lineedit23.text()][0]}-실패')
self.listwidget32.item(cnt-1).setBackground(Qt.red)
# self.fn_pdf_create("밀1")
# self.fn_send(self.lineedit23.text(), self.df_table_02.loc[self.lineedit23.text()][0])
# cnt += 1
# self.listwidget32.insertItem(cnt, f'{self.lineedit23.text()}-{self.df_table_02.loc[self.lineedit23.text()][0]}-전송완료')
self.server.quit()
self.app.kill()
# self.fn_print_name(self.lineedit23.text(), self.df_table_02.loc[self.lineedit23.text()][0])
# except: # 예외가 발생했을 때 실행됨
# print('예외가 발생했습니다.')
# self.listwidget32.insertItem(cnt, f'{"밀1"}-{self.df_table_02.loc["밀1"][0]}-실패')
def fn_run(self):
# 메일 서버를 설정합니다.
# server = smtplib.SMTP('smtp.com', port_number)
# server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# server = smtplib.SMTP_SSL('smtp.kakao.com')
# server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# 로그인이 필요하면 로그인 설정
# server.login(secret.kakao_id, secret.kakao_pw)
# 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
self.listwidget32.clear()
if len(self.lineedit11.text()) == 0:
QMessageBox.about(self,'이메일계정 확인','이메일계정을 입력하십시요.')
return
p = re.compile('^[a-zA-Z0-9+-_.]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$')
if p.match(self.lineedit11.text()) == None:
# print(p.match(self.lineedit11.text()) != None)
QMessageBox.about(self,'이메일 형식 확인','올바른 이메일 형식이 아닙니다.')
return
if len(self.lineedit12.text()) == 0:
QMessageBox.about(self,'비밀번호 확인','비밀번호를 입력하십시요.')
return
cnt = 0
if len(self.lineedit21.text()) == 0:
QMessageBox.about(self,'제목 입력 확인','제목을 입력하십시요.')
return
self.fn_subject_save()
self.fn_html_save()
# self.fn_send("밀1", self.df_table_02.loc["밀1"][0])
# self.fn_print_name("밀1", self.df_table_02.loc["밀1"][0])
for idx_name in self.idx_name_list:
# print(idx)
# print(self.df_table_02.loc[idx][0])
# print(idx, table_02.loc[idx][0])
self.fn_DeleteAllFiles(os.getcwd()+"\pdf")
self.fn_pdf_create(idx_name)
try:
if self.df_table_02.loc[idx_name][0] != "nan":
self.fn_send(idx_name, self.df_table_02.loc[idx_name][0])
cnt += 1
self.listwidget32.insertItem(cnt, f'{idx_name}-{self.df_table_02.loc[idx_name][0]}-전송완료')
except:
cnt += 1
self.listwidget32.insertItem(cnt, f'{idx_name}-{self.df_table_02.loc[idx_name][0]}-실패')
self.listwidget32.item(cnt-1).setBackground(Qt.red)
# if self.df_table_02.loc[idx_name][0] == "nan":
# print(self.listwidget32.)
# self.listwidget32.item(cnt).setBackground(Qt.red)
# print("예외가 발생했습니다.-fn_run",cnt,self.df_table_02.loc[idx_name][0])
# self.fn_print_name(idx_name, self.df_table_02.loc[idx_name][0])
self.server.quit()
self.app.kill()
# print('예외가 발생했습니다.')
# self.listwidget32.insertItem(cnt, f'{idx_name}-{self.df_table_02.loc[idx_name][0]}-실패')
if __name__ == '__main__':
# don't auto scale when drag app to a different monitor.
# QGuiApplication.setHighDpiScaleFactorRoundingPolicy(Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
excel_file_path = '급여1.xlsx'
worksheet_name = '4대급여'
emailsheet_name = '이메일'
app = QApplication(sys.argv)
app.setStyleSheet('''
QWidget {
font-size: 17px;
}
''')
myApp = MyApp()
myApp.show()
try:
sys.exit(app.exec())
except SystemExit:
print('Closing Window...')
====================
pay21.py--------------------
# from operator import index
# from unittest import result
# from xml.dom.minidom import Document
from PyQt5.QtWidgets import QApplication, QWidget, QTableWidget, QTableWidgetItem, QPushButton, \
QHeaderView, QHBoxLayout, QVBoxLayout, QGridLayout, QAbstractScrollArea, QLabel, QListWidget, \
QFileDialog, QMessageBox, QTextEdit, QAbstractItemView, QLineEdit, QGroupBox, QRadioButton
from PyQt5.QtCore import Qt
# from PyQt5 import QtGui
from PyQt5.QtGui import QTextCursor
import sys
import pandas as pd # pip install pandas
import os
import io
import secret
import xlwings as xw
import re
import smtplib
from email.encoders import encode_base64
from email.header import Header
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText # 메일의 본문 내용을 만드는 모듈 내용을 base64형식으로 변환
from email.utils import formatdate
from email.mime.application import MIMEApplication # 메일의 첨부 파일을 base64 형식으로 변환
from email.mime.image import MIMEImage # 메일의 이미지 파일을 base64 형식으로 변환
# 출처: https://nowonbun.tistory.com/684 [명월 일지:티스토리]
from email import encoders
from email.encoders import encode_base64
class MyApp(QWidget):
def __init__(self):
super().__init__()
self.window_width, self.window_height = 1150, 600
self.resize(self.window_width, self.window_height)
self.setWindowTitle('pay')
# self.server = smtplib.SMTP_SSL('smtp.kakao.com')
# self.server.login(secret.kakao_id, secret.kakao_pw)
# self.msg_from = 'miero@kakao.com'
##### layout_main #####
layout_main = QHBoxLayout()
self.setLayout(layout_main)
##### layout_1 #####
layout_1 = QVBoxLayout()
vBox11 = QVBoxLayout()
groupBoxLogin11 = QGroupBox("로그인 정보")
groupBoxLogin11.setLayout(vBox11)
layout_1.addWidget(groupBoxLogin11)
self.label11 = QLabel("이메일계정")
vBox11.addWidget(self.label11)
self.lineedit11 = QLineEdit("miero@kakao.com")
vBox11.addWidget(self.lineedit11)
self.label12 = QLabel("패스워드")
vBox11.addWidget(self.label12)
self.lineedit12 = QLineEdit()
self.lineedit12.setEchoMode(QLineEdit.Password)
# self.lineedit12.show()
vBox11.addWidget(self.lineedit12)
label13 = QLabel('직원 메일')
# self.button = QPushButton('&Load Data')
# self.button.clicked.connect(lambda _, xl_path=excel_file_path, sheet_name=worksheet_name: self.loadExcelData(xl_path, sheet_name))
# layout_v.addWidget(self.button)
layout_1.addWidget(label13)
self.table = QTableWidget()
self.table.setFixedWidth(350)
layout_1.addWidget(self.table)
layout_main.addLayout(layout_1)
##### layout_2 #####
layout_2 = QGridLayout()
label21 = QLabel('이메일 제목')
layout_2.addWidget(label21, 0, 0)
self.lineedit21 = QLineEdit()
layout_2.addWidget(self.lineedit21, 1, 0, 1, 2)
label22 = QLabel('첨부파일')
layout_2.addWidget(label22, 2, 0)
self.listwidget22 = QListWidget()
# self.listwidget22.setFixedWidth(300)
self.listwidget22.setMinimumWidth(400)
# self.listwidget22.setSelectionMode(QAbstractItemView.ExtendedSelection)
layout_2.addWidget(self.listwidget22, 3, 0, 3, 1)
self.btn_file_add = QPushButton('파일 추가') # sendlist
# self.btn_file_add.setMinimumHeight(80)
layout_2.addWidget(self.btn_file_add, 3, 1, 1, 1)
self.btn_file_add.clicked.connect(self.fn_fileadd)
self.btn_file_del = QPushButton('파일 삭제')
layout_2.addWidget(self.btn_file_del, 4, 1, 1, 1)
self.btn_file_del.clicked.connect(self.fn_filedel)
# label21 = QLabel('본문 (HTML형식)')
# layout_2.addWidget(label21, 8, 0)
# radio_1 ~ 4 버튼을 그룹으로 설정
groupBoxMid = QGroupBox("테스트 메일 보내기")
layout_2.addWidget(groupBoxMid, 6, 0, 1, 2)
hBox1 = QHBoxLayout()
groupBoxMid.setLayout(hBox1)
self.label23 = QLabel("성명")
hBox1.addWidget(self.label23)
self.lineedit23 = QLineEdit("정용만") # 이름기본값
hBox1.addWidget(self.lineedit23)
self.pushbutton23 = QPushButton("테스트 보내기")
self.pushbutton23.clicked.connect(self.fn_test)
hBox1.addWidget(self.pushbutton23)
groupBoxBottom = QGroupBox("본문 보기형식 선택")
layout_2.addWidget(groupBoxBottom, 7, 0, 1, 2)
hBox2 = QHBoxLayout()
groupBoxBottom.setLayout(hBox2)
self.radioBtn1 = QRadioButton("HTML")
self.radioBtn1.setChecked(True)
self.radioBtn1.clicked.connect(self.fn_radio_select)
hBox2.addWidget(self.radioBtn1)
self.radioBtn2 = QRadioButton("미리보기")
self.radioBtn2.clicked.connect(self.fn_radio_select)
hBox2.addWidget(self.radioBtn2)
self.textedit23 = QTextEdit()
# self.textedit23.setFixedWidth(400)
# self.textedit23.setAcceptRichText(False)
layout_2.addWidget(self.textedit23, 8, 0, 4, 1)
self.textedit23.show()
self.textedit24 = QTextEdit()
layout_2.addWidget(self.textedit24, 8, 0, 4, 1)
self.textedit24.hide()
self.btn_send = QPushButton("보내기")
self.btn_send.setMaximumHeight(500) # gridlayout button size
layout_2.addWidget(self.btn_send, 8, 1, 4, 1)
self.btn_send.clicked.connect(self.fn_run) #@@@@@@@@@@@@@@@@@@@@@@@@@@
layout_main.addLayout(layout_2)
##### layout_3 #####
layout_3 = QVBoxLayout()
label31 = QLabel('발송 결과')
layout_3.addWidget(label31)
self.listwidget32 = QListWidget()
# self.listwidget32.setMinimumWidth(self.listwidget32.sizeHintForColumn(0))
# self.listwidget32.setWidth(10)
layout_3.addWidget(self.listwidget32)
layout_main.addLayout(layout_3)
# subject0 파일이 존재하면
filename_subject = 'subject0.txt'
if os.path.isfile(filename_subject) == True:
source_text = open(filename_subject,'r', encoding="UTF-8").read()
# self.lineedit21.setText(source_text) # TextEdit에 RichText 형식의 글을 입력합니다.
self.lineedit21.setText(source_text) # TextEdit에 PlainText 형식의 글을 새로 입력합니다.
# html0 파일이 존재하면
filename_html = 'html0.txt'
if os.path.isfile(filename_html) == True:
source_text = open(filename_html,'r', encoding="UTF-8").read()
# self.textedit23.setText(source_text) # TextEdit에 RichText 형식의 글을 입력합니다.
self.textedit23.setPlainText(source_text) # TextEdit에 PlainText 형식의 글을 새로 입력합니다.
# self.textedit24.setHtml(source_text) # TextEdit에 PlainText 형식의 글을 새로 입력합니다.
# table_data = self.loadExcelData(excel_file_path, worksheet_name)
# print(table_data.keys())
df_table = self.loadExcelData(excel_file_path, worksheet_name)
# print(table_df["성명"][0])
self.df_table_02 = df_table.set_index("성명")
self.idx_name_list = self.df_table_02.index.to_list()
# print(index)
# for i in table_02["이메일"]:
def fn_radio_select(self):
# QRadioButton1 클릭 여부 표시
if self.radioBtn1.isChecked():
self.textedit23.show()
self.textedit24.hide()
self.hidden = False
# self.btn_send.setText('보내기')
elif self.radioBtn2.isChecked():
self.fn_html_save()
self.textedit23.hide()
self.textedit24.show()
self.hidden = True
# self.btn_send.setText('미리보기')
def loadExcelData(self, excel_file_dir, worksheet_name):
df_work_sheet = pd.read_excel(excel_file_path, worksheet_name)
df_email_sheet = pd.read_excel(excel_file_path, emailsheet_name)
df_table = df_work_sheet.merge(df_email_sheet, how='left')
df_table_mail = df_table[['성명','이메일']]
res = df_table_mail
# res = df_table_mail.to_dict()
# self.table.setRowCount(df.shape[0])
# self.table.setColumnCount(df.shape[1])
self.table.setRowCount(df_table_mail.shape[0])
self.table.setColumnCount(df_table_mail.shape[1])
# self.table.setHorizontalHeaderLabels(df.columns)
self.table.setHorizontalHeaderLabels(df_table_mail.columns)
header = self.table.horizontalHeader()
# header.setSectionResizeMode(0, QHeaderView.Stretch)
# header.setSectionResizeMode(0, QHeaderView.ResizeToContents)
header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
# returns pandas array object
# for row in df.iterrows():
for row in df_table_mail.iterrows():
values = row[1]
for col_index, value in enumerate(values):
if isinstance(value, (float, int)):
value = '{0:0,.0f}'.format(value)
tableItem = QTableWidgetItem(str(value))
if value == "nan":
tableItem.setBackground(Qt.red)
self.table.setItem(row[0], col_index, tableItem)
self.table.setColumnWidth(2, 310)
return res
def fn_fileadd(self):
# f_name = QFileDialog.getOpenFileName(None, '열기', '', "All Files(*.*)")
f_names = QFileDialog.getOpenFileNames(None, '열기', '', "All Files(*.*)")
# txtPath = f_name[0]
filelist = f_names[0]
if filelist:
for f_name in filelist:
# ext = os.path.splitext(f_name[0])[1]
ext = os.path.splitext(f_name)[1] # 확장자 확인
# if f_names[0]:
icnt = 0
for i in range(self.listwidget22.count()):
# if str(self.listwidget22.item(i).text()) == txtPath.replace("/","\\") or str(self.listwidget22.item(i).text()) == txtPath:
if str(self.listwidget22.item(i).text()) == f_name.replace("/","\\") or str(self.listwidget22.item(i).text()) == f_name:
icnt = 1
break
if icnt != 1:
f_path = f_name
if ext == '.exe':
QMessageBox.about(self,'파일 형식 확인','exe파일은 전송할 수 없습니다.')
pass
else:
cnt = self.listwidget22.count() +1
# self.listwidget22.insertItem(cnt, os.path.basename(txtPath))
# self.listwidget22.insertItem(cnt, txtPath)
# f_path = f_names[0]
# print(f_path)
self.listwidget22.insertItem(cnt, f_path)
# self.listwidget22.insertItem(cnt, f_path.replace("/","\\"))
def fn_filedel(self):
currentrow = self.listwidget22.currentRow()
self.listwidget22.takeItem(currentrow) # currentrowRight번째 항목을 삭제합니다
self.listwidget22.clearSelection()
def fn_subject_save(self):
if len(self.lineedit21.text())>0:
S__File = os.path.join(os.getcwd(),'subject0.txt')
Text = self.lineedit21.text()
if S__File:
# Finally this will Save your file to the path selected.
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
file.write(Text)
def fn_html_save(self):
if len(self.textedit23.toPlainText())>0:
# print(len(self.textedit.toPlainText()))
# S__File = QFileDialog.getSaveFileName(None,'문자 파일저장','/', "Text Files (*.txt)")
# S__File = QFileDialog.getSaveFileName(None,'문자 파일저장','html0', "Text Files (*.txt)")
S__File = os.path.join(os.getcwd(),'html0.txt')
# This will let you access the test in your QTextEdit
Text = self.textedit23.toPlainText()
self.textedit24.setHtml(Text)
# document = self.textedit23.document()
# cursor = QTextCursor(document)
# p1 = cursor.position() # return int
# cursor.insertImage(r"C:\Users\newstep\Pictures\number1.jpg")
# This will prevent you from an error if pressed cancel on file dialog.
# if S__File[0]:
if S__File:
# Finally this will Save your file to the path selected.
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
file.write(Text)
# txtPath = S__File[0]
# icnt = 0
# for i in range(self.listwidget31.count()):
# if str(self.listwidget31.item(i).text()) == txtPath.replace("/","\\"):
# icnt = 1
# break
# if icnt != 1:
# cnt = self.listwidget31.count() +1
# self.listwidget31.insertItem(cnt, os.path.basename(txtPath))
# self.listwidget31.insertItem(cnt, txtPath)
else:
QMessageBox.about(self,'메시지 입력 확인','메시지를 입력하셔야 합니다.')
def fn_print_name(self, name, email):
# f_name_pre = r"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' width='50%' height='0%'></center>"
# f_name = f_name_pre.replace("\\","/")
# with io.open('file_name.html','r') as f:
# with io.open(f_name,'r') as f:
# # emailtext = f.read()
# emailtext = f_name
# attachment = 'attachment_file_name.png'
# attachment = f_name
# print(name, self.df_table_02.loc[name][0])
# print(name, email)
if len(self.textedit23.toPlainText())>0:
S__File = os.path.join(os.getcwd(),'html0.txt')
# print(len(self.textedit23.toPlainText()))
# print(S__File)
# pretext = f'{name} 님<br/><br/>'
# pretext += f'당신의 이메일은 {email} 입니다.<br/>'
contents = self.textedit23.toPlainText()
# nexttext = f'<br/><img src="cid:{attachment}" >'
# nexttext = f"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' id='millstudio logo' width='10%' height='0%'></center>"
# document = self.textedit23.document()
# cursor = QTextCursor(document)
# p1 = cursor.position() # return int
# cursor.insertImage(f_name)
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
# file.write(pretext)
file.write(contents)
# file.write(nexttext)
# print(contents)
# msgText = MIMEText(contents, 'html')
print(name, email, "전송완료")
# self.fn_result_window(name, email)
def fn_DeleteAllFiles(self,filePath):
if os.path.exists(filePath):
for file in os.scandir(filePath):
os.remove(file.path)
return '폴더 내 모든 파일 지우기 완료'
else:
return '폴더가 없습니다.'
def fn_pdf_create(self, idx_name):
#####################################
# xlwings
self.current_pdf_path = os.getcwd()+"\pdf"
fname = "급여1.xlsx"
# for n in self.target_name_list:
name = idx_name
df_data = pd.read_excel(fname, sheet_name='4대급여')
df_data = df_data.fillna(0)
df_employee = pd.read_excel(fname, sheet_name='직원현황')
idx_df_data = df_data.index[df_data['성명']==name].tolist()[0]
# print("4대급여 인덱스 :",idx_df_data)
normal = df_data.loc[idx_df_data,['기본급']][0]
overtime = df_data.loc[idx_df_data,['연장수당']][0]
holiday = df_data.loc[idx_df_data,['휴일수당']][0]
holidayovertime = df_data.loc[idx_df_data,['휴일연장수당']][0]
extra = df_data.loc[idx_df_data,['추가수당']][0]
meals = df_data.loc[idx_df_data,['식대']][0]
bonus = df_data.loc[idx_df_data,['상여금']][0]
normal_calculation = df_data.loc[idx_df_data,['기']][0]
overtime_calculation = df_data.loc[idx_df_data,['연']][0]
holiday_calculation = df_data.loc[idx_df_data,['휴']][0]
holidayovertime_calculation = df_data.loc[idx_df_data,['휴연']][0]
extra_calculation = df_data.loc[idx_df_data,['추']][0]
nationalpension = df_data.loc[idx_df_data,['국민연금']][0]
healthinsurance = df_data.loc[idx_df_data,['건강보험']][0]
longtermcareinsurance = df_data.loc[idx_df_data,['장기요양보험']][0]
employmentinsurance = df_data.loc[idx_df_data,['고용보험']][0]
healthsettlement = df_data.loc[idx_df_data,['정산건강']][0]
longtermcaresettlement = df_data.loc[idx_df_data,['정산장기요양']][0]
advancepayment = df_data.loc[idx_df_data,['선지급']][0]
etc = df_data.loc[idx_df_data,['기타']][0]
incometax = df_data.loc[idx_df_data,['소득세']][0]
localincometax = df_data.loc[idx_df_data,['지방소득세']][0]
idx_df_employee = df_employee.index[df_employee['성명']==name].tolist()[0]
# print("직원현황 인덱스 :",idx_df_employee)
jobposition = df_employee.loc[idx_df_employee,['직위']][0]
department = df_employee.loc[idx_df_employee,['부서']][0]
birthday = df_employee.loc[idx_df_employee,['생일']][0]
# 엑셀 인스턴스 생성
xw.App(visible=False)
book = xw.Book(fname)
sh_paystub = book.sheets('급여명세서사대보험')
sh_paystub["B4"].value = name
sh_paystub["D4"].value = jobposition
sh_paystub["B5"].value = department
sh_paystub["D5"].value = birthday
sh_paystub["B8"].value = normal
sh_paystub["B9"].value = overtime
sh_paystub["B10"].value = holiday
sh_paystub["B11"].value = holidayovertime
sh_paystub["B12"].value = extra
sh_paystub["B13"].value = meals
sh_paystub["D8"].value = nationalpension
sh_paystub["D9"].value = healthinsurance
sh_paystub["D10"].value = longtermcareinsurance
sh_paystub["D11"].value = employmentinsurance
sh_paystub["D12"].value = healthsettlement
sh_paystub["D13"].value = longtermcaresettlement
sh_paystub["D14"].value = advancepayment
sh_paystub["D15"].value = etc
sh_paystub["D16"].value = incometax
sh_paystub["D17"].value = localincometax
sh_paystub["B23"].value = normal_calculation
sh_paystub["B24"].value = overtime_calculation
sh_paystub["B25"].value = holiday_calculation
sh_paystub["B26"].value = holidayovertime_calculation
sh_paystub["B27"].value = extra_calculation
sh_paystub["D23"].value = normal
sh_paystub["D24"].value = overtime
sh_paystub["D25"].value = holiday
sh_paystub["D26"].value = holidayovertime
sh_paystub["D27"].value = extra
# rng = sh_paystub.range("D35")
# sh_paystub.pictures.add(r'B:\python\vscode\excel\millstudio_logo.png', left=rng.left, top=rng.top)
if len(self.lineedit21.text())==0:
book.save()
book.close()
return
# print(len(self.lineedit21.text()))
# pdf 로 저장하기
# current_path = os.getcwd() # 현재 작업중인 폴더에 저장하기
# 절대경로로 파일 위치 입력
subject_before = self.lineedit21.text()
# 문자치환 f-string 사용하여 변수 적용하기
subject = subject_before.replace("{성명}",f'{name}')
pdf_file = os.path.join(self.current_pdf_path, f"{subject}.pdf")
# PDF 로 저장할 시트 선택하기(본 예제에서는 첫 번째 시트 선택하기)
# report_sheet = book.sheets[1]
report_sheet = sh_paystub
# PDF 로 저장하기
# report_sheet.ExportAsFixedFormat(0, pdf_path)
report_sheet.api.ExportAsFixedFormat(0, pdf_file)
book.save()
book.close()
#####################################
def fn_send(self, name, email_i):
# # 메일 서버를 설정합니다.
account_id = self.lineedit11.text().split("@")[0]
emailserver = self.lineedit11.text().split("@")[1]
# self.server = smtplib.SMTP_SSL('smtp.kakao.com')
smtp_server = 'smtp.'+ emailserver
# print(account_id)
self.server = smtplib.SMTP_SSL(smtp_server)
# self.server.login(secret.kakao_id, secret.kakao_pw)
self.server.login(account_id, self.lineedit12.text())
# self.msg_from = 'miero@kakao.com'
self.msg_from = self.lineedit11.text()
# # server = smtplib.SMTP('smtp.com', port_number)
# # server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# server = smtplib.SMTP_SSL('smtp.kakao.com')
# # server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# # 로그인이 필요하면 로그인 설정
# server.login(secret.kakao_id, secret.kakao_pw)
# # 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
# msg_to = email_i
# cc = 'b@b.com, c@c.com'
# cc = ''
# print(name,email_i)
# 메세지 구성
# msg = MIMEBase('multipart','mixed')
msg = MIMEMultipart()
msg['From'] = self.msg_from
msg['To'] = email_i
msg['Date'] = formatdate(localtime=True)
# msg['Subject'] = f'2022년08월급여명세서-{name}'
subject_before = self.lineedit21.text()
# 문자치환 f-string 사용하여 변수 적용하기
subject = subject_before.replace("{성명}",f'{name}')
msg['Subject'] = Header(s=subject, charset='utf-8')
# msg['Subject'] = Header(s=f'2022년08월급여명세서-{name}', charset='utf-8')
# msg['Cc'] = ""
# 메일 본문 작성
# # html 로 되어있던 파일을 불러 오고 거기에 파일을 붙여서 보냅니다.
# msgText = MIMEText('<h1>%s</h1><hr>, <img src="cid:%s" >' % (emailtext, attachment), 'html')
# contents = '<h1>%s</h1>'
# contents += '<hr>'
# contents += '<img src="cid:%s" >'
# msgText = MIMEText(contents % (emailtext, attachment), 'html')
# contents = f'<h1>{emailtext}</h1>'
# contents += f'<h2>{msg_to} 님 메일이 도착했습니다.</h2>'
# contents += '<hr>'
# contents += f'<img src="cid:{attachment}" >'
# msgText = MIMEText(contents, 'html')
# pretext = f'수신: {name}<br/>'
# pretext += '발신: 주식회사 밀앤아이, 주식회사 헴펠 대표이사<br/>'
# pretext += '<br/>'
# msgpreText = MIMEText(pretext, 'html')
# msg.attach(msgpreText)
# contents = self.textedit23.toPlainText()
contents_before = self.textedit23.toPlainText()
# 문자치환 f-string 사용하여 변수 적용하기
contents = contents_before.replace("{성명}",f'수신: {name}')
# msgText = MIMEText(contents, 'plain')
msgText = MIMEText(contents, 'html')
# msgText = MIMEText(contents, _charset='utf-8')
# 메세지를 메일에 붙여 줍니다.
msg.attach(msgText)
# 메일 제일 밑에 로고그림 붙여 줍니다.
# logo_file = "logo.jpg"
# img_f_name = logo_file.replace("\\","/")
# logo_file = r"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' width='10%' height='0%'></center>"
# img_f_name = logo_file.replace("\\","/")
# # with io.open('file_name.html','r') as f:
# with io.open(img_f_name,'r') as f:
# # emailtext = f.read()
# emailtext = img_f_name
# # attachment = 'attachment_file_name.png'
# attachment = img_f_name
# attachment = logo_file
# fp = open(attachment, 'rb')
# img = MIMEImage(fp.read())
# fp.close()
# img.add_header('Content-ID', '<{}>'.format(attachment))
# msg.attach(img)
# 파일첨부
files = list()
pdf_file_name = f"{subject}.pdf"
pdf_file = os.path.join(os.getcwd()+"\pdf", pdf_file_name)
files.append(pdf_file)
# if os.path.isfile(pdf_file):
# binary_pdf = open(pdf_file, 'rb')
# payload = MIMEBase('application', 'octate-stream', Name=pdf_file_name)
# payload.set_payload((binary_pdf).read())
# encoders.encode_base64(payload)
# payload.add_header('Content-Decomposition', 'attachment', filename=pdf_file_name)
# msg.attach(payload)
for i in range(self.listwidget22.count()):
files.append(self.listwidget22.item(i).text())
# print(files)
for f in files:
# print(f)
part = MIMEBase('application', "octet-stream")
part.set_payload(open(f,"rb").read())
encoders.encode_base64(part)
fstr_name = os.path.basename(f)
# part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(f))
part.add_header('Content-Disposition',"attachment", filename= fstr_name, charset='utf-8')
# [출처] 파이썬에서 지메일 보내기(w/첨부파일) 한글파일도 가능|작성자 데이터공방
# Header(s=f'2022년08월급여명세서-{name}', charset='utf-8')
msg.attach(part)
# 메일 서버를 이용하여 메일을 발송합니다.
# server.sendmail(msg_from, msg["To"].split(",") + msg["Cc"].split(","), msg.as_string())
self.server.sendmail(msg['From'], msg['To'], msg.as_string())
# self.server.quit()
# def fn_result_window(self, name, email):
# self.listwidget32.clear()
# cnt = self.listwidget32.count() +1
# # print(cnt, name, email, "전송완료")
# # self.listwidget32.insertItem(cnt,name&email&"전송완료")
# self.listwidget32.insertItem(cnt, f'{name}-{email}-전송완료')
def fn_test(self):
# try:
# 메일 서버를 설정합니다.
# server = smtplib.SMTP('smtp.com', port_number)
# server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# self.server = smtplib.SMTP_SSL('smtp.kakao.com')
# server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# 로그인이 필요하면 로그인 설정
# self.server.login(secret.kakao_id, secret.kakao_pw)
# 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
self.listwidget32.clear()
if len(self.lineedit11.text()) == 0:
QMessageBox.about(self,'이메일계정 확인','이메일계정을 입력하십시요.')
return
p = re.compile('^[a-zA-Z0-9+-_.]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$')
if p.match(self.lineedit11.text()) == None:
# print(p.match(self.lineedit11.text()) != None)
QMessageBox.about(self,'이메일 형식 확인','올바른 이메일 형식이 아닙니다.')
return
if len(self.lineedit12.text()) == 0:
QMessageBox.about(self,'비밀번호 확인','비밀번호를 입력하십시요.')
return
cnt = 0
if len(self.lineedit21.text()) == 0:
QMessageBox.about(self,'제목 입력 확인','제목을 입력하십시요.')
return
self.fn_subject_save()
self.fn_html_save()
self.fn_DeleteAllFiles(os.getcwd()+"\pdf")
self.fn_pdf_create(self.lineedit23.text())
try:
if self.df_table_02.loc[self.lineedit23.text()][0] != "nan":
self.fn_send(self.lineedit23.text(), self.df_table_02.loc[self.lineedit23.text()][0])
cnt += 1
# self.listwidget32.insertItem(cnt, f'{self.lineedit23.text()}-{self.df_table_02.loc[self.lineedit23.text()][0]}-전송완료')
self.listwidget32.addItem(f'{self.lineedit23.text()}-{self.df_table_02.loc[self.lineedit23.text()][0]}-전송완료')
except:
cnt += 1
# self.listwidget32.insertItem(cnt, f'{self.lineedit23.text()}-{self.df_table_02.loc[self.lineedit23.text()][0]}-실패')
# self.listwidget32.item(cnt-1).setBackground(Qt.red)
self.listwidget32.addItem(f'{self.lineedit23.text()}-{self.df_table_02.loc[self.lineedit23.text()][0]}-실패')
self.listwidget32.item(cnt-1).setBackground(Qt.red)
# self.fn_pdf_create("밀1")
# self.fn_send(self.lineedit23.text(), self.df_table_02.loc[self.lineedit23.text()][0])
# cnt += 1
# self.listwidget32.insertItem(cnt, f'{self.lineedit23.text()}-{self.df_table_02.loc[self.lineedit23.text()][0]}-전송완료')
self.server.quit()
# self.app.kill()
# self.fn_print_name(self.lineedit23.text(), self.df_table_02.loc[self.lineedit23.text()][0])
# except: # 예외가 발생했을 때 실행됨
# print('예외가 발생했습니다.')
# self.listwidget32.insertItem(cnt, f'{"밀1"}-{self.df_table_02.loc["밀1"][0]}-실패')
def fn_run(self):
# 메일 서버를 설정합니다.
# server = smtplib.SMTP('smtp.com', port_number)
# server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# server = smtplib.SMTP_SSL('smtp.kakao.com')
# server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# 로그인이 필요하면 로그인 설정
# server.login(secret.kakao_id, secret.kakao_pw)
# 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
self.listwidget32.clear()
if len(self.lineedit11.text()) == 0:
QMessageBox.about(self,'이메일계정 확인','이메일계정을 입력하십시요.')
return
p = re.compile('^[a-zA-Z0-9+-_.]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$')
if p.match(self.lineedit11.text()) == None:
# print(p.match(self.lineedit11.text()) != None)
QMessageBox.about(self,'이메일 형식 확인','올바른 이메일 형식이 아닙니다.')
return
if len(self.lineedit12.text()) == 0:
QMessageBox.about(self,'비밀번호 확인','비밀번호를 입력하십시요.')
return
cnt = 0
if len(self.lineedit21.text()) == 0:
QMessageBox.about(self,'제목 입력 확인','제목을 입력하십시요.')
return
self.fn_subject_save()
self.fn_html_save()
# self.fn_send("밀1", self.df_table_02.loc["밀1"][0])
# self.fn_print_name("밀1", self.df_table_02.loc["밀1"][0])
for idx_name in self.idx_name_list:
# print(idx)
# print(self.df_table_02.loc[idx][0])
# print(idx, table_02.loc[idx][0])
self.fn_DeleteAllFiles(os.getcwd()+"\pdf")
self.fn_pdf_create(idx_name)
try:
if self.df_table_02.loc[idx_name][0] != "nan":
self.fn_send(idx_name, self.df_table_02.loc[idx_name][0])
cnt += 1
self.listwidget32.insertItem(cnt, f'{idx_name}-{self.df_table_02.loc[idx_name][0]}-전송완료')
except:
cnt += 1
self.listwidget32.insertItem(cnt, f'{idx_name}-{self.df_table_02.loc[idx_name][0]}-실패')
self.listwidget32.item(cnt-1).setBackground(Qt.red)
# if self.df_table_02.loc[idx_name][0] == "nan":
# print(self.listwidget32.)
# self.listwidget32.item(cnt).setBackground(Qt.red)
# print("예외가 발생했습니다.-fn_run",cnt,self.df_table_02.loc[idx_name][0])
# self.fn_print_name(idx_name, self.df_table_02.loc[idx_name][0])
self.server.quit()
# self.app.kill()
# print('예외가 발생했습니다.')
# self.listwidget32.insertItem(cnt, f'{idx_name}-{self.df_table_02.loc[idx_name][0]}-실패')
if __name__ == '__main__':
# don't auto scale when drag app to a different monitor.
# QGuiApplication.setHighDpiScaleFactorRoundingPolicy(Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
excel_file_path = '급여1.xlsx'
worksheet_name = '4대급여'
emailsheet_name = '이메일'
app = QApplication(sys.argv)
app.setStyleSheet('''
QWidget {
font-size: 17px;
}
''')
myApp = MyApp()
myApp.show()
try:
sys.exit(app.exec())
except SystemExit:
print('Closing Window...')
====================
pay22.py--------------------
# from operator import index
# from unittest import result
# from xml.dom.minidom import Document
from PyQt5.QtWidgets import QApplication, QWidget, QTableWidget, QTableWidgetItem, QPushButton, \
QHeaderView, QHBoxLayout, QVBoxLayout, QGridLayout, QAbstractScrollArea, QLabel, QListWidget, \
QFileDialog, QMessageBox, QTextEdit, QAbstractItemView, QLineEdit, QGroupBox, QRadioButton
from PyQt5.QtCore import Qt
# from PyQt5 import QtGui
from PyQt5.QtGui import QTextCursor
import sys
import pandas as pd # pip install pandas
import os
import io
import secret
import xlwings as xw
import re
import smtplib
from email.encoders import encode_base64
from email.header import Header
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText # 메일의 본문 내용을 만드는 모듈 내용을 base64형식으로 변환
from email.utils import formatdate
from email.mime.application import MIMEApplication # 메일의 첨부 파일을 base64 형식으로 변환
from email.mime.image import MIMEImage # 메일의 이미지 파일을 base64 형식으로 변환
# 출처: https://nowonbun.tistory.com/684 [명월 일지:티스토리]
from email import encoders
from email.encoders import encode_base64
class MyApp(QWidget):
def __init__(self):
super().__init__()
self.window_width, self.window_height = 1150, 600
self.resize(self.window_width, self.window_height)
self.setWindowTitle('pay')
# self.server = smtplib.SMTP_SSL('smtp.kakao.com')
# self.server.login(secret.kakao_id, secret.kakao_pw)
# self.msg_from = 'miero@kakao.com'
##### layout_main #####
layout_main = QHBoxLayout()
self.setLayout(layout_main)
##### layout_1 #####
layout_1 = QVBoxLayout()
vBox11 = QVBoxLayout()
groupBoxLogin11 = QGroupBox("로그인 정보")
groupBoxLogin11.setLayout(vBox11)
layout_1.addWidget(groupBoxLogin11)
self.label11 = QLabel("이메일계정")
vBox11.addWidget(self.label11)
self.lineedit11 = QLineEdit("miero@kakao.com")
vBox11.addWidget(self.lineedit11)
self.label12 = QLabel("패스워드")
vBox11.addWidget(self.label12)
self.lineedit12 = QLineEdit()
self.lineedit12.setEchoMode(QLineEdit.Password)
# self.lineedit12.show()
vBox11.addWidget(self.lineedit12)
label13 = QLabel('직원 메일')
# self.button = QPushButton('&Load Data')
# self.button.clicked.connect(lambda _, xl_path=excel_file_path, sheet_name=worksheet_name: self.loadExcelData(xl_path, sheet_name))
# layout_v.addWidget(self.button)
layout_1.addWidget(label13)
self.table = QTableWidget()
self.table.setFixedWidth(350)
layout_1.addWidget(self.table)
layout_main.addLayout(layout_1)
##### layout_2 #####
layout_2 = QGridLayout()
label21 = QLabel('이메일 제목')
layout_2.addWidget(label21, 0, 0)
self.lineedit21 = QLineEdit()
layout_2.addWidget(self.lineedit21, 1, 0, 1, 2)
label22 = QLabel('첨부파일')
layout_2.addWidget(label22, 2, 0)
self.listwidget22 = QListWidget()
# self.listwidget22.setFixedWidth(300)
self.listwidget22.setMinimumWidth(400)
# self.listwidget22.setSelectionMode(QAbstractItemView.ExtendedSelection)
layout_2.addWidget(self.listwidget22, 3, 0, 3, 1)
self.btn_file_add = QPushButton('파일 추가') # sendlist
# self.btn_file_add.setMinimumHeight(80)
layout_2.addWidget(self.btn_file_add, 3, 1, 1, 1)
self.btn_file_add.clicked.connect(self.fn_fileadd)
self.btn_file_del = QPushButton('파일 삭제')
layout_2.addWidget(self.btn_file_del, 4, 1, 1, 1)
self.btn_file_del.clicked.connect(self.fn_filedel)
# label21 = QLabel('본문 (HTML형식)')
# layout_2.addWidget(label21, 8, 0)
# radio_1 ~ 4 버튼을 그룹으로 설정
groupBoxMid = QGroupBox("테스트 메일 보내기")
layout_2.addWidget(groupBoxMid, 6, 0, 1, 2)
hBox1 = QHBoxLayout()
groupBoxMid.setLayout(hBox1)
self.label23 = QLabel("성명")
hBox1.addWidget(self.label23)
self.lineedit23 = QLineEdit("정용만") # 이름기본값
hBox1.addWidget(self.lineedit23)
self.pushbutton23 = QPushButton("테스트 보내기")
self.pushbutton23.clicked.connect(self.fn_test)
hBox1.addWidget(self.pushbutton23)
groupBoxBottom = QGroupBox("본문 보기형식 선택")
layout_2.addWidget(groupBoxBottom, 7, 0, 1, 2)
hBox2 = QHBoxLayout()
groupBoxBottom.setLayout(hBox2)
self.radioBtn1 = QRadioButton("HTML")
self.radioBtn1.setChecked(True)
self.radioBtn1.clicked.connect(self.fn_radio_select)
hBox2.addWidget(self.radioBtn1)
self.radioBtn2 = QRadioButton("미리보기")
self.radioBtn2.clicked.connect(self.fn_radio_select)
hBox2.addWidget(self.radioBtn2)
self.textedit23 = QTextEdit()
# self.textedit23.setFixedWidth(400)
# self.textedit23.setAcceptRichText(False)
layout_2.addWidget(self.textedit23, 8, 0, 4, 1)
self.textedit23.show()
self.textedit24 = QTextEdit()
layout_2.addWidget(self.textedit24, 8, 0, 4, 1)
self.textedit24.hide()
self.btn_send = QPushButton("보내기")
self.btn_send.setMaximumHeight(500) # gridlayout button size
layout_2.addWidget(self.btn_send, 8, 1, 4, 1)
self.btn_send.clicked.connect(self.fn_run) #@@@@@@@@@@@@@@@@@@@@@@@@@@
layout_main.addLayout(layout_2)
##### layout_3 #####
layout_3 = QVBoxLayout()
label31 = QLabel('발송 결과')
layout_3.addWidget(label31)
self.listwidget32 = QListWidget()
# self.listwidget32.setMinimumWidth(self.listwidget32.sizeHintForColumn(0))
# self.listwidget32.setWidth(10)
layout_3.addWidget(self.listwidget32)
layout_main.addLayout(layout_3)
# subject0 파일이 존재하면
filename_subject = 'subject0.txt'
if os.path.isfile(filename_subject) == True:
source_text = open(filename_subject,'r', encoding="UTF-8").read()
# self.lineedit21.setText(source_text) # TextEdit에 RichText 형식의 글을 입력합니다.
self.lineedit21.setText(source_text) # TextEdit에 PlainText 형식의 글을 새로 입력합니다.
# html0 파일이 존재하면
filename_html = 'html0.txt'
if os.path.isfile(filename_html) == True:
source_text = open(filename_html,'r', encoding="UTF-8").read()
# self.textedit23.setText(source_text) # TextEdit에 RichText 형식의 글을 입력합니다.
self.textedit23.setPlainText(source_text) # TextEdit에 PlainText 형식의 글을 새로 입력합니다.
# self.textedit24.setHtml(source_text) # TextEdit에 PlainText 형식의 글을 새로 입력합니다.
# table_data = self.loadExcelData(excel_file_path, worksheet_name)
# print(table_data.keys())
# df_table = self.loadExcelData(excel_file_path, worksheet_name)
df_table = self.loadExcelData()
# print(table_df["성명"][0])
self.df_table_02 = df_table.set_index("성명")
self.idx_name_list = self.df_table_02.index.to_list()
# print(index)
# for i in table_02["이메일"]:
def fn_radio_select(self):
# QRadioButton1 클릭 여부 표시
if self.radioBtn1.isChecked():
self.textedit23.show()
self.textedit24.hide()
self.hidden = False
# self.btn_send.setText('보내기')
elif self.radioBtn2.isChecked():
self.fn_html_save()
self.textedit23.hide()
self.textedit24.show()
self.hidden = True
# self.btn_send.setText('미리보기')
# def loadExcelData(self, excel_file_dir, worksheet_name):
def loadExcelData(self):
df_work_sheet = pd.read_excel(excel_file_path, worksheet_name)
df_email_sheet = pd.read_excel(excel_file_path, emailsheet_name)
df_table = df_work_sheet.merge(df_email_sheet, how='left')
df_table_mail = df_table[['성명','이메일']]
res = df_table_mail
# res = df_table_mail.to_dict()
# self.table.setRowCount(df.shape[0])
# self.table.setColumnCount(df.shape[1])
self.table.setRowCount(df_table_mail.shape[0])
self.table.setColumnCount(df_table_mail.shape[1])
# self.table.setHorizontalHeaderLabels(df.columns)
self.table.setHorizontalHeaderLabels(df_table_mail.columns)
header = self.table.horizontalHeader()
# header.setSectionResizeMode(0, QHeaderView.Stretch)
# header.setSectionResizeMode(0, QHeaderView.ResizeToContents)
header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
# returns pandas array object
# for row in df.iterrows():
for row in df_table_mail.iterrows():
values = row[1]
for col_index, value in enumerate(values):
if isinstance(value, (float, int)):
value = '{0:0,.0f}'.format(value)
tableItem = QTableWidgetItem(str(value))
if value == "nan":
tableItem.setBackground(Qt.red)
self.table.setItem(row[0], col_index, tableItem)
self.table.setColumnWidth(2, 310)
return res
def fn_fileadd(self):
# f_name = QFileDialog.getOpenFileName(None, '열기', '', "All Files(*.*)")
f_names = QFileDialog.getOpenFileNames(None, '열기', '', "All Files(*.*)")
# txtPath = f_name[0]
filelist = f_names[0]
if filelist:
for f_name in filelist:
# ext = os.path.splitext(f_name[0])[1]
ext = os.path.splitext(f_name)[1] # 확장자 확인
# if f_names[0]:
icnt = 0
for i in range(self.listwidget22.count()):
# if str(self.listwidget22.item(i).text()) == txtPath.replace("/","\\") or str(self.listwidget22.item(i).text()) == txtPath:
if str(self.listwidget22.item(i).text()) == f_name.replace("/","\\") or str(self.listwidget22.item(i).text()) == f_name:
icnt = 1
break
if icnt != 1:
f_path = f_name
if ext == '.exe':
QMessageBox.about(self,'파일 형식 확인','exe파일은 전송할 수 없습니다.')
pass
else:
cnt = self.listwidget22.count() +1
# self.listwidget22.insertItem(cnt, os.path.basename(txtPath))
# self.listwidget22.insertItem(cnt, txtPath)
# f_path = f_names[0]
# print(f_path)
self.listwidget22.insertItem(cnt, f_path)
# self.listwidget22.insertItem(cnt, f_path.replace("/","\\"))
def fn_filedel(self):
currentrow = self.listwidget22.currentRow()
self.listwidget22.takeItem(currentrow) # currentrowRight번째 항목을 삭제합니다
self.listwidget22.clearSelection()
def fn_subject_save(self):
if len(self.lineedit21.text())>0:
S__File = os.path.join(os.getcwd(),'subject0.txt')
Text = self.lineedit21.text()
if S__File:
# Finally this will Save your file to the path selected.
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
file.write(Text)
def fn_html_save(self):
if len(self.textedit23.toPlainText())>0:
# print(len(self.textedit.toPlainText()))
# S__File = QFileDialog.getSaveFileName(None,'문자 파일저장','/', "Text Files (*.txt)")
# S__File = QFileDialog.getSaveFileName(None,'문자 파일저장','html0', "Text Files (*.txt)")
S__File = os.path.join(os.getcwd(),'html0.txt')
# This will let you access the test in your QTextEdit
Text = self.textedit23.toPlainText()
self.textedit24.setHtml(Text)
# document = self.textedit23.document()
# cursor = QTextCursor(document)
# p1 = cursor.position() # return int
# cursor.insertImage(r"C:\Users\newstep\Pictures\number1.jpg")
# This will prevent you from an error if pressed cancel on file dialog.
# if S__File[0]:
if S__File:
# Finally this will Save your file to the path selected.
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
file.write(Text)
# txtPath = S__File[0]
# icnt = 0
# for i in range(self.listwidget31.count()):
# if str(self.listwidget31.item(i).text()) == txtPath.replace("/","\\"):
# icnt = 1
# break
# if icnt != 1:
# cnt = self.listwidget31.count() +1
# self.listwidget31.insertItem(cnt, os.path.basename(txtPath))
# self.listwidget31.insertItem(cnt, txtPath)
else:
QMessageBox.about(self,'메시지 입력 확인','메시지를 입력하셔야 합니다.')
def fn_print_name(self, name, email):
# f_name_pre = r"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' width='50%' height='0%'></center>"
# f_name = f_name_pre.replace("\\","/")
# with io.open('file_name.html','r') as f:
# with io.open(f_name,'r') as f:
# # emailtext = f.read()
# emailtext = f_name
# attachment = 'attachment_file_name.png'
# attachment = f_name
# print(name, self.df_table_02.loc[name][0])
# print(name, email)
if len(self.textedit23.toPlainText())>0:
S__File = os.path.join(os.getcwd(),'html0.txt')
# print(len(self.textedit23.toPlainText()))
# print(S__File)
# pretext = f'{name} 님<br/><br/>'
# pretext += f'당신의 이메일은 {email} 입니다.<br/>'
contents = self.textedit23.toPlainText()
# nexttext = f'<br/><img src="cid:{attachment}" >'
# nexttext = f"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' id='millstudio logo' width='10%' height='0%'></center>"
# document = self.textedit23.document()
# cursor = QTextCursor(document)
# p1 = cursor.position() # return int
# cursor.insertImage(f_name)
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
# file.write(pretext)
file.write(contents)
# file.write(nexttext)
# print(contents)
# msgText = MIMEText(contents, 'html')
print(name, email, "전송완료")
# self.fn_result_window(name, email)
def fn_DeleteAllFiles(self,filePath):
if os.path.exists(filePath):
for file in os.scandir(filePath):
os.remove(file.path)
return '폴더 내 모든 파일 지우기 완료'
else:
return '폴더가 없습니다.'
def fn_pdf_create(self, idx_name):
#####################################
# xlwings
self.current_pdf_path = os.getcwd()+"\pdf"
# fname = "급여1.xlsx"
fname = excel_file_path
# for n in self.target_name_list:
name = idx_name
df_data = pd.read_excel(fname, sheet_name=worksheet_name)
df_data = df_data.fillna(0)
df_employee = pd.read_excel(fname, sheet_name='직원현황')
idx_df_data = df_data.index[df_data['성명']==name].tolist()[0]
# print("4대급여 인덱스 :",idx_df_data)
normal = df_data.loc[idx_df_data,['기본급']][0]
overtime = df_data.loc[idx_df_data,['연장수당']][0]
holiday = df_data.loc[idx_df_data,['휴일수당']][0]
holidayovertime = df_data.loc[idx_df_data,['휴일연장수당']][0]
extra = df_data.loc[idx_df_data,['추가수당']][0]
meals = df_data.loc[idx_df_data,['식대']][0]
bonus = df_data.loc[idx_df_data,['상여금']][0]
normal_calculation = df_data.loc[idx_df_data,['기']][0]
overtime_calculation = df_data.loc[idx_df_data,['연']][0]
holiday_calculation = df_data.loc[idx_df_data,['휴']][0]
holidayovertime_calculation = df_data.loc[idx_df_data,['휴연']][0]
extra_calculation = df_data.loc[idx_df_data,['추']][0]
nationalpension = df_data.loc[idx_df_data,['국민연금']][0]
healthinsurance = df_data.loc[idx_df_data,['건강보험']][0]
longtermcareinsurance = df_data.loc[idx_df_data,['장기요양보험']][0]
employmentinsurance = df_data.loc[idx_df_data,['고용보험']][0]
healthsettlement = df_data.loc[idx_df_data,['정산건강']][0]
longtermcaresettlement = df_data.loc[idx_df_data,['정산장기요양']][0]
advancepayment = df_data.loc[idx_df_data,['선지급']][0]
etc = df_data.loc[idx_df_data,['기타']][0]
incometax = df_data.loc[idx_df_data,['소득세']][0]
localincometax = df_data.loc[idx_df_data,['지방소득세']][0]
idx_df_employee = df_employee.index[df_employee['성명']==name].tolist()[0]
# print("직원현황 인덱스 :",idx_df_employee)
jobposition = df_employee.loc[idx_df_employee,['직위']][0]
department = df_employee.loc[idx_df_employee,['부서']][0]
birthday = df_employee.loc[idx_df_employee,['생일']][0]
# 엑셀 인스턴스 생성
xw.App(visible=False)
book = xw.Book(fname)
sh_paystub = book.sheets('급여명세서사대보험')
sh_paystub["B4"].value = name
sh_paystub["D4"].value = jobposition
sh_paystub["B5"].value = department
sh_paystub["D5"].value = birthday
sh_paystub["B8"].value = normal
sh_paystub["B9"].value = overtime
sh_paystub["B10"].value = holiday
sh_paystub["B11"].value = holidayovertime
sh_paystub["B12"].value = extra
sh_paystub["B13"].value = meals
sh_paystub["D8"].value = nationalpension
sh_paystub["D9"].value = healthinsurance
sh_paystub["D10"].value = longtermcareinsurance
sh_paystub["D11"].value = employmentinsurance
sh_paystub["D12"].value = healthsettlement
sh_paystub["D13"].value = longtermcaresettlement
sh_paystub["D14"].value = advancepayment
sh_paystub["D15"].value = etc
sh_paystub["D16"].value = incometax
sh_paystub["D17"].value = localincometax
sh_paystub["B23"].value = normal_calculation
sh_paystub["B24"].value = overtime_calculation
sh_paystub["B25"].value = holiday_calculation
sh_paystub["B26"].value = holidayovertime_calculation
sh_paystub["B27"].value = extra_calculation
sh_paystub["D23"].value = normal
sh_paystub["D24"].value = overtime
sh_paystub["D25"].value = holiday
sh_paystub["D26"].value = holidayovertime
sh_paystub["D27"].value = extra
# rng = sh_paystub.range("D35")
# sh_paystub.pictures.add(r'B:\python\vscode\excel\millstudio_logo.png', left=rng.left, top=rng.top)
if len(self.lineedit21.text())==0:
book.save()
book.close()
return
# print(len(self.lineedit21.text()))
# pdf 로 저장하기
# current_path = os.getcwd() # 현재 작업중인 폴더에 저장하기
# 절대경로로 파일 위치 입력
subject_before = self.lineedit21.text()
# 문자치환 f-string 사용하여 변수 적용하기
subject = subject_before.replace("{성명}",f'{name}')
pdf_file = os.path.join(self.current_pdf_path, f"{subject}.pdf")
# PDF 로 저장할 시트 선택하기(본 예제에서는 첫 번째 시트 선택하기)
# report_sheet = book.sheets[1]
report_sheet = sh_paystub
# PDF 로 저장하기
# report_sheet.ExportAsFixedFormat(0, pdf_path)
report_sheet.api.ExportAsFixedFormat(0, pdf_file)
book.save()
book.close()
#####################################
def fn_send(self, name, email_i):
# # 메일 서버를 설정합니다.
account_id = self.lineedit11.text().split("@")[0]
emailserver = self.lineedit11.text().split("@")[1]
# self.server = smtplib.SMTP_SSL('smtp.kakao.com')
smtp_server = 'smtp.'+ emailserver
# print(account_id)
self.server = smtplib.SMTP_SSL(smtp_server)
# self.server.login(secret.kakao_id, secret.kakao_pw)
self.server.login(account_id, self.lineedit12.text())
# self.msg_from = 'miero@kakao.com'
self.msg_from = self.lineedit11.text()
# # server = smtplib.SMTP('smtp.com', port_number)
# # server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# server = smtplib.SMTP_SSL('smtp.kakao.com')
# # server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# # 로그인이 필요하면 로그인 설정
# server.login(secret.kakao_id, secret.kakao_pw)
# # 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
# msg_to = email_i
# cc = 'b@b.com, c@c.com'
# cc = ''
# print(name,email_i)
# 메세지 구성
# msg = MIMEBase('multipart','mixed')
msg = MIMEMultipart()
msg['From'] = self.msg_from
msg['To'] = email_i
msg['Date'] = formatdate(localtime=True)
# msg['Subject'] = f'2022년08월급여명세서-{name}'
subject_before = self.lineedit21.text()
# 문자치환 f-string 사용하여 변수 적용하기
subject = subject_before.replace("{성명}",f'{name}')
msg['Subject'] = Header(s=subject, charset='utf-8')
# msg['Subject'] = Header(s=f'2022년08월급여명세서-{name}', charset='utf-8')
# msg['Cc'] = ""
# 메일 본문 작성
# # html 로 되어있던 파일을 불러 오고 거기에 파일을 붙여서 보냅니다.
# msgText = MIMEText('<h1>%s</h1><hr>, <img src="cid:%s" >' % (emailtext, attachment), 'html')
# contents = '<h1>%s</h1>'
# contents += '<hr>'
# contents += '<img src="cid:%s" >'
# msgText = MIMEText(contents % (emailtext, attachment), 'html')
# contents = f'<h1>{emailtext}</h1>'
# contents += f'<h2>{msg_to} 님 메일이 도착했습니다.</h2>'
# contents += '<hr>'
# contents += f'<img src="cid:{attachment}" >'
# msgText = MIMEText(contents, 'html')
# pretext = f'수신: {name}<br/>'
# pretext += '발신: 주식회사 밀앤아이, 주식회사 헴펠 대표이사<br/>'
# pretext += '<br/>'
# msgpreText = MIMEText(pretext, 'html')
# msg.attach(msgpreText)
# contents = self.textedit23.toPlainText()
contents_before = self.textedit23.toPlainText()
# 문자치환 f-string 사용하여 변수 적용하기
contents = contents_before.replace("{성명}",f'수신: {name}')
# msgText = MIMEText(contents, 'plain')
msgText = MIMEText(contents, 'html')
# msgText = MIMEText(contents, _charset='utf-8')
# 메세지를 메일에 붙여 줍니다.
msg.attach(msgText)
# 메일 제일 밑에 로고그림 붙여 줍니다.
# logo_file = "logo.jpg"
# img_f_name = logo_file.replace("\\","/")
# logo_file = r"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' width='10%' height='0%'></center>"
# img_f_name = logo_file.replace("\\","/")
# # with io.open('file_name.html','r') as f:
# with io.open(img_f_name,'r') as f:
# # emailtext = f.read()
# emailtext = img_f_name
# # attachment = 'attachment_file_name.png'
# attachment = img_f_name
# attachment = logo_file
# fp = open(attachment, 'rb')
# img = MIMEImage(fp.read())
# fp.close()
# img.add_header('Content-ID', '<{}>'.format(attachment))
# msg.attach(img)
# 파일첨부
files = list()
pdf_file_name = f"{subject}.pdf"
pdf_file = os.path.join(os.getcwd()+"\pdf", pdf_file_name)
files.append(pdf_file)
# if os.path.isfile(pdf_file):
# binary_pdf = open(pdf_file, 'rb')
# payload = MIMEBase('application', 'octate-stream', Name=pdf_file_name)
# payload.set_payload((binary_pdf).read())
# encoders.encode_base64(payload)
# payload.add_header('Content-Decomposition', 'attachment', filename=pdf_file_name)
# msg.attach(payload)
for i in range(self.listwidget22.count()):
files.append(self.listwidget22.item(i).text())
# print(files)
for f in files:
# print(f)
part = MIMEBase('application', "octet-stream")
part.set_payload(open(f,"rb").read())
encoders.encode_base64(part)
fstr_name = os.path.basename(f)
# part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(f))
part.add_header('Content-Disposition',"attachment", filename= fstr_name, charset='utf-8')
# [출처] 파이썬에서 지메일 보내기(w/첨부파일) 한글파일도 가능|작성자 데이터공방
# Header(s=f'2022년08월급여명세서-{name}', charset='utf-8')
msg.attach(part)
# 메일 서버를 이용하여 메일을 발송합니다.
# server.sendmail(msg_from, msg["To"].split(",") + msg["Cc"].split(","), msg.as_string())
self.server.sendmail(msg['From'], msg['To'], msg.as_string())
# self.server.quit()
# def fn_result_window(self, name, email):
# self.listwidget32.clear()
# cnt = self.listwidget32.count() +1
# # print(cnt, name, email, "전송완료")
# # self.listwidget32.insertItem(cnt,name&email&"전송완료")
# self.listwidget32.insertItem(cnt, f'{name}-{email}-전송완료')
def fn_test(self):
# try:
# 메일 서버를 설정합니다.
# server = smtplib.SMTP('smtp.com', port_number)
# server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# self.server = smtplib.SMTP_SSL('smtp.kakao.com')
# server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# 로그인이 필요하면 로그인 설정
# self.server.login(secret.kakao_id, secret.kakao_pw)
# 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
self.listwidget32.clear()
if len(self.lineedit11.text()) == 0:
QMessageBox.about(self,'이메일계정 확인','이메일계정을 입력하십시요.')
return
p = re.compile('^[a-zA-Z0-9+-_.]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$')
if p.match(self.lineedit11.text()) == None:
# print(p.match(self.lineedit11.text()) != None)
QMessageBox.about(self,'이메일 형식 확인','올바른 이메일 형식이 아닙니다.')
return
if len(self.lineedit12.text()) == 0:
QMessageBox.about(self,'비밀번호 확인','비밀번호를 입력하십시요.')
return
cnt = 0
if len(self.lineedit21.text()) == 0:
QMessageBox.about(self,'제목 입력 확인','제목을 입력하십시요.')
return
self.fn_subject_save()
self.fn_html_save()
self.fn_DeleteAllFiles(os.getcwd()+"\pdf")
self.fn_pdf_create(self.lineedit23.text())
try:
if self.df_table_02.loc[self.lineedit23.text()][0] != "nan":
self.fn_send(self.lineedit23.text(), self.df_table_02.loc[self.lineedit23.text()][0])
cnt += 1
# self.listwidget32.insertItem(cnt, f'{self.lineedit23.text()}-{self.df_table_02.loc[self.lineedit23.text()][0]}-전송완료')
self.listwidget32.addItem(f'{self.lineedit23.text()}-{self.df_table_02.loc[self.lineedit23.text()][0]}-전송완료')
except:
cnt += 1
# self.listwidget32.insertItem(cnt, f'{self.lineedit23.text()}-{self.df_table_02.loc[self.lineedit23.text()][0]}-실패')
# self.listwidget32.item(cnt-1).setBackground(Qt.red)
self.listwidget32.addItem(f'{self.lineedit23.text()}-{self.df_table_02.loc[self.lineedit23.text()][0]}-실패')
self.listwidget32.item(cnt-1).setBackground(Qt.red)
# self.fn_pdf_create("밀1")
# self.fn_send(self.lineedit23.text(), self.df_table_02.loc[self.lineedit23.text()][0])
# cnt += 1
# self.listwidget32.insertItem(cnt, f'{self.lineedit23.text()}-{self.df_table_02.loc[self.lineedit23.text()][0]}-전송완료')
self.server.quit()
# self.app.kill()
# self.fn_print_name(self.lineedit23.text(), self.df_table_02.loc[self.lineedit23.text()][0])
# except: # 예외가 발생했을 때 실행됨
# print('예외가 발생했습니다.')
# self.listwidget32.insertItem(cnt, f'{"밀1"}-{self.df_table_02.loc["밀1"][0]}-실패')
QMessageBox.about(self,'전송 완료','전송 작업 완료')
def fn_run(self):
# 메일 서버를 설정합니다.
# server = smtplib.SMTP('smtp.com', port_number)
# server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# server = smtplib.SMTP_SSL('smtp.kakao.com')
# server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# 로그인이 필요하면 로그인 설정
# server.login(secret.kakao_id, secret.kakao_pw)
# 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
self.listwidget32.clear()
if len(self.lineedit11.text()) == 0:
QMessageBox.about(self,'이메일계정 확인','이메일계정을 입력하십시요.')
return
p = re.compile('^[a-zA-Z0-9+-_.]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$')
if p.match(self.lineedit11.text()) == None:
# print(p.match(self.lineedit11.text()) != None)
QMessageBox.about(self,'이메일 형식 확인','올바른 이메일 형식이 아닙니다.')
return
if len(self.lineedit12.text()) == 0:
QMessageBox.about(self,'비밀번호 확인','비밀번호를 입력하십시요.')
return
cnt = 0
if len(self.lineedit21.text()) == 0:
QMessageBox.about(self,'제목 입력 확인','제목을 입력하십시요.')
return
self.fn_subject_save()
self.fn_html_save()
# self.fn_send("밀1", self.df_table_02.loc["밀1"][0])
# self.fn_print_name("밀1", self.df_table_02.loc["밀1"][0])
for idx_name in self.idx_name_list:
# print(idx)
# print(self.df_table_02.loc[idx][0])
# print(idx, table_02.loc[idx][0])
self.fn_DeleteAllFiles(os.getcwd()+"\pdf")
self.fn_pdf_create(idx_name)
try:
if self.df_table_02.loc[idx_name][0] != "nan":
self.fn_send(idx_name, self.df_table_02.loc[idx_name][0])
cnt += 1
self.listwidget32.insertItem(cnt, f'{idx_name}-{self.df_table_02.loc[idx_name][0]}-전송완료')
except:
cnt += 1
self.listwidget32.insertItem(cnt, f'{idx_name}-{self.df_table_02.loc[idx_name][0]}-실패')
self.listwidget32.item(cnt-1).setBackground(Qt.red)
# if self.df_table_02.loc[idx_name][0] == "nan":
# print(self.listwidget32.)
# self.listwidget32.item(cnt).setBackground(Qt.red)
# print("예외가 발생했습니다.-fn_run",cnt,self.df_table_02.loc[idx_name][0])
# self.fn_print_name(idx_name, self.df_table_02.loc[idx_name][0])
self.server.quit()
# self.app.kill()
# print('예외가 발생했습니다.')
# self.listwidget32.insertItem(cnt, f'{idx_name}-{self.df_table_02.loc[idx_name][0]}-실패')
QMessageBox.about(self,'전송 완료','전송 작업 완료')
if __name__ == '__main__':
# don't auto scale when drag app to a different monitor.
# QGuiApplication.setHighDpiScaleFactorRoundingPolicy(Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
excel_file_path = '급여1.xlsx'
worksheet_name = '4대급여'
emailsheet_name = '이메일'
app = QApplication(sys.argv)
app.setStyleSheet('''
QWidget {
font-size: 17px;
}
''')
myApp = MyApp()
myApp.show()
try:
sys.exit(app.exec())
except SystemExit:
print('Closing Window...')
====================
pay23.py--------------------
# from operator import index
# from unittest import result
# from xml.dom.minidom import Document
from PyQt5.QtWidgets import QApplication, QWidget, QTableWidget, QTableWidgetItem, QPushButton, \
QHeaderView, QHBoxLayout, QVBoxLayout, QGridLayout, QAbstractScrollArea, QLabel, QListWidget, \
QFileDialog, QMessageBox, QTextEdit, QAbstractItemView, QLineEdit, QGroupBox, QRadioButton
from PyQt5.QtCore import Qt
# from PyQt5 import QtGui
from PyQt5.QtGui import QTextCursor
import sys
import pandas as pd # pip install pandas
import os
import io
import secret
import xlwings as xw
import re
import smtplib
from email.encoders import encode_base64
from email.header import Header
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText # 메일의 본문 내용을 만드는 모듈 내용을 base64형식으로 변환
from email.utils import formatdate
from email.mime.application import MIMEApplication # 메일의 첨부 파일을 base64 형식으로 변환
from email.mime.image import MIMEImage # 메일의 이미지 파일을 base64 형식으로 변환
# 출처: https://nowonbun.tistory.com/684 [명월 일지:티스토리]
from email import encoders
from email.encoders import encode_base64
class MyApp(QWidget):
def __init__(self):
super().__init__()
self.window_width, self.window_height = 1150, 600
self.resize(self.window_width, self.window_height)
self.setWindowTitle('pay')
# self.server = smtplib.SMTP_SSL('smtp.kakao.com')
# self.server.login(secret.kakao_id, secret.kakao_pw)
# self.msg_from = 'miero@kakao.com'
##### layout_main #####
layout_main = QHBoxLayout()
self.setLayout(layout_main)
##### layout_1 #####
layout_1 = QVBoxLayout()
vBox11 = QVBoxLayout()
groupBoxLogin11 = QGroupBox("로그인 정보")
groupBoxLogin11.setLayout(vBox11)
layout_1.addWidget(groupBoxLogin11)
self.label11 = QLabel("이메일계정")
vBox11.addWidget(self.label11)
self.lineedit11 = QLineEdit("miero@kakao.com")
vBox11.addWidget(self.lineedit11)
self.label12 = QLabel("패스워드")
vBox11.addWidget(self.label12)
self.lineedit12 = QLineEdit()
self.lineedit12.setEchoMode(QLineEdit.Password)
# self.lineedit12.show()
vBox11.addWidget(self.lineedit12)
label13 = QLabel('직원 메일')
# self.button = QPushButton('&Load Data')
# self.button.clicked.connect(lambda _, xl_path=excel_file_path, sheet_name=worksheet_name: self.loadExcelData(xl_path, sheet_name))
# layout_v.addWidget(self.button)
layout_1.addWidget(label13)
self.table = QTableWidget()
self.table.setFixedWidth(350)
layout_1.addWidget(self.table)
layout_main.addLayout(layout_1)
##### layout_2 #####
layout_2 = QGridLayout()
label21 = QLabel('이메일 제목')
layout_2.addWidget(label21, 0, 0)
self.lineedit21 = QLineEdit()
layout_2.addWidget(self.lineedit21, 1, 0, 1, 2)
label22 = QLabel('첨부파일')
layout_2.addWidget(label22, 2, 0)
self.listwidget22 = QListWidget()
# self.listwidget22.setFixedWidth(300)
self.listwidget22.setMinimumWidth(400)
# self.listwidget22.setSelectionMode(QAbstractItemView.ExtendedSelection)
layout_2.addWidget(self.listwidget22, 3, 0, 3, 1)
self.btn_file_add = QPushButton('파일 추가') # sendlist
# self.btn_file_add.setMinimumHeight(80)
layout_2.addWidget(self.btn_file_add, 3, 1, 1, 1)
self.btn_file_add.clicked.connect(self.fn_fileadd)
self.btn_file_del = QPushButton('파일 삭제')
layout_2.addWidget(self.btn_file_del, 4, 1, 1, 1)
self.btn_file_del.clicked.connect(self.fn_filedel)
# label21 = QLabel('본문 (HTML형식)')
# layout_2.addWidget(label21, 8, 0)
# radio_1 ~ 4 버튼을 그룹으로 설정
groupBoxMid = QGroupBox("테스트 메일 보내기")
layout_2.addWidget(groupBoxMid, 6, 0, 1, 2)
hBox1 = QHBoxLayout()
groupBoxMid.setLayout(hBox1)
self.label23 = QLabel("성명")
hBox1.addWidget(self.label23)
self.lineedit23 = QLineEdit("정용만") # 이름기본값
hBox1.addWidget(self.lineedit23)
self.pushbutton23 = QPushButton("테스트 보내기")
self.pushbutton23.clicked.connect(self.fn_test)
hBox1.addWidget(self.pushbutton23)
groupBoxBottom = QGroupBox("본문 보기형식 선택")
layout_2.addWidget(groupBoxBottom, 7, 0, 1, 2)
hBox2 = QHBoxLayout()
groupBoxBottom.setLayout(hBox2)
self.radioBtn1 = QRadioButton("HTML")
self.radioBtn1.setChecked(True)
self.radioBtn1.clicked.connect(self.fn_radio_select)
hBox2.addWidget(self.radioBtn1)
self.radioBtn2 = QRadioButton("미리보기")
self.radioBtn2.clicked.connect(self.fn_radio_select)
hBox2.addWidget(self.radioBtn2)
self.textedit23 = QTextEdit()
# self.textedit23.setFixedWidth(400)
# self.textedit23.setAcceptRichText(False)
layout_2.addWidget(self.textedit23, 8, 0, 4, 1)
self.textedit23.show()
self.textedit24 = QTextEdit()
layout_2.addWidget(self.textedit24, 8, 0, 4, 1)
self.textedit24.hide()
self.btn_send = QPushButton("보내기")
self.btn_send.setMaximumHeight(500) # gridlayout button size
layout_2.addWidget(self.btn_send, 8, 1, 4, 1)
self.btn_send.clicked.connect(self.fn_run) #@@@@@@@@@@@@@@@@@@@@@@@@@@
layout_main.addLayout(layout_2)
##### layout_3 #####
layout_3 = QVBoxLayout()
label31 = QLabel('발송 결과')
layout_3.addWidget(label31)
self.listwidget32 = QListWidget()
# self.listwidget32.setMinimumWidth(self.listwidget32.sizeHintForColumn(0))
# self.listwidget32.setWidth(10)
layout_3.addWidget(self.listwidget32)
layout_main.addLayout(layout_3)
# subject0 파일이 존재하면
filename_subject = 'subject0.txt'
if os.path.isfile(filename_subject) == True:
source_text = open(filename_subject,'r', encoding="UTF-8").read()
# self.lineedit21.setText(source_text) # TextEdit에 RichText 형식의 글을 입력합니다.
self.lineedit21.setText(source_text) # TextEdit에 PlainText 형식의 글을 새로 입력합니다.
# html0 파일이 존재하면
filename_html = 'html0.txt'
if os.path.isfile(filename_html) == True:
source_text = open(filename_html,'r', encoding="UTF-8").read()
# self.textedit23.setText(source_text) # TextEdit에 RichText 형식의 글을 입력합니다.
self.textedit23.setPlainText(source_text) # TextEdit에 PlainText 형식의 글을 새로 입력합니다.
# self.textedit24.setHtml(source_text) # TextEdit에 PlainText 형식의 글을 새로 입력합니다.
# table_data = self.loadExcelData(excel_file_path, worksheet_name)
# print(table_data.keys())
# df_table = self.loadExcelData(excel_file_path, worksheet_name)
df_table = self.loadExcelData()
# print(table_df["성명"][0])
self.df_table_02 = df_table.set_index("성명")
self.idx_name_list = self.df_table_02.index.to_list()
# print(index)
# for i in table_02["이메일"]:
def fn_radio_select(self):
# QRadioButton1 클릭 여부 표시
if self.radioBtn1.isChecked():
self.textedit23.show()
self.textedit24.hide()
self.hidden = False
# self.btn_send.setText('보내기')
elif self.radioBtn2.isChecked():
self.fn_html_save()
self.textedit23.hide()
self.textedit24.show()
self.hidden = True
# self.btn_send.setText('미리보기')
# def loadExcelData(self, excel_file_dir, worksheet_name):
def loadExcelData(self):
df_work_sheet = pd.read_excel(excel_file_path, worksheet_name)
df_email_sheet = pd.read_excel(excel_file_path, emailsheet_name)
df_table = df_work_sheet.merge(df_email_sheet, how='left')
df_table_mail = df_table[['성명','이메일']]
res = df_table_mail
# res = df_table_mail.to_dict()
# self.table.setRowCount(df.shape[0])
# self.table.setColumnCount(df.shape[1])
self.table.setRowCount(df_table_mail.shape[0])
self.table.setColumnCount(df_table_mail.shape[1])
# self.table.setHorizontalHeaderLabels(df.columns)
self.table.setHorizontalHeaderLabels(df_table_mail.columns)
header = self.table.horizontalHeader()
# header.setSectionResizeMode(0, QHeaderView.Stretch)
# header.setSectionResizeMode(0, QHeaderView.ResizeToContents)
header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
# returns pandas array object
# for row in df.iterrows():
for row in df_table_mail.iterrows():
values = row[1]
for col_index, value in enumerate(values):
if isinstance(value, (float, int)):
value = '{0:0,.0f}'.format(value)
tableItem = QTableWidgetItem(str(value))
if value == "nan":
tableItem.setBackground(Qt.red)
self.table.setItem(row[0], col_index, tableItem)
self.table.setColumnWidth(2, 310)
return res
def fn_fileadd(self):
# f_name = QFileDialog.getOpenFileName(None, '열기', '', "All Files(*.*)")
f_names = QFileDialog.getOpenFileNames(None, '열기', '', "All Files(*.*)")
# txtPath = f_name[0]
filelist = f_names[0]
if filelist:
for f_name in filelist:
# ext = os.path.splitext(f_name[0])[1]
ext = os.path.splitext(f_name)[1] # 확장자 확인
# if f_names[0]:
icnt = 0
for i in range(self.listwidget22.count()):
# if str(self.listwidget22.item(i).text()) == txtPath.replace("/","\\") or str(self.listwidget22.item(i).text()) == txtPath:
if str(self.listwidget22.item(i).text()) == f_name.replace("/","\\") or str(self.listwidget22.item(i).text()) == f_name:
icnt = 1
break
if icnt != 1:
f_path = f_name
if ext == '.exe':
QMessageBox.about(self,'파일 형식 확인','exe파일은 전송할 수 없습니다.')
pass
else:
cnt = self.listwidget22.count() +1
# self.listwidget22.insertItem(cnt, os.path.basename(txtPath))
# self.listwidget22.insertItem(cnt, txtPath)
# f_path = f_names[0]
# print(f_path)
self.listwidget22.insertItem(cnt, f_path)
# self.listwidget22.insertItem(cnt, f_path.replace("/","\\"))
def fn_filedel(self):
currentrow = self.listwidget22.currentRow()
self.listwidget22.takeItem(currentrow) # currentrowRight번째 항목을 삭제합니다
self.listwidget22.clearSelection()
def fn_subject_save(self):
if len(self.lineedit21.text())>0:
S__File = os.path.join(os.getcwd(),'subject0.txt')
Text = self.lineedit21.text()
if S__File:
# Finally this will Save your file to the path selected.
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
file.write(Text)
def fn_html_save(self):
if len(self.textedit23.toPlainText())>0:
# print(len(self.textedit.toPlainText()))
# S__File = QFileDialog.getSaveFileName(None,'문자 파일저장','/', "Text Files (*.txt)")
# S__File = QFileDialog.getSaveFileName(None,'문자 파일저장','html0', "Text Files (*.txt)")
S__File = os.path.join(os.getcwd(),'html0.txt')
# This will let you access the test in your QTextEdit
Text = self.textedit23.toPlainText()
self.textedit24.setHtml(Text)
# document = self.textedit23.document()
# cursor = QTextCursor(document)
# p1 = cursor.position() # return int
# cursor.insertImage(r"C:\Users\newstep\Pictures\number1.jpg")
# This will prevent you from an error if pressed cancel on file dialog.
# if S__File[0]:
if S__File:
# Finally this will Save your file to the path selected.
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
file.write(Text)
# txtPath = S__File[0]
# icnt = 0
# for i in range(self.listwidget31.count()):
# if str(self.listwidget31.item(i).text()) == txtPath.replace("/","\\"):
# icnt = 1
# break
# if icnt != 1:
# cnt = self.listwidget31.count() +1
# self.listwidget31.insertItem(cnt, os.path.basename(txtPath))
# self.listwidget31.insertItem(cnt, txtPath)
else:
QMessageBox.about(self,'메시지 입력 확인','메시지를 입력하셔야 합니다.')
def fn_print_name(self, name, email):
# f_name_pre = r"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' width='50%' height='0%'></center>"
# f_name = f_name_pre.replace("\\","/")
# with io.open('file_name.html','r') as f:
# with io.open(f_name,'r') as f:
# # emailtext = f.read()
# emailtext = f_name
# attachment = 'attachment_file_name.png'
# attachment = f_name
# print(name, self.df_table_02.loc[name][0])
# print(name, email)
if len(self.textedit23.toPlainText())>0:
S__File = os.path.join(os.getcwd(),'html0.txt')
# print(len(self.textedit23.toPlainText()))
# print(S__File)
# pretext = f'{name} 님<br/><br/>'
# pretext += f'당신의 이메일은 {email} 입니다.<br/>'
contents = self.textedit23.toPlainText()
# nexttext = f'<br/><img src="cid:{attachment}" >'
# nexttext = f"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' id='millstudio logo' width='10%' height='0%'></center>"
# document = self.textedit23.document()
# cursor = QTextCursor(document)
# p1 = cursor.position() # return int
# cursor.insertImage(f_name)
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
# file.write(pretext)
file.write(contents)
# file.write(nexttext)
# print(contents)
# msgText = MIMEText(contents, 'html')
print(name, email, "전송완료")
# self.fn_result_window(name, email)
def fn_DeleteAllFiles(self,filePath):
if os.path.exists(filePath):
for file in os.scandir(filePath):
os.remove(file.path)
return '폴더 내 모든 파일 지우기 완료'
else:
return '폴더가 없습니다.'
def fn_pdf_create(self, idx_name):
#####################################
# xlwings
self.current_pdf_path = os.getcwd()+"\pdf"
# fname = "급여1.xlsx"
fname = excel_file_path
# for n in self.target_name_list:
name = idx_name
df_data = pd.read_excel(fname, sheet_name=worksheet_name)
df_data = df_data.fillna(0)
df_employee = pd.read_excel(fname, sheet_name='직원현황')
idx_df_data = df_data.index[df_data['성명']==name].tolist()[0]
# print("4대급여 인덱스 :",idx_df_data)
normal = df_data.loc[idx_df_data,['기본급']][0]
overtime = df_data.loc[idx_df_data,['연장수당']][0]
holiday = df_data.loc[idx_df_data,['휴일수당']][0]
holidayovertime = df_data.loc[idx_df_data,['휴일연장수당']][0]
extra = df_data.loc[idx_df_data,['추가수당']][0]
meals = df_data.loc[idx_df_data,['식대']][0]
bonus = df_data.loc[idx_df_data,['상여금']][0]
normal_calculation = df_data.loc[idx_df_data,['기']][0]
overtime_calculation = df_data.loc[idx_df_data,['연']][0]
holiday_calculation = df_data.loc[idx_df_data,['휴']][0]
holidayovertime_calculation = df_data.loc[idx_df_data,['휴연']][0]
extra_calculation = df_data.loc[idx_df_data,['추']][0]
nationalpension = df_data.loc[idx_df_data,['국민연금']][0]
healthinsurance = df_data.loc[idx_df_data,['건강보험']][0]
longtermcareinsurance = df_data.loc[idx_df_data,['장기요양보험']][0]
employmentinsurance = df_data.loc[idx_df_data,['고용보험']][0]
healthsettlement = df_data.loc[idx_df_data,['정산건강']][0]
longtermcaresettlement = df_data.loc[idx_df_data,['정산장기요양']][0]
advancepayment = df_data.loc[idx_df_data,['선지급']][0]
etc = df_data.loc[idx_df_data,['기타']][0]
incometax = df_data.loc[idx_df_data,['소득세']][0]
localincometax = df_data.loc[idx_df_data,['지방소득세']][0]
idx_df_employee = df_employee.index[df_employee['성명']==name].tolist()[0]
# print("직원현황 인덱스 :",idx_df_employee)
jobposition = df_employee.loc[idx_df_employee,['직위']][0]
department = df_employee.loc[idx_df_employee,['부서']][0]
birthday = df_employee.loc[idx_df_employee,['생일']][0]
# 엑셀 인스턴스 생성
xw.App(visible=False)
book = xw.Book(fname)
sh_paystub = book.sheets('급여명세서사대보험')
sh_paystub["B4"].value = name
sh_paystub["D4"].value = jobposition
sh_paystub["B5"].value = department
sh_paystub["D5"].value = birthday
sh_paystub["B8"].value = normal
sh_paystub["B9"].value = overtime
sh_paystub["B10"].value = holiday
sh_paystub["B11"].value = holidayovertime
sh_paystub["B12"].value = extra
sh_paystub["B13"].value = meals
sh_paystub["D8"].value = nationalpension
sh_paystub["D9"].value = healthinsurance
sh_paystub["D10"].value = longtermcareinsurance
sh_paystub["D11"].value = employmentinsurance
sh_paystub["D12"].value = healthsettlement
sh_paystub["D13"].value = longtermcaresettlement
sh_paystub["D14"].value = advancepayment
sh_paystub["D15"].value = etc
sh_paystub["D16"].value = incometax
sh_paystub["D17"].value = localincometax
sh_paystub["B23"].value = normal_calculation
sh_paystub["B24"].value = overtime_calculation
sh_paystub["B25"].value = holiday_calculation
sh_paystub["B26"].value = holidayovertime_calculation
sh_paystub["B27"].value = extra_calculation
sh_paystub["D23"].value = normal
sh_paystub["D24"].value = overtime
sh_paystub["D25"].value = holiday
sh_paystub["D26"].value = holidayovertime
sh_paystub["D27"].value = extra
# rng = sh_paystub.range("D35")
# sh_paystub.pictures.add(r'B:\python\vscode\excel\millstudio_logo.png', left=rng.left, top=rng.top)
if len(self.lineedit21.text())==0:
book.save()
book.close()
return
# print(len(self.lineedit21.text()))
# pdf 로 저장하기
# current_path = os.getcwd() # 현재 작업중인 폴더에 저장하기
# 절대경로로 파일 위치 입력
subject_before = self.lineedit21.text()
# 문자치환 f-string 사용하여 변수 적용하기
subject = subject_before.replace("{성명}",f'{name}')
pdf_file = os.path.join(self.current_pdf_path, f"{subject}.pdf")
# PDF 로 저장할 시트 선택하기(본 예제에서는 첫 번째 시트 선택하기)
# report_sheet = book.sheets[1]
report_sheet = sh_paystub
# PDF 로 저장하기
# report_sheet.ExportAsFixedFormat(0, pdf_path)
report_sheet.api.ExportAsFixedFormat(0, pdf_file)
book.save()
book.close()
#####################################
def fn_send(self, name, email_i):
# # 메일 서버를 설정합니다.
account_id = self.lineedit11.text().split("@")[0]
emailserver = self.lineedit11.text().split("@")[1]
# self.server = smtplib.SMTP_SSL('smtp.kakao.com')
smtp_server = 'smtp.'+ emailserver
# print(account_id)
self.server = smtplib.SMTP_SSL(smtp_server)
# self.server.login(secret.kakao_id, secret.kakao_pw)
self.server.login(account_id, self.lineedit12.text())
# self.msg_from = 'miero@kakao.com'
self.msg_from = self.lineedit11.text()
# # server = smtplib.SMTP('smtp.com', port_number)
# # server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# server = smtplib.SMTP_SSL('smtp.kakao.com')
# # server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# # 로그인이 필요하면 로그인 설정
# server.login(secret.kakao_id, secret.kakao_pw)
# # 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
# msg_to = email_i
# cc = 'b@b.com, c@c.com'
# cc = ''
# print(name,email_i)
# 메세지 구성
# msg = MIMEBase('multipart','mixed')
msg = MIMEMultipart()
msg['From'] = self.msg_from
msg['To'] = email_i
msg['Date'] = formatdate(localtime=True)
# msg['Subject'] = f'2022년08월급여명세서-{name}'
subject_before = self.lineedit21.text()
# 문자치환 f-string 사용하여 변수 적용하기
subject = subject_before.replace("{성명}",f'{name}')
msg['Subject'] = Header(s=subject, charset='utf-8')
# msg['Subject'] = Header(s=f'2022년08월급여명세서-{name}', charset='utf-8')
# msg['Cc'] = ""
# 메일 본문 작성
# # html 로 되어있던 파일을 불러 오고 거기에 파일을 붙여서 보냅니다.
# msgText = MIMEText('<h1>%s</h1><hr>, <img src="cid:%s" >' % (emailtext, attachment), 'html')
# contents = '<h1>%s</h1>'
# contents += '<hr>'
# contents += '<img src="cid:%s" >'
# msgText = MIMEText(contents % (emailtext, attachment), 'html')
# contents = f'<h1>{emailtext}</h1>'
# contents += f'<h2>{msg_to} 님 메일이 도착했습니다.</h2>'
# contents += '<hr>'
# contents += f'<img src="cid:{attachment}" >'
# msgText = MIMEText(contents, 'html')
# pretext = f'수신: {name}<br/>'
# pretext += '발신: 주식회사 밀앤아이, 주식회사 헴펠 대표이사<br/>'
# pretext += '<br/>'
# msgpreText = MIMEText(pretext, 'html')
# msg.attach(msgpreText)
# contents = self.textedit23.toPlainText()
contents_before = self.textedit23.toPlainText()
# 문자치환 f-string 사용하여 변수 적용하기
contents = contents_before.replace("{성명}",f'수신: {name}')
# msgText = MIMEText(contents, 'plain')
msgText = MIMEText(contents, 'html')
# msgText = MIMEText(contents, _charset='utf-8')
# 메세지를 메일에 붙여 줍니다.
msg.attach(msgText)
# 메일 제일 밑에 로고그림 붙여 줍니다.
# logo_file = "logo.jpg"
# img_f_name = logo_file.replace("\\","/")
# logo_file = r"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' width='10%' height='0%'></center>"
# img_f_name = logo_file.replace("\\","/")
# # with io.open('file_name.html','r') as f:
# with io.open(img_f_name,'r') as f:
# # emailtext = f.read()
# emailtext = img_f_name
# # attachment = 'attachment_file_name.png'
# attachment = img_f_name
# attachment = logo_file
# fp = open(attachment, 'rb')
# img = MIMEImage(fp.read())
# fp.close()
# img.add_header('Content-ID', '<{}>'.format(attachment))
# msg.attach(img)
# 파일첨부
files = list()
pdf_file_name = f"{subject}.pdf"
pdf_file = os.path.join(os.getcwd()+"\pdf", pdf_file_name)
files.append(pdf_file)
# if os.path.isfile(pdf_file):
# binary_pdf = open(pdf_file, 'rb')
# payload = MIMEBase('application', 'octate-stream', Name=pdf_file_name)
# payload.set_payload((binary_pdf).read())
# encoders.encode_base64(payload)
# payload.add_header('Content-Decomposition', 'attachment', filename=pdf_file_name)
# msg.attach(payload)
for i in range(self.listwidget22.count()):
files.append(self.listwidget22.item(i).text())
# print(files)
for f in files:
# print(f)
part = MIMEBase('application', "octet-stream")
part.set_payload(open(f,"rb").read())
encoders.encode_base64(part)
fstr_name = os.path.basename(f)
# part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(f))
part.add_header('Content-Disposition',"attachment", filename= fstr_name, charset='utf-8')
# [출처] 파이썬에서 지메일 보내기(w/첨부파일) 한글파일도 가능|작성자 데이터공방
# Header(s=f'2022년08월급여명세서-{name}', charset='utf-8')
msg.attach(part)
# 메일 서버를 이용하여 메일을 발송합니다.
# server.sendmail(msg_from, msg["To"].split(",") + msg["Cc"].split(","), msg.as_string())
self.server.sendmail(msg['From'], msg['To'], msg.as_string())
# self.server.quit()
# def fn_result_window(self, name, email):
# self.listwidget32.clear()
# cnt = self.listwidget32.count() +1
# # print(cnt, name, email, "전송완료")
# # self.listwidget32.insertItem(cnt,name&email&"전송완료")
# self.listwidget32.insertItem(cnt, f'{name}-{email}-전송완료')
def fn_test(self):
# try:
# 메일 서버를 설정합니다.
# server = smtplib.SMTP('smtp.com', port_number)
# server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# self.server = smtplib.SMTP_SSL('smtp.kakao.com')
# server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# 로그인이 필요하면 로그인 설정
# self.server.login(secret.kakao_id, secret.kakao_pw)
# 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
self.listwidget32.clear()
if len(self.lineedit11.text()) == 0:
QMessageBox.about(self,'이메일계정 확인','이메일계정을 입력하십시요.')
return
p = re.compile('^[a-zA-Z0-9+-_.]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$')
if p.match(self.lineedit11.text()) == None:
# print(p.match(self.lineedit11.text()) != None)
QMessageBox.about(self,'이메일 형식 확인','올바른 이메일 형식이 아닙니다.')
return
if len(self.lineedit12.text()) == 0:
QMessageBox.about(self,'비밀번호 확인','비밀번호를 입력하십시요.')
return
cnt = 0
if len(self.lineedit21.text()) == 0:
QMessageBox.about(self,'제목 입력 확인','제목을 입력하십시요.')
return
self.fn_subject_save()
self.fn_html_save()
self.fn_DeleteAllFiles(os.getcwd()+"\pdf")
try:
self.fn_pdf_create(self.lineedit23.text())
except:
QMessageBox.about(self,'대상자 확인','유효하지 않은 이름입니다.')
return
try:
if self.df_table_02.loc[self.lineedit23.text()][0] != "nan":
self.fn_send(self.lineedit23.text(), self.df_table_02.loc[self.lineedit23.text()][0])
cnt += 1
# self.listwidget32.insertItem(cnt, f'{self.lineedit23.text()}-{self.df_table_02.loc[self.lineedit23.text()][0]}-전송완료')
self.listwidget32.addItem(f'{self.lineedit23.text()}-{self.df_table_02.loc[self.lineedit23.text()][0]}-전송완료')
except:
cnt += 1
# self.listwidget32.insertItem(cnt, f'{self.lineedit23.text()}-{self.df_table_02.loc[self.lineedit23.text()][0]}-실패')
# self.listwidget32.item(cnt-1).setBackground(Qt.red)
self.listwidget32.addItem(f'{self.lineedit23.text()}-{self.df_table_02.loc[self.lineedit23.text()][0]}-실패')
self.listwidget32.item(cnt-1).setBackground(Qt.red)
# self.fn_pdf_create("밀1")
# self.fn_send(self.lineedit23.text(), self.df_table_02.loc[self.lineedit23.text()][0])
# cnt += 1
# self.listwidget32.insertItem(cnt, f'{self.lineedit23.text()}-{self.df_table_02.loc[self.lineedit23.text()][0]}-전송완료')
self.server.quit()
# self.app.kill()
# self.fn_print_name(self.lineedit23.text(), self.df_table_02.loc[self.lineedit23.text()][0])
# except: # 예외가 발생했을 때 실행됨
# print('예외가 발생했습니다.')
# self.listwidget32.insertItem(cnt, f'{"밀1"}-{self.df_table_02.loc["밀1"][0]}-실패')
QMessageBox.about(self,'전송 완료','전송 작업 완료')
def fn_run(self):
# 메일 서버를 설정합니다.
# server = smtplib.SMTP('smtp.com', port_number)
# server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# server = smtplib.SMTP_SSL('smtp.kakao.com')
# server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# 로그인이 필요하면 로그인 설정
# server.login(secret.kakao_id, secret.kakao_pw)
# 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
self.listwidget32.clear()
if len(self.lineedit11.text()) == 0:
QMessageBox.about(self,'이메일계정 확인','이메일계정을 입력하십시요.')
return
p = re.compile('^[a-zA-Z0-9+-_.]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$')
if p.match(self.lineedit11.text()) == None:
# print(p.match(self.lineedit11.text()) != None)
QMessageBox.about(self,'이메일 형식 확인','올바른 이메일 형식이 아닙니다.')
return
if len(self.lineedit12.text()) == 0:
QMessageBox.about(self,'비밀번호 확인','비밀번호를 입력하십시요.')
return
cnt = 0
if len(self.lineedit21.text()) == 0:
QMessageBox.about(self,'제목 입력 확인','제목을 입력하십시요.')
return
self.fn_subject_save()
self.fn_html_save()
# self.fn_send("밀1", self.df_table_02.loc["밀1"][0])
# self.fn_print_name("밀1", self.df_table_02.loc["밀1"][0])
self.fn_DeleteAllFiles(os.getcwd()+"\pdf")
for idx_name in self.idx_name_list:
# print(idx)
# print(self.df_table_02.loc[idx][0])
# print(idx, table_02.loc[idx][0])
self.fn_pdf_create(idx_name)
try:
if self.df_table_02.loc[idx_name][0] != "nan":
self.fn_send(idx_name, self.df_table_02.loc[idx_name][0])
cnt += 1
self.listwidget32.addItem(f'{idx_name}-{self.df_table_02.loc[idx_name][0]}-전송완료')
except:
cnt += 1
self.listwidget32.addItem(f'{idx_name}-{self.df_table_02.loc[idx_name][0]}-실패')
self.listwidget32.item(cnt-1).setBackground(Qt.red)
# if self.df_table_02.loc[idx_name][0] == "nan":
# print(self.listwidget32.)
# self.listwidget32.item(cnt).setBackground(Qt.red)
# print("예외가 발생했습니다.-fn_run",cnt,self.df_table_02.loc[idx_name][0])
# self.fn_print_name(idx_name, self.df_table_02.loc[idx_name][0])
self.server.quit()
# self.app.kill()
# print('예외가 발생했습니다.')
# self.listwidget32.insertItem(cnt, f'{idx_name}-{self.df_table_02.loc[idx_name][0]}-실패')
QMessageBox.about(self,'전송 완료','전송 작업 완료')
if __name__ == '__main__':
# don't auto scale when drag app to a different monitor.
# QGuiApplication.setHighDpiScaleFactorRoundingPolicy(Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
excel_file_path = '급여1.xlsx'
worksheet_name = '4대급여'
emailsheet_name = '이메일'
app = QApplication(sys.argv)
app.setStyleSheet('''
QWidget {
font-size: 17px;
}
''')
myApp = MyApp()
myApp.show()
try:
sys.exit(app.exec())
except SystemExit:
print('Closing Window...')
====================
pay24.py--------------------
# from operator import index
# from unittest import result
# from xml.dom.minidom import Document
from PyQt5.QtWidgets import QApplication, QWidget, QTableWidget, QTableWidgetItem, QPushButton, \
QHeaderView, QHBoxLayout, QVBoxLayout, QGridLayout, QAbstractScrollArea, QLabel, QListWidget, \
QFileDialog, QMessageBox, QTextEdit, QAbstractItemView, QLineEdit, QGroupBox, QRadioButton
from PyQt5.QtCore import Qt
# from PyQt5 import QtGui
from PyQt5.QtGui import QTextCursor
import sys
import pandas as pd # pip install pandas
import os
import io
import secret
import xlwings as xw
import re
import smtplib
from email.encoders import encode_base64
from email.header import Header
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText # 메일의 본문 내용을 만드는 모듈 내용을 base64형식으로 변환
from email.utils import formatdate
from email.mime.application import MIMEApplication # 메일의 첨부 파일을 base64 형식으로 변환
from email.mime.image import MIMEImage # 메일의 이미지 파일을 base64 형식으로 변환
# 출처: https://nowonbun.tistory.com/684 [명월 일지:티스토리]
from email import encoders
from email.encoders import encode_base64
class MyApp(QWidget):
def __init__(self):
super().__init__()
self.window_width, self.window_height = 1150, 600
self.resize(self.window_width, self.window_height)
self.setWindowTitle('pay')
# self.server = smtplib.SMTP_SSL('smtp.kakao.com')
# self.server.login(secret.kakao_id, secret.kakao_pw)
# self.msg_from = 'miero@kakao.com'
##### layout_main #####
layout_main = QHBoxLayout()
self.setLayout(layout_main)
##### layout_1 #####
layout_1 = QVBoxLayout()
vBox11 = QVBoxLayout()
groupBoxLogin11 = QGroupBox("로그인 정보")
groupBoxLogin11.setLayout(vBox11)
layout_1.addWidget(groupBoxLogin11)
self.label11 = QLabel("이메일계정")
vBox11.addWidget(self.label11)
self.lineedit11 = QLineEdit("miero@kakao.com")
vBox11.addWidget(self.lineedit11)
self.label12 = QLabel("패스워드")
vBox11.addWidget(self.label12)
self.lineedit12 = QLineEdit()
self.lineedit12.setEchoMode(QLineEdit.Password)
# self.lineedit12.show()
vBox11.addWidget(self.lineedit12)
label13 = QLabel('직원 메일')
# self.button = QPushButton('&Load Data')
# self.button.clicked.connect(lambda _, xl_path=excel_file_path, sheet_name=worksheet_name: self.loadExcelData(xl_path, sheet_name))
# layout_v.addWidget(self.button)
layout_1.addWidget(label13)
self.table = QTableWidget()
self.table.setFixedWidth(350)
layout_1.addWidget(self.table)
layout_main.addLayout(layout_1)
##### layout_2 #####
layout_2 = QGridLayout()
label21 = QLabel('이메일 제목')
layout_2.addWidget(label21, 0, 0)
self.lineedit21 = QLineEdit()
layout_2.addWidget(self.lineedit21, 1, 0, 1, 2)
label22 = QLabel('첨부파일')
layout_2.addWidget(label22, 2, 0)
self.listwidget22 = QListWidget()
# self.listwidget22.setFixedWidth(300)
self.listwidget22.setMinimumWidth(400)
# self.listwidget22.setSelectionMode(QAbstractItemView.ExtendedSelection)
layout_2.addWidget(self.listwidget22, 3, 0, 3, 1)
self.btn_file_add = QPushButton('파일 추가') # sendlist
# self.btn_file_add.setMinimumHeight(80)
layout_2.addWidget(self.btn_file_add, 3, 1, 1, 1)
self.btn_file_add.clicked.connect(self.fn_fileadd)
self.btn_file_del = QPushButton('파일 삭제')
layout_2.addWidget(self.btn_file_del, 4, 1, 1, 1)
self.btn_file_del.clicked.connect(self.fn_filedel)
# label21 = QLabel('본문 (HTML형식)')
# layout_2.addWidget(label21, 8, 0)
# radio_1 ~ 4 버튼을 그룹으로 설정
groupBoxMid = QGroupBox("테스트 메일 보내기")
layout_2.addWidget(groupBoxMid, 6, 0, 1, 2)
hBox1 = QHBoxLayout()
groupBoxMid.setLayout(hBox1)
self.label23 = QLabel("성명")
hBox1.addWidget(self.label23)
self.lineedit23 = QLineEdit("정용만") # 이름기본값
hBox1.addWidget(self.lineedit23)
self.pushbutton23 = QPushButton("테스트 보내기")
self.pushbutton23.clicked.connect(self.fn_test)
hBox1.addWidget(self.pushbutton23)
groupBoxBottom = QGroupBox("본문 보기형식 선택")
layout_2.addWidget(groupBoxBottom, 7, 0, 1, 2)
hBox2 = QHBoxLayout()
groupBoxBottom.setLayout(hBox2)
self.radioBtn1 = QRadioButton("HTML")
self.radioBtn1.setChecked(True)
self.radioBtn1.clicked.connect(self.fn_radio_select)
hBox2.addWidget(self.radioBtn1)
self.radioBtn2 = QRadioButton("미리보기")
self.radioBtn2.clicked.connect(self.fn_radio_select)
hBox2.addWidget(self.radioBtn2)
self.textedit23 = QTextEdit()
# self.textedit23.setFixedWidth(400)
# self.textedit23.setAcceptRichText(False)
layout_2.addWidget(self.textedit23, 8, 0, 4, 1)
self.textedit23.show()
self.textedit24 = QTextEdit()
layout_2.addWidget(self.textedit24, 8, 0, 4, 1)
self.textedit24.hide()
self.btn_send = QPushButton("보내기")
self.btn_send.setMaximumHeight(500) # gridlayout button size
layout_2.addWidget(self.btn_send, 8, 1, 4, 1)
self.btn_send.clicked.connect(self.fn_run) #@@@@@@@@@@@@@@@@@@@@@@@@@@
layout_main.addLayout(layout_2)
##### layout_3 #####
layout_3 = QVBoxLayout()
label31 = QLabel('발송 결과')
layout_3.addWidget(label31)
self.listwidget32 = QListWidget()
# self.listwidget32.setMinimumWidth(self.listwidget32.sizeHintForColumn(0))
# self.listwidget32.setWidth(10)
layout_3.addWidget(self.listwidget32)
layout_main.addLayout(layout_3)
# subject0 파일이 존재하면
filename_subject = 'subject0.txt'
if os.path.isfile(filename_subject) == True:
source_text = open(filename_subject,'r', encoding="UTF-8").read()
# self.lineedit21.setText(source_text) # TextEdit에 RichText 형식의 글을 입력합니다.
self.lineedit21.setText(source_text) # TextEdit에 PlainText 형식의 글을 새로 입력합니다.
# html0 파일이 존재하면
filename_html = 'html0.txt'
if os.path.isfile(filename_html) == True:
source_text = open(filename_html,'r', encoding="UTF-8").read()
# self.textedit23.setText(source_text) # TextEdit에 RichText 형식의 글을 입력합니다.
self.textedit23.setPlainText(source_text) # TextEdit에 PlainText 형식의 글을 새로 입력합니다.
# self.textedit24.setHtml(source_text) # TextEdit에 PlainText 형식의 글을 새로 입력합니다.
# table_data = self.loadExcelData(excel_file_path, worksheet_name)
# print(table_data.keys())
# df_table = self.loadExcelData(excel_file_path, worksheet_name)
df_table = self.loadExcelData()
# print(table_df["성명"][0])
self.df_table_02 = df_table.set_index("성명")
self.idx_name_list = self.df_table_02.index.to_list()
# print(index)
# for i in table_02["이메일"]:
def fn_radio_select(self):
# QRadioButton1 클릭 여부 표시
if self.radioBtn1.isChecked():
self.textedit23.show()
self.textedit24.hide()
self.hidden = False
# self.btn_send.setText('보내기')
elif self.radioBtn2.isChecked():
self.fn_html_save()
self.textedit23.hide()
self.textedit24.show()
self.hidden = True
# self.btn_send.setText('미리보기')
# def loadExcelData(self, excel_file_dir, worksheet_name):
def loadExcelData(self):
df_work_sheet = pd.read_excel(excel_file_path, worksheet_name)
df_email_sheet = pd.read_excel(excel_file_path, emailsheet_name)
df_table = df_work_sheet.merge(df_email_sheet, how='left')
df_table_mail = df_table[['성명','이메일']]
res = df_table_mail
# res = df_table_mail.to_dict()
# self.table.setRowCount(df.shape[0])
# self.table.setColumnCount(df.shape[1])
self.table.setRowCount(df_table_mail.shape[0])
self.table.setColumnCount(df_table_mail.shape[1])
# self.table.setHorizontalHeaderLabels(df.columns)
self.table.setHorizontalHeaderLabels(df_table_mail.columns)
header = self.table.horizontalHeader()
# header.setSectionResizeMode(0, QHeaderView.Stretch)
# header.setSectionResizeMode(0, QHeaderView.ResizeToContents)
header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
# returns pandas array object
# for row in df.iterrows():
for row in df_table_mail.iterrows():
values = row[1]
for col_index, value in enumerate(values):
if isinstance(value, (float, int)):
value = '{0:0,.0f}'.format(value)
tableItem = QTableWidgetItem(str(value))
if value == "nan":
tableItem.setBackground(Qt.red)
self.table.setItem(row[0], col_index, tableItem)
self.table.setColumnWidth(2, 310)
return res
def fn_fileadd(self):
# f_name = QFileDialog.getOpenFileName(None, '열기', '', "All Files(*.*)")
f_names = QFileDialog.getOpenFileNames(None, '열기', '', "All Files(*.*)")
# txtPath = f_name[0]
filelist = f_names[0]
if filelist:
for f_name in filelist:
# ext = os.path.splitext(f_name[0])[1]
ext = os.path.splitext(f_name)[1] # 확장자 확인
# if f_names[0]:
icnt = 0
for i in range(self.listwidget22.count()):
# if str(self.listwidget22.item(i).text()) == txtPath.replace("/","\\") or str(self.listwidget22.item(i).text()) == txtPath:
if str(self.listwidget22.item(i).text()) == f_name.replace("/","\\") or str(self.listwidget22.item(i).text()) == f_name:
icnt = 1
break
if icnt != 1:
f_path = f_name
if ext == '.exe':
QMessageBox.about(self,'파일 형식 확인','exe파일은 전송할 수 없습니다.')
pass
else:
cnt = self.listwidget22.count() +1
# self.listwidget22.insertItem(cnt, os.path.basename(txtPath))
# self.listwidget22.insertItem(cnt, txtPath)
# f_path = f_names[0]
# print(f_path)
self.listwidget22.insertItem(cnt, f_path)
# self.listwidget22.insertItem(cnt, f_path.replace("/","\\"))
def fn_filedel(self):
currentrow = self.listwidget22.currentRow()
self.listwidget22.takeItem(currentrow) # currentrowRight번째 항목을 삭제합니다
self.listwidget22.clearSelection()
def fn_subject_save(self):
if len(self.lineedit21.text())>0:
S__File = os.path.join(os.getcwd(),'subject0.txt')
Text = self.lineedit21.text()
if S__File:
# Finally this will Save your file to the path selected.
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
file.write(Text)
def fn_html_save(self):
if len(self.textedit23.toPlainText())>0:
# print(len(self.textedit.toPlainText()))
# S__File = QFileDialog.getSaveFileName(None,'문자 파일저장','/', "Text Files (*.txt)")
# S__File = QFileDialog.getSaveFileName(None,'문자 파일저장','html0', "Text Files (*.txt)")
S__File = os.path.join(os.getcwd(),'html0.txt')
# This will let you access the test in your QTextEdit
Text = self.textedit23.toPlainText()
self.textedit24.setHtml(Text)
# document = self.textedit23.document()
# cursor = QTextCursor(document)
# p1 = cursor.position() # return int
# cursor.insertImage(r"C:\Users\newstep\Pictures\number1.jpg")
# This will prevent you from an error if pressed cancel on file dialog.
# if S__File[0]:
if S__File:
# Finally this will Save your file to the path selected.
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
file.write(Text)
# txtPath = S__File[0]
# icnt = 0
# for i in range(self.listwidget31.count()):
# if str(self.listwidget31.item(i).text()) == txtPath.replace("/","\\"):
# icnt = 1
# break
# if icnt != 1:
# cnt = self.listwidget31.count() +1
# self.listwidget31.insertItem(cnt, os.path.basename(txtPath))
# self.listwidget31.insertItem(cnt, txtPath)
else:
QMessageBox.about(self,'메시지 입력 확인','메시지를 입력하셔야 합니다.')
def fn_print_name(self, name, email):
# f_name_pre = r"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' width='50%' height='0%'></center>"
# f_name = f_name_pre.replace("\\","/")
# with io.open('file_name.html','r') as f:
# with io.open(f_name,'r') as f:
# # emailtext = f.read()
# emailtext = f_name
# attachment = 'attachment_file_name.png'
# attachment = f_name
# print(name, self.df_table_02.loc[name][0])
# print(name, email)
if len(self.textedit23.toPlainText())>0:
S__File = os.path.join(os.getcwd(),'html0.txt')
# print(len(self.textedit23.toPlainText()))
# print(S__File)
# pretext = f'{name} 님<br/><br/>'
# pretext += f'당신의 이메일은 {email} 입니다.<br/>'
contents = self.textedit23.toPlainText()
# nexttext = f'<br/><img src="cid:{attachment}" >'
# nexttext = f"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' id='millstudio logo' width='10%' height='0%'></center>"
# document = self.textedit23.document()
# cursor = QTextCursor(document)
# p1 = cursor.position() # return int
# cursor.insertImage(f_name)
# with open(S__File[0], 'w', encoding='utf-8') as file:
with open(S__File, 'w', encoding='utf-8') as file:
# file.write(pretext)
file.write(contents)
# file.write(nexttext)
# print(contents)
# msgText = MIMEText(contents, 'html')
print(name, email, "전송완료")
# self.fn_result_window(name, email)
def fn_DeleteAllFiles(self,filePath):
if os.path.exists(filePath):
for file in os.scandir(filePath):
os.remove(file.path)
return '폴더 내 모든 파일 지우기 완료'
else:
return '폴더가 없습니다.'
def fn_pdf_create(self, idx_name):
#####################################
# xlwings
self.current_pdf_path = os.getcwd()+"\pdf"
# fname = "급여1.xlsx"
fname = excel_file_path
# for n in self.target_name_list:
name = idx_name
df_data = pd.read_excel(fname, sheet_name=worksheet_name)
df_data = df_data.fillna(0)
df_employee = pd.read_excel(fname, sheet_name='직원현황')
idx_df_data = df_data.index[df_data['성명']==name].tolist()[0]
# print("4대급여 인덱스 :",idx_df_data)
normal = df_data.loc[idx_df_data,['기본급']][0]
overtime = df_data.loc[idx_df_data,['연장수당']][0]
holiday = df_data.loc[idx_df_data,['휴일수당']][0]
holidayovertime = df_data.loc[idx_df_data,['휴일연장수당']][0]
extra = df_data.loc[idx_df_data,['추가수당']][0]
meals = df_data.loc[idx_df_data,['식대']][0]
bonus = df_data.loc[idx_df_data,['상여금']][0]
normal_calculation = df_data.loc[idx_df_data,['기']][0]
overtime_calculation = df_data.loc[idx_df_data,['연']][0]
holiday_calculation = df_data.loc[idx_df_data,['휴']][0]
holidayovertime_calculation = df_data.loc[idx_df_data,['휴연']][0]
extra_calculation = df_data.loc[idx_df_data,['추']][0]
nationalpension = df_data.loc[idx_df_data,['국민연금']][0]
healthinsurance = df_data.loc[idx_df_data,['건강보험']][0]
longtermcareinsurance = df_data.loc[idx_df_data,['장기요양보험']][0]
employmentinsurance = df_data.loc[idx_df_data,['고용보험']][0]
healthsettlement = df_data.loc[idx_df_data,['정산건강']][0]
longtermcaresettlement = df_data.loc[idx_df_data,['정산장기요양']][0]
advancepayment = df_data.loc[idx_df_data,['선지급']][0]
etc = df_data.loc[idx_df_data,['기타']][0]
incometax = df_data.loc[idx_df_data,['소득세']][0]
localincometax = df_data.loc[idx_df_data,['지방소득세']][0]
idx_df_employee = df_employee.index[df_employee['성명']==name].tolist()[0]
# print("직원현황 인덱스 :",idx_df_employee)
jobposition = df_employee.loc[idx_df_employee,['직위']][0]
department = df_employee.loc[idx_df_employee,['부서']][0]
birthday = df_employee.loc[idx_df_employee,['생일']][0]
# 엑셀 인스턴스 생성
xw.App(visible=False)
book = xw.Book(fname)
sh_paystub = book.sheets('급여명세서사대보험')
sh_paystub["B4"].value = name
sh_paystub["D4"].value = jobposition
sh_paystub["B5"].value = department
sh_paystub["D5"].value = birthday
sh_paystub["B8"].value = normal
sh_paystub["B9"].value = overtime
sh_paystub["B10"].value = holiday
sh_paystub["B11"].value = holidayovertime
sh_paystub["B12"].value = extra
sh_paystub["B13"].value = meals
sh_paystub["D8"].value = nationalpension
sh_paystub["D9"].value = healthinsurance
sh_paystub["D10"].value = longtermcareinsurance
sh_paystub["D11"].value = employmentinsurance
sh_paystub["D12"].value = healthsettlement
sh_paystub["D13"].value = longtermcaresettlement
sh_paystub["D14"].value = advancepayment
sh_paystub["D15"].value = etc
sh_paystub["D16"].value = incometax
sh_paystub["D17"].value = localincometax
sh_paystub["B23"].value = normal_calculation
sh_paystub["B24"].value = overtime_calculation
sh_paystub["B25"].value = holiday_calculation
sh_paystub["B26"].value = holidayovertime_calculation
sh_paystub["B27"].value = extra_calculation
sh_paystub["D23"].value = normal
sh_paystub["D24"].value = overtime
sh_paystub["D25"].value = holiday
sh_paystub["D26"].value = holidayovertime
sh_paystub["D27"].value = extra
# rng = sh_paystub.range("D35")
# sh_paystub.pictures.add(r'B:\python\vscode\excel\millstudio_logo.png', left=rng.left, top=rng.top)
if len(self.lineedit21.text())==0:
book.save()
book.close()
return
# print(len(self.lineedit21.text()))
# pdf 로 저장하기
# current_path = os.getcwd() # 현재 작업중인 폴더에 저장하기
# 절대경로로 파일 위치 입력
subject_before = self.lineedit21.text()
# 문자치환 f-string 사용하여 변수 적용하기
subject = subject_before.replace("{성명}",f'{name}')
pdf_file = os.path.join(self.current_pdf_path, f"{subject}.pdf")
# PDF 로 저장할 시트 선택하기(본 예제에서는 첫 번째 시트 선택하기)
# report_sheet = book.sheets[1]
report_sheet = sh_paystub
# PDF 로 저장하기
# report_sheet.ExportAsFixedFormat(0, pdf_path)
report_sheet.api.ExportAsFixedFormat(0, pdf_file)
book.save()
book.close()
#####################################
def fn_send(self, name, email_i):
# # 메일 서버를 설정합니다.
account_id = self.lineedit11.text().split("@")[0]
emailserver = self.lineedit11.text().split("@")[1]
# self.server = smtplib.SMTP_SSL('smtp.kakao.com')
smtp_server = 'smtp.'+ emailserver
# print(account_id)
self.server = smtplib.SMTP_SSL(smtp_server)
# self.server.login(secret.kakao_id, secret.kakao_pw)
self.server.login(account_id, self.lineedit12.text())
# self.msg_from = 'miero@kakao.com'
self.msg_from = self.lineedit11.text()
# # server = smtplib.SMTP('smtp.com', port_number)
# # server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# server = smtplib.SMTP_SSL('smtp.kakao.com')
# # server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# # 로그인이 필요하면 로그인 설정
# server.login(secret.kakao_id, secret.kakao_pw)
# # 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
# msg_to = email_i
# cc = 'b@b.com, c@c.com'
# cc = ''
# print(name,email_i)
# 메세지 구성
# msg = MIMEBase('multipart','mixed')
msg = MIMEMultipart()
msg['From'] = self.msg_from
msg['To'] = email_i
msg['Date'] = formatdate(localtime=True)
# msg['Subject'] = f'2022년08월급여명세서-{name}'
subject_before = self.lineedit21.text()
# 문자치환 f-string 사용하여 변수 적용하기
subject = subject_before.replace("{성명}",f'{name}')
msg['Subject'] = Header(s=subject, charset='utf-8')
# msg['Subject'] = Header(s=f'2022년08월급여명세서-{name}', charset='utf-8')
# msg['Cc'] = ""
# 메일 본문 작성
# # html 로 되어있던 파일을 불러 오고 거기에 파일을 붙여서 보냅니다.
# msgText = MIMEText('<h1>%s</h1><hr>, <img src="cid:%s" >' % (emailtext, attachment), 'html')
# contents = '<h1>%s</h1>'
# contents += '<hr>'
# contents += '<img src="cid:%s" >'
# msgText = MIMEText(contents % (emailtext, attachment), 'html')
# contents = f'<h1>{emailtext}</h1>'
# contents += f'<h2>{msg_to} 님 메일이 도착했습니다.</h2>'
# contents += '<hr>'
# contents += f'<img src="cid:{attachment}" >'
# msgText = MIMEText(contents, 'html')
# pretext = f'수신: {name}<br/>'
# pretext += '발신: 주식회사 밀앤아이, 주식회사 헴펠 대표이사<br/>'
# pretext += '<br/>'
# msgpreText = MIMEText(pretext, 'html')
# msg.attach(msgpreText)
# contents = self.textedit23.toPlainText()
contents_before = self.textedit23.toPlainText()
# 문자치환 f-string 사용하여 변수 적용하기
contents = contents_before.replace("{성명}",f' {name}')
# msgText = MIMEText(contents, 'plain')
msgText = MIMEText(contents, 'html')
# msgText = MIMEText(contents, _charset='utf-8')
# 메세지를 메일에 붙여 줍니다.
msg.attach(msgText)
# 메일 제일 밑에 로고그림 붙여 줍니다.
# logo_file = "logo.jpg"
# img_f_name = logo_file.replace("\\","/")
# logo_file = r"<center><img src='https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYTHu%2FbtrKqQes3BJ%2F2UVr0HkX0ht7utKmwUqKb0%2Fimg.jpg' width='10%' height='0%'></center>"
# img_f_name = logo_file.replace("\\","/")
# # with io.open('file_name.html','r') as f:
# with io.open(img_f_name,'r') as f:
# # emailtext = f.read()
# emailtext = img_f_name
# # attachment = 'attachment_file_name.png'
# attachment = img_f_name
# attachment = logo_file
# fp = open(attachment, 'rb')
# img = MIMEImage(fp.read())
# fp.close()
# img.add_header('Content-ID', '<{}>'.format(attachment))
# msg.attach(img)
# 파일첨부
files = list()
pdf_file_name = f"{subject}.pdf"
pdf_file = os.path.join(os.getcwd()+"\pdf", pdf_file_name)
files.append(pdf_file)
# if os.path.isfile(pdf_file):
# binary_pdf = open(pdf_file, 'rb')
# payload = MIMEBase('application', 'octate-stream', Name=pdf_file_name)
# payload.set_payload((binary_pdf).read())
# encoders.encode_base64(payload)
# payload.add_header('Content-Decomposition', 'attachment', filename=pdf_file_name)
# msg.attach(payload)
for i in range(self.listwidget22.count()):
files.append(self.listwidget22.item(i).text())
# print(files)
for f in files:
# print(f)
part = MIMEBase('application', "octet-stream")
part.set_payload(open(f,"rb").read())
encoders.encode_base64(part)
fstr_name = os.path.basename(f)
# part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(f))
part.add_header('Content-Disposition',"attachment", filename= fstr_name, charset='utf-8')
# [출처] 파이썬에서 지메일 보내기(w/첨부파일) 한글파일도 가능|작성자 데이터공방
# Header(s=f'2022년08월급여명세서-{name}', charset='utf-8')
msg.attach(part)
# 메일 서버를 이용하여 메일을 발송합니다.
# server.sendmail(msg_from, msg["To"].split(",") + msg["Cc"].split(","), msg.as_string())
self.server.sendmail(msg['From'], msg['To'], msg.as_string())
# self.server.quit()
# def fn_result_window(self, name, email):
# self.listwidget32.clear()
# cnt = self.listwidget32.count() +1
# # print(cnt, name, email, "전송완료")
# # self.listwidget32.insertItem(cnt,name&email&"전송완료")
# self.listwidget32.insertItem(cnt, f'{name}-{email}-전송완료')
def fn_test(self):
# try:
# 메일 서버를 설정합니다.
# server = smtplib.SMTP('smtp.com', port_number)
# server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# self.server = smtplib.SMTP_SSL('smtp.kakao.com')
# server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# 로그인이 필요하면 로그인 설정
# self.server.login(secret.kakao_id, secret.kakao_pw)
# 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
self.listwidget32.clear()
if len(self.lineedit11.text()) == 0:
QMessageBox.about(self,'이메일계정 확인','이메일계정을 입력하십시요.')
return
p = re.compile('^[a-zA-Z0-9+-_.]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$')
if p.match(self.lineedit11.text()) == None:
# print(p.match(self.lineedit11.text()) != None)
QMessageBox.about(self,'이메일 형식 확인','올바른 이메일 형식이 아닙니다.')
return
if len(self.lineedit12.text()) == 0:
QMessageBox.about(self,'비밀번호 확인','비밀번호를 입력하십시요.')
return
cnt = 0
if len(self.lineedit21.text()) == 0:
QMessageBox.about(self,'제목 입력 확인','제목을 입력하십시요.')
return
self.fn_subject_save()
self.fn_html_save()
self.fn_DeleteAllFiles(os.getcwd()+"\pdf")
try:
self.fn_pdf_create(self.lineedit23.text())
except:
QMessageBox.about(self,'대상자 확인','유효하지 않은 이름입니다.')
return
try:
if self.df_table_02.loc[self.lineedit23.text()][0] != "nan":
self.fn_send(self.lineedit23.text(), self.df_table_02.loc[self.lineedit23.text()][0])
cnt += 1
# self.listwidget32.insertItem(cnt, f'{self.lineedit23.text()}-{self.df_table_02.loc[self.lineedit23.text()][0]}-전송완료')
self.listwidget32.addItem(f'{self.lineedit23.text()}-{self.df_table_02.loc[self.lineedit23.text()][0]}-전송완료')
except:
cnt += 1
# self.listwidget32.insertItem(cnt, f'{self.lineedit23.text()}-{self.df_table_02.loc[self.lineedit23.text()][0]}-실패')
# self.listwidget32.item(cnt-1).setBackground(Qt.red)
self.listwidget32.addItem(f'{self.lineedit23.text()}-{self.df_table_02.loc[self.lineedit23.text()][0]}-실패')
self.listwidget32.item(cnt-1).setBackground(Qt.red)
# self.fn_pdf_create("밀1")
# self.fn_send(self.lineedit23.text(), self.df_table_02.loc[self.lineedit23.text()][0])
# cnt += 1
# self.listwidget32.insertItem(cnt, f'{self.lineedit23.text()}-{self.df_table_02.loc[self.lineedit23.text()][0]}-전송완료')
self.server.quit()
# self.app.kill()
# self.fn_print_name(self.lineedit23.text(), self.df_table_02.loc[self.lineedit23.text()][0])
# except: # 예외가 발생했을 때 실행됨
# print('예외가 발생했습니다.')
# self.listwidget32.insertItem(cnt, f'{"밀1"}-{self.df_table_02.loc["밀1"][0]}-실패')
QMessageBox.about(self,'전송 완료','전송 작업 완료')
def fn_run(self):
# 메일 서버를 설정합니다.
# server = smtplib.SMTP('smtp.com', port_number)
# server = smtplib.SMTP_SSL('smtp.kakao.com:465')
# server = smtplib.SMTP_SSL('smtp.kakao.com')
# server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
# 로그인이 필요하면 로그인 설정
# server.login(secret.kakao_id, secret.kakao_pw)
# 보내는 사람, 받는 사람 설정
# msg_from = 'miero@kakao.com'
self.listwidget32.clear()
if len(self.lineedit11.text()) == 0:
QMessageBox.about(self,'이메일계정 확인','이메일계정을 입력하십시요.')
return
p = re.compile('^[a-zA-Z0-9+-_.]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$')
if p.match(self.lineedit11.text()) == None:
# print(p.match(self.lineedit11.text()) != None)
QMessageBox.about(self,'이메일 형식 확인','올바른 이메일 형식이 아닙니다.')
return
if len(self.lineedit12.text()) == 0:
QMessageBox.about(self,'비밀번호 확인','비밀번호를 입력하십시요.')
return
cnt = 0
if len(self.lineedit21.text()) == 0:
QMessageBox.about(self,'제목 입력 확인','제목을 입력하십시요.')
return
self.fn_subject_save()
self.fn_html_save()
# self.fn_send("밀1", self.df_table_02.loc["밀1"][0])
# self.fn_print_name("밀1", self.df_table_02.loc["밀1"][0])
self.fn_DeleteAllFiles(os.getcwd()+"\pdf")
for idx_name in self.idx_name_list:
# print(idx)
# print(self.df_table_02.loc[idx][0])
# print(idx, table_02.loc[idx][0])
self.fn_pdf_create(idx_name)
try:
if self.df_table_02.loc[idx_name][0] != "nan":
self.fn_send(idx_name, self.df_table_02.loc[idx_name][0])
cnt += 1
self.listwidget32.addItem(f'{idx_name}-{self.df_table_02.loc[idx_name][0]}-전송완료')
except:
cnt += 1
self.listwidget32.addItem(f'{idx_name}-{self.df_table_02.loc[idx_name][0]}-실패')
self.listwidget32.item(cnt-1).setBackground(Qt.red)
# if self.df_table_02.loc[idx_name][0] == "nan":
# print(self.listwidget32.)
# self.listwidget32.item(cnt).setBackground(Qt.red)
# print("예외가 발생했습니다.-fn_run",cnt,self.df_table_02.loc[idx_name][0])
# self.fn_print_name(idx_name, self.df_table_02.loc[idx_name][0])
self.server.quit()
# self.app.kill()
# print('예외가 발생했습니다.')
# self.listwidget32.insertItem(cnt, f'{idx_name}-{self.df_table_02.loc[idx_name][0]}-실패')
QMessageBox.about(self,'전송 완료','전송 작업 완료')
if __name__ == '__main__':
# don't auto scale when drag app to a different monitor.
# QGuiApplication.setHighDpiScaleFactorRoundingPolicy(Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
excel_file_path = '급여1.xlsx'
worksheet_name = '4대급여'
emailsheet_name = '이메일'
app = QApplication(sys.argv)
app.setStyleSheet('''
QWidget {
font-size: 17px;
}
''')
myApp = MyApp()
myApp.show()
try:
sys.exit(app.exec())
except SystemExit:
print('Closing Window...')
====================
pay25.py--------------------
'컴퓨터 > Python' 카테고리의 다른 글
python 파일 합치기 (0) | 2022.09.14 |
---|---|
python selenium chromedriver 다운 안받아도 되네요 (0) | 2022.09.08 |
excel to pdf (0) | 2022.08.28 |
AI코인 email (0) | 2022.08.28 |
코딩나우-pandas (0) | 2022.08.27 |