美文网首页
2020-01-09

2020-01-09

作者: 少儿创客 | 来源:发表于2020-01-09 22:30 被阅读0次
    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

          本文链接:https://www.haomeiwen.com/subject/wtvuactx.html