import xlrd
import xlrd
from docxtpl import DocxTemplate, InlineImage
from docx.shared import Mm
import pyecharts
import numpy as np
from random import random
import matplotlib.pyplot as plt
import matplotlib
import os
from docxtpl import DocxTemplate, InlineImage
from docx.shared import Mm
#===================開始設置中文字體=================
font = {
'family' : 'SimHei',
'size' : 20
}
matplotlib.rc('font', **font)
#===================結束設置中文字體=================
class GenerateReport:
def __init__(self, files, stuClass='1.1'):
if not files:
return None
else:
self.files = files
self.radarIndex = 0
# TODO:這種字符串可以用字符串分割方法生成數組
# 反之用數字拼接字符串可以降低拼寫的效率
# 怪不得校園寶要設置學科
self.subjects = ['語文','數學','英語','歷史','道法','地理','生物','物理']
self.subjects_en = ['chinese','maths','english','history','tao','geography','bio','physical']
self.root = stuClass
def mkdir(path):
if not os.path.isdir(path):
mkdir(os.path.split(path)[0],'/')
else:
return
os.mkdir(path)
if not os.path.exists(self.root):
os.mkdir(self.root)
os.mkdir("/{}/doc".format(self.root))
os.mkdir("/{}/line".format(self.root))
os.mkdir("/{}/radar".format(self.root))
self.dataset = self.processFiles(files)
def setTemplate(self, file):
self.template = file
def paraXls(self, filename):
# TODO:要添加異常處理
# {
# 'stuName': 'langxm',
# 'scores': [
# {
# 'chinese': 80,
# 'math' : 90
# },
# ],
# 'grades': [
# {
# 'chinese': A,
# 'math' : B
# },
# ],
# 'sum': 20,
# 'rank': 20,
# 'total': 20
# }
dataset = {}
wb = xlrd.open_workbook(filename)
sht = wb.sheet_by_index(0)
rows = sht.nrows
cols = sht.ncols
header = sht.row_values(0, 0, cols)
self.students = sht.col_values(0, 1, rows)
# 查詢index的代碼有待優化
def getIndex(value, valuelist):
# TODO:重名的情況
return valuelist.index(value)
subjectIndexes = [getIndex(subject, header) for subject in self.subjects]
# TODO:numpy的數組加載xls處理效率更高,可以用numpy的np數組改寫
for i in range(1, rows):
line = sht.row_values(i, 0, cols)
stuName = line[0]
scores = [line[index] for index in subjectIndexes]
grades = [line[index + 1] for index in subjectIndexes]
examData = {}
item = {}
item['scores'] = scores
item['grades'] = grades # 這些項目都是可以做成可以配置的
# 可以用工廠模式改寫
item['total'] = sum(scores)
item['avg'] = sum(scores) / len(subjectIndexes)
examData[stuName] = item
dataset[stuName] = examData
return dataset
def processFiles(self, files):
d = {}
def setValue(key, value):
d[key] = value
[setValue(file, self.paraXls(file)) for file in files]
return d
def drawRadar(self, stuName, index=0):
pass
labels = np.array(self.subjects[index:]) # 標簽
dataLenth = len(labels) # 數據長度
angles = np.linspace(0, 2*np.pi, dataLenth, endpoint=False) # 分割圓周長
angles = np.concatenate((angles, [angles[0]])) # 閉合
dataset = []
# stuName = '徐文清'
for file in self.files[index:]:
dataset.append(self.dataset[file][stuName][stuName]['scores'])
polars = []
plt.clf()
for ds in dataset:
ds = np.concatenate((ds, [ds[0]]))
p1, = plt.polar(angles, ds, 'o-', linewidth=1) #做極坐標系
polars.append(p1)
plt.legend(polars,[file[0:-5] for file in self.files[index:]] ,prop={'family':'SimHei'})
plt.thetagrids(angles * 180/np.pi, labels, fontproperties='SimHei') # 設置網格、標簽
plt.ylim(0,100) # polar的極值設置為ylim
plt.savefig(self.root + '/radar/{}radar.png'.format(stuName))
pass
plt.close('all')
plt.clf()
labels = np.array(self.subjects) # 標簽
fig, ax1 = plt.subplots(figsize=(12,9))
# stuName = '徐文清'
# plt.cla()
for file in self.files:
ax1.plot(labels, self.dataset[file][stuName][stuName]['scores'], label=file[0:-5])
plt.title("{}期中期末成績折線圖".format(stuName),fontproperties='SimHei',fontsize=30)
ax1.legend()
ax1.grid(axis="y",color="grey",linestyle="--",alpha=0.5)
ax1.tick_params(axis="x",labelsize=16)
ax1.tick_params(axis="y",labelsize=16)
ax1.set_ylabel("成績",fontsize = 16)
ax1.set_xlabel("學科",fontsize = 16)
ax1.set_ylim(0,100)
for tl in ax1.get_yticklabels():
tl.set_color('r')
ax1.spines['top'].set_visible(True)
plt.savefig(self.root + '/line/{}line.png'.format(stuName))
plt.close(0)
def drawLine(self, stuName):
pass
labels = np.array(self.subjects) # 標簽
fig, ax1 = plt.subplots(figsize=(12,9))
# stuName = '徐文清'
for file in self.files:
ax1.plot(labels, self.dataset[file][stuName][stuName]['scores'], label=file[0:-5])
plt.title("{}期中期末成績折線圖".format(stuName),fontproperties='SimHei',fontsize=30)
ax1.legend()
ax1.grid(axis="y",color="grey",linestyle="--",alpha=0.5)
ax1.tick_params(axis="x",labelsize=16)
ax1.tick_params(axis="y",labelsize=16)
ax1.set_ylabel("成績",fontsize = 16)
ax1.set_xlabel("學科",fontsize = 16)
ax1.set_ylim(0,100)
for tl in ax1.get_yticklabels():
tl.set_color('r')
ax1.spines['top'].set_visible(True)
plt.savefig(self.root + '/line/{}line.png'.format(stuName))
plt.close()
def saveDoc(self, stuName):
# plt.clear()
pass
# TODO:模板生成word雖然方便但是寫模板變量太煩了
# 后面改成直接生成
doc = DocxTemplate(r"./{}".format(self.template))
dataset = []
# stuName = '徐文清'
context = {}
for file in self.files:
dataset.append(self.dataset[file][stuName][stuName])
context['stuName'] = stuName
for key, ds in enumerate(dataset):
context['file'+str(key)] = self.files[key]
scores = ds["scores"]
for i in range(len(scores)):
context[self.subjects_en[i]+str(key)] = scores[i]
context['linechart'] = InlineImage(doc, 'line/{}line.png'.format(stuName), width=Mm(100))
context['radarchart'] = InlineImage(doc, 'radar/{}radar.png'.format(stuName), width=Mm(100))
doc.render(context)
doc.save(r"./{}/doc/{}.docx".format(self.root, stuName))
def genDocs(self):
for stuName in self.students:
# self.drawLine(stuName)
if stuName == '趙爍源':
continue
self.drawRadar(stuName,index=self.radarIndex)
# TODO:文件名應該是可以配置的包括路徑
self.saveDoc(stuName)
print('{}的文檔已經生成,位于./{}/doc/{}.docx'.format(stuName, self.root, stuName))
if __name__ == "__main__":
pass
gr = GenerateReport(['86.xlsx','861.xlsx','862.xlsx','863.xlsx'])
gr.setTemplate('86temp.docx')
# gr.drawLine('徐文清')
print(len(gr.students))
gr.genDocs()
# print(gr.dataset)
2020-01-09
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
推薦閱讀更多精彩內容
- 賺錢、提升自己 這是我2020年人生規劃里的兩個重大選項,面對人生境遇、面對生活壓力,這是目前最需要解決的問題。今...
- 聊聊2020年怎么賺錢? 酣暢淋漓的看完羅胖的跨年演講,對個人財富的基本盤最感興趣。 曾鳴教授說:“容易賺的錢肯定...