標籤

bat (54) 作品 (41) python (24) shell (17) windows (11) 虛擬機 (11) php (10) CPP (6) KMS (6) 程式設計 (6) docker (5) 使用教學 (5) xoops (4) 公文 (4) Apache2 (3) Excel (3) juniper (3) 資料庫 (3) 轉檔 (3) mysql (2) 免動手 (2) 資料結構 (2) 軟體廣播 (2) 電腦維修 (2) Android Studio (1) Apple IPAD管理 (1) Arduino (1) CSS (1) LAMP (1) NAS (1) Ubuntu (1) VHD (1) Windows Server (1) 原因 (1) 程式應用 (1) 程式積木 (1) 編輯器 (1) 雲端硬碟 (1)

2022年9月28日 星期三

只要點兩下,就能寄送全班個人成績單

        最近段考剛過,又要通知家長學生成績。原本讓學生寫聯絡簿,然後將紙本成績單貼上聯絡簿,家長在聯絡簿與紙本成績單上簽名,導師批閱聯絡簿與紙本成績單就可以知道家長是否知情。但是,學生會仿冒家長簽名或拿家長的印章蓋章,阻止家長得知成績。老師必須要比對筆跡,才能知道學生是否仿冒家長簽名。
        由於法規限制,家長只能收到自己孩子的成績,不能知道班上其他學生的成績。老師會從學校方面取得紙本全班成績單或從雲端校務系統下載電子全班成績單。換言之,老師要讓家長知道自己孩子的成績,就得對紙本全班成績單做處理,將之一一切割成紙本個人成績單。或是重新整理電子全班成績單,將之複製貼上到個人成績單。總之,這是一項大工程。
        是否能夠開發程式,讓老師只要點兩下就能夠建立全班個人成績單。接下來,點兩下就能夠將個人成績單一一發送到家長電子信箱。
        最後完成程式:
下載檔案。解壓密碼:demo1234
教學影片:


        以下是使用教學,共有五個步驟:
一.若沒有Gmail,請先建立自己的Gmail
二.下載程式與解壓縮
三.設定寄件者電郵與密碼
四.自雲端校務系統下載report.xlsx
五.對著01建立學生成績PDF_PyScroeTablePdf.exe點兩下
六.對著02批次寄電郵給家長_PythonGmail.exe點兩下
        
        依序如下:
一.若沒有Gmail,請先建立自己的Gmail
        一次設定




二.下載程式與解壓縮
      解壓縮時,要注意:不能破壞資料夾結構。





.設定寄件者電郵與密碼
        一次設定
        程式預設使用Gmail。若沒有Gmail,請建立Gmail。
        設定兩步驟驗證


        設定 應用程式密碼



.自雲端校務系統下載report.xlsx

.對著01建立學生成績PDF_PyScroeTablePdf.exe點兩下

.對著02批次寄電郵給家長_PythonGmail.exe點兩下

程式設計部分:
程式目的:讀取report.xlsx 並整理全班學生成績匯出學生個人成績.pdf  到 附件資料夾
檔案名稱:PyScroeTablePdf.py
檔案內容:
import os
import openpyxl as opxl
from win32com.client import DispatchEx

class StudentDataDict():
    def __init__(self,FileName):
        self.FileName = FileName

    def StudentData(self):
        #取得學生成績資料
        wb = opxl.load_workbook(self.FileName)
        wbsh = wb['Worksheet']
        StudentDataDict = dict()
        ScoreName = wbsh.cell(1,1).value
        StudentDataDict[1] = ScoreName
        SubjectNameList = []
       
        for i in range(1,wbsh.max_column+1):
            SubjectNameList.append(wbsh.cell(2,i).value)
        StudentDataDict[2] = SubjectNameList
       
        for j in range(3,wbsh.max_row+1):
            StudentDataList = []
            for i in range(1,wbsh.max_column+1):
                StudentDataList.append(wbsh.cell(j,i).value)
            StudentDataDict[j] = StudentDataList

        return StudentDataDict

