zoukankan      html  css  js  c++  java
  • WPF开发查询加班小工具

      先说一下,我们公司是六点下班,超过7点开始算加班,但是加班的时间是从六点开始计算,以0.5个小时为计数,就是你到了六点半,不算加班半小时,但是加班到七点半,就是加班了一个半小时。

    一、打卡记录

      首先,看一下我们公司的打卡记录,公司的打卡工具是不区分上下班的,而且一天可以打多次,也可能忘记打卡,这都是有可能的,人在观察这些数据的时候,可以轻易的分辨出什么是上班时间,什么是下班时间,并且是不是我忘打卡了,但是一旦放到程序里,判断的逻辑就复杂了。

    二、加班申请单

      加班申请单,也就是程序最后需要导出的Word文件,样子是这样的,页眉处是公司的LOGO,中部是标题,然后是一个表格

    三、小工具效果演示

      姓名部分如果不用选择按钮,选择部门人员名单的话,也可以手动填写

      备注、申请人和申请时间是可以不填写的,如果不填写,则最后导出的Word相应的位置就是空。

    四、开发过程

    1、由于我们的加班申请单,是有固定的几个部分组成的,姓名,加班类型,加班时间起、止,小时数和备注,因此,创建了一个实体类OverTimeModel

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.ComponentModel;
    using System.Collections;
    
    namespace SelectWorkOvertime
    {
        public class OverTimeModel : INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;
    
            private void INotifyPropertyChanged(string name)
            {
                if(PropertyChanged!=null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(name));
                }
            }
    
            private string name;//姓名
            private string overtimeType;//加班类型
            private string overtimeStart;//加班时间起
            private string overtimeEnd;//加班时间止
            private string overtimeHours;//小时数
            private string remark;//备注
    
            public string Name//姓名
            {
                get
                {
                    return name;
                }
    
                set
                {
                    name = value;
                    INotifyPropertyChanged("Name");
                }
            }        
    
            public string OvertimeType//加班类型
            {
                get
                {
                    return overtimeType;
                }
    
                set
                {
                    overtimeType = value;
                    INotifyPropertyChanged("OvertimeType");
                }
            }
    
            public string OvertimeStart//加班时间起
            {
                get
                {
                    return overtimeStart;
                }
    
                set
                {
                    overtimeStart = value;
                    INotifyPropertyChanged("OvertimeStart");
                }
            }
    
            public string OvertimeEnd//加班时间止
            {
                get
                {
                    return overtimeEnd;
                }
    
                set
                {
                    overtimeEnd = value;
                    INotifyPropertyChanged("OvertimeEnd");
                }
            }
    
            public string OvertimeHours//小时数
            {
                get
                {
                    return overtimeHours;
                }
    
                set
                {
                    overtimeHours = value;
                    INotifyPropertyChanged("OvertimeHours");
                }
            }
    
            public string Remark//备注
            {
                get
                {
                    return remark;
                }
    
                set
                {
                    remark = value;
                    INotifyPropertyChanged("Remark");
                }
            }
        }
    }
    OverTimeModel

    2、需要写要给工具类,这个工具类包含的内容如下:

      读取Excel(打卡记录是Excel文件)

      读取TXT文档(部门人员名单是TXT文件)

      判断Excel中的所有时间是工作日还周末,还是节假日(加班类型是有这三种的,因为有的时候节假日加班我们不用调休,给双倍工资)

      计算两个时间的小时差、获取上一天等

    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Data.OleDb;
    using System.IO;
    using System.Linq;
    using System.Net;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace SelectWorkOvertime
    {
        public class Tools
        {
            /// <summary>
            /// 读取TXT文档
            /// </summary>
            /// <param name="path"></param>
            /// <returns></returns>
            public string ReadTxt(string path)
            {
                string lines = "";
                StreamReader streamReader = new StreamReader(path, Encoding.Default);
                string line;
                while ((line = streamReader.ReadLine()) != null)
                {
                    lines += line.ToString() + " ";
                }
                return lines;
            }
            /// <summary>
            /// 调用远程接口
            /// </summary>
            /// <param name="date"></param>
            /// <returns></returns>
            public string IsHoliday(string date)
            {
                string url = @"http://www.easybots.cn/api/holiday.php?d=";
                url = url + date;
                HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(url);
                httpRequest.Timeout = 20000;
                httpRequest.Method = "GET";
                HttpWebResponse httpResponse = (HttpWebResponse)httpRequest.GetResponse();
                StreamReader sr = new StreamReader(httpResponse.GetResponseStream(), System.Text.Encoding.GetEncoding("gb2312"));
                string result = sr.ReadToEnd();
                result = result.Replace("
    ", "").Replace("
    ", "").Replace("	", "");
                int status = (int)httpResponse.StatusCode;
                sr.Close();
                return result;
            }
            /// <summary>
            /// 读取Excel到Dataset
            /// </summary>
            /// <param name="Path"></param>
            /// <param name="fileName"></param>
            /// <returns></returns>
            public DataSet ExcelToDS(string Path, string fileName)
            {
                string strConn = "Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=" + Path + ";" + "Extended Properties=Excel 8.0;";
                OleDbConnection conn = new OleDbConnection(strConn);
                conn.Open();
                string strExcel = "";
                OleDbDataAdapter myCommand = null;
                DataSet ds = null;
                strExcel = "select * from [" + fileName + "$]";
                myCommand = new OleDbDataAdapter(strExcel, strConn);
                ds = new DataSet();
                myCommand.Fill(ds, "table1");
                return ds;
            }
            /// <summary>
            /// 获取日期的类型,是工作日,周末或节假日
            /// </summary>
            /// <param name="dateTime"></param>
            /// <returns></returns>
            public string getDateType(string dateTime)
            {
                string date = Convert.ToDateTime(dateTime.Split(' ')[0].ToString()).ToString("yyyyMMdd");//获得到日期
                string isHoliday = IsHoliday(date);
                string numHoliday = isHoliday.Substring(isHoliday.Length - 3, 1);
                if (numHoliday == "1" || numHoliday == "2")//判断是不是节假日{2},或者周末{1}
                {
                    return numHoliday;
                }
                else
                    return "0";//返回工作日{0}
            }
            /// <summary>
            /// 获取小时值
            /// </summary>
            /// <param name="dateTime"></param>
            /// <returns></returns>
            public string getTimeHour(string dateTime)
            {
                string timeSFM = dateTime.Split(' ')[1].ToString();//时分秒
                string timeHour = timeSFM.Split(':')[0].ToString();
                return timeHour;
            }
            /// <summary>
            /// 计算小时差值 正常情况
            /// </summary>
            /// <param name="dateStart"></param>
            /// <param name="dateEnd"></param>
            /// <returns></returns>
            public string CalTimesNormal(DateTime dateStart, DateTime dateEnd)
            {
                string numTime;
                TimeSpan ts = dateEnd.Subtract(dateStart);
                if (ts.Minutes >= 30)
                {
                    numTime = (ts.Hours + 0.5).ToString();
                }
                else
                {
                    numTime = ts.Hours.ToString();
                }
                return numTime;
            }
            /// <summary>
            /// 计算小时差值 上班时间在12点之前的加班要减去1小时
            /// </summary>
            /// <param name="dateStart"></param>
            /// <param name="dateEnd"></param>
            /// <returns></returns>
            public string CalTimesAllDay(DateTime dateStart, DateTime dateEnd)
            {
                string numTime;
                TimeSpan ts = dateEnd.Subtract(dateStart);
                if (ts.Minutes >= 30)
                {
                    numTime = (ts.Hours + 0.5 - 1).ToString();
                }
                else
                {
                    numTime = (ts.Hours - 1).ToString();
                }
                return numTime;
            }
            /// <summary>
            /// 获取上一天
            /// </summary>
            /// <param name="dateTime"></param>
            /// <returns></returns>
            public string getDateBefore(string dateTime)
            {
                string dateBefore = Convert.ToDateTime(dateTime).AddDays(-1).ToString();
                return dateBefore;
            }
            /// <summary>
            /// 比较两个时间是否相同
            /// </summary>
            /// <param name="dateTime1"></param>
            /// <param name="dateTime2"></param>
            /// <returns></returns>
            public int getCompareDate(string dateTime1, string dateTime2)
            {
                DateTime dt1 = Convert.ToDateTime(dateTime1.Split(' ')[0].ToString());
                DateTime dt2 = Convert.ToDateTime(dateTime2.Split(' ')[0].ToString());
                if (dt1 == dt2)
                    return 1;
                return 0;
            }
        }
    }
    Tool

    3、写一个设定加班开始时间的类

      因为由于规则不一样,因此加班的开始时间是不一样的,例如:

      周一到周五 18:00以后下班,加班不超过当天或者加班到第二天

      周末或者假日 上班时间为9:00 之前或9:00之后

      周末或者假日 打卡时间在12点到13点之间

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace SelectWorkOvertime
    {
        /// <summary>
        /// 计算在不同的规则下加班的开始时间
        /// </summary>
        public class OverTimeStart
        {
            Tools tools = new Tools();
    
            /// <summary>
            /// 周一到周五 18:00以后下班,加班不超过当天
            /// </summary>
            /// <param name="dateTime">当天下班打卡时间</param>
            /// <returns></returns>
            public string OverTimeStart1(string dateTime)
            {
                DateTime dateTimeStart = Convert.ToDateTime(dateTime.Split(' ')[0].ToString() + " 18:00:00");
                return dateTimeStart.ToString("yyyy-MM-dd HH:mm");
            }
            /// <summary>
            /// 周一到周五 18:00以后下班,加班到第二天
            /// </summary>
            /// <param name="dateTime">当天下班打卡时间</param>
            /// <returns></returns>
            public string OverTimeStart2(string dateTime)
            {
                DateTime dateTimeStart = Convert.ToDateTime(tools.getDateBefore(dateTime).Split(' ')[0].ToString() + " 18:00:00");
                return dateTimeStart.ToString("yyyy-MM-dd HH:mm");
            }
            /// <summary>
            /// 周末或者假日 上班时间为9:00 之前
            /// </summary>
            /// <param name="dateTime">当天上班打卡时间</param>
            /// <returns></returns>
            public string OverTimeStart3(string dateTime)
            {
                DateTime dateTimeStart = Convert.ToDateTime(dateTime.Split(' ')[0].ToString() + " 9:00:00");
                return dateTimeStart.ToString("yyyy-MM-dd HH:mm");
            }
            /// <summary>
            /// 周末或者假日 上班时间为9:00 之后 
            /// </summary>
            /// <param name="dateTime">当天上班打卡时间</param>
            /// <returns></returns>
            public string OverTimeStart4(string dateTime)
            {
                DateTime dateTimeStart = Convert.ToDateTime(dateTime);
                return dateTimeStart.ToString("yyyy-MM-dd HH:mm");
            }
            /// <summary>
            /// 周末或者假日 打卡时间在12点到13点之间
            /// </summary>
            /// <param name="dateTime">当天上班打卡时间</param>
            /// <returns></returns>
            public string OverTimeStart5(string dateTime)
            {
                DateTime dateTimeStart = Convert.ToDateTime(dateTime.Split(' ')[0].ToString() + " 13:00:00");
                return dateTimeStart.ToString("yyyy-MM-dd HH:mm");
            }
        }
    }
    OverTimeStart

    4、写主页面的内容

      由于公司没有重名的,因此在读取了Excel后,只从里面取了姓名和时间字段,其他字段都抛弃掉,而加班申请表上的“加班类型,加班时间起、止,小时数”这四列,都是根据时间字段来进行计算得出的。

      由于打卡时间本身的问题,我在前面也提到了,可能存在重复打卡,漏打的问题,所以,在计算加班上,就会出现不准的现象,所以为了提醒小伙伴,就用了一个转换器,把加班小于0的,显示为红色;小于0.5小时的,显示为黄色;大于12小时的显示为绿色,大于12小时是有可能正确的,但是一般不会出现,所以提醒一下比较好,而小于0的,就是数据不正确了,如图

      小冉和王哥对应的周末加班上,由于颜色标注,就知道应该是数据方面可能存在问题了,这样就要去查看原始的打卡记录,如图

      小冉的是没有问题的

      王哥是因为都打了两次卡,导致软件在逻辑判别时出现了问题,所以加班记录里的那条负值就可以在导出的Word里删除掉了。

    5、导出

      导出Word的话,就是常用的C#操作Word,没什么。

    6、总结

      软件本身在技术上不是很难,用到异步线程、Linq、对文件的操作、转换器,基本都是常用的技术,难点其实就是在逻辑的判断上,无法做到全面的无误的去合理的计算出加班时间和加班类型,十分感谢彭哥,因为在写第一个版本的时候,让逻辑都快搞崩溃了,是彭哥告诉我,可以写每一个小的逻辑,然后再把小的逻辑组合成大的逻辑。总起来说,做这个小软件还有有技术上和思维上的收获的,仁者见仁智者见智吧,最起码,以后基本上不需要人手动的去写加班申请了,谁让懒是程序员的天性呢。

    注:软件存在以下BUG

      1、还是逻辑上不完善

      2、由于是调用的WEB上提供的接口去判断,是工作日、节假日、周末,例如阅兵就是节假日,所以,软件运行时需要联网

    GitHub源码

    希望园里的朋友批评指正,大家一起探讨,共同进步。

  • 相关阅读:
    python中scipy学习——随机稀疏矩阵及操作
    ptyhon中文本挖掘精简版
    ptyhon中文本挖掘精简版
    [python] 使用scikit-learn工具计算文本TF-IDF值
    [python] 使用scikit-learn工具计算文本TF-IDF值
    python高手的自修课
    python高手的自修课
    C/C++ scanf 函数中%s 和%c 的简单差别
    Ctags基本配置
    搭建gitserver
  • 原文地址:https://www.cnblogs.com/ZXdeveloper/p/4793041.html
Copyright © 2011-2022 走看看