前言:
很多项目组也都有本人的检配表查办法,我也见过两个项目组的两种不同做法,然而我是不太认同的。我综合思考出另外一种做法(集体感觉是不错的,而且目前履行起来深得我意),然而因为某些起因,我没有在原来我的项目中去推动我的想法实现。
这个想法两年前就有了,惋惜始终没机会实际。2020 年 4 月的时候终于迎来一次机会,于是把想法付诸理论。现在回望,也是颇有感叹。写一写我怎么做的吧。
筹备:
我须要去思考的一些点:
配表改变可能会很频繁,包含但不限于增删表头、改数据格式等
配表可能会有多文件夹同名表格(SLG 多赛季,不同赛季会有 season1、season2 文件夹,而且 season 下也可能有同名表)
当配置表多、规定多的状况下,需不需要去思考效率问题。小几分钟出查看后果,我能够承受,10 以上是不能承受的。
简略、方便快捷反对规定配置,规定增删
简单明了输入谬误问题
要不要思考平台化
......
尝试实现:
不晓得咋想的,过后就有一个想法,通过规定表映射去查看配表(刚好满足很多我的需要)。具体做法是:
新建规定查看文件夹
将须要查看的表格复制过去,删除表格内容,在对应列配置规定
这个做法在落实之后也有一些小问题继续优化,这点前面说。先说下外围做法的实现:
main 函数
if __name__ == '__main__': table = Table() //这里用xlsx作为规定配置表,是因为前面优化有主动写入性能,相比xls,xlsx会更不便一些 excel = file.File.get_file_dir(config.RULE_DIR, file_type=".xlsx") d_excel = file.File.get_file_dir(config.DOC_DIR, file_type=".xls") dd_excel = [i+"x" for i in d_excel] print("策动配置表有然而规定表没有的表格(留神补充):", list(set(dd_excel).difference(set(excel)))) print("规定表有然而策动配置表没有的表格(能够删除):", list(set(excel).difference(set(dd_excel)))) for every_excel in excel: # if every_excel != "\冬天的机密表.xlsx": # continue check_excel(every_excel)check_excel 办法外围代码for head_name in head_list: if head_name == '': continue if head_name not in d_head_list: print(head_name, excel_name, "规定表的表头不存在配置表的表头") continue d_col = d_head_list.index(head_name) col = head_list.index(head_name) for i in range(config.ROW_START, sheet.nrows): if sheet.cell_value(i, col) is "": continue cell = str(sheet.cell_value(i, col)).replace('\r', '').replace('\n', '').replace('\\', '\\\\') try: # value_dict = json.loads(cell) value_dict = json.loads(cell, strict=False) except ValueError: print("@@@@@@@@@@@@@@@@@@@规定配置谬误{}".format(cell), excel_name) (key, value), = value_dict.items() # 传参:所查看的表的相干信息 getattr(rule, config.switch[key])(value, excel_name=excel_name[:-1], sheet_name=sheet_name, col_index=d_col)
Rule 规定定义与代码实现
我心愿把 rule 别离归类,这样会非常容易去找到我对应的规定。我在 config 中会配置有多少类规定,比方 In 类规定,泛指 A 列存在 B 列、当 A=X,B 列存在 C 列...此类规定;Match 规定,蕴含 A 列满足正则表白、当 A 列=X,B 列满足正则表白这两种规定。
switch = { "_Only": "Only", "_In": "Ainb", "_Equal": "Equal", "_Match": "Match", "_Dict": "Dictionary", "_Condition": "Condition", "_Increasing": "Increasing",}
接下来我以 In 类为例,说下我的做法。
class Ainb(object): def __init__(self, *args, **kwargs): # **kwargs 记录正在查看的表格的相干信息 # r_wbk 指数据配置表中对应规定表的那个表(也就是数据表) # d_wbk 指数据配置表中对应规定表配置的规定所指向的那个表(也就是我配的规定里指向的那个表) self.excel_name = kwargs["excel_name"] self.sheet_name = kwargs["sheet_name"] self.col_index = kwargs["col_index"] self.args = args self.r_wbk = table.open_workbook(config.DOC_DIR, self.excel_name) self.r_sheet = self.r_wbk.sheet_by_name(self.sheet_name) r_head = self.r_sheet.row_values(config.HEAD_CN) self.col_index_name = r_head[self.col_index] temp = {"All": "all_in", "Assign": "assign_in", "Part": "part_in", "Sequence": "sequence", "Whenassign": "whenassign", "Whenpoint": "whenpoint", "Every": "every_in", "Neighbor": "neighbor", "Allpoint": "allpoint"} if isinstance(self.args[0], dict): (key, value), = self.args[0].items() self.__getattribute__(temp[key])(value) # 每个单元格都in指定的表格指定列的合集 # {"_In":{"All":["/冬天的机密.xls","冬天的机密--sheet","冬天的机密--colname"]}} def all_in(self, _value): d_wbk = table.open_workbook(config.DOC_DIR, _value[0]) d_sheet = d_wbk.sheet_by_name(_value[1]) d_head = d_sheet.row_values(config.HEAD) d_index = d_head.index(_value[2]) d_col_list = table.get_content_by_col( config.DOC_DIR, _value[0], _value[1], d_index) d_col_list1 = [str(j) for j in d_col_list] for i in range(config.ROW_START, self.r_sheet.nrows): if not agent.pass_empty(i, self.r_sheet, self.col_index): continue temp = Common.change_format( self.r_sheet.cell_value( i, self.col_index)) if str(temp) not in d_col_list1: agent.pri_excel( self.excel_name, self.sheet_name, i, self.col_index_name) print("规定:每个单元格都in指定的表格指定列的合集。数据:::{}--{}". format( str(self.r_sheet.cell_value(i, self.col_index)), _value))
如上代码,In 为大类,大类蕴含小类。In 类型规定,蕴含 All 类规定(每个单元格都 in 指定的表格指定列的合集)、Assign 类规定(每个单元格都存在于由你设定的合集)等等(其余规定就不具体说了)。self.__getattribute__(temp[key])(value)
会依据映射关系去执行对应办法来做查看。all_in
办法会打印谬误的规定以及谬误数据;pri_excel
办法负责通用打印,次要打印谬误地位。上面给出打印后果示例。
@staticmethod def pri_excel(name, sheet, row='', col=''): if row == '' and col == '': print( "表格地位----------------------------------{}-------------------------{}".format(name, sheet,)) else: print( "表格地位----------------------------------{}--------------------------{}--行{}--列{}".format( name, sheet, row, col))//规定:每个单元格都in指定的表格指定列的合集。数据:::208--['/冬天的机密--表.xls', '冬天的机密--Sheet1', '冬天的机密--列']//表格地位----------------------------------\XXX表.xls--------------------------Sheet1--行712--列XXX(冬天的机密--列名,留神不是列的index哦,列名,间接让你疾速找到地位)//依据下面输入立即能够得悉,712行,列名为冬天的机密,数据内容为208,原本应该存在与冬天的机密表,冬天的机密sheet,冬天的机密列该列中,然而没有存在,所以须要查看208这个数据。
整体思路:
遍历规定表
依据配置在规定表对应列下的规定,找到对应须要查看的配置表,以及规定中指向须要配合查看的另一个配置表(如果有的话)
依照规定执行查看,打印谬误输入
理论利用与优化:
好的方面:
目前我有的规定类,在上文中的switch能够看进去,有 7 大类,每个类下可能有不定数量的规定,总体来说 99% 满足了我的日常须要了。
代码构造反对随时自定义规定,你想减少删除规定,也是分分钟的事。你的想法有多优良,规定就能够有多优良。
配规定很简略。有多简略?找到对应规定表地位,关上,写入规定,完事了。规定很简单吗?看你本人定义了。我日常做法:复制规定,改规定中的 excel name,sheet name,col name 三个参数,完事。
输入后果高深莫测。错在哪,哪一行,列名是什么,因为什么规定错了,通通都有,会有人看不明确?看不明确的话,那我是真的佛了。
优化:
问题一:表头常常改变,列名也常常变动,规定表的表头就得手动更改保障和配置表一样(我强迫症,我就想一样,这样子很容易找地位)。比方原来配置表 ABCD 列,规定表也是 ABCD 列,起初迭代屡次表变成了 ABCFG 列,我就又要手动删除 D,又要手动补充 FG。麻烦。于是主动同步表头配置脚本,又应运而生了。
这个脚本次要做什么事?帮我把 D 删除,帮我新建 FG,如果 AB 之间多了个小三,那么也会主动把 B 列(以及 B 列下的所有规定)往后挪,小三则依照程序放在 A 之后。总之,就是同步表头,同时把对应表头下的规定跟着表头一起移动。
# 只反对xlsxdef write_excel(excel, df): # 先革除格局,再写入,能力胜利 pd.io.formats.excel.header_style = None with pd.ExcelWriter(excel) as writer: df.to_excel(writer, sheet_name='Sheet1', startrow=0, index=False, header=False) workbook = writer.book worksheets = writer.sheets worksheet = worksheets['Sheet1'] worksheet.set_column('A:AD', 20) format1 = workbook.add_format({ # 'bold': True, # 字体加粗 # 'border': 20, # 单元格边框宽度 # 'align': 'left', # 程度对齐形式 # 'valign': 'vcenter', # 垂直对齐形式 'fg_color': '#FFC000', # 单元格背景色彩 # 'text_wrap': True, # 是否主动换行 }) for k in range(2, 5): worksheet.set_row(k, 20, format1) format2 = workbook.add_format({'fg_color': '#5B9BD5'}) worksheet.set_row(1, 20, format2) for j in range(5, 15): worksheet.set_row(j, 20)
弄完之后,所有表长得截然不同,还有背景色彩,一家人就要整整齐齐,真开心。
问题二:平台化?
不打算,不倡议搞,于是我砍掉了这个优化。我出于以下思考:
游戏行业人员会更喜爱和 excel 打交道
表头过多,web 很难操作,款式也没 excel 难看。excel 和策动配置表长的一样,容易造成习惯,有助于规定配置。
平台化的话,须要数据库。那就又要从新优化问题一了(又要写主动同步数据库表头的脚本)
我懒,不想搞平台,也不会搞前端。就是懒,咋的啦。
问题三:工具运行中,某些规定兼容性不好,报错,就阻断了前面的查看。
举个例子,你配置一个Dict类规定,默认这个表格内容是能够转换为json或者python dict去做查看,然而配表数据呈现了问题,导致报错,阻断前面流程(而后有人就会来找我说报错啦)。我目前的做法是,继续优化规定代码,减少兼容性,提前查看必要的数据格式,或者对易报错代码应用try。当初继续优化后,曾经很少呈现报错阻断了。一个字,美滋滋(三个字)。
问题四:效率问题?
目前 100+ 表格,各种规定配置起来也蛮多的,然而运行工夫不须要超过 1 分钟。所以临时不必管了。
其实我也蛮期待,在更多表格数据、规定数据的状况下,工具的运行效率。我也提前料想过一些优化计划来提高效率。
问题五:规定保护问题 ---- 会不会呈现同个规定存在很多表,而后你须要一个一个去更改这些规定的写法?
我认为是不会呈现的。在定义规定之前,就曾经思考通用性了,后续根本不会变动原有规定的写法,最多只会新增新的规定写法。所以旧的规定写法永远不须要去改变,也不倡议去改变。如果切实要改变,倡议改变代码去兼容原有规定写法。反正至今我都没改变过。
其余: 有点想把取出来的规定归类整顿,再getattr一个类,跑完一个类的查看,再做下一个类,而不是当初混着查看(简略说就是查看程序跟着大类走)。不过查看程序又想着跟着表走也好,输入后果也能依照表程序,也蛮好的。也有点想退出协程,然而波及open同个表的问题,须要上锁,麻烦,算了,先这样,反正几十秒出后果了,效率能承受。
附言:
仁者见仁智者见智,心愿这个工具,成为比拟好的配置表查看计划,也期待有人通知我更好的计划。