Sub SubtotalPickFile()
Dim StartTime As Variant
Dim UsedTime As Variant
StartTime = VBA.Timer
Dim firstday As Date, lastday As Date
Dim Wb As Workbook
Dim Sht As Worksheet
Dim oSht As Worksheet
Dim Dic As Object
Dim d As Object
Set d = CreateObject("Scripting.Dictionary")
Set ud = CreateObject("Scripting.Dictionary")
Set Dic = CreateObject("Scripting.Dictionary")
Dim onDay, onTime, offTime
Const ON_TIME = "8:30:00"
Const OFF_TIME = "17:00:00"
Const MID_TIME = "12:00:00"
Dim onForget, offForget, onLate, offEarly, forgetTime, lateTime, earlyTime, duration
Dim lateday, earlyday, forgetday
Set Wb = ThisWorkbook '选取考勤数据文件
FilePath = FilePicker()
If FilePath = "" Then Exit Sub
Set OpenWb = Application.Workbooks.Open(FilePath)
Set Sht = OpenWb.Worksheets(1)
With Sht
endrow = .Cells(.Cells.Rows.Count, 1).End(xlUp).Row
Set Rng = .Range("A3:F" & endrow)
arr = Rng.Value
End With
OpenWb.Close False '设置考勤起止日期
startday = Application.InputBox("请输入起始日期,格式为 2019/01/01 : ", "InputBox", , , , , , 2)
If startday = False Then
MsgBox "没有输入日期!"
Exit Sub
End If
endday = Application.InputBox("请输入结束日期,格式为 2019/01/31 : ", "InputBox", , , , , , 2)
If endday = False Then
MsgBox "没有输入日期!"
Exit Sub
End If '计算工作日天数
On Error Resume Next
firstday = CDate(startday)
lastday = CDate(endday)
'wkdays = WorkdaysBetween(firstday, lastday) counter = 0
today = firstday
Do
Key = Format(today, "yyyy/mm/dd")
If Weekday(today, vbMonday) <= 5 Then
counter = counter + 1 d(Key) = ""
''debug.Print today; " 是工作日 "; counter
Else
ud(Key) = ""
''Debug.Print today; " 是工作日 "; counter
End If today = DateAdd("d", 1, today)
If today = DateAdd("d", 1, lastday) Then Exit Do
Loop
wkdays = counter If Err.Number <> 0 Then
Exit Sub
MsgBox "输入的日期范围可能有误!", vbInformation, "Information"
End If Set oSht = Wb.Worksheets("result")
For i = LBound(arr) To UBound(arr)
Key = CStr(arr(i, 2))
td = CDate(arr(i, 4))
If DateDiff("d", firstday, td) >= 0 And DateDiff("d", td, lastday) >= 0 Then
''debug.Print td; " 符合要求"
'截取上下班时间
onTime = CDate(Split(arr(i, 5), " ")(1))
offTime = CDate(Split(arr(i, 6), " ")(1))
onForget = False
offForget = False '计算工作时长
duration = DateDiff("n", onTime, offTime)
If Not Dic.Exists(Key) Then
lateTime = 0
earlyTime = 0
forgetTime = 0
forgetday = ""
lateday = ""
earlyday = ""
onDay = 1
'迟到判断
onLate = (DateDiff("s", CDate(ON_TIME), onTime) > 0)
onForget = (DateDiff("s", CDate(MID_TIME), onTime) > 0)
If onForget Then
forgetTime = forgetTime + 1
forgetday = arr(i, 4) & "上午"
Else
If onLate Then
If duration < 510 Then
lateTime = lateTime + 1
If lateday = "" Then
lateday = arr(i, 4) & "上午"
Else
lateday = lateday & vbCrLf & arr(i, 4) & "上午"
End If
End If
End If
End If
'早退判断
offEarly = (DateDiff("s", offTime, CDate(OFF_TIME)) > 0)
offForget = (DateDiff("s", CDate(MID_TIME), offTime) < 0)
If offForget Then
forgetTime = forgetTime + 1
If forgetday <> "" Then
forgetday = forgetday & vbCrLf & arr(i, 4) & "下午"
Else
forgetday = arr(i, 4) & "下午"
End If
Else
If offEarly Then
If duration < 510 Then
earlyTime = earlyTime + 1
If earlyday = "" Then
earlyday = arr(i, 4) & "下午"
Else
earlyday = earlyday & vbCrLf & arr(i, 4) & "下午"
End If
End If
End If
End If
ar = Array(arr(i, 1), arr(i, 2), arr(i, 3), wkdays, onDay, 0, Format(arr(i, 4), "yyyy/mm/dd"), lateTime, lateday, earlyTime, earlyday, forgetTime, forgetday)
Dic(Key) = ar
Else
ar = Dic(Key)
ar(4) = ar(4) + 1
ar(6) = ar(6) & ";" & Format(arr(i, 4), "yyyy/mm/dd")
'If Key = "2018000766" Then Debug.Print td; " ----------"; ar(6)
'迟到判断
onLate = (DateDiff("s", CDate(ON_TIME), onTime) > 0)
onForget = (DateDiff("s", CDate(MID_TIME), onTime) > 0)
If onForget Then
ar(11) = ar(11) + 1
If ar(12) <> "" Then
ar(12) = ar(12) & vbCrLf & arr(i, 4) & "上午"
Else
ar(12) = arr(i, 4) & "上午"
End If
Else
If onLate Then
If duration < 510 Then
ar(7) = ar(7) + 1
If ar(8) = "" Then
ar(8) = arr(i, 4) & "上午"
Else
ar(8) = ar(8) & vbCrLf & arr(i, 4) & "上午"
End If
End If
End If
End If
'早退判断
offEarly = (DateDiff("s", offTime, CDate(OFF_TIME)) > 0)
offForget = (DateDiff("s", CDate(MID_TIME), offTime) < 0)
If offForget Then
ar(11) = ar(11) + 1
If ar(12) <> "" Then
ar(12) = ar(12) & vbCrLf & arr(i, 4) & "下午"
Else
ar(12) = arr(i, 4) & "下午"
End If
Else
If offEarly Then
If duration < 510 Then
ar(9) = ar(9) + 1
If ar(10) = "" Then
ar(10) = arr(i, 4) & "下午"
Else
ar(10) = ar(10) & vbCrLf & arr(i, 4) & "下午"
End If
End If
End If
End If
Dic(Key) = ar
End If
End If
Next i '计算缺考天数和缺考日期
'On Error Resume Next
For Each K In Dic.keys
ar = Dic(K)
ar(4) = UBound(ar(6)) + 1
ar(5) = ar(3) - ar(4)
'If K = "2018000766" Then Debug.Print "缺考天数 : "; ar(5)
'If K = "2018000766" Then Debug.Print ar(2); " 打卡日期: "; ar(6)
s = ""
For Each wd In d.keys
'If K = "2018000766" Then Debug.Print "工作日》》"; wd
'If K = "2018000766" Then Debug.Print "判断日期在不在工作日内:"; wd; " "; InStr(ar(6), wd)
If InStr(ar(6), wd) <= 0 Then
If s = "" Then
s = wd & "缺考"
Else
s = s & vbCrLf & wd & "缺考"
End If
End If
Next wd w = ""
For Each u In ud.keys
If K = "2018000766" Then Debug.Print "非工作日》》"; u
If K = "2018000766" Then Debug.Print "判断日期在不在工作日内:"; u; " "; InStr(ar(6), u)
If InStr(ar(6), u) > 0 Then
If w = "" Then
w = u & "加班"
Else
w = w & vbCrLf & u & "加班"
End If
End If
Next u 'If K = "2018000766" Then Debug.Print ar(2); " 缺考日期: "; s
'If K = "2018000766" Then Debug.Print ar(2); " 加班日期: "; w
ar(6) = s & vbCrLf & w
Dic(K) = ar Next K With oSht
.UsedRange.Offset(2).Clear
Set Rng = .Range("A3")
Set Rng = Rng.Resize(Dic.Count, 13)
Rng.Value = Application.Rept(Dic.Items, 1)
Sort_2003 Rng, False
SetCenters .UsedRange
SetBorders .UsedRange
.Activate
Rows("3:3").Select
ActiveWindow.FreezePanes = True
End With Call StepForward UsedTime = VBA.Timer - StartTime
''debug.Print "UsedTime :" & Format(UsedTime, "#0.0000 Seconds")
MsgBox "UsedTime :" & Format(UsedTime, "#0.0000 Seconds")
Set Dic = Nothing
Set Wb = Nothing
Set Sht = Nothing
Set oSht = Nothing
Set OpenWb = Nothing
End Sub
Private Sub SetBorders(ByVal Rng As Range)
With Rng.Borders
.LineStyle = xlContinuous
.ColorIndex = xlAutomatic
.TintAndShade = 0
.Weight = xlThin
End With
End Sub
Private Sub SetCenters(ByVal Rng As Range)
With Rng
.HorizontalAlignment = xlCenter
.VerticalAlignment = xlCenter
.WrapText = True
'.Columns.AutoFit
End With
End Sub
'FilePath=FilePicker(InitialPath)
'If FilePath = "" Then Exit Sub
Function FilePicker(Optional InitialPath As String = "")
Dim FilePath As String
If InitialPath = "" Then
InitialPath = Application.ActiveWorkbook.Path
End If
With Application.FileDialog(msoFileDialogFilePicker)
.AllowMultiSelect = False
.InitialFileName = InitialPath
.Title = "请选择单个Excel工作簿"
.Filters.Clear
.Filters.Add "Excel工作簿", "*.xls*"
If .Show = -1 Then
FilePath = .SelectedItems(1)
Else
MsgBox "您没有选中任何文件,本次汇总中断!"
End If
End With
FilePicker = FilePath
End Function
Function WorkdaysInMonth(ByVal month As Date)
Dim counter
counter = 0
firstday = CDate(Format(month, "yyyy/mm") & "/01")
lastday = DateAdd("d", -1, CDate(Format(DateAdd("m", 1, month), "yyyy/mm") & "/01"))
today = firstday
Do
If Weekday(today, vbFriday) <= 5 Then counter = counter + 1
today = DateAdd("d", 1, today)
If today = lastday Then Exit Do
Loop
WorkdaysInMonth = counter
End Function
Function WorkdaysBetween(ByVal firstday As Date, ByVal lastday As Date)
Dim counter
today = firstday
Do
If Weekday(today, vbFriday) <= 5 Then counter = counter + 1
today = DateAdd("d", 1, today)
If today = lastday Then Exit Do
Loop
WorkdaysBetween = counter
End Function
Function IsWorkday(ByVal OneDay As Date) As Boolean
IsWorkday = (Weekday(OneDay, vbMonday) <= 5)
' ''debug.Print OneDay; " 是工作日 "; IsWorkday
End Function
Private Sub Sort_2003(ByVal Rng As Range, Optional WithHeader As Boolean = True)
With Rng 'xlAscending
.Sort _
Key1:=Rng.Cells(1, 1), Order1:=xlAscending, _
Header:=IIf(WithHeader, xlYes, xlNo), _
MatchCase:=False, _
Orientation:=xlTopToBottom, _
SortMethod:=xlPinYin
End With
End Sub

  

