考勤报表生成

需要:根据原始打开记录生成考勤报表

配置:班次, 由开始时间,结束时间点, 开始时间区间,结束时间区间组成

一天多个班次的需要考虑班次之间的连续打卡情况(允许),两次打卡时间间隔需要大于3分钟

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.OleDb;
using System.Collections;
using F.Studio.Util;
namespace Checking_In.UI
{
    public partial class frmMain : Form
    {

        #region Excel相关操作
        const string C_ExcelConnTmp = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source= {0};Extended Properties=‘Excel 8.0;HDR=YES;IMEX=1‘;";
        public string ExcelFile
        {
            get { return @"E:\Net\HR_KQ\9月质量部.xls"; }
        }
        public string Sheet
        {
            get
            {
                return "9月质量部$";
            }
        }
        public string ExcelConnectString
        {
            get
            {
                return string.Format(C_ExcelConnTmp, ExcelFile);
            }
        }

        public new List<TableInfo> Tables
        {
            get;
            private set;
        }
        public ArrayList ExcelSheetName()
        {
            ArrayList al = new ArrayList();
            string strConn;
            strConn = ExcelConnectString;
            OleDbConnection conn = new OleDbConnection(strConn);
            conn.Open();
            DataTable sheetNames = conn.GetOleDbSchemaTable
            (System.Data.OleDb.OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" });
            conn.Close();
            foreach (DataRow dr in sheetNames.Rows)
            {
                al.Add(dr[2]);
            }
            return al;
        }
        private void LoadExcelTableInfo()
        {

            Tables = new List<TableInfo>();

            var ds = LoadExcelData();

            TableInfo curTable = null;
            for (int i = 1; i < ds.Tables[0].Rows.Count; i++)
            {
                DataRow dr = ds.Tables[0].Rows[i];
                if (string.IsNullOrWhiteSpace(dr["新加"].ToString()))//空表示表信息
                {
                    curTable = new TableInfo();
                    curTable.Name = dr["F2"].ToString().Trim();
                    curTable.Code = dr["p_bs"].ToString().Trim();

                    Tables.Add(curTable);
                    continue;

                }
                var column = new ColumnInfo();
                column.Code = dr["新加"].ToString().Trim();
                string tmp = dr["删除"].ToString();
                if (!string.IsNullOrWhiteSpace(tmp))
                {
                    column.Name = tmp.Trim().Split(" ".ToArray(), StringSplitOptions.RemoveEmptyEntries)[0];
                    column.Comment = tmp.Trim();
                    if (column.Name.Length >= 10)
                    {
                        column.Name = column.Name.Substring(0, 10);
                    }
                    column.NeedSync = true;
                }
                curTable.Columns.Add(column);
            }

        }
        private DataSet LoadExcelData()
        {
            DataSet dsExcelSheet = new DataSet();

            //打开并读取Excel表信息
            OleDbConnection connExecel = new OleDbConnection(ExcelConnectString);
            OleDbDataAdapter dpQualityLevel = new OleDbDataAdapter("SELECT * FROM [" + Sheet + "]", connExecel);

            connExecel.Open();

            dpQualityLevel.Fill(dsExcelSheet);
            connExecel.Close();

            return dsExcelSheet;
        }
        #region Class
        public class TableInfo
        {
            public TableInfo()
            {
                Columns = new List<ColumnInfo>();
            }
            public string Name { get; set; }
            public string Code { get; set; }
            public List<ColumnInfo> Columns { get; set; }

        }
        public class ColumnInfo
        {
            public string Name { get; set; }
            public string Code { get; set; }
            public string Comment { get; set; }
            /// <summary>
            /// 是否需要同步
            /// </summary>
            public bool NeedSync { get; set; }
        }
        #endregion
        #endregion

        private List<CheckingRule> CheckingRules = new List<CheckingRule>();
        private List<ShiftInfo> ShiftList = new List<ShiftInfo>();
        private List< CheckingInfo> CheckingRecords=null;
        private List<EmpInfo> Emps = new List<EmpInfo>();
        private List<DateTime> Days = new List<DateTime>();
        private List<CheckingRstInfo> Rpt = new List<CheckingRstInfo>();
        public frmMain()
        {
            InitializeComponent();

            #region 上班时间配置配置
            ShiftList.Add(
                new ShiftInfo(){
                    InRule=new CheckingRule() { CheckPoint = "07:00", CheckType = 1, RangBegin = "00:00", RangEnd = "09:00",Title="质量上午进" },
                    OutRule=new CheckingRule() { CheckPoint = "11:00", CheckType = 2, RangBegin = "09:00", RangEnd = "12:00", Title = "质量上午出" },
                    Name="质量早班"
                });
            ShiftList.Add(
                new ShiftInfo(){
                    InRule=new CheckingRule() { CheckPoint = "13:00", CheckType = 1, RangBegin = "12:00", RangEnd = "15:30", Title = "质量下午进" },
                    OutRule=new CheckingRule() { CheckPoint = "17:00", CheckType = 2, RangBegin = "15:30", RangEnd = "17:30", Title = "质量下午出" },
                    Name="质量中班"
                });
            ShiftList.Add(
               new ShiftInfo()
               {
                   InRule = new CheckingRule() { CheckPoint = "18:00", CheckType = 1, RangBegin = "17:30", RangEnd = "19:30", Title = "质量晚上进" },
                   OutRule = new CheckingRule() { CheckPoint = "21:00", CheckType = 2, RangBegin = "19:30", RangEnd = "23:59", Title = "质量晚上出" },
                   Name = "质量晚班"
               });

            #endregion
        }

        private void  LoadData()
        {
            var ds = LoadExcelData();
            var list=new List< CheckingInfo>();
            var index = 0;
            foreach (DataRow item in ds.Tables[0].Rows)
            {
                index++;
                DateTime addtime;
                var dtStr = item["日期时间"].ToString();
                if (!DateTime.TryParse(dtStr, out addtime))
                {
                    Console.WriteLine("异常记录!"+index);
                    continue;
                }

                var it=new CheckingInfo();
                it.Dept = item["部门"].ToString();
                it.EmpNo = item["编号"].ToString();
                it.Name = item["姓名"].ToString();
                it.AddTime = addtime;
                it.RawAddTime = addtime;
                it.MachineNo = item["机器号"].ToString();
                it.CheckType = item["比对方式"].ToString();
                list.Add(it);
            }

            #region 排除间隔过短的记录
            //时间 2分钟
            int count = 0;
            int intervalSeconds = 1800;
            list = list.OrderBy(ent => ent.AddTime).ToList();
            for (int i = 0; i < list.Count;i++ )
            {
                var it = list[i];
                if (it.DelFlag) continue;
                for (var j = i + 1; j < list.Count; j++)
                {

                    var next = list[j];
                    if (next.DelFlag)continue;
                    if( (next.AddTime - it.AddTime).TotalSeconds >intervalSeconds)break;
                    if (next.EmpNo==it.EmpNo)
                    {
                        next.DelFlag = true;
                        Console.WriteLine(next.Name + "," + next.AddTime + "," + next.EmpNo);
                        count++;
                    }
                }
            }
            Console.WriteLine(count);

            #endregion
            CheckingRecords =list.Where(ent=>ent.DelFlag==false).OrderBy(ent=>ent.AddTime).ToList();
        }
        private void ExtractEmpAndDate()
        {

            var list = CheckingRecords.GroupBy(ent => ent.EmpNo).ToList();
            foreach (var it in list)
            {
                var emp=new EmpInfo();
                emp.EmpNo = it.Key;
                emp.Name = it.FirstOrDefault().Name;
                emp.Dept = it.FirstOrDefault().Dept;
                Emps.Add(emp);
            }
            var list2 = CheckingRecords.GroupBy(ent => ent.AddTime.Date);
            foreach(var it in list2)
            {
                Days.Add(it.Key);
            }
            Days=  Days.OrderBy(ent => ent.Date).ToList();

        }

        private void Analyze()
        {
            var rpts = new List<CheckingRstInfo>();

            foreach (var day in Days)
            {
                foreach (var emp in Emps)
                {
                   var checklist=  CheckingRecords.Where(ent => ent.AddTime >= day && ent.AddTime <= day.AddHours(23.999) && ent.EmpNo == emp.EmpNo).OrderBy(ent => ent.AddTime).ToList();

                    for(int index=0;index< ShiftList.Count;index++)
                    {
                        var shift=ShiftList[index];
                      #region 按配置进行分析

                       var rpt = new CheckingRstInfo() {
                           Date=day,Dept=emp.Dept,EmpNo=emp.EmpNo,
                           ShowInReport=false,Name=emp.Name,
                           IsAbsenteeism=false,InTime="",OutTime="" };
                       rpts.Add(rpt);

                       rpt.RuleTitle = shift.Name;

                       foreach (var rule in new List<CheckingRule>() { shift.InRule, shift.OutRule })
                       {
                           #region 上下班检测
                           DateTime eventTime;
                           var btime = rule.GetTime(day, rule.RangBegin);
                           var etime = rule.GetTime(day, rule.RangEnd);
                           var ptime = rule.GetTime(day, rule.CheckPoint);
                           if (rule.CheckType == 1)//上班
                           {
                               var inTimeList = checklist.Where(ent => ent.AddTime > btime && ent.AddTime <= etime).ToList();
                               if (inTimeList.Count <= 0)
                               {
                                   #region 向前寻找
                                   if (index == 1)
                                   {
                                       var prevTime = rule.GetTime(day, ShiftList[0].OutRule.CheckPoint);
                                       var lista = checklist.Where(ent => ent.AddTime > prevTime && ent.AddTime <= etime).ToList();
                                       if (lista.Count >= 2)
                                       {
                                           var item = lista.OrderBy(ent => ent.AddTime).ToList().LastOrDefault();
                                           inTimeList.Add(item);
                                           checklist.Remove(item);
                                       }
                                   }
                                   else if (index == 2)
                                   {
                                       var prevTime = rule.GetTime(day, ShiftList[1].OutRule.CheckPoint);
                                       var lista = checklist.Where(ent => ent.AddTime > prevTime && ent.AddTime <= etime).ToList();
                                       if (lista.Count >= 2)
                                       {
                                           var item = lista.OrderBy(ent => ent.AddTime).ToList().LastOrDefault();
                                           inTimeList.Add(item);
                                           checklist.Remove(item);
                                       }
                                   }
                                   #endregion
                                   if (inTimeList.Count <= 0)
                                   {
                                       rpt.ShowInReport = true;
                                       rpt.IsAbsenteeism = true;
                                       continue;
                                   }
                               }
                               eventTime = inTimeList.Min(ent => ent.AddTime);
                               rpt.InTime = eventTime.ToString("yyyy-MM-dd HH:mm:ss");
                               var lateMinute = (eventTime - ptime).TotalMinutes;
                               if (lateMinute >= 1)
                               {
                                   rpt.LateMinute = (int)lateMinute;
                                   rpt.ShowInReport = true;
                               }
                           }
                           else if (rule.CheckType == 2)//下班
                           {
                               var outTimeList = checklist.Where(ent => ent.AddTime > btime && ent.AddTime <= etime).ToList();
                               if (outTimeList.Count() <= 0)
                               {
                                   #region 向后寻找
                                   if (index == 0 && ShiftList.Count >= 2)
                                   {
                                       var nextTime = rule.GetTime(day, ShiftList[1].InRule.CheckPoint);
                                       var lista = checklist.Where(ent => ent.AddTime > btime && ent.AddTime <= nextTime).ToList();
                                       if (lista.Count >= 2)
                                       {
                                           var item = lista.OrderBy(ent => ent.AddTime).ToList().FirstOrDefault();
                                           outTimeList.Add(item);
                                           checklist.Remove(item);
                                       }
                                   }
                                   else if (index == 1 && ShiftList.Count >= 3)
                                   {
                                       var nextTime = rule.GetTime(day, ShiftList[2].InRule.CheckPoint);
                                       var lista = checklist.Where(ent => ent.AddTime > btime && ent.AddTime <= nextTime).ToList();
                                       if (lista.Count >= 2)
                                       {
                                           var item = lista.OrderBy(ent => ent.AddTime).ToList().FirstOrDefault();
                                           outTimeList.Add(item);
                                           checklist.Remove(item);
                                       }
                                   }
                                   #endregion
                                   if (outTimeList.Count <= 0)
                                   {
                                       rpt.ShowInReport = true;
                                       rpt.IsAbsenteeism = true;
                                       continue;
                                   }
                               }
                               eventTime = outTimeList.Min(ent => ent.AddTime);
                               rpt.OutTime = eventTime.ToString("yyyy-MM-dd HH:mm:ss");
                               var leaveEarlyMinute = (ptime - eventTime).TotalMinutes;
                               if (leaveEarlyMinute >= 1)
                               {
                                   rpt.LeaveEarlyMinute = (int)leaveEarlyMinute;
                                   rpt.ShowInReport = true;
                               }
                           }
                           #endregion

                       }
                    #endregion

                    }
                }
            }
            var list = rpts.Where(ent => ent.ShowInReport == true).ToList();
            dataGridView1.DataSource = list;
            Rpt = list;
        }
        private void button1_Click(object sender, EventArgs e)
        {
            LoadData();
            ExtractEmpAndDate();
            Analyze();
            button1.Enabled = false;
            //saveFileDialog1.FileName = DateTime.Now.ToString("考勤分析yyMMddHHmmss") + ".xls";
            //if (saveFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.Cancel)
            //{
            //    return;
            //}
            //if (string.IsNullOrWhiteSpace(saveFileDialog1.FileName)) return;
            //var filename = saveFileDialog1.FileName;
            //NPOIUtil.Export(Rpt.ToDataTable(), "打卡记录分析", filename);

        }
    }
}

数据结构