class ScoreTablePdf():
    def __init__(self,StudentData):
        self.StudentData = StudentData

    def RecipientData(self):
        #建立收件者資料
        RecipientFile = str(os.path.abspath(os.getcwd()))+'\\收件者資料.xlsx'
        TempStudentData = self.StudentData
        if not os.path.exists(RecipientFile):
            print("建立收件者資料.xlsx.......")
            #收件者資料.xlsx不存在,則自動建立收件者資料.xlsx
            TempExcelFile = opxl.Workbook()
            TempExcelFileSheet = TempExcelFile.active
            TitleName = ['年班座號','學生姓名','家長姓名','家長電郵','附件名稱','附件副檔名']
            for i in range(0,len(TitleName)):
                TempExcelFileSheet.cell(row=1,column=i+1).value = TitleName[i]
            for j in range(0,len(TempStudentData)):
                TempExcelFileSheet.cell(row=j+2,column=1).value = TempStudentData[j+3][0]+str(TempStudentData[j+3][1]).zfill(2)
                TempExcelFileSheet.cell(row=j+2,column=2).value = TempStudentData[j+3][3]
                TempExcelFileSheet.cell(row=j+2,column=5).value = TempExcelFileSheet.cell(row=j+2,column=1).value
                TempExcelFileSheet.cell(row=j+2,column=6).value = 'pdf'
            TempExcelFile.save(RecipientFile)    
            print("建立收件者資料.xlxs OK")
           
    def ScoreTable(self):
        TempPath = str(os.path.abspath(os.getcwd()))+'\\Temp\\'
        if not os.path.isdir(TempPath):
            os.mkdir(TempPath)
        AttachPath = str(os.path.abspath(os.getcwd()))+'\\附件\\'
        if not os.path.isdir(AttachPath):
            os.mkdir(AttachPath)
        TempStudentData = self.StudentData    
        TableSubject = self.StudentData[1]
        TempStudentData.pop(1)
        TestSubject = self.StudentData[2]
        TempStudentData.pop(2)
        for i in TempStudentData:
            ExcelWorkBook = opxl.Workbook()
            ExcelSheet = ExcelWorkBook.worksheets[0]
            ExcelSheet['A1'] = TableSubject
            for j in range(1,len(TestSubject)):
                ExcelSheet.cell(row=j+1,column=1).value = TestSubject[j]
                ExcelSheet.cell(row=j+1,column=2).value = TempStudentData[i][j]
            ExcelFileName = TempStudentData[i][0]+str(TempStudentData[i][1]).zfill(2)+".xlsx"    
            ExcelWorkBook.save(TempPath+ExcelFileName)
            PdfFileName = TempStudentData[i][0]+str(TempStudentData[i][1]).zfill(2)+".pdf"    
            TempExcelApplication = DispatchEx("Excel.Application")
            TempExcelApplication.Visible = False
            TempExcelApplication.DisplayAlerts = 0
            TempBooks = TempExcelApplication.Workbooks.Open(TempPath+ExcelFileName,False)
            TempBooks.ExportAsFixedFormat(0,AttachPath+PdfFileName)
            TempBooks.Close(False)
            print("建立學生 "+PdfFileName+" 成績單...OK")
            os.remove(TempPath+ExcelFileName)
        os.removedirs(TempPath)
       

print("取得report.xlsx 資料....")
pep01 = StudentDataDict('report.xlsx').StudentData()
print("取得report.xlsx 資料OK")
print("建立全班學生個人成績單.....")
ScoreTablePdf(pep01).ScoreTable()
print("建立全班學生個人成績單OK")
ScoreTablePdf(pep01).RecipientData()
os.system("pause")
os.system("exit")

程式設計部分:
程式目的:將附件內的學生個人成績.pdf 依著收件者資料.xlsx 一一寄給家長
檔案名稱:PythonGmail.py
檔案內容:
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import smtplib
from email.mime.image import MIMEImage
from pathlib import Path
from email.mime.application import MIMEApplication
import os
import openpyxl as opxl

           
class EmailOpenFiles():
    #開啟檔案
   
    def __init__(self,DirectoryName,FileName):
        self.DirectoryName = DirectoryName
        self.FileName = FileName

    def AttachFiles(self):
        #取得附件資料夾內所有檔案名稱並回傳List
        AttachDirPath=str(os.path.abspath(os.getcwd()))+'\\'+self.DirectoryName+'\\'
        AttachFileNameList = os.listdir(AttachDirPath)
        return AttachFileNameList
   
    def EmailFileContent(self):
        #設定信件內容檔名並取得檔案內容並回傳List
        EmailContentFileName = str(os.path.abspath(os.getcwd()))+"\\"+self.FileName
        EmailContentFile = open(EmailContentFileName,'r')
        EmailContentList = EmailContentFile.readlines()
        EmailContentFile.close()
        return EmailContentList
   
    def AttachDirPath(self):
        #取得附件資料夾路徑
        AttachDirPath=str(os.path.abspath(os.getcwd()))+'\\'+self.DirectoryName+'\\'
        return AttachDirPath
   
    def AttachExcelOpen(self):
        #打開附件為Excel檔案並回傳List
        AttachExcelFileName = str(os.path.abspath(os.getcwd()))+"\\"+self.FileName
        TempExcelWorkBook = opxl.load_workbook(AttachExcelFileName)
        TempMax_Row = TempExcelWorkBook.worksheets[0].max_row
        TempMax_Column = TempExcelWorkBook.worksheets[0].max_column
        TempReturnList = []
        for i in range(1,TempMax_Row+1):
            TempList = []
            for j in range(1,TempMax_Column+1):
                TempList.append(TempExcelWorkBook.worksheets[0].cell(i,j).value)
            TempReturnList.append(TempList)
        return TempReturnList