Public Sub StepForward()
Dim Dic As Object
Dim Wb As Workbook
Dim Sht As Worksheet
Dim oSht As Worksheet Set Wb = Application.ThisWorkbook
Set Dic = CreateObject("Scripting.Dictionary")
Set Sht = Wb.Worksheets("result")
Set oSht = Wb.Worksheets("analyze")
With Sht
endrow = .Cells(.Cells.Rows.Count, 1).End(xlUp).Row
Set Rng = .Range("A3:M" & endrow)
arr = Rng.Value For i = LBound(arr) To UBound(arr)
Key = CStr(arr(i, 2))
company = arr(i, 1)
staff = arr(i, 3) IsSave = False If arr(i, 6) >= 1 Then
debt = arr(i, 6)
IsSave = True
Else
debt = ""
End If If arr(i, 8) >= 3 Then
late = arr(i, 8)
IsSave = True
Else
late = ""
End If If arr(i, 10) >= 3 Then
early = arr(i, 10)
IsSave = True
Else
early = ""
End If If arr(i, 12) >= 3 Then
forget = arr(i, 12)
IsSave = True
Else
forget = ""
End If If IsSave Then Dic(Key) = Array(company, Key, staff, debt, late, early, forget) Next i End With With oSht
.UsedRange.Offset(2).Clear
Set Rng = .Range("A3")
Set Rng = Rng.Resize(Dic.Count, 7)
Rng.Value = Application.Rept(Dic.Items, 1)
SetCenters .UsedRange
SetBorders .UsedRange
Sort_2003 Rng, False
.Activate
Rows("3:3").Select
ActiveWindow.FreezePanes = True
End With UsedTime = VBA.Timer - StartTime End Sub
Private Sub SetBorders(ByVal Rng As Range)
With Rng.Borders
.LineStyle = xlContinuous
.ColorIndex = xlAutomatic
.TintAndShade = 0
.Weight = xlThin
End With
End Sub
Private Sub SetCenters(ByVal Rng As Range)
With Rng
.HorizontalAlignment = xlCenter
.VerticalAlignment = xlCenter
.WrapText = True
'.Columns.AutoFit
End With
End Sub
Private Sub Sort_2003(ByVal Rng As Range, Optional WithHeader As Boolean = True)
With Rng 'xlAscending
.Sort _
Key1:=Rng.Cells(1, 1), Order1:=xlAscending, _
Header:=IIf(WithHeader, xlYes, xlNo), _
MatchCase:=False, _
Orientation:=xlTopToBottom, _
SortMethod:=xlPinYin
End With
End Sub

  

20190319xlVBA_根据考勤数据统计缺勤缺考数据的更多相关文章

  1. Github Statistics 一个基于 React 的 GitHub 数据统计工具

    V 站曾经有个热帖说为何我的开源项目只有 Fork 没有 Star,楼下有个热评说开源项目关注的不应该是 Commit 数据吗?先不论 Star.Fork 和 Commit,issue .pr 也应是 ...

  2. 有关“数据统计”的一些概念 -- PV UV VV IP跳出率等

    有关"数据统计"的一些概念 -- PV UV VV IP跳出率等 版权声明:本文为博主原创文章,未经博主允许不得转载. 此文是本人工作中碰到的,随时记下来的零散概念,特此整理一下. ...

  3. TFS工作项数据统计及相关数据库结构分析

    今天为客户的质量管理部门人员提供TFS咨询过程中,客户的质量管理专家基于TFS提出了一个比较棘手的数据统计需求.需求是这样,客户的数十个软件项目通过质量管理部按照年度版本计划进行软件产品系统的发布,因 ...

  4. 常用的数据统计Sql 总结

    最近刚在搞一个BI的项目,里面需要大量的sql 数据统计相关运用,加深了我又对SQL的理解与使用. 所以,分享几个数据统计时常用的sql 语句总结: 1. 统计各个条件下的数据 select Batc ...

  5. Echarts 之三 —— 地市联动数据统计二

    一.简介 除了是一个地图之外,我们也可以使用多地图进行地市.区县联动数据统计.需求如下:展示整改广东省的地图,并显示统计信息,当点击某一个地市的时候,就显示该地市的地图,并统计该地市区县的数据信息.二 ...

  6. Echarts 之二——地市联动数据统计

    一.简介 通过地图可以更直观地展示各个地区的统计数据,能够更清楚地进行数据分析.有些场景下,我们不仅仅需要对每个地市进行统计分析.更需要对地市一下的区县进行数据统计,并进行联动.此事我们可以通过Ech ...

  7. TFS二次开发系列:七、TFS二次开发的数据统计以PBI、Bug、Sprint等为例(一)

    在TFS二次开发中,我们可能会根据某一些情况对各个项目的PBI.BUG等工作项进行统计.在本文中将大略讲解如果进行这些数据统计. 一:连接TFS服务器,并且得到之后需要使用到的类方法. /// < ...

  8. PHP+Mysql+jQuery实现地图区域数据统计-展示数据

    我们要在地图上有限的区块内展示更多的信息,更好的办法是通过地图交互来实现.本文将给大家讲解通过鼠标滑动到地图指定省份区域,在弹出的提示框中显示对应省份的数据信息.适用于数据统计和地图区块展示等场景. ...

  9. python数据统计,总数,平均值等

    一般我们进行数据统计的时候要进行数据摸查,可能是摸查整体的分布情况啊.平均值,标准差,总数,各分段的人数啊.这时候用excel或者数据库统计都不方便. 我要统计的一个文件,太大了,还得分成15个文件, ...

随机推荐

  1. SparkSQL与Hive on Spark的比较

    简要介绍了SparkSQL与Hive on Spark的区别与联系 一.关于Spark 简介 在Hadoop的整个生态系统中,Spark和MapReduce在同一个层级,即主要解决分布式计算框架的问题 ...

  2. MySQL慢查询日志总结 日志分析工具mysqldumpslow

    MySQL慢查询日志总结 - 潇湘隐者 - 博客园 https://www.cnblogs.com/kerrycode/p/5593204.html 2016-06-17 10:32 by 潇湘隐者, ...

  3. linux学习:【第3篇】远程连接及软件安装

    狂神声明 : 文章均为自己的学习笔记 , 转载一定注明出处 ; 编辑不易 , 防君子不防小人~共勉 ! linux学习:[第3篇]远程连接及软件安装 远程连接 xshell , xftp软件官网 : ...

  4. Apache ab并发负载压力测试(python+django+mysql+apache)

    如标题,大家都知道秒杀中存在高并发使库存骤然为0,但在我们个人PC或小区域内是模拟不出这样的情景 现在利用 Apache ab并发负载压力测试 1,数据库建入库存字段并映射模型 2,view编写脚本 ...

  5. css3 伸缩布局 display:flex等

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. sql 范式:1NF、2NF、3NF、BCNF(函数依赖)

    第一范式(1NF) 每个属性都是不可分的基本数据项.(必须有主键,列不可分) eg:非第一范式的表:(列可再分) 学院名称 高级职称人数 教授 副教授 信电学院 3 34 管理学院 5 23 外语学院 ...

  7. 网络视频播放ZFPlayer

    根据项目需要,公司app需要用到视频播放功能,推荐ZFPlayer,视频播放几乎有你想要的任何样式,该博客只是为了给自己留一个以后查找的资料, 改代码可以使用ZFPlayer github地址 htt ...

  8. 常见web UI 元素操作 及API使用

    1. 链接(Link) // 找到链接元素,这个方法比较直接,即通过超文本链接上的文字信息来定位元素,这种方式一般专门用于定位页面上的超文本链接 WebElement link1 = driver.f ...

  9. Java发送邮件功能

    package com.hd.all.test.testjava; import java.util.Properties; import javax.mail.Address; import jav ...

  10. JavaScript中各种对象之间的关系

    上图: 此外,补充一下图中用到的概念: 1.内置(Build-in)对象与原生(Naitve)对象的区别在于:前者总是在引擎初始化阶段就被创建好的对象,是后者的一个子集:而后者包括了一些在运行过程中动 ...