   class CheckingRule
    {
        /// <summary>
        /// 格式00:00
        /// </summary>
        public String CheckPoint { get; set; }
        public String RangBegin { get; set; }
        public String RangEnd { get; set; }
        /// <summary>
        /// 上班:1
        /// 下班:2
        ///
        /// </summary>
        public int CheckType { get; set; }
        public String Title { get; set; }

        public DateTime GetTime(DateTime day,string v)
        {
            var arr= v.Split(":".ToCharArray());
            return day.Date.AddHours(double.Parse(arr[0])).AddMinutes(double.Parse(arr[1]));
        }
    }

    class CheckingRstInfo
    {
        public String Name { get; set; }
        public String EmpNo { get; set; }
        public String Dept { get; set; }
        public DateTime Date { get; set; }
        public String InTime { get; set; }
        public String OutTime { get; set; }
        public bool? IsAbsenteeism { get; set; }
        public int LateMinute { get; set; }
        public int LeaveEarlyMinute { get; set; }
        public bool? ShowInReport { get; set; }
        public String RuleTitle { get; set; }
    }

using System.Data;
using System.Collections.Generic;
using System.Reflection;
using System;
using System.Collections;
namespace F.Studio.Util
{
    public static class DataTableExtensions
    {
        /// <summary>
        /// 转化一个DataTable
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list"></param>
        /// <returns></returns>
        public static DataTable ToDataTable<T>(this IEnumerable<T> list, params string[] tableName)
        {
            //创建属性的集合
            List<PropertyInfo> pList = new List<PropertyInfo>();
            //获得反射的入口
            Type type = typeof(T);
            string tname = "Table1";
            if (tableName.Length >= 1)
            {
                tname = tableName[0];
            }
            DataTable dt = new DataTable(tname);
            //把所有的public属性加入到集合 并添加DataTable的列
            Array.ForEach<PropertyInfo>(type.GetProperties(), p =>
            {
                pList.Add(p);
                var theType = p.PropertyType;
                //处理可空类型
                if (theType.IsGenericType && theType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
                {
                    dt.Columns.Add(p.Name, Nullable.GetUnderlyingType(theType));
                }
                else
                {
                    dt.Columns.Add(p.Name, theType);
                }
            });
            foreach (var item in list)
            {
                //创建一个DataRow实例
                DataRow row = dt.NewRow();
                //给row 赋值
                pList.ForEach(p =>
                {
                    var v = p.GetValue(item, null);
                    row[p.Name] = v == null ? DBNull.Value : v;

                });
                //加入到DataTable
                dt.Rows.Add(row);
            }
            return dt;
        }
    }
}

