Working with dates in Visual Basic / Excel - excel

Very new to working with Visual Basic / Excel. I am trying to write a quick script that enters the current time in one column, and allows the user to enter how many days/hours/minutes will pass until a new time, and output that in another column.
I'm sure this isn't the best way to do it, but what I have so far is the following. I have given up on fiddling with dates, and am just working with the time:
Sub TimeModule()
Dim DaysLeft, HoursLeft, MinutesLeft As Double
DaysLeft = Val(InputBox("Days left"))
HoursLeft = Val(InputBox("Hours left"))
MinutesLeft = Val(InputBox("Minutes left"))
Dim CurrentTime As Date
CurrentTime = TimeValue(Now())
ActiveCell.Value = CurrentTime
ActiveCell.Offset(0, 1) = CurrentTime + Time(HoursLeft, MinutesLeft, 0)
End Sub
I am getting an error, of course. If anyone could shed some light on a better way to do this, along with the functions I'm misusing, I would really appreciate it!
Edit: I would, of course ultimately like for the script to handle days as well.

I think this is possible just using cell functions in Excel, if I've understood you correctly.
For example, this is what you'd see...
Time Now: Days: Hours: Minutes: New Time:
30/05/2012 23:34 15 6 23 15/06/2012 05:57
...and this is what is in each cell (assuming top-left cell is A1)...
Time Now: Days: Hours: Minutes: New Time:
=NOW() 15 6 23 =A2+B2+TIME(C2,D2,0)
Describing each function:
NOW() returns the current date and time formatted as a date and time.
DATE(year,month,day) returns the number that represents the date in MS Excel date-time code.
TIME(hours,minutes,seconds) converts hours, minutes, and seconds given as numbers to an Excel serial number, formatted with a time format.
Dissecting the equation in the last cell:
A2 is the cell containing the current date/time (as of last worksheet calculation).
B2 is the user-inputted value for days.
TIME(C2,D2,0) is the TIME() function, taking the user-inputted values for hours and minutes from cells C2 and D2 respectively.
Is this anything like your intended functionality...?

If you want to use VBA the only issue with your code is the "Time" function.
You can use CDate instead :
Sub TimeModule()
Dim DaysLeft, HoursLeft, MinutesLeft As Double
DaysLeft = Val(InputBox("Days left"))
HoursLeft = Val(InputBox("Hours left"))
MinutesLeft = Val(InputBox("Minutes left"))
Dim CurrentTime As Date
CurrentTime = TimeValue(Now())
ActiveCell.Value = Now()
ActiveCell.Offset(0, 1) = ActiveCell.Value + DaysLeft + CDate(HoursLeft & ":" & MinutesLeft)
'ActiveCell.Offset(0, 1) = CurrentTime + Time(HoursLeft, MinutesLeft, 0)
End Sub

When you 'Dim' in that fashion, you have to record the data type for each variable. The way you have it MinutesLeft is a Double and everything is (by default) a Variant.
The Time function you're looking for is TimeSerial.
Dates are stored as the number of days since a certain date. To add days to a date, you can simply add the numbers together.
Sub TimeModule()
Dim lDaysLeft As Long
Dim lHoursLeft As Long
Dim lMinutesLeft As Double
Dim dtCurrent As Date
lDaysLeft = Val(InputBox("Days left"))
lHoursLeft = Val(InputBox("Hours left"))
lMinutesLeft = Val(InputBox("Minutes left"))
dtCurrent = Now()
ActiveCell.Value = dtCurrent
ActiveCell.Offset(0, 1).Value = dtCurrent + lDaysLeft + TimeSerial(lHoursLeft, lMinutesLeft, 0)
End Sub

Related

How to count emails within an hourly range?

My team uses outlook to track completed work. All work needs to be completed within 48 hours of receipt and we need to keep strict track of it. I've managed to put together a function that counts the emails that have fallen outside of the 2 day range, but the track needs to be kept down to an hour.
No matter how many configurations I try I was unable to get my code to count within hourly range. This is what my current code looks like:
Dim OOSLAitms As Outlook.Items
Dim DateDiff As Long
Dim Filter As String
Dim i As Long
DateDiff = Now - 2
Filter = "[Received] < '" & Day(DateDiff) & _
"/" & Month(DateDiff) & _
"/" & Year(DateDiff) & "'"
Set OOSLAitms = itms.Restrict("[FlagStatus] = 0")
Set OOSLAitms = OOSLAitms.Restrict(Filter)
For i = OOSLAitms.Count To 1 Step -1
Worksheets("Sheet1").Range("F4").Value = OOSLAitms.Count
Next
This manages to count all the emails received within the calendar day, but does not take hours of the day into account. So for example if we received 300 cases on Sunday, it will count all of them up to midnight, instead of only counting ones up to current time (4pm for example).
I need help incorporating hour/minutes criteria into my code on top of day/month/year if it's possible.
There is no Received property, you must use the ReceivedTime instead.
And if you need to get hourly range only, you must specify boundaries for the search criteria:
Dim searchCriteria As String = "[ReceivedTime]<=""" + dateTimeEnd + """ AND [ReceivedTime]>=""" + dateTimeStart + """"
Okay after playing around with it some more (and a generous amount of debug messageboxes) I've managed to get it to work using the following trick:
Created an output cell 'A11' on the first sheet running a =NOW() function formatted to "ddd dd/mm/yyyy hh:mm"
Created a cell 'A1' on the processing sheet that was running 'Sheet1!A11 - 2' formula. The reason why is that for some reason when doing 'Now - 2' through VBA, even with formatting it was always giving midnight. Doing it through autocalc in cells gives correct deduction down to a second.
The reason for formatting "dd dd/mm/yyyy hh:mm" is that this is the format that the "Received" column in outlook stores the receive times. Not providing that 'ddd' in front of the datetime string results in an automation error.
Final code looks like this:
Dim OOSLAitms As Outlook.Items
Dim DateDiff As Long
Dim Filter As String
Dim Today As String
Today = Format(ThisWorkbook.Sheets("Sheet2").Range("A1"), "ddd dd/mm/yyyy hh:mm")
Filter = "[Received]" & "<" & Today
Set OOSLAitms = itms.Restrict("[FlagStatus] = 0")
Set OOSLAitms = OOSLAitms.Restrict(Filter)
Worksheets("Sheet1").Range("F4").Value = OOSLAitms.Count

Excel Formula - Comparing Range of Date

how to write EXCEL VBA to make my date from 04/JUNE > 04/JUNE 23:59. i cannot use the '= date + 5/6' as i have to run the VBA many times a day and it will add my dates to tomorrow/ the day after tomorrow. i just wanna make the date to end of date. please help.
The example will be like
CELL A1 : 12/June
CELL B1 : 15/June
CELL C1 : 15/June 12:00 HRS
CELL D1 : =IF C1B2, “OUT OF RANGE”, “Okay !”)
in this case D1 will still display OUT OF RANGE.
I have loads of such to change so I was thinking of writing a VBA to automatically convert C1 from 15/JUNE -> 15/JUNE 23:59 , so that D1 will display Okay !
I tried Cdate(Range(“D1”)) + 5/6 in vba to make it 23:00 hrs and I run this macro a few times in a day and it will keep adding 23hrs to the date and made it change to another date.
About what you are talking?
About:
- "Excel Formula" or
- "EXCEL VBA"
?
About:
- "Comparing Range of Date" or
- "to make my date"
?
Assume, that VBA is...
The Date type in VBA is Double, where:
- Integer part as quantity of days from... (look F1), and
- Fractional part of day.
So, your desired "04/JUNE > 04/JUNE 23:59" will:
? DateSerial(2018, 06, 4) + ((23& * 60& * 60&) + (59& * 60&)) / 86400&
18-06-04 23:59:00
Yeah, sure, you can use TimeSerialinstead of above, but ... it didn't give you right understanding of VBA dates.
.
----------
ADD:
Sorry but will this code only work for one cell because I have lots of
cells with dates and I need VBA to extract them out and convert to
23:59 for eg I run a for loop to change like 20 cells in a row with
multiple range. And I will run the macro a few times in a day will it
add 23hrs to that date every time and cause it to change dates ?
Public Sub sp_Test_Date()
Dim rSel As Range
Dim i&
Const H23M59 As Double = 1 - 60 / 86400
Set rSel = Selection
With rSel
For i = 1 To .Cells.Count
With .Cells(i)
If IsDate(.Value) Then
.Offset(0, 1).Value = CDate(Int(.Value) + H23M59)
End If
End With ' .Cells(i)
Next
End With ' rSel
End Sub
i tried modifying it to below and it failed me :(
`
Dim x As Integer
Dim test1 As Date
Dim schdWS, compWS As Worksheet
Const H23M59 As Double = 1 - 60 / 86400
Set schdWS = Sheet1
Set compWS = Sheet11
lastrow = schdWS.Cells(Rows.Count, 8).End(xlUp).Row
For x = 20 To lastrow
If IsDate(schdWS.Cells(x, 3).Value) Then
Cells(x, 3).Value = CDate(Int(Cells(x, 3).Value + H23M59))
End If
'test1.NumberFormat = "dd/mm/yyyy"
'schdWS.Cells(x, 3).FormulaR1C1 = test1 & " 23:59"
Next x
End Sub
`

Find dates that fall within Monday-Sunday work week

I currently have a program that finds dates within a table and compares them to a date range and uses them for something else. What I've been using for a week to compare against has been saying Date + 7, but I want to just take the dates of the current week from Monday-Sunday and use that as the Date range.
I think the way to go would be to use the current WeekNum and find the dates of the Monday and Sunday from there, but I honestly have no idea how to begin to do this from VBA. I would appreciate if anyone had a direction to send me in to accomplish this, or if I'm even thinking about this the right way.
Here is an easy way to get the Monday & following Sunday of the current week:
Sub getadate()
Dim N As Long
N = Weekday(Date)
d1 = Date - N + 2
d2 = d1 + 6
MsgBox d1 & vbCrLf & d2
End Sub
You can use the weekday formula to determine the start and end of the week. The formula would look as such:
startWeek = Date - (Weekday(Date, vbMonday) - 1)
and
endWeek = Date + (7 - Weekday(Date, vbMonday))
Let me know if this works

VBA Convert and combine date and time

I am new to VBA and am working an a macro that will help me transform call records into something useful for analysis.
Column E contains the Date of Call which is formatted YYYYMMDD. I need to convert to MM/DD/YYYY. (i.e. 20140101 convert to 1/1/2014)
Column F contains the Time of Call which is formatted HHMMSS or HMMSS depending on whether the hour has two digits or one. I need to convert to HH:MM:SS (i.e. 130101 or 90101 which needs to convert to 13:01:01 and 9:01:01, respectively). Because the hour is missing the tens digit if the value is below ten, (below) I have added a "0" to the beginning of the value so I can use the date function.
I currently enter the the following formula in Column K and autofill until the end of the range:
=DATE(LEFT(E2,4),MID(E2,5,2),RIGHT(E2,2))+TIME(LEFT(IF(LEN(F2)=5, 0&F2, F2),2),MID(IF(LEN(F2)=5, 0&F2, F2),3,2),RIGHT(IF(LEN(F2)=5, 0&F2, F2),2))
The formula results in a value like "1/1/2013 13:01:01".
Can someone help me write the VBA code to automate this process?
Thank you.
Created separate UDFs for this. Paste the following into a module.
Function MorphDate(DateRng As Range)
Dim DateStr As String: DateStr = DateRng.Value
Dim Yr As String, Mt As String, Dy As String
Yr = Left(DateStr, 4)
Mt = Mid(DateStr, 5, 2)
Dy = Right(DateStr, 2)
MorphDate = Format(DateSerial(Yr, Mt, Dy), "m/dd/yyyy")
End Function
Function MorphTime(TimeRng As Range)
Dim TimeStr As String: TimeStr = TimeRng.Value
Dim Hh As String, Mm As String, Ss As String
If Len(TimeStr) = 5 Then TimeStr = "0" & TimeStr
Hh = Left(TimeStr, 2)
Mm = Mid(TimeStr, 3, 2)
Ss = Right(TimeStr, 2)
MorphTime = Format(TimeSerial(Hh, Mm, Ss), "hh:mm:ss")
End Function
Function MorphDateTime(DateRng As Range, TimeRng As Range)
Application.Volatile
MorphDateTime = CDate(MorphDate(DateRng)) + CDate(MorphTime(TimeRng))
End Function
Now you can use the formulas MorphDate to change the date, MorphTime to change the time, and MorphDateTime for a combination of both.
Screenshot:
Let us know if this helps.
EDIT:
If you want to use it inside a subroutine, add the following code to the module:
Sub MorphingTime()
Dim DateRng As Range, Cell As Range
Set DateRng = Range("E2:E100") '--Modify as needed.
For Each Cell in DateRng
Range("K" & Cell.Row).Value = MorphDateTime(Cell, Cell.Offset(0,1))
Next Cell
End Sub
Hope this helps.

VBA Excel - Equal dates do not evaluate as equal

MS Excel Professional Plus v14 on Win7.
I am having trouble comparing equality for date/times.
Two dates that appear to be equal, 12/16/2013 12:19:33 pm are both dimensioned as dates. One is in a date array, the other is a date variable. arrPP is ReDim'ed later. When I do DateDiff("s",date1,date2) it yields 0.
Dim arrPP() As Date ' During runtime shows type is Date(1 to 2, 1 to 1)
Dim dNextStartTime as Date
'...code removed ...
If arrPP(iPP_START, lPP_index) <= dNextStartTime Then
GoTo PP_OUT
End If
Even though they are equal, the above evaluates to false and the wrong path is taken. This was hard to track down and causes unexpected/wrong results.
Is there an offical "gotcha" regarding date equality? Are there hidden milliseconds that need to be compared, or a way to limit the comparison down to the seconds level?
I have tried several other alternatives including placing CDate in front of the array element.
FAIL:
If Not(arrPP(iPP_START, lPP_index) > dNextStartTime) Then
GoTo PP_OUT
End If
PASS: (But who would think to do this?)
If arrPP(iPP_START, lPP_index) <= dNextStartTime Or _
DateDiff("s",arrPP(iPP_START,lPP_index),dNextStartTime) = 0 Then
GoTo PP_OUT
End If
This is most likely due to floating point precission issues. Dates are stored as double precission floats, where the integer part is date and fractional part is time.
To test if arrPP(iPP_START,lPP_index) is before dNextStartTime it's probably best to use
If DateDiff("s",dNextStartTime,arrPP(iPP_START,lPP_index)) <= 0 Then
Note that DateDiff returns possitive when the first date parameter is earlier than the second.
To demonstrate how two apparently equal dates may not be equal, try running this
Sub demo()
Dim d1 As Date, d2 As Date
d1 = #12/17/1986 12:19:33 PM#
d2 = #12/17/1986#
d2 = d2 + 12# / 24# ' Add 12 hour
d2 = d2 + 19# / 60# / 24# ' Add 19 minutes
d2 = d2 + 33# / 60# / 60# / 24# ' Add 33 seconds
Debug.Print d1; d2
Debug.Print d1 = d2
Debug.Print d1 - d2
End Sub
Immediate window output
17/12/1986 12:19:33 p.m. 17/12/1986 12:19:33 p.m.
False
3.63797880709171E-12
VBA Excel - Equal dates do not evaluate as equal
It works for me.
I guess it boils down to how are you storing the date in the date variable or the date array. How are you populating the dates?
Here is the test that I did. Let me know if I have misunderstood your query.
Sub Sample()
Dim dt As Date
Dim MyAr(1, 1) As Date
dt = #12/16/2013 12:19:33 PM#
MyAr(1, 1) = #12/16/2013 12:19:33 PM#
If (MyAr(1, 1) > dt) Then
MsgBox "MyAr is greater"
ElseIf (MyAr(1, 1) < dt) Then
MsgBox "MyAr is lesser"
Else
MsgBox "They are equal" '<~~ This is what I get
Debug.Print DateDiff("s", MyAr(1, 1), dt)
End If
End Sub
Most likely you don't need an answer after so many years but if anybody will join this question maybe it will be useful.
Function DateEqual(date1 As Date, date2 As Date) As Boolean
'use should never compare as equal dates or any double values but if you really need to do it carefully use this function.
'converting to integers to test if they are equal. if you need to test time values recorded with less then 1second DO NOT USE THIS FUNCTION.
Dim day1, day2 As Date
Dim time1, time2 As Date
day1 = Int(date1)
day2 = Int(date2)
If day1 = day2 Then
If Hour(date1) = Hour(date2) And Minute(date1) = Minute(date2) And Second(date1) = Second(date2) Then
DateEqual = True: Exit Function
Else
DateEqual = False: Exit Function
End If
Else
DateEqual = False: Exit Function
End If
End Function

Resources