英文:
VBA code not working correctly in some scenario's
问题
好的,以下是翻译好的内容:
希望有人能帮忙解决以下问题。
这是标准:
周一至周五: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。
希望有人能帮忙,谢谢。
这段代码在某些场景下存在问题,我不太理解,如果你将时间稍微推后一点,它就能正确运行。
英文:
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
- 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
- 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 "<="
- 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, "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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论