根据滚动天数和间隔计算工时

时间:2013-12-12 14:10:35

标签: vba excel-2010 worksheet-function

我正在尝试计算工作日的间隔,其中小时数具有不同的类别/收入,标准小时数根据天数而不同。我正在使用Excel 2010,但我希望一旦我弄清楚这是如何完成的,它将作为工资单系统的一部分实现。

标准时间,类别如下:

Monday-thursday: 08.00 - 14.30 Category AA
Monday-thursday: 14:30 - 21:00 Category AB
Monday-thursday: 21:00 - 08:00 Category AC
Friday: 08.00 - 14:00 Category AA
Friday: 14:00 - 21:00 Category AB
Friday: 21.00 - 08:00 Category AC

Sat and Sun: Category AC

所以我正在寻找的是一些执行以下操作的方法。

如果员工在接下来的几天工作,具有给定的开始和午餐时间

Day;WorkStart;WorkEnd;LunchStart;LunchEnd
Mon;18;04;23:30;00:00
Thu;06;15;11;11:30
Fri;08;17;12;12:30
Sat;05;12;09;09:30

然后我应该得到以下

Result:
Day;intervalStart;IntervalEnd;Category; HoursCount
Mon;18:00;23:30;AC;5,5;-- due to lunch being subtracted
Mon:00:00;04:00;AC;4
Thu;06:00;08:00;AC;2
Thu;08:00;14:30;AA;6 --due to lunch being subtracted
Thu;14:30;15:00;AB;0,5
Fri;08:00;14:00;AA;5,5; --due to lunch being subtracted
Fri;14:00;17:00;AB;3
Sat;05:00;12:00;AC;6,5;--due to lunch being subtracted

Mon: AC -> 9,5
Thu: AC -> 2
Thu: AB -> 0,5
Thu: AA -> 2
Fri: AA -> 5,5
Fri: AB -> 3
Sun: AC -> 6,5

我已经尝试了基于日期的查找,然后我最终得到了大量的公式来检查所有不同的情况,但它是非常,慢,如果我在小时或不同的事情做出改变就会中断。

我也尝试过各种不同的表格,但由于周五不同,我不断得到错误的答案,并且必须考虑到该类别在21:00交叉时也会切换。

因为这是间隔工作的,所以我必须跨间隔进行计算,并且我还没有找到一种计算方法,因此我可以在一天中为不同的时间间隔分配一个类别。虽然管理那个星期五也是不同的,而且滚动工作日也存在问题。

我想弄清楚如何在公式中做到这一点,但我并不排除使用VBA。理想情况下,当我使用这个原型时,我可以要求在计算工时和分配工资的系统中实施。

Calculating overtime work有点相似,但未考虑不同的时间间隔或滚动工作日。

我还没找到任何我可以使用的东西。也许是因为我不熟悉这个区域所以我不能完全把手指放在正确的搜索词上。

1 个答案:

答案 0 :(得分:0)

这是一个非常基本的示例,需要使用大量额外代码进行扩展,以处理日翻转和许多其他事情,但只是为了给您一个概念

班级类别:

VERSION 1.0 CLASS
BEGIN
    MultiUse = -1  'True
END
Attribute VB_Name = "Category"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Private pweekday As String
Private ptime_start As Double
Private ptime_stop As Double
Private pcategory As String

Public Property Let weekday(day As String)
    pweekday = day
End Property
Public Property Let time_start(time As Double)
   If checkTime(time) Then
      ptime_start = time
   Else
      MsgBox "Start Error"
   End If
End Property
Public Property Let time_stop(time As Double)
   If checkTime(time) Then
      ptime_stop = time
   Else
      MsgBox "Stop Error"
   End If
End Property
Public Property Let category(cat As String)
   pcategory = cat
End Property
Public Sub setup(cat As String, day As String, t_start As Double, t_stop As Double)
   If checkTime(t_start) And checkTime(t_stop) Then
      pcategory = cat
      pweekday = day
      ptime_start = t_start
      ptime_stop = t_stop
   Else
      MsgBox "SetupError"
   End If
End Sub
Public Property Get category() As String
   category = pcategory
End Property
Public Property Get weekday() As String
   weekday = pweekday
End Property
Public Property Get time_start() As Double
   time_start = ptime_start
End Property
Public Property Get time_stop() As Double
    time_stop = ptime_stop
End Property
Private Function checkTime(time As Double) As Boolean
    checkTime = time <= 24 And time >= 0
End Function

Class TimeTable

VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
END
Attribute VB_Name = "TimeTable"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Private ptime_table As New Collection

Public Sub add(cat As String, day As String, t_start As Double, t_stop As Double)
    Dim addcat As New category
    addcat.setup cat, day, t_start, t_stop
    ptime_table.add addcat
End Sub
Public Function getStartCategory(day As String, t_start As Double, hours As Double) As String
    Dim c As category
    Dim c_start As String
    Dim start_hours As Double
    For Each c In ptime_table
        If c.weekday = day Then
            If t_start >= c.time_start And t_start <= c.time_stop Then
                If hours > (c.time_stop - t_start) Then
                    start_hours = c.time_stop - t_start
                Else
                    start_hours = hours
                End If
                c_start = CStr(start_hours) & ";" & c.category
            End If
        End If
    Next c
    getStartCategory = c_start
End Function
Public Function getStopCategory(day As String, t_stop As Double, hours As Double) As String
    Dim c As category
    Dim c_stop As String
    Dim stop_hours As Double
    For Each c In ptime_table
        If c.weekday = day Then
            If t_stop <= c.time_stop And t_stop >= c.time_start Then
                If hours > (t_stop - c.time_start) Then
                    stop_hours = t_stop - c.time_start
                Else
                    stop_hours = hours
                End If
                c_stop = CStr(stop_hours) & ";" & c.category
            End If
        End If
    Next c
    getStopCategory = c_stop
End Function
Public Function getCategory(day As String, t_start As Double, t_stop As Double) As String
    Dim hours As Double
    hours = hoursworked(t_start, t_stop)
    c_start = getStartCategory(day, t_start, hours)
    c_stop = getStopCategory(day, t_stop, hours)
    getCategory = c_start & ";" & c_stop
End Function
Private Function hoursworked(t_start As Double, t_stop As Double) As Double
    hoursworked = t_stop - t_start
End Function

简单示例模块

Sub setup()
    Dim tt As New TimeTable
    With tt
      .add "AA", "Monday", 8, 14.5
      .add "AA", "Tuesday", 8, 14.5
      .add "AA", "Wednesday", 8, 14.5
      .add "AA", "Thursday", 8, 14.5
      .add "AA", "Friday", 8, 14
      .add "AB", "Monday", 14.5, 21
      .add "AB", "Tuesday", 14.5, 21
      .add "AB", "Wednesday", 14.5, 21
      .add "AB", "Thursday", 14.5, 21
      .add "AB", "Friday", 14, 21
      .add "AC", "Monday", 21, 8
      .add "AC", "Tuesday", 21, 8
      .add "AC", "Wednesday", 21, 8
      .add "AC", "Thursday", 21, 8
      .add "AC", "Friday", 21, 8
      .add "AC", "Saturday", 0, 24
      .add "AC", "Sunday", 0, 24
   End With
   MsgBox tt.getCategory("Monday", 12, 18)

End Sub

这将返回“2.5; AA; 3.5; AB”含义星期一,这个人在AA类工作2.5小时,在AB类工作3.5小时。

就像我说的这是一个简单的例子,说明如何启动并需要更多的错误处理,功能和数据映射,但希望它能让你入门