VBA快速动态考勤统计

news2024/11/27 14:32:22

实例需求:某公司的上下班打卡记录如下所示,其中Table_In为上班打卡记录,Table_Out为下班打卡记录。
在这里插入图片描述
现在需要根据日期整理为如下格式的考勤表。需要注意如下几点:

  • 每天的打卡次数不确定
  • 最后一列Total/Day统计该天的出勤总时长,忽略有缺卡的时间段
  • 对于缺卡记录标记为Missing,例如10/14,员工108500,7:59:3414:59:34两次上班打卡记录之间并没有下班打卡记录,那么7:59:34对应的下班打卡记录为缺失
    在这里插入图片描述
    示例代码如下。
Sub Demo()
    Const MISSING_DT = "Missing"
    Dim objDic As Object, rngData As Range
    Dim i As Long, j As Long
    Dim arrData, arrRes(), arrTotal(), sKey
    Dim oSht As Worksheet, srcSheet As Worksheet
    Set objDic = CreateObject("scripting.dictionary")
    Set srcSheet = Sheets("Sheet1") 
    Set oSht = Sheets.Add
    srcSheet.ListObjects("Table_In").Range.Copy oSht.Cells(1, 1)
    oSht.Range("D1") = "Flag"
    oSht.Range(oSht.ListObjects(1).Name & "[Flag]").Value = "In"
    srcSheet.ListObjects("Table_Out").DataBodyRange.Copy oSht.Cells(1, 1).End(xlDown).Offset(1)
    oSht.Range(oSht.ListObjects(1).Name & "[Flag]").SpecialCells(xlCellTypeBlanks).Value = "Out"
    oSht.ListObjects(1).Range.Sort key1:="ID Number", Order1:=xlAscending, key2:="Date", _
        Order2:=xlAscending, key3:="Time", Order3:=xlAscending, Header:=xlYes
    arrData = oSht.ListObjects(1).DataBodyRange.Value
    oSht.ListObjects(1).Range.Clear
    Dim pair_cnt As Integer
    ReDim arrRes(UBound(arrData), 1 To 2)
    ReDim arrTotal(UBound(arrData), 0)
    arrRes(0, 1) = "Date"
    arrRes(0, 2) = "ID Number"
    arrTotal(0, 0) = "Total/Day"
    j = 0: pair_cnt = 0
    For i = LBound(arrData) To UBound(arrData)
        sKey = arrData(i, 1) & "|" & arrData(i, 2)
        If objDic.exists(sKey) Then
            objDic(sKey) = objDic(sKey) + 1
        Else
            j = j + 1
            arrRes(j, 1) = arrData(i, 1)
            arrRes(j, 2) = arrData(i, 2)
            objDic(sKey) = 1
        End If
        If objDic(sKey) > pair_cnt Then
            pair_cnt = objDic(sKey)
            ReDim Preserve arrRes(UBound(arrData), 1 To pair_cnt * 2 + 2)
            arrRes(0, pair_cnt * 2 + 1) = "In_" & pair_cnt
            arrRes(0, pair_cnt * 2 + 2) = "Out_" & pair_cnt
        End If
        If arrData(i, 4) = "In" Then
            arrRes(j, objDic(sKey) * 2 + 1) = arrData(i, 3)
            If arrData(i + 1, 4) = "Out" Then
                arrRes(j, objDic(sKey) * 2 + 2) = arrData(i + 1, 3)
                arrTotal(j, 0) = arrTotal(j, 0) + arrData(i + 1, 3) - arrData(i, 3)
                i = i + 1
            Else
                arrRes(j, objDic(sKey) * 2 + 2) = MISSING_DT
            End If
        Else
            arrRes(j, objDic(sKey) * 2 + 1) = MISSING_DT
            arrRes(j, objDic(sKey) * 2 + 2) = arrData(i, 3)
        End If
    Next i
    With oSht.Range("A3")
        .Resize(UBound(arrRes), UBound(arrRes, 2)).Value = arrRes
        .Offset(0, 2).Resize(, pair_cnt * 2 + 1).EntireColumn.NumberFormat = "h:mm:ss"
        .End(xlToRight).Offset(0, 1).Resize(UBound(arrRes), 1) = arrTotal
    End With
End Sub