class PythonGmail():
    def __init__(self,EmailSubject,EmailFrom,EmailTo,EmailContent,EmailAttachments,EmailSender,EmailPass):
        self.EmailSubject = EmailSubject
        self.EmailFrom = EmailFrom
        self.EmailTo = EmailTo
        self.EmailContent = EmailContent
        self.EmailAttachments = EmailAttachments
        self.EmailSender = EmailSender
        self.EmailPass = EmailPass
   
    def PythonGmail(self):
        #建立MIMEMMultipart物件
        content = MIMEMultipart()
        #郵件標題
        content["subject"] = self.EmailSubject
        #寄件者Email
        content["from"] = self.EmailFrom
        #收件者Email
        content["to"] = self.EmailTo
        #郵件內容
        content.attach(MIMEText(self.EmailContent))
       
        #附件寄送檔案
        AttachFileName = self.EmailAttachments
        AttachFileload = MIMEApplication(open(AttachFileName,'rb').read())
        AttachFileload.add_header('Content-Disposition','attachment',filename=AttachFileName)
        content.attach(AttachFileload)
       
        #設定SMTP伺服器
        with smtplib.SMTP(host="smtp.gmail.com",port="587") as smtp:
            try:
                #驗證SMTP伺服器
                smtp.ehlo()
                #建立加密傳輸
                smtp.starttls()
                #登入寄件者Gmail
                #smtp.login("寄件者信箱","寄件者密碼")
                smtp.login(self.EmailSender,self.EmailPass)
                #寄送郵件
                smtp.send_message(content)
                #顯示訊息
                return "Success! Send OK!"
            except Exception as e:
                return "Error message:"+str(e)

#取得附件資料夾內所有檔案名稱
EmailAttachments = EmailOpenFiles('附件','').AttachFiles()
#取得附件資料夾的絕對路徑
EmailAttachDirPath = EmailOpenFiles('附件','').AttachDirPath()

#取得信件標題檔案內容並存成信件標題list
EmailSubjectlist = EmailOpenFiles('','信件標題.txt').EmailFileContent()
#從信件標題list取得信件標題字串
EmailSubject = EmailSubjectlist[0]

#取得信件內容檔案內容並存成信件內容list
EmailContentlist = EmailOpenFiles('','信件內文.txt').EmailFileContent()
#從信件內容list取得信件內容字串
EmailContent = ""
for i in EmailContentlist:
    EmailContent = EmailContent + i

#從寄件者電郵與密碼.txt取得List
EmailSenderAddrList = EmailOpenFiles('','寄件者電郵與密碼.txt').EmailFileContent()
#去除List[0]標題
EmailSenderAddrList.pop(0)
#取得寄信者email與密碼
EmailSender,EmailPass = EmailSenderAddrList[0].split(',')

#從收件者資料.xlsx 取得List
EmailToList = EmailOpenFiles('','收件者資料.xlsx').AttachExcelOpen()
#去除List[0]標題
EmailToList.pop(0)
#取得收件者資料並逐一寄信
for i in EmailToList:
    A1,A2,A3,A4,A5,A6 = i
    EmailAttachFileName=EmailAttachDirPath+A5+'.'+A6
    EmailTest=PythonGmail(EmailSubject,EmailSender,A4,EmailContent,EmailAttachFileName,EmailSender,EmailPass).PythonGmail()
    print(A1+" "+A2+" Email "+ EmailTest)

os.system("pause")
os.system("exit")



資料來源:
1.Python實現Gmail客製化信件大量發送 — 【基礎篇】
2.Python 初學第十二講—檔案處理
3.Python split 字串分割用法與範例




沒有留言:

張貼留言

只要點兩下,就能夠將InputAndOutput資料夾底下的子子孫孫資料夾內所有Word通通轉成PDF

  系列文章: 1. 只要點兩下,就能將一堆的Doc與Docx 轉成 PDF 1. https://skjhcreator.blogspot.com/2023/05/docdocx-pdf.html 2. 只要點兩下,就能將一堆的JPG轉成一個PDF,並以JPG所在的資料夾名稱為...