一,背景介绍
平时工作中需要计算退休年龄,分为公务员,参公,事业三类。
以前都是手工计算的,因为人会不断更新流动,每次需要这些数据的时候,都需要重新计算一遍。
这样存在几个问题:
1,公务员,参公,事业有三个表格,每个表格的处理方法都不一样,一个任务需要做3遍。
2,数据量比较大,有上万人,以后可能是2w人,容易忽略一些特殊数据。
3,不同从业人员对业务和表格的理解不一样,算出来的结果会不一样,变得很依靠耐心。
这种重复性、有固定标准的操作,就交给机器好了。
二,操作方法
1,Excel表格预处理。
删除表头,删除身份证和手机号两列。
删除最末一行。
(如果自己在Excel里分析,需要对日期做个分列,全部调整为一种格式。)
表结构,还是不上传了,涉及隐私哦。
2,使用Navicat,导入表格到数据库。
选择了workbook和sheet以后,再选择Excel表格和sql table的key映射,因为之前我就是根据Excel生成sql table的,所以两个key是一致的,一直下一步就好了。
3,导入人员名单到程序。
4,选择退休时间,未来的任何一天,点击查询按钮。
5,导出花名册,可以选择输出按钮,也可以在视图层直接复制。
6,各种分析,可以扩展。
三,退休标准
(一)公务员和参公的标准
男性,60周岁退休。
女性,55周岁;如果是副处级以上,60周岁退休。
公务员分为党政群和公检法。党政群里面的职级级别是写了处级科级,方便直接判断。公检法,用的是另外一套职级序列,得要对照起来。
现在简单介绍一下这些序列:
1,党政群序列
职务级别:县处级副职,县处级正职,副省副局职,厅局级副职(保留),厅局级副职,厅局级正职。
职级级别:四级调研员,三级调研员,二级调研员,一级调研员,二级巡视员,一级巡视员。
2,公安序列
公安分为两类,执法警务警员和技术职务。
执法警务警员的职级级别:四级高级警长,三级高级警长,二级高级警长,一级高级警长,一级高级警长(市管),二级警务专员,一级警务专员。
公安技术职务:警务技术四级主任,警务技术三级主任,警务技术二级主任,警务技术一级主任,警务技术二级总监,警务技术一级总监。
3,法院检察院序列
法院检察院是用同一种序列的:四级高级法官检察官,三级高级法官检察官,二级高级法官检察官,一级高级法官检察官
(二)事业的标准
事业分为两类,一类是管理类,一类是专业技术类,还有一类是工勤类。
1,管理类的退休情况:
男性,60周岁退休。
女性,55周岁退休,管理6级以上的女性,60周岁。(管理6级对应的就是公务员的处级。)
2,专业技术类的退休情况:
男性,60周岁退休。
女性,55周岁退休,副高和以上级别的女性,60周岁退休。
3,工勤类
男性,60周岁退休。
女性,50周岁退休。(高级技师、高级工,怎么处理?)
TODO 工勤类,我好像忘记分析了。。。留个疑问。
bala bala,类型好多啊,好吃力啊。。。这些对应的高于处级的,全部都需要加入集合里判断。
四,表格格式
公务员,参公,事业因为字段不一样,目前系统里是分为三个表格。其中,参公和事业的表格是类似的,但是计算退休的标准不一样,参公参照公务员的标准来计算退休。所以这里就体现了2次复用,第1次复用是参公表格的加载和各种操作,复用事业模块;第2次是参公的退休和各种计算,复用公务员模块。
表格从系统中导出,先做预处理。删除表头,删除身份证和手机号两列。
如果自己在Excel里分析,需要对日期做个分列,全部调整为一种格式。这里导入到sql的时候,会将日期格式统一为一种格式。
五,程序原理
方法有很多种,可以直接在Excel里开发vba或者是使用python的,但是习惯了c#,就用c#了。
流程如下:
1,从数据库里读取表格,填充到datatable。
2,根据生日计算,计算退休日期,参考性别,参考职级或者职务,判断退休时期是否在参考日期以前。
DateTime tuixiuDt;//其中男性60周岁退休,女性副处级以上(含副处)60周岁退休,副处级以下则是55周岁退休。if (strSex.Equals("男")){tuixiuDt = DateTime.Parse(strBirthday).AddYears(60);if (targetDt < tuixiuDt){//设置的时间<退休时间,那么还不能退休,所以跳过continue;}}else{if (!tuixiu_zhiwuJibieSet.Contains(strZhiwu) && !tuixiu_zhijiJibieSet.Contains(strZhiji)){//职务和职级都不满足,那么就是副处级一下;反之,只要有一个满足,就可以了。tuixiuDt = DateTime.Parse(strBirthday).AddYears(55);if (targetDt < tuixiuDt){continue;}}else{tuixiuDt = DateTime.Parse(strBirthday).AddYears(60);if (targetDt < tuixiuDt){continue;}}}
3,将所有退休人员,保存到一个集合。
tuixiuList.Add(dt.Rows[i]);
queryDataTables.ImportRow(datarow);//复制行数据到新表
queryDataTables.Rows[queryDataTables.Rows.Count - 1][queryDataTables.Columns.Count - 1] = tuixiuDt;
4,然后各种分析都可以做,不过没时间去做。
六,遇到的问题
1,数据不全,字段缺失,容易漏算。
总共有1w多人呢,肯定会存在有些人的有些字段是缺失的,导致你没法分析他们,所以结果只能做到95%以上的准确率。解决办法也有两种:
第一种思路是:整体情况计算好了以后,再回头手工处理这几个人,把他们字段补补全,然后再次导入系统做分析。
第二种思路是:不去管它,因为有些人的退休时间实际上是会变的,如果她在55岁的时候提拔到了副处级,就自动延长到60岁了。所以不用搞得那么精确,一般情况下,这种就够用了。
我个人是倾向第二种思路,抓住事物的本质就可以了,细节的东西别太去深究,允许误差和失败存在,这样才能把事情办好。而且还省力。
2,人员类型很多,如果能够统一下来就好了。
3,导入方法的优化。使用office自带的Excel dll,读取Excel表格的速度很慢,一个五千条记录的表格,可能需要十分钟加载(如果在笔记本上,时间还不止)。后来做了点优化,不在本程序中插入到数据库,**直接使用数据库工具navicat导入表格,1-2秒钟就好了。**估计原因:
1,少了视图对象的创建,直接使用文件io,所以速度就很快了。
2,office Excel dll,速度本来就不行。
七,后期扩展
1,有时间的话,就去做点扩展,可以扩展的地方还是很多的,例如:按照单位计算,按照级别计算,都可以的。前面一段时间研究其他东西去了,现在下班了继续回来搞搞it。
2,如果只是分析的话,其实不需要搞得那么麻烦,导入数据库,几段sql语句就搞定了,工作量会少很多。主要是那几个语句怎么设计,我忘记了,一时想不起来,所以就直接在代码里判断了。
3,还有好多任务没介绍,就这样好了。。