【代码解析】
第7行代码创建自怼对象
第9行代码添加工作表用于保存临时数据。
第10行代码将表格Table_In的数据拷贝到新建工作表。
第11~12行代码增加新列Flag,并填充In,标记为上班打卡记录。
第13~14行代码表格Table_Out的数据拷贝到新建工作表,并增加新列。
第15行代码在新建工作表中对数据进行排序,排序字段依次为:ID Number, Date, Time
第16行代码将排序后的数据读取到数组中。
第18行代码清除新建工作表中的数据,以便于后续用于保存统计结果。
第20行代码声明数组arrRes用于保存考勤表。
第21行代码声明数组arrTotal用于保存出勤时间。
第22~24行代码填充表头
第26~55行代码循环处理考勤数据。
第27行代码将ID Number, Date作为排重统计的关键字段。
第28行代码判断字段中是否已经存在指定的关键字段。
如果已经存在,第29行代码将统计出现次数。
如果不存在,第32~33行代码将ID Number, Date保存到结果数组中。
第36~41行代码根据统计结果扩展结果数组。
第42~54行代码统计出勤时间和缺卡记录。
如果当前行为上班打卡记录,第43行代码记录上班打卡时间。
如果下一行为下班打卡记录,第45行代码记录下班打卡时间,并且第46行代码统计出勤时间。
如果下一行为不是下班打卡记录,第49行代码记录缺卡。
类似逻辑,第52~53行代码记录上班缺卡和相应的下班打卡时间。
第57行代码将考勤结果写入结果工作表中。
第58行代码设置最后一列的数字格式。
第59行代码将出勤时间写入工作表。


小结: 本示例有如下几个核心要点,各位小伙伴理解之后,可以更容易的看懂代码。

  • 借助Excel原生排序功能有时是简单高效的方式
  • 由于无法确定每天打卡总次数,因此需要使用动态数组保存考勤统计数据
  • 单独使用一个数组保存出勤时间,看似多使用一个变量,但是可以更方便随时调整上述动态数组

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1169065.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

服务器数据恢复—Zfs文件系统下文件被误删除的如何恢复数据?

服务器故障: 一台zfs文件系统服务器,管理员误操作删除服务器上的数据。 服务器数据恢复过程: 1、将故障服务器所有磁盘编号后取出,硬件工程师检测所有硬盘后没有发现有磁盘存在硬件故障。以只读方式将全部磁盘做扇区级别的镜像备…

如何有效搭建产品帮助中心?看这一篇文就够了!

在当今快节奏的数字化时代,产品帮助中心成为了企业提供优质客户支持和增强用户体验的重要组成部分。无论是软件、电子设备还是在线服务,用户都期望能够快速找到解决问题的方法和获得详细的产品指导。因此,搭建一个高效且易于使用的产品帮助中…

Canvas绘制简易雨滴碰撞效果

实现会动的图形&#xff0c;向下播放多张静态的图片。一秒内要大于屏幕刷新的帧数(60) 也就是每隔1/60s执行一次函数在每次绘制的正方形上添加一个背景色为白色蒙板。 效果图 源代码 <!DOCTYPE html> <html lang"en"><head><meta charset"…

数据库进阶教学——数据库故障恢复(日志文件)

目录 一、日志简介 二、日志文件操作 1、查看日志状态 2、开启日志功能 3、查看日志文件 4、查看当前日志 5、查看日志中的事件 6、删除日志文件 7、查看和修改日志文件有效期 8、查看日志文件详细信息 三、删除的数据库恢复 一、日志简介 日志是记录所有数据库表结…

全国首批!中国儿童青少年戏剧艺术普及推广中心——福建省艺术馆、福州市文化馆推广中心授牌仪式在福州举办

2023年11月1日&#xff0c;由中国儿童艺术剧院、文化和旅游部全国公共文化发展中心主办&#xff0c;福建省文化和旅游厅支持&#xff0c;福建省艺术馆、福州市文化和旅游局承办&#xff0c;福州市文化馆协办的“中国儿童青少年戏剧艺术普及推广中心——福建省艺术馆、福州市文化…

Centos 7.x上利用certbot申请Let‘s Encrypt的SSH证书(HTTPS证书)

目录 01-安装Certbot02-在网站的根目录依次新建文件夹.well-known和acme-challenge03-申请证书 要在CentOS 7.x上为域名申请Let’s Encrypt证书&#xff0c;你可以使用Certbot工具&#xff0c;它是一个自动化证书颁发工具&#xff0c;用于管理Let’s Encrypt证书。以下是在Cent…

天津优选Java培训机构 影响Java培训费用的因素

Java作为如今流行的计算机编程语言&#xff0c;其优势在于言语简略、面向对象&#xff0c;并且应用广泛。随着市场对于Java开发人员的需求越来越大&#xff0c;越来越多非本专业的人也通过培训转行进入IT行业。 Java的就业优势 市场需求大&#xff1a;Java人才的市场需求很大…

高匿IP有什么作用

在互联网的蓬勃发展中&#xff0c;IP地址作为网络通信的基础&#xff0c;一直扮演着举足轻重的角色。而在诸多IP地址中&#xff0c;高匿IP地址则是一种特殊类型&#xff0c;其作用和价值在某些特定场合下尤为突出。那么&#xff0c;高匿IP地址究竟有哪些用处呢&#xff1f; 首先…

