VBA代码在某些情况下无法正常工作。

huangapple go评论82阅读模式
英文:

VBA code not working correctly in some scenario's

问题

好的,以下是翻译好的内容:

VBA代码在某些情况下无法正常工作。你好,

希望有人能帮忙解决以下问题。

这是标准:

周一至周五:06:00至7:30(每小时2分)14:00至17:00(每小时1分)17:00至19:00(每小时2分)19:00至01:00(每小时3分)

周六06:00至17:00(每小时2分)17:00至01:00(每小时3分)

周日06:00至17:00(每小时2分)17:00至01:00(每小时4分)

这是代码:

Sub CalculateOvertimePoints()
    Dim i As Long
    Dim lastRow As Long
    Dim startTime As Date, endTime As Date
    Dim timeString As String
    Dim duration As Double
    
    ' 获取E列的最后一行
    lastRow = Cells(Rows.Count, "E").End(xlUp).Row
    
    ' 循环遍历从30行到最后一行的每一行
    For i = 30 To lastRow
        timeString = Cells(i, "F").Value
        If InStr(1, timeString, "-") > 0 Then
            startTime = TimeValue(Split(timeString, "-")(0))
            endTime = TimeValue(Split(timeString, "-")(1))
            
            If endTime < startTime Then
                endTime = DateAdd("d", 1, endTime)
            End If

            duration = endTime - startTime
            If duration > 0 Then
                Dim points As Double
                points = 0
                
                Dim currentTime As Date
                currentTime = startTime
                
                While currentTime < endTime
                    Dim nextTime As Date
                    nextTime = DateAdd("n", 30, currentTime)
                    
                    Dim hourPoints As Double
                    hourPoints = 0
                    
                    Select Case Cells(i, "E").Value
                        Case "Monday-Friday"
                            If (currentTime >= TimeValue("06:00") And currentTime < TimeValue("07:30")) Then
                                hourPoints = 1
                            ElseIf (currentTime >= TimeValue("14:00") And currentTime < TimeValue("17:00")) Then
                                hourPoints = 0.5

                            ElseIf (currentTime >= TimeValue("17:00") And currentTime < TimeValue("19:00")) Then
                                hourPoints = 1
                            ElseIf (currentTime >= TimeValue("19:00") Or currentTime < TimeValue("01:00")) Then
                                hourPoints = 1.5
                            End If
                            
                        Case "Saturday"
                            If (currentTime >= TimeValue("06:00") And currentTime < TimeValue("17:00")) Then
                                hourPoints = 1
                                
                            ElseIf (currentTime >= TimeValue("17:00") And currentTime < TimeValue("19:00")) Then
                                hourPoints = 1
                            ElseIf (currentTime >= TimeValue("19:00") Or currentTime < TimeValue("02:00")) Then
                                hourPoints = 1.5
                            End If
                            
                        Case "Sunday"
                            If (currentTime >= TimeValue("06:00") And currentTime < TimeValue("17:00")) Then
                                hourPoints = 2
                            ElseIf (currentTime >= TimeValue("17:00") And currentTime < TimeValue("18:00")) Then
                                hourPoints = 1
                            ElseIf (currentTime >= TimeValue("18:00") And currentTime < TimeValue("19:00")) Then
                                hourPoints = 2
                            End If
                    End Select
                    
                    points = points + hourPoints
                    
                    currentTime = nextTime
                Wend
                
                ' 根据小数小时调整分数
                Dim fractionalHours As Double
                fractionalHours = (endTime - startTime) * 24 Mod 1
                points = points + fractionalHours * (hourPoints / 60)
                totalPoints = totalPoints - prevHourPoints ' 减去上一个hourPoints的值
    totalPoints = totalPoints + fractionalHours * (prevHourPoints / 1) ' 计算小数点
                Cells(i, "L").Value = points
            Else
                Cells(i, "L").Value = 0
            End If
        Else
            Cells(i, "L").Value = 0
        End If
    Next i
End Sub

我附上了3个场景的图片-第一个答案应该是4.5,第二个答案应该是12,第三个答案应该是24。

希望有人能帮忙,谢谢。

这段代码在某些场景下存在问题,我不太理解,如果你将时间稍微推后一点,它就能正确运行。

英文:

VBA代码在某些情况下无法正常工作。Good day,

was hoping someone could help with the following.

this is the criteria:

Monday to Friday:06:00 to 7:30 (2 points per hour) 14:00 to 17:00 (1 point per hour) 17:00 to 19:00 (2 points per hour) 19:00-01:00 (3 points per hour)

Saturday 06:00 to 17:00 (2 points per hour) 17:00 to 01:00 (3 points per hour)

Sunday 06:00 to 17:00 (2 points per hour) 17:00 to 01:00 (4 points per hour)

This is the code:

Sub CalculateOvertimePoints()
    Dim i As Long
    Dim lastRow As Long
    Dim startTime As Date, endTime As Date
    Dim timeString As String
    Dim duration As Double
    
    ' Get the last row in column E
    lastRow = Cells(Rows.Count, "E").End(xlUp).Row
    
    ' Loop through each row from 30 to the last row
    For i = 30 To lastRow
        timeString = Cells(i, "F").Value
        If InStr(1, timeString, "-") > 0 Then
            startTime = TimeValue(Split(timeString, "-")(0))
            endTime = TimeValue(Split(timeString, "-")(1))
            
            If endTime < startTime Then
                endTime = DateAdd("d", 1, endTime)
            End If

            duration = endTime - startTime
            If duration > 0 Then
                Dim points As Double
                points = 0
                
                Dim currentTime As Date
                currentTime = startTime
                
                While currentTime < endTime
                    Dim nextTime As Date
                    nextTime = DateAdd("n", 30, currentTime)
                    
                    Dim hourPoints As Double
                    hourPoints = 0
                    
                    Select Case Cells(i, "E").Value
                        Case "Monday-Friday"
                            If (currentTime >= TimeValue("06:00") And currentTime < TimeValue("07:30")) Then
                                hourPoints = 1
                            ElseIf (currentTime >= TimeValue("14:00") And currentTime < TimeValue("17:00")) Then
                                hourPoints = 0.5

                            ElseIf (currentTime >= TimeValue("17:00") And currentTime < TimeValue("19:00")) Then
                                hourPoints = 1
                            ElseIf (currentTime >= TimeValue("19:00") Or currentTime < TimeValue("01:00")) Then
                                hourPoints = 1.5
                            End If
                            
                        Case "Saturday"
                            If (currentTime >= TimeValue("06:00") And currentTime < TimeValue("17:00")) Then
                                hourPoints = 1
                                
                            ElseIf (currentTime >= TimeValue("17:00") And currentTime < TimeValue("19:00")) Then
                                hourPoints = 1
                            ElseIf (currentTime >= TimeValue("19:00") Or currentTime < TimeValue("02:00")) Then
                                hourPoints = 1.5
                            End If
                            
                        Case "Sunday"
                            If (currentTime >= TimeValue("06:00") And currentTime < TimeValue("17:00")) Then
                                hourPoints = 2
                            ElseIf (currentTime >= TimeValue("17:00") And currentTime < TimeValue("18:00")) Then
                                hourPoints = 1
                            ElseIf (currentTime >= TimeValue("18:00") And currentTime < TimeValue("19:00")) Then
                                hourPoints = 2
                            End If
                    End Select
                    
                    points = points + hourPoints
                    
                    currentTime = nextTime
                Wend
                
                ' Adjust points based on fractional hours
                Dim fractionalHours As Double
                fractionalHours = (endTime - startTime) * 24 Mod 1
                points = points + fractionalHours * (hourPoints / 60)
                totalPoints = totalPoints - prevHourPoints ' Subtract the last hourPoints value
    totalPoints = totalPoints + fractionalHours * (prevHourPoints / 1) ' Calculate fractional points
                
                Cells(i, "L").Value = points
            Else
                Cells(i, "L").Value = 0
            End If
        Else
            Cells(i, "L").Value = 0
        End If
    Next i
End Sub

I attached a picture of 3 scenario's - 1Ste answer should be 4.5 second one should be 12 and 3de one should be 24.

Hope someone can help, thank you.

The code has issu's with only some scenario's and I dont understand it, if you change the times to maybe a bit later then it works out correctly.

答案1

得分: 1

对你的错误进行评论:
1)5.5是正确的。1pt/hr(2hrs + .5hr)* 1pt/hr = 2.5pts,2pts/hr组=(1hr + .5hr)* 2pt/hr = 3pt。总计为2.5 + 3 = 5.5。
2)我没有花足够的时间来弄清楚为什么,但是当currentTime和endTime都是下午1:00时,它会进入你的While循环,即使使用的是“<”而不是“<=”。
3)1:30超出了你的规则范围,星期六从[17:00,01:00]开始..而且我认为你的任何跨越到第二天的范围都会遇到问题。

我重新编写了代码,不是计算半小时的“bean”来计算你的点数,而是找到相交的日期时间范围,并计算小时差并应用你的乘数。

Sub CalcOTPts()
    Dim startTime As Date, endTime As Date
    Dim timeString As String
    Dim oPts As Double
    
    Dim i As Integer
    For i = 30 To Cells(Rows.Count, "E").End(xlUp).Row
        timeString = Cells(i, "F").Value
        If InStr(1, timeString, "-") > 0 Then
            startTime = TimeValue(Split(timeString, "-")(0))
            endTime = TimeValue(Split(timeString, "-")(1))
            
            If endTime < startTime Then
                endTime = DateAdd("d", 1, endTime)
            End If

            oPts = 0
            Select Case Cells(i, "E").Value
                Case "Monday-Friday"
                    oPts = oPts + CalcPts(startTime, endTime, "6:00", "7:30", 2)
                    oPts = oPts + CalcPts(startTime, endTime, "14:00", "17:00", 1)
                    oPts = oPts + CalcPts(startTime, endTime, "17:00", "19:30", 2)
                    oPts = oPts + CalcPts(startTime, endTime, "19:00", "01:00", 3)
                Case "Saturday"
                    oPts = oPts + CalcPts(startTime, endTime, "06:00", "17:00", 2)
                    ' Extended rule to 3:00 to test
                    oPts = oPts + CalcPts(startTime, endTime, "17:00", "03:00", 3)
                Case "Sunday"
                    oPts = oPts + CalcPts(startTime, endTime, "06:00", "17:00", 3)
                    oPts = oPts + CalcPts(startTime, endTime, "17:00", "01:00", 4)
            End Select
            
            Cells(i, "M").Value = oPts
            
        End If
    Next
End Sub


Private Function CalcPts(ByVal startTime As Date, ByVal endTime As Date, startTimeRule As Date, endTimeRule As Date, multiplier As Double) As Double
    ' Finds the intersecting time between the two ranges and applies the hourly modifier
    
    Dim oStartIntersection As Date
    Dim oEndIntersection As Date
    
    ' Assume it's the next day if the endtime is less than starttime
    If endTimeRule < startTimeRule Then
        endTimeRule = DateAdd("d", 1, endTimeRule)
    End If
    
    CalcPts = 0     ' Default to not add any points
    If (startTime < endTimeRule) And (endTime > startTimeRule) Then
        'There is an intersection beween these two date ranges
        
        ' Find the start time for the intersection
        If startTime > startTimeRule Then
            oStartIntersection = startTime
        Else
            oStartIntersection = startTimeRule
        End If
        
        ' Find the end time for the intersection
        If endTime < endTimeRule Then
            oEndIntersection = endTime
        Else
            oEndIntersection = endTimeRule
        End If
        
        ' Calculate the points
        CalcPts = DateDiff("n", oStartIntersection, oEndIntersection) / 60 * multiplier
    End If
    
End Function
英文:

Comments on your error's

  1. 5.5 is correct. 1pt/hr (2hrs + .5hr)*1pt/hr = 2.5pts, 2pts/hr group = (1hr + .5hr)*2pt/hr = 3pt. Which totals 2.5+3 = 5.5
  2. I haven't spent enough time to be able to figure out why but it's entering your While loop when currentTime and endTime are both 1:00 PM, even with a "<" not "<="
  3. 1:30 is outside the range of your rules Saturday goes from [17:00,01:00].. also I think you will run into problems with any of your ranges that are going over to the next day.

Instead of counting half-hour "bean's" to tally up your points, I re-wrote it to find intersecting date time ranges and taking the difference in hours and applying your multiplier.

    Sub CalcOTPts()
        Dim startTime As Date, endTime As Date
        Dim timeString As String
        Dim oPts As Double
        
        Dim i As Integer
        For i = 30 To Cells(Rows.Count, &quot;E&quot;).End(xlUp).Row
            timeString = Cells(i, &quot;F&quot;).Value
            If InStr(1, timeString, &quot;-&quot;) &gt; 0 Then
                startTime = TimeValue(Split(timeString, &quot;-&quot;)(0))
                endTime = TimeValue(Split(timeString, &quot;-&quot;)(1))
                
                If endTime &lt; startTime Then
                    endTime = DateAdd(&quot;d&quot;, 1, endTime)
                End If
    
                oPts = 0
                Select Case Cells(i, &quot;E&quot;).Value
                    Case &quot;Monday-Friday&quot;
                        oPts = oPts + CalcPts(startTime, endTime, &quot;6:00&quot;, &quot;7:30&quot;, 2)
                        oPts = oPts + CalcPts(startTime, endTime, &quot;14:00&quot;, &quot;17:00&quot;, 1)
                        oPts = oPts + CalcPts(startTime, endTime, &quot;17:00&quot;, &quot;19:30&quot;, 2)
                        oPts = oPts + CalcPts(startTime, endTime, &quot;19:00&quot;, &quot;01:00&quot;, 3)
                    Case &quot;Saturday&quot;
                        oPts = oPts + CalcPts(startTime, endTime, &quot;06:00&quot;, &quot;17:00&quot;, 2)
                        &#39; Extended rule to 3:00 to test
                        oPts = oPts + CalcPts(startTime, endTime, &quot;17:00&quot;, &quot;03:00&quot;, 3)
                    Case &quot;Sunday&quot;
                        oPts = oPts + CalcPts(startTime, endTime, &quot;06:00&quot;, &quot;17:00&quot;, 3)
                        oPts = oPts + CalcPts(startTime, endTime, &quot;17:00&quot;, &quot;01:00&quot;, 4)
                End Select
                
                Cells(i, &quot;M&quot;).Value = oPts
                
            End If
        Next
    End Sub
    
    
    Private Function CalcPts(ByVal startTime As Date, ByVal endTime As Date, startTimeRule As Date, endTimeRule As Date, multiplier As Double) As Double
        &#39; Finds the intersecting time between the two ranges and applies the hourly modifier
        
        Dim oStartIntersection As Date
        Dim oEndIntersection As Date
        
        &#39; Assume it&#39;s the next day if the endtime is less than starttime
        If endTimeRule &lt; startTimeRule Then
            endTimeRule = DateAdd(&quot;d&quot;, 1, endTimeRule)
        End If
        
        CalcPts = 0     &#39; Default to not add any points
        If (startTime &lt; endTimeRule) And (endTime &gt; startTimeRule) Then
            &#39;There is an intersection beween these two date ranges
            
            &#39; Find the start time for the intersection
            If startTime &gt; startTimeRule Then
                oStartIntersection = startTime
            Else
                oStartIntersection = startTimeRule
            End If
            
            &#39; Find the end time for the intersection
            If endTime &lt; endTimeRule Then
                oEndIntersection = endTime
            Else
                oEndIntersection = endTimeRule
            End If
            
            &#39; Calculate the points
            CalcPts = DateDiff(&quot;n&quot;, oStartIntersection, oEndIntersection) / 60 * multiplier
        End If
        
    End Function

huangapple
  • 本文由 发表于 2023年7月27日 18:10:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/76778677.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定