前言:同事给了我一个看起来并不简单的活,根据一定的规则随机抽取一定数量的人参加下次考试,为什么我觉得不容易呢?规则如下:
- 60-69分:该人员继续参加下月考试;
- 70-79分:无;
- 80-89分:该人员下月免试;
- 90分以上:该人员所在门店下月免试(若当月同门店有其他参考人员且分数低于70分,该人员免试但取消该门店免试资格)。
直接用excel公式几乎不可能,条件太多了;我又想用VBA来做(虽然肯定可以),但是VBA中如Python中列表、字典的东东我并不熟悉,所以决定还是用Python吧。另外因为要打包给非程序员的同事使用,所以openpyxl这种打包困难的库直接舍弃了,还是使用win32com.client。最后因为代码量不多(不足100行),所以就不封装了。
excel的sheet样式如图:
3月25日更新:出现了一个小乌龙,我一开始在判断成绩的时候用了if not score的方式来排除上次没考试的人员,但谁想还真有0分的人员,导致得0分的也被踢掉了,找了好久才找到这个bug,赶忙用if score is None来代替
from win32com.client import Dispatch
from os import path
import random
'''规则:
1、每月固定参加考试人员:80人;
2、下月参加考试人员评判标准:
if 0 <= score<=69:
下月继续参加考试;
if score>=80:
下月该人员免试;
if score>=90 and 所属门店本次参加考试的所有人员的score>=70:
下月该门店免试;
'''
try:
xl = Dispatch("Excel.Application")
xl.Visible = False #True是显示, False是隐藏
xl.DisplayAlerts = 0
sn_dict = {} #序号和门店的组合字典,形如{1:'周浦营业厅', 2:'周浦营业厅', 3:'仲诚德平路营业厅'...}
less_than_sixty_nine = [] #0-69分的序号列表,形如[2, 3, 7...]
more_than_eighty = [] #大于等于80分的序号列表,形如[1, 5, 9...]
more_than_ninety = [] #大于等于90分的门店列表,形如['周浦营业厅', '仲诚德平路营业厅'...]
next_exam_list = [] #下场参加考试的序号列表,形如[2, 3, 7...]
pre_list = [] #有可能参加下场考试的序号列表
store_list_path = path.abspath('.')+"\\门店考试人员.xlsx"
wb = xl.Workbooks.Open(store_list_path)
ws = wb.Sheets('总清单')
ws_next = wb.Sheets('下次考试人员')
max_row = ws.UsedRange.Rows.Count + 1 #最大行数+1
# max_col = ws.UsedRange.Columns.Count #最大列数
for i in range(2, max_row):
sn = int(ws.Cells(i, 1).Value) #序号
store = ws.Cells(i, 3).Value #门店
sn_dict[sn] = store
score = ws.Cells(i, 13).Value # 成绩
if score is None:
continue
else:
score = int(score)
if score <=69:
less_than_sixty_nine.append(sn)
print('{}的成绩小于70分,分数是{}'.format(sn, score))
next_exam_list.append(sn)
elif 80<= score <=89:
more_than_eighty.append(sn)
elif score >=90:
more_than_eighty.append(sn)
if store in more_than_ninety:
continue
else:
more_than_ninety.append(store)
print('小于70分的人员序号是:{}'.format(less_than_sixty_nine))
print('下次免考的人员序号是:{}'.format(more_than_eighty))
#剔除有其它考试人员低于70分的门店
for i in less_than_sixty_nine:
if sn_dict[i] in more_than_ninety:
more_than_ninety.remove(sn_dict[i])
else:
continue
print('下次免考的门店是:{}'.format(more_than_ninety))
#获得准备抽奖参与下场考试的人员序号列表
for i in range(1, max_row-1):
if i in more_than_eighty:
continue
elif sn_dict[i] in more_than_ninety:
continue
elif i in next_exam_list:
continue
else:
pre_list.append(i)
#获得参加下次考试的人员序号列表
lack_num = 80 - len(next_exam_list)
random.shuffle(pre_list)
new_next_exam_list = next_exam_list + pre_list[0:lack_num]
print('参加下次考试的人员序号是:{}'.format(new_next_exam_list))
#把参加下次考试的人员做成一个新的sheet
n = 2
for i in new_next_exam_list:
j = i + 1
for k in range(1, 14):
ws_next.Cells(n, k).Value = ws.Cells(j, k).Value
n += 1
print('下次考试人员整理完毕!')
except Exception as e:
print(e)
finally:
wb.Close(True)
xl.quit()
end = input('按回车键退出:')
最后成品如图: