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. Python的命令模式和交互模式

    Python的命令行模式和交互模式 请注意区分命令行模式和Python交互模式. 在命令行模式下,可以执行python进入Python交互式环境,也可以执行python first.py运行一个.py ...

  2. django 1.11 目录

    django 信号 django form

  3. python基础(15)-socket网络编程&socketserver

    socket 参数及方法说明 初始化参数 sk = socket.socket(参数1,参数2,参数3) 参数1:地址簇 socket.AF_INET IPv4(默认) socket.AF_INET6 ...

  4. python框架之Django(15)-contenttype模块

    假如有一个书城系统,需要给作者和书籍加上评论功能.如果给每个表单独建一个评论表,那么我们以后要扩展其它模块评论功能的时候,还需要随之新建一张评论表,会显得很冗余.对于这种情况,Django 给我们提供 ...

  5. 四、latex字体字号设置

    latex的思想是格式与内容的分离,所以不建议在文中使用大量命令,而是定义一个新的命令

  6. linux下git服务器安装

    git服务器配置http://www.cnblogs.com/dee0912/p/5815267.html git教程https://www.liaoxuefeng.com/wiki/00137395 ...

  7. WinSDK(菜单笔记)

  8. VMware vSphere 5.x 与 vSphere 6.0各版本功能特性对比

    各版本中的新特性及功能对比:   VMware vSphere 5.0 VMware vSphere 5.1 VMware vSphere 5.5 VMware vSphere 6.0 ESXi 5. ...

  9. go get Unknown SSL protocol error in connection to gopkg.in

    OSX go get报错 go get Unknown SSL protocol error in connection to gopkg.in https://github.com/niemeyer ...

  10. iOS项目之WKWebView替换UIWebView相关

    在网上已经有了许多关于UIWebView替换为WKWebView的文章,所以在这里就不在多说替换的细节了,不会的可以在网上搜搜. 下面是我在项目中遇到的问题: 问题一:在UIWebView中,网页显示 ...