Got this sorted with help from VBForums.
http://www.vbforums.com/showthread.php?&t=501753&is_resolved=1
Posting my solution her for reference.
Cheers
TonyS.
Dim bUserEnteredTheTime As Boolean
Const ROUNDING_FACTOR As Integer = 5
Private Sub DTPicker1_Change()
Static PrevTime As Date
dtpicker1 = CDate(RoundTimeTo(dtpicker1, PrevTime,
bUserEnteredTheTime, ROUNDING_FACTOR))
End Sub
Private Sub DTPicker1_KeyUp(KeyCode As Integer, ByVal Shift As
Integer)
bUserEnteredTheTime = bTestUserKeysFlag(KeyCode)
End Sub
Function bTestUserKeysFlag(KeyCode As Integer) As Boolean
'Skip Arrow keys because they affect the result already
'KeyCodes: 37 = ArrowLeft
' 38 = ArrowUp
' 39 = RightArrow
' 40 = ArrowDown
If Not (KeyCode >= 38 And KeyCode <= 40) Then
bTestUserKeysFlag = True
Else
bTestUserKeysFlag = False
End If
End Function
Function RoundTimeTo(ByVal TargetDateTime As String, ByRef PrevTime As
Date, _
ByRef bUserKeyed As Boolean, ByVal
RoundingInterval As Integer) As String
Dim wrk As Date
Dim AdjustByVal
Dim Remainder
Dim hr
Remainder = Minute(TargetDateTime) Mod RoundingInterval
If Remainder < RoundingInterval / 2 Then
AdjustByVal = -Remainder
ElseIf Remainder > RoundingInterval / 2 Then
AdjustByVal = RoundingInterval - Remainder
End If
If bUserKeyed Then
bUserKeyed = False
Remainder = Minute(TargetDateTime) Mod RoundingInterval
If Remainder < RoundingInterval / 2 Then
AdjustByVal = -Remainder
ElseIf Remainder > RoundingInterval / 2 Then
AdjustByVal = RoundingInterval - Remainder
End If
wrk = DateAdd("n", AdjustByVal, TargetDateTime)
Else
If Minute(TargetDateTime) = Minute(PrevTime) Then
'No change because we are only changing the hour
wrk = TargetDateTime
ElseIf Minute(TargetDateTime) < Minute(PrevTime) Then
wrk = DateAdd("n", -Remainder, TargetDateTime)
ElseIf Minute(TargetDateTime) < Minute(PrevTime) Or
(Minute(PrevTime) = 0 And Not Minute(TargetDateTime) <
RoundingInterval) Then
If Minute(PrevTime) = 0 Then hr = 60
wrk = DateAdd("n", -hr - ((Minute(TargetDateTime) Mod
RoundingInterval)), TargetDateTime)
Else
wrk = DateAdd("n", RoundingInterval -
((Minute(TargetDateTime) Mod RoundingInterval)), TargetDateTime)
End If
End If
PrevTime = wrk
RoundTimeTo = wrk
End Function
> Hi Everyone,
>
[quoted text clipped - 145 lines]
> RoundTimeTo = wrk
> End Function
Got this sorted with help from VBForums.
http://www.vbforums.com/showthread.php?&t=501753&is_resolved=1
Posting my solution her for reference.
Cheers
TonyS.
Dim bUserEnteredTheTime As Boolean
Const ROUNDING_FACTOR As Integer = 5
Private Sub DTPicker1_Change()
Static PrevTime As Date
dtpicker1 = CDate(RoundTimeTo(dtpicker1, PrevTime,
bUserEnteredTheTime, ROUNDING_FACTOR))
End Sub
Private Sub DTPicker1_KeyUp(KeyCode As Integer, ByVal Shift As
Integer)
bUserEnteredTheTime = bTestUserKeysFlag(KeyCode)
End Sub
Function bTestUserKeysFlag(KeyCode As Integer) As Boolean
'Skip Arrow keys because they affect the result already
'KeyCodes: 37 = ArrowLeft
' 38 = ArrowUp
' 39 = RightArrow
' 40 = ArrowDown
If Not (KeyCode >= 38 And KeyCode <= 40) Then
bTestUserKeysFlag = True
Else
bTestUserKeysFlag = False
End If
End Function
Function RoundTimeTo(ByVal TargetDateTime As String, ByRef PrevTime As
Date, _
ByRef bUserKeyed As Boolean, ByVal
RoundingInterval As Integer) As String
Dim wrk As Date
Dim AdjustByVal
Dim Remainder
Dim hr
Remainder = Minute(TargetDateTime) Mod RoundingInterval
If Remainder < RoundingInterval / 2 Then
AdjustByVal = -Remainder
ElseIf Remainder > RoundingInterval / 2 Then
AdjustByVal = RoundingInterval - Remainder
End If
If bUserKeyed Then
bUserKeyed = False
Remainder = Minute(TargetDateTime) Mod RoundingInterval
If Remainder < RoundingInterval / 2 Then
AdjustByVal = -Remainder
ElseIf Remainder > RoundingInterval / 2 Then
AdjustByVal = RoundingInterval - Remainder
End If
wrk = DateAdd("n", AdjustByVal, TargetDateTime)
Else
If Minute(TargetDateTime) = Minute(PrevTime) Then
'No change because we are only changing the hour
wrk = TargetDateTime
ElseIf Minute(TargetDateTime) < Minute(PrevTime) Then
wrk = DateAdd("n", -Remainder, TargetDateTime)
ElseIf Minute(TargetDateTime) < Minute(PrevTime) Or
(Minute(PrevTime) = 0 And Not Minute(TargetDateTime) <
RoundingInterval) Then
If Minute(PrevTime) = 0 Then hr = 60
wrk = DateAdd("n", -hr - ((Minute(TargetDateTime) Mod
RoundingInterval)), TargetDateTime)
Else
wrk = DateAdd("n", RoundingInterval -
((Minute(TargetDateTime) Mod RoundingInterval)), TargetDateTime)
End If
End If
PrevTime = wrk
RoundTimeTo = wrk
End Function
> Hi Everyone,
>
[quoted text clipped - 145 lines]
> RoundTimeTo = wrk
> End Function
Got this sorted with help from VBForums.
http://www.vbforums.com/showthread.php?&t=501753&is_resolved=1
Posting my solution here for reference with thanks to
http://www.vbforums.com/member.php?u=53814.
Cheers
TonyS.
Dim bUserEnteredTheTime As Boolean
Const ROUNDING_FACTOR As Integer = 5
Private Sub DTPicker1_Change()
Static PrevTime As Date
dtpicker1 = CDate(RoundTimeTo(dtpicker1, PrevTime,
bUserEnteredTheTime, ROUNDING_FACTOR))
End Sub
Private Sub DTPicker1_KeyUp(KeyCode As Integer, ByVal Shift As
Integer)
bUserEnteredTheTime = bTestUserKeysFlag(KeyCode)
End Sub
Function bTestUserKeysFlag(KeyCode As Integer) As Boolean
'Skip Arrow keys because they affect the result already
'KeyCodes: 37 = ArrowLeft
' 38 = ArrowUp
' 39 = RightArrow
' 40 = ArrowDown
If Not (KeyCode >= 38 And KeyCode <= 40) Then
bTestUserKeysFlag = True
Else
bTestUserKeysFlag = False
End If
End Function
Function RoundTimeTo(ByVal TargetDateTime As String, ByRef PrevTime As
Date, _
ByRef bUserKeyed As Boolean, ByVal
RoundingInterval As Integer) As String
Dim wrk As Date
Dim AdjustByVal
Dim Remainder
Dim hr
Remainder = Minute(TargetDateTime) Mod RoundingInterval
If Remainder < RoundingInterval / 2 Then
AdjustByVal = -Remainder
ElseIf Remainder > RoundingInterval / 2 Then
AdjustByVal = RoundingInterval - Remainder
End If
If bUserKeyed Then
bUserKeyed = False
Remainder = Minute(TargetDateTime) Mod RoundingInterval
If Remainder < RoundingInterval / 2 Then
AdjustByVal = -Remainder
ElseIf Remainder > RoundingInterval / 2 Then
AdjustByVal = RoundingInterval - Remainder
End If
wrk = DateAdd("n", AdjustByVal, TargetDateTime)
Else
If Minute(TargetDateTime) = Minute(PrevTime) Then
'No change because we are only changing the hour
wrk = TargetDateTime
ElseIf Minute(TargetDateTime) < Minute(PrevTime) Then
wrk = DateAdd("n", -Remainder, TargetDateTime)
ElseIf Minute(TargetDateTime) < Minute(PrevTime) Or
(Minute(PrevTime) = 0 And Not Minute(TargetDateTime) <
RoundingInterval) Then
If Minute(PrevTime) = 0 Then hr = 60
wrk = DateAdd("n", -hr - ((Minute(TargetDateTime) Mod
RoundingInterval)), TargetDateTime)
Else
wrk = DateAdd("n", RoundingInterval -
((Minute(TargetDateTime) Mod RoundingInterval)), TargetDateTime)
End If
End If
PrevTime = wrk
RoundTimeTo = wrk
End Function
- Hide quoted text -
- Show quoted text -
> Hi Everyone,
> I have a need support data entry of a time. My client wants all times
> entered to be rounded to the nearest 15 minutes. I thought it would be
> useful to use the DateTimePicker control to do this since it allows
> for 12 and 24 hr clock values and can format the output with or
> without AM/PM indicators. I was already using it on the form to input
> some dates.
> It seemed like a good idea at the time! <g>
> I came across two basic problems with this control.
> 1. I want the control to display empty until a time is actually keyed
[quoted text clipped - 6 lines]
> DTPicker1.Format = dtpCustom
> DTPicker1.CustomFormat = Time_Null_Marker_Format
> Note this does not change the value of the control just the display.
> Knowing this, I set the format to something else in the control's
> Enter event so that if I want to know if the control hasn't yet been
> edited I can test for DTPicker1.CustomFormat = Time_Null_Marker_Format
> Now the problem I can's solve.
> 2. How to round the time entered to the nearest 15 minutes.
> This is where I have noticed some strange (for me anyway) behaviour.
> I thought it would be a simple matter of putting some code in the
> BeforeUpdate, AfterUpdate or Exit event for the control. I have even
> tried the Change event.
> The problem is that the events do not behave in a way a can use.
> Neither the BeforeUpdate or AfterUpdate events seem to fire.
[quoted text clipped - 5 lines]
> digit.
> The Exit event fires if you click the UpDown arrows of the control.
> Any insight into how to make this work would be appreciated.
> Cheers
> Happy Christmas and Other Festivities,
> TonyS.
> Do the following to produce a working form to see this in action.
> Create a form.
> To be able to create the control you need to display the VBA toolbox
> and right click somewhere on the toolbox. Select "Additional
> Controls" from the context menu that is displayed.
> Scroll through the Additional Controls list (make sure the Show
> "Selected Items Only" checkbox is unchecked)
> to bring up the "Microsoft Date Time Picker Control 6.0 (SP4)" (the
> file this is is in is MSCOMCT2.OCX )
> Select the Checkbox beside the listing.
> Now Place a textbox (or any other control that can receive focus when
> you exit the dtp) and one DateTimePicker control onto the form.
> Paste the following code into the UserForm's general section then run
> the form.
> if you put breakpoints on the BeforeUpdate or AfterUpdate events you
> can see that they don't fire.
> Try changing the minutes by entering a value by keyboard. You will
> see that if you quickly tan out of the control, the value is not
> rounded.
> Also see the note in the Change event.
> Private Sub DTPicker_AfterUpdate()
> DTPicker = CDate(RoundTimeTo(DTPicker, 15))
> End Sub
> Private Sub DTPicker_BeforeUpdate(ByVal Cancel As
> MSForms.ReturnBoolean)
> DTPicker = CDate(RoundTimeTo(DTPicker, 15))
> End Sub
> Private Sub DTPicker_Change()
> 'If this is enabled then you can't change the time using the
[quoted text clipped - 3 lines]
> DTPicker = CDate(RoundTimeTo(DTPicker, 15))
> End Sub
> Private Sub DTPicker_Exit(ByVal Cancel As MSForms.ReturnBoolean)
> DTPicker = CDate(RoundTimeTo(DTPicker, 15))
> End Sub
> Private Sub UserForm_Activate()
> With DTPicker
[quoted text clipped - 3 lines]
> End With
> End Sub
> Function RoundTimeTo(TargetDateTime As String, RoundingInterval As
> Integer) As String
> 'Please ignore the clumsiness of this procedure. I was tired and
> it was late.!
> Dim CurrMinute
> Dim Num
> Dim hrs
> Dim difr
> Dim wrk
> Dim adjustment
> Dim remainder
> Dim TimeInMinutes
> Dim wrkDate As Date
> wrkDate = CDate(TargetDateTime)
> hrs = Hour(wrkDate)
> CurrMinute = Minute(CDate(TargetDateTime))
> TimeInMinutes = (hrs * 60) + CurrMinute
> remainder = TimeInMinutes Mod RoundingInterval
> If remainder < RoundingInterval / 2 Then
> adjustment = -remainder
[quoted text clipped - 3 lines]
> adjustment = 0
> End If
> wrk = (hrs * 60) + CurrMinute + adjustment
> Dim dt As Date
> dt = DateSerial(Year(TargetDateTime), Month(TargetDateTime),
> Day(TargetDateTime))
> wrk = DateAdd("n", wrk, dt)
> RoundTimeTo = wrk
> End Function