ctOS_ 发表于 2020-3-9 12:07

用python3统计数据我们学校的德育加分数据

本帖最后由 ctOS_ 于 2020-3-9 21:40 编辑

引入:
前些日子我们学校部门上头要求统计上个学期的德育分
(就是统计上个学期所有学生参加志愿者的时长,然后汇总成表)
虽然好像很简单的样子
但是每个学院都需要一个独立的表格,但是总的数据表把全校所有学生的数据都放在一起了。
并且同一个学生可能参加多次志愿者,要把记录放到一起,合并单元格,从大到小排序
之前我想过用excel的分类汇总,但是部门其他几个人对Office软件似乎并不怎么理解
(我只用做两个学院,所以工作并不是很艰辛,但经常要帮她们处理问题)
这就很累人了。
于是我就想着用python写套代码,把中间流程去掉。

这样,这套德育分汇总代码就诞生了!


虽然可能对大部分坛友没什么用(我感觉自己的代码一点都不精简)

就当留个纪念好了

while True:# 学院统计
    import xlrd
    import xlwt
    import pandas as pd
    from os import remove

    college = input('请问你当前要筛选的学院是?')
    doc = input('请输入数据库的文件名(带后缀)')
    outdoc = input('请输入你要输出的文件名(.xls)')
    data = xlrd.open_workbook(doc)# 打开d数据库
    dataout = xlwt.Workbook(encoding='utf-8')
    dataout_sheet = dataout.add_sheet('result')
    line = 0
    sheet = data.sheet_by_index(0)# 打开data.xlsx中第一个表
    nrows = sheet.nrows# 获取表的行数
    Class = ['班级']# 存放该学院班级的列表
    Notclass = []# 存放不是该学院的班级列表


    # 第一步,找出该学院的相关数据

    def writein(x, l, s):
      fanwei = len(x)
      for i in range(fanwei):
            s.write(l, i, x)

    print('-----------------------------------开始从数据中筛选班级------------------------')
    for i in range(nrows):# 表中的第i行
      idata = sheet.row_values(i)# 获取第i行数据
      iclass = idata# 获取班级单元格的值
      eleclass = iclass# 获取前两个字(也就是班级专业简称)
      isclass = False
      notclass = False
      for y in Class:
            if y == eleclass:
                isclass = True
      for y in Notclass:
            if y == eleclass:
                notclass = True
      if isclass:
            writein(idata, line, dataout_sheet)
            line += 1
      if notclass == False and isclass == False:
            ask = input('请问<' + eleclass + '>是不是<' + college + '>的班级?(y/n):')
            if ask == 'y':
                Class.append(eleclass)
                writein(idata, line, dataout_sheet)
                line += 1
            elif ask == 'n':
                Notclass.append(eleclass)

    dataout.save('step.xls')
    print('-----------------------------------筛选完毕------------------------')
    # 第二步,就当前数据按照姓名,班级,日期进行排序
    print('-----------------------------------开始给数据排序------------------------')
    data = pd.read_excel('step.xls')# 用pd打开excel
    data.sort_values(by=['姓名', '班级', '日期'], inplace=True)
    data.to_excel('step1.xlsx')# 输出排序后的结果
    print('-----------------------------------计算时长与加分(记得请将加分细则填入表2)------------------------')
    # 第三步,准备根据时长总和排序
    data = xlrd.open_workbook('step1.xlsx')# 打开数据库
    sheet = data.sheet_by_index(0)# 打开第一个表
    nrows = sheet.nrows# 读取数据表行数
    start = 0
    end = 0
    timetotal = 0# 该学生总时长

    newdoc = xlwt.Workbook(encoding='utf-8')# 新表(存储总时长和姓名)
    newsheet = newdoc.add_sheet('result')
    line = 1# 实时更新新表写入数据的行数
    newsheet.write(0, 0, '姓名')
    newsheet.write(0, 1, '时长')

    for i in range(1, nrows-1):# 因为数据表第一行不是数据,所以从第二行开始
      idata = sheet.row_values(i)
      iname = idata
      y = i + 1
      ydata = sheet.row_values(y)
      yname = ydata
      if i < nrows:
            if iname == yname:
                timetotal += idata
            else:
                timetotal += idata
                newsheet.write(line, 0, iname)
                newsheet.write(line, 1, timetotal)# 纪录这个学生的总时长
                timetotal = 0
                line += 1
    timetotal += idata# 在i=nrows时,没有i+1了,所以独立出来再写一次
    newsheet.write(line, 0, iname)
    newsheet.write(line, 1, timetotal)


    newdoc.save('step2.xls')

    data = pd.read_excel('step2.xls')# 用pd打开excel
    data.sort_values(by='时长', inplace=True, ascending=False)
    data.to_excel('step3.xlsx')# 输出排序后的结果
    remove('step.xls')
    remove('step2.xls')# 清理一下之前的文件


    # 第四步 在原数据表的表2进行时长与分数的换算
    print('-----------------------------------准备写入最终数据------------------------')
    def score(x):
      lable2 = xlrd.open_workbook('data.xlsx')
      sheet2 = lable2.sheet_by_index(1)
      lines = sheet2.nrows
      for i in range(1, lines):
            idata = sheet2.row_values(i)
            maxtime = float(idata)
            if maxtime >= x:
                return float(idata)


    # 第五步 以step1.xlsx和step3.xlsx为参考,最终成表

    data = xlrd.open_workbook('step3.xlsx')# 打开新表
    sheet = data.sheet_by_index(0)
    nrows = sheet.nrows# 获取新表行数

    data2 = xlrd.open_workbook('step1.xlsx')
    sheet2 = data2.sheet_by_index(0)
    nrows2 = sheet2.nrows# 旧表行数

    result = xlwt.Workbook(encoding='utf-8')# 最终数据库
    result_sheet = result.add_sheet('result', cell_overwrite_ok=True)# 结果表
    x = sheet2.row_values(0)

    style = xlwt.XFStyle()
    al = xlwt.Alignment()
    al.horz = 0x02
    al.vert = 0x01
    style.alignment = al


    def wrotein(data, line, doc):
      lenline = len(data)
      for i in range(lenline - 1):
            doc.write(line, i, data, style)
      print('-----------------------------------写入'+data+'的数据------------------------')

    wrotein(x, 0, result_sheet)# 写入表头
    line = 1# 从第一行开始写入数据

    for i in range(1, nrows):# 新表中遍历
      idata = sheet.row_values(i)# 新表第i行
      iname = idata# 姓名
      iscore = score(idata)# 总时长
      place = False# 判断是否找对了地方
      for y in range(1, nrows2):
            ydata = sheet2.row_values(y)
            yname = ydata

            if place == False and iname == yname:
                wrotein(ydata, line, result_sheet)
                place = True
                step = 0
                start = line
                Place = y
                line += 1
            elif place == True and iname == yname:
                wrotein(ydata, line, result_sheet)
                step += 1
                line += 1
            if place == True and iname != yname:
                place = False
                break

      the_data = sheet2.row_values(Place)
      theclass = the_data
      thename = the_data
      thescore = str(iscore)
      result_sheet.write_merge(start, start + step, 0, 0, theclass, style)
      result_sheet.write_merge(start, start + step, 1, 1, thename, style)
      result_sheet.write_merge(start, start + step, 5, 5, thescore, style)



      print('-----------------------------------合并相同数据------------------------')
    remove('step1.xlsx')
    remove('step3.xlsx')
    result.save(outdoc + '.xls')
    print('--------------------------------------------------------------------------<成功>')
    print('---------------------------------------------------------------------------请记得修改日期的单元格格式')

表一放数据
表二是具体的加分规则(两个表第一行都不写数据)


班级姓名日期服务项目服务时长/小时加分组织部门

linling 发表于 2020-3-9 12:24

代码很棒,方便他人,自己有时候也可以快速改改应急呀。

ericwise 发表于 2020-3-9 13:02

谢谢分享代码

GalaxyMimi 发表于 2020-3-9 13:27

python写起来还是舒服

HighBox 发表于 2020-3-9 13:47

收下了,谢谢楼主分享

知意执意 发表于 2020-3-9 20:38

值得学习

ctOS_ 发表于 2020-3-9 21:42

我今晚测试的时候发现
程序不会算上该学院中最后一个学生纪录
现在修改好了
不好意思

wolaileo 发表于 2020-3-10 10:48

我觉得 还是 把 表格一起传(修改掉 真实数据),这样才好测试代码

ctOS_ 发表于 2020-3-10 11:12

wolaileo 发表于 2020-3-10 10:48
我觉得 还是 把 表格一起传(修改掉 真实数据),这样才好测试代码

表格里其实就班级,姓名还有服务项目比较涉及隐私
数据量大的话测试代码也比较麻烦
可以自己随便做个数据少一点的excel啦

我们学校的班级命名格式是<专业简称+入学年份+班级序列>
比如说19年入学的大数据技术与应用,就写成<数应191>
判断班级是否所属学院也只根据前面两个字
其他姓名张三李四王五之类都没问题
加分那一栏留空,在表二里用这样的格式输入就好了
最大时长        得分
5        0.5
10        1
20        1.5
30        2

plasd 发表于 2020-3-10 12:34

先收藏,感谢
页: [1]
查看完整版本: 用python3统计数据我们学校的德育加分数据