无声的世界,精神科用药并结合临床的一些分析及笔记(十)

目录 回 “ 家 ” 克服恐惧 奥沙西泮 除夕 酒与药 警告 离别 回 “ 家 ” 她的锥切手术进行的很顺利&#xff0c;按计划继续返回安定医院调节心理状态&#xff0c;病友们都盼着我们回“家”。当我俩跨入病区&#xff0c;大家都涌过来帮我们大包小包的拎着行李&#xff0…

Airtest工具根据App页面文字信息提取坐标进行截图保存在自定义文件夹

Airtest工具根据App页面文字信息提取坐标进行截图保存在自定义文件夹 一、项目背景 在一个项目中&#xff0c;选项被选中和未选中的节点元素的属性值无变化&#xff0c;通过AI识别率达不到百分百&#xff0c;想着通过计算图片的HSV值来判断选择能否被选中。&#xff08;HSV比…

Android笔记(十一):Compose中使用ViewModel

通过ViewModel组件用于保存视图中需要的数据。ViewModel主要目的是将与用户界面相关的数据模型和应用程序的逻辑与负责实际显示和管理用户界面以及与操作系统交互的代码分离开来&#xff0c;为UI界面管理数据。常见的管理方式主要有&#xff1a;LiveData和StateFlow两种形式来实…

路由器基础(十一):ACL 配置

访问控制列表 (Access Control List,ACL) 是目前使用最多的访问控制实现技术。访问控制列表是路由器接口的指令列表&#xff0c;用来控制端口进出的数据包。ACL适用于所有的被路由协议&#xff0c;如IP、IPX、AppleTalk 等。访问控制列表可以分为基本访问控制列表和高级访问控制…

nodejs+springboot+elementui+python的Sd球鞋销售平台的设计与实现-毕业设计

此网站系统的开发方式和信息管理方式&#xff0c;借鉴前人设计的信息和研发。以网站商品信息为主&#xff0c;购物商品为核心功能来进行设计和研发&#xff0c;把网站信息和技术整合&#xff0c;开发出一套Sd球鞋销售平台。用目前现有的新技术进行系统开发&#xff0c;提供后台…

K-edge 和逃逸问题

一 k-eage基本概念 1 k-edge概念 K-edge称为K边, 其物理意义是高原子序数物质原子内部K层自由电子, 易与特定能量下X射线光子发生光电吸收作用, 导致对该能量的X射线光子吸收特别大。 而K-edge特性表现为X射线与物质发生相互作用时, 其衰减系数随着能量的增加而逐渐减小, 但在…

【优选算法系列】第一节.栈的简介(1047. 删除字符串中的所有相邻重复项和844. 比较含退格的字符串)

文章目录 前言一、删除字符串中的所有相邻重复项和 1.1 题目描述 1.2 题目解析 1.2.1 算法原理 1.2.2 代码编写二、比较含退格的字符串 2.1 题目描述 2.2 题目解析 2.2.1 算法原理 2.2.2 代码编写总结 前言 …

Vue组件化开发,组件的创建,注册,使用,详解Vue,vm,VueComponent,vc

组件化开发 模块是指将一个大的js文件按照模块化拆分规则进行拆分成的每个js文件, 凡是采用模块方式开发的应用都可以称为模块化应用(组件包括模块) 传统方式开发的一个网页通常包括三部分: 结构(HTML)、样式(CSS)、交互(JavaScript) 关系纵横交织复杂&#xff0c;牵一发动全…

4+m6A+机器学习+分型,要素过多,没有思路的同学可借鉴

今天给同学们分享一篇生信文章“Diagnostic, clustering, and immune cell infiltration analysis of m6A regulators in patients with sepsis”&#xff0c;这篇文章发表在Sci Rep.期刊上&#xff0c;影响因子为4.6。 结果解读&#xff1a; 脓毒症中m6A调节因子的转录改变 …

ChinaSoft 论坛巡礼 | 安全攸关软件的智能化开发方法论坛

2023年CCF中国软件大会&#xff08;CCF ChinaSoft 2023&#xff09;由CCF主办&#xff0c;CCF系统软件专委会、形式化方法专委会、软件工程专委会以及复旦大学联合承办&#xff0c;将于2023年12月1-3日在上海国际会议中心举行。 本次大会主题是“智能化软件创新推动数字经济与社…

5.RDD持久化

概述 今日目标&#xff1a; RDD 持久化 RDD持久化原理RDD持久化策略如何选择RDD持久化策略案例 相关文章如下&#xff1a; spark官网地址RDD编程指南 RDD 持久化 RDD持久化原理 Spark中最重要的功能之一是跨操作在内存中持久化&#xff08;或缓存&#xff09;数据集。当…