    public class CheckingInfo
    {
        public CheckingInfo()
        {
            DelFlag = false;
        }
        public String Dept { get; set; }
        public String Name { get; set; }
        public DateTime AddTime { get; set; }
        public DateTime RawAddTime { get; set; }
        public String MachineNo { get; set; }
        public String EmpNo { get; set; }
        public String CheckType { get; set; }
        public bool DelFlag { get; set; }
    }

时间: 2024-10-13 00:49:46

考勤报表生成的相关文章

[原创软件]考勤查询工具

软件主要功能: 显示考勤机数据 定时上报考勤数据 全自动无人值守操作,监控提醒 程序界面截图: 开发环境及语言: c# .NET Framework 4.5.2 Visual Studio 2017 更新日志: v2.1(2017.4.8) 修复数据上报的某些BUG 新增失败重试次数设置 新增显示信息选项设置 新增快捷打开日志目录方式 优化考勤起止时间设置 v2.0(2017.4.1) 重新设计界面UI 自动运行和手动运行界面分离 提高查询效率 新增获取信息后的上报方式 更新配置文件格式 更新登

考勤管理系统:实现数据在文件的读取功能

//获取系统时间的方法:Date date=new Date(new java.util.Date().getTime()); /* * 考勤管理系统:实现数据在文件的读取功能;两个模块,功能如下: * ----管理员模块: * 1.注册新用户 * 2.查询所用用户 * ----用户模块: * 1.上班打卡 * 2.下班打卡 * 3.查询历史打卡记录 * */public class TestUser { static Scanner input=new Scanner(System.in);

考勤表格制作

前几天有个行政MM来找我哭诉,各种心软,于是周日花了时间修改一下网上大师代码. 首先感谢大师们! Sub kaoqinfenxi() Dim RowB, RowA, iRow, iCol, iRQ, jRow, jCol As Integer Dim sXM, x1, x2, y, m, n As String Dim Rng As Range     RowA = Sheets("考勤记录").Range("A65536").End(xlUp).Row     F

关于10-22起突然采集不到考勤数据的问题

前几天在公司OA系统里面查看考勤时,发现有考勤数据遗漏现象.登录到服务器上发现平时工作正常的考勤数据采集软件,却突然采集不到数据了.为了查明原因,在本机对用来开发测试的考勤机进行采集测试,一切正常.重新编译后再上传到服务器覆盖,再次在服务器上采集,却还是采集不到,期间也没任何DLL异常.症状是:在服务器上能连接考勤机,能进行读取操作,但却没有任何数据.由于是VPN跨市操作,不方便现场调试.起初怀疑是考勤机里面根本不存在数据,后通过人事部拿到考勤数据后,显然这个推测不准.后又确认不是更换设备的问题

员工考勤系统

员工考勤系统中的主要思想是,窗体间的传递以及datagridview之间的数据绑定刷新 public class SE { public string Id { get; set; } public string Name { get; set; } public int Age { get; set; } public string Sex { get; set; } } 创建se类储存对象 public class Record { public DateTime intime { get;

微信企业号开发:微信考勤摇一摇考勤

看到网上又不好微信企业号的摇一摇考勤,自己也想做一个,但查遍了微信企业号文档,也没有看到摇一摇的相关API,本以为做不出来了,想不到再问了同事后,才知道其实很简单,摇一摇不需要微信企业号的文档,HTML5就有,摇一摇其实就是相当于点击了保存按钮而已. 其实获取地理位置HTML5也支持. HTML5 - 使用地理定位 <script> var x=document.getElementById("demo"); function getLocation() { if (nav

作业1:小型考勤登记表

这次在广州实习了20天,收获还比较大.不过仍需要继续努力.这次总共布置了两个作业,我总结一下: 登记考勤信息,查看信息--主要就是往数据库增加数据,然后再从数据库中读取出来. 代码演示: 从数据库里面写入数据: <%@page import="com.Seraphjin.Attence.model.attence"%> <%@page import="com.Attence.BizImpl.AttenceBizImpl"%> <%@pa

考勤助手类图的设计

以上为类图1.0版本,其中在“教务老师”与“信箱”的关系处争议较大,但是从调用关系上来分析我认为这样的设计是没有错误的,所以这个问题大家最终达成一致.至于学生和出勤表之间的联系的确是我的考虑不周,所以是应该做修改的.再有就是一张考勤表应该匹配一张出勤表,所以组合的数量关系上是有错误的,以下是修改后的版本: 根据以上仅考虑重要逻辑部分的类的关系,以及时序图的设计,我将uml类图进行了进一步的补充设计:

任课教师管理考勤子系统之用例图

本周根据“任课教师管理考勤”子系统画出用例图的任务,描述出了该子系统下用例图的具体表现,表现形式如图: