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

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

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分)

这是代码:

  1. Sub CalculateOvertimePoints()
  2. Dim i As Long
  3. Dim lastRow As Long
  4. Dim startTime As Date, endTime As Date
  5. Dim timeString As String
  6. Dim duration As Double
  7. ' 获取E列的最后一行
  8. lastRow = Cells(Rows.Count, "E").End(xlUp).Row
  9. ' 循环遍历从30行到最后一行的每一行
  10. For i = 30 To lastRow
  11. timeString = Cells(i, "F").Value
  12. If InStr(1, timeString, "-") > 0 Then
  13. startTime = TimeValue(Split(timeString, "-")(0))
  14. endTime = TimeValue(Split(timeString, "-")(1))
  15. If endTime < startTime Then
  16. endTime = DateAdd("d", 1, endTime)
  17. End If
  18. duration = endTime - startTime
  19. If duration > 0 Then
  20. Dim points As Double
  21. points = 0
  22. Dim currentTime As Date
  23. currentTime = startTime
  24. While currentTime < endTime
  25. Dim nextTime As Date
  26. nextTime = DateAdd("n", 30, currentTime)
  27. Dim hourPoints As Double
  28. hourPoints = 0
  29. Select Case Cells(i, "E").Value
  30. Case "Monday-Friday"
  31. If (currentTime >= TimeValue("06:00") And currentTime < TimeValue("07:30")) Then
  32. hourPoints = 1
  33. ElseIf (currentTime >= TimeValue("14:00") And currentTime < TimeValue("17:00")) Then
  34. hourPoints = 0.5
  35. ElseIf (currentTime >= TimeValue("17:00") And currentTime < TimeValue("19:00")) Then
  36. hourPoints = 1
  37. ElseIf (currentTime >= TimeValue("19:00") Or currentTime < TimeValue("01:00")) Then
  38. hourPoints = 1.5
  39. End If
  40. Case "Saturday"
  41. If (currentTime >= TimeValue("06:00") And currentTime < TimeValue("17:00")) Then
  42. hourPoints = 1
  43. ElseIf (currentTime >= TimeValue("17:00") And currentTime < TimeValue("19:00")) Then
  44. hourPoints = 1
  45. ElseIf (currentTime >= TimeValue("19:00") Or currentTime < TimeValue("02:00")) Then
  46. hourPoints = 1.5
  47. End If
  48. Case "Sunday"
  49. If (currentTime >= TimeValue("06:00") And currentTime < TimeValue("17:00")) Then
  50. hourPoints = 2
  51. ElseIf (currentTime >= TimeValue("17:00") And currentTime < TimeValue("18:00")) Then
  52. hourPoints = 1
  53. ElseIf (currentTime >= TimeValue("18:00") And currentTime < TimeValue("19:00")) Then
  54. hourPoints = 2
  55. End If
  56. End Select
  57. points = points + hourPoints
  58. currentTime = nextTime
  59. Wend
  60. ' 根据小数小时调整分数
  61. Dim fractionalHours As Double
  62. fractionalHours = (endTime - startTime) * 24 Mod 1
  63. points = points + fractionalHours * (hourPoints / 60)
  64. totalPoints = totalPoints - prevHourPoints ' 减去上一个hourPoints的值
  65. totalPoints = totalPoints + fractionalHours * (prevHourPoints / 1) ' 计算小数点
  66. Cells(i, "L").Value = points
  67. Else
  68. Cells(i, "L").Value = 0
  69. End If
  70. Else
  71. Cells(i, "L").Value = 0
  72. End If
  73. Next i
  74. 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:

  1. Sub CalculateOvertimePoints()
  2. Dim i As Long
  3. Dim lastRow As Long
  4. Dim startTime As Date, endTime As Date
  5. Dim timeString As String
  6. Dim duration As Double
  7. ' Get the last row in column E
  8. lastRow = Cells(Rows.Count, "E").End(xlUp).Row
  9. ' Loop through each row from 30 to the last row
  10. For i = 30 To lastRow
  11. timeString = Cells(i, "F").Value
  12. If InStr(1, timeString, "-") > 0 Then
  13. startTime = TimeValue(Split(timeString, "-")(0))
  14. endTime = TimeValue(Split(timeString, "-")(1))
  15. If endTime < startTime Then
  16. endTime = DateAdd("d", 1, endTime)
  17. End If
  18. duration = endTime - startTime
  19. If duration > 0 Then
  20. Dim points As Double
  21. points = 0
  22. Dim currentTime As Date
  23. currentTime = startTime
  24. While currentTime < endTime
  25. Dim nextTime As Date
  26. nextTime = DateAdd("n", 30, currentTime)
  27. Dim hourPoints As Double
  28. hourPoints = 0
  29. Select Case Cells(i, "E").Value
  30. Case "Monday-Friday"
  31. If (currentTime >= TimeValue("06:00") And currentTime < TimeValue("07:30")) Then
  32. hourPoints = 1
  33. ElseIf (currentTime >= TimeValue("14:00") And currentTime < TimeValue("17:00")) Then
  34. hourPoints = 0.5
  35. ElseIf (currentTime >= TimeValue("17:00") And currentTime < TimeValue("19:00")) Then
  36. hourPoints = 1
  37. ElseIf (currentTime >= TimeValue("19:00") Or currentTime < TimeValue("01:00")) Then
  38. hourPoints = 1.5
  39. End If
  40. Case "Saturday"
  41. If (currentTime >= TimeValue("06:00") And currentTime < TimeValue("17:00")) Then
  42. hourPoints = 1
  43. ElseIf (currentTime >= TimeValue("17:00") And currentTime < TimeValue("19:00")) Then
  44. hourPoints = 1
  45. ElseIf (currentTime >= TimeValue("19:00") Or currentTime < TimeValue("02:00")) Then
  46. hourPoints = 1.5
  47. End If
  48. Case "Sunday"
  49. If (currentTime >= TimeValue("06:00") And currentTime < TimeValue("17:00")) Then
  50. hourPoints = 2
  51. ElseIf (currentTime >= TimeValue("17:00") And currentTime < TimeValue("18:00")) Then
  52. hourPoints = 1
  53. ElseIf (currentTime >= TimeValue("18:00") And currentTime < TimeValue("19:00")) Then
  54. hourPoints = 2
  55. End If
  56. End Select
  57. points = points + hourPoints
  58. currentTime = nextTime
  59. Wend
  60. ' Adjust points based on fractional hours
  61. Dim fractionalHours As Double
  62. fractionalHours = (endTime - startTime) * 24 Mod 1
  63. points = points + fractionalHours * (hourPoints / 60)
  64. totalPoints = totalPoints - prevHourPoints ' Subtract the last hourPoints value
  65. totalPoints = totalPoints + fractionalHours * (prevHourPoints / 1) ' Calculate fractional points
  66. Cells(i, "L").Value = points
  67. Else
  68. Cells(i, "L").Value = 0
  69. End If
  70. Else
  71. Cells(i, "L").Value = 0
  72. End If
  73. Next i
  74. 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”来计算你的点数,而是找到相交的日期时间范围,并计算小时差并应用你的乘数。

  1. Sub CalcOTPts()
  2. Dim startTime As Date, endTime As Date
  3. Dim timeString As String
  4. Dim oPts As Double
  5. Dim i As Integer
  6. For i = 30 To Cells(Rows.Count, "E").End(xlUp).Row
  7. timeString = Cells(i, "F").Value
  8. If InStr(1, timeString, "-") > 0 Then
  9. startTime = TimeValue(Split(timeString, "-")(0))
  10. endTime = TimeValue(Split(timeString, "-")(1))
  11. If endTime < startTime Then
  12. endTime = DateAdd("d", 1, endTime)
  13. End If
  14. oPts = 0
  15. Select Case Cells(i, "E").Value
  16. Case "Monday-Friday"
  17. oPts = oPts + CalcPts(startTime, endTime, "6:00", "7:30", 2)
  18. oPts = oPts + CalcPts(startTime, endTime, "14:00", "17:00", 1)
  19. oPts = oPts + CalcPts(startTime, endTime, "17:00", "19:30", 2)
  20. oPts = oPts + CalcPts(startTime, endTime, "19:00", "01:00", 3)
  21. Case "Saturday"
  22. oPts = oPts + CalcPts(startTime, endTime, "06:00", "17:00", 2)
  23. ' Extended rule to 3:00 to test
  24. oPts = oPts + CalcPts(startTime, endTime, "17:00", "03:00", 3)
  25. Case "Sunday"
  26. oPts = oPts + CalcPts(startTime, endTime, "06:00", "17:00", 3)
  27. oPts = oPts + CalcPts(startTime, endTime, "17:00", "01:00", 4)
  28. End Select
  29. Cells(i, "M").Value = oPts
  30. End If
  31. Next
  32. End Sub
  33. Private Function CalcPts(ByVal startTime As Date, ByVal endTime As Date, startTimeRule As Date, endTimeRule As Date, multiplier As Double) As Double
  34. ' Finds the intersecting time between the two ranges and applies the hourly modifier
  35. Dim oStartIntersection As Date
  36. Dim oEndIntersection As Date
  37. ' Assume it's the next day if the endtime is less than starttime
  38. If endTimeRule < startTimeRule Then
  39. endTimeRule = DateAdd("d", 1, endTimeRule)
  40. End If
  41. CalcPts = 0 ' Default to not add any points
  42. If (startTime < endTimeRule) And (endTime > startTimeRule) Then
  43. 'There is an intersection beween these two date ranges
  44. ' Find the start time for the intersection
  45. If startTime > startTimeRule Then
  46. oStartIntersection = startTime
  47. Else
  48. oStartIntersection = startTimeRule
  49. End If
  50. ' Find the end time for the intersection
  51. If endTime < endTimeRule Then
  52. oEndIntersection = endTime
  53. Else
  54. oEndIntersection = endTimeRule
  55. End If
  56. ' Calculate the points
  57. CalcPts = DateDiff("n", oStartIntersection, oEndIntersection) / 60 * multiplier
  58. End If
  59. 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.

  1. Sub CalcOTPts()
  2. Dim startTime As Date, endTime As Date
  3. Dim timeString As String
  4. Dim oPts As Double
  5. Dim i As Integer
  6. For i = 30 To Cells(Rows.Count, &quot;E&quot;).End(xlUp).Row
  7. timeString = Cells(i, &quot;F&quot;).Value
  8. If InStr(1, timeString, &quot;-&quot;) &gt; 0 Then
  9. startTime = TimeValue(Split(timeString, &quot;-&quot;)(0))
  10. endTime = TimeValue(Split(timeString, &quot;-&quot;)(1))
  11. If endTime &lt; startTime Then
  12. endTime = DateAdd(&quot;d&quot;, 1, endTime)
  13. End If
  14. oPts = 0
  15. Select Case Cells(i, &quot;E&quot;).Value
  16. Case &quot;Monday-Friday&quot;
  17. oPts = oPts + CalcPts(startTime, endTime, &quot;6:00&quot;, &quot;7:30&quot;, 2)
  18. oPts = oPts + CalcPts(startTime, endTime, &quot;14:00&quot;, &quot;17:00&quot;, 1)
  19. oPts = oPts + CalcPts(startTime, endTime, &quot;17:00&quot;, &quot;19:30&quot;, 2)
  20. oPts = oPts + CalcPts(startTime, endTime, &quot;19:00&quot;, &quot;01:00&quot;, 3)
  21. Case &quot;Saturday&quot;
  22. oPts = oPts + CalcPts(startTime, endTime, &quot;06:00&quot;, &quot;17:00&quot;, 2)
  23. &#39; Extended rule to 3:00 to test
  24. oPts = oPts + CalcPts(startTime, endTime, &quot;17:00&quot;, &quot;03:00&quot;, 3)
  25. Case &quot;Sunday&quot;
  26. oPts = oPts + CalcPts(startTime, endTime, &quot;06:00&quot;, &quot;17:00&quot;, 3)
  27. oPts = oPts + CalcPts(startTime, endTime, &quot;17:00&quot;, &quot;01:00&quot;, 4)
  28. End Select
  29. Cells(i, &quot;M&quot;).Value = oPts
  30. End If
  31. Next
  32. End Sub
  33. Private Function CalcPts(ByVal startTime As Date, ByVal endTime As Date, startTimeRule As Date, endTimeRule As Date, multiplier As Double) As Double
  34. &#39; Finds the intersecting time between the two ranges and applies the hourly modifier
  35. Dim oStartIntersection As Date
  36. Dim oEndIntersection As Date
  37. &#39; Assume it&#39;s the next day if the endtime is less than starttime
  38. If endTimeRule &lt; startTimeRule Then
  39. endTimeRule = DateAdd(&quot;d&quot;, 1, endTimeRule)
  40. End If
  41. CalcPts = 0 &#39; Default to not add any points
  42. If (startTime &lt; endTimeRule) And (endTime &gt; startTimeRule) Then
  43. &#39;There is an intersection beween these two date ranges
  44. &#39; Find the start time for the intersection
  45. If startTime &gt; startTimeRule Then
  46. oStartIntersection = startTime
  47. Else
  48. oStartIntersection = startTimeRule
  49. End If
  50. &#39; Find the end time for the intersection
  51. If endTime &lt; endTimeRule Then
  52. oEndIntersection = endTime
  53. Else
  54. oEndIntersection = endTimeRule
  55. End If
  56. &#39; Calculate the points
  57. CalcPts = DateDiff(&quot;n&quot;, oStartIntersection, oEndIntersection) / 60 * multiplier
  58. End If
  59. 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:

确定