Comparing dates with different date format in system - vba

I need to compare two Dates. They are in text format and they look like 30.05.2016, because they are extracted from other program.
The problem is that on one system I got different date formatting (5/30/2016), than on another (30/5/2016).
I would like to know whether my thinking is in right direction, if not what should I do.
Firstly I will check which formatting do I have.
If (5/30/2016) then I will do
1. Replace "." to "/"
2. CDate(value)
3. NumberFormat = "General"
4. Comparing date1 < date2
If (30/5/2016) then I will do
1. DateValue(Replace "." to "/")
2. NumberFormat = "General"
3. Comparing date1 < date2
I am still thinking how to write this code, and your help on this stage would be nice.

This assumes that the date are actually in Text format. The first UDF() handles US-style dates:
Public Function IsD1LessThanD2(d1 As String, d2 As String) As Boolean
' US Date format
IsD1LessThanD2 = CDate(Replace(d1, ".", "/")) < CDate(Replace(d2, ".", "/"))
End Function
The second UDF() handles European format:
Public Function IsD1LessThanD2_E(d1 As String, d2 As String) As Boolean
' European Date format
ary1 = Split(d1, ".")
ary2 = Split(d2, ".")
d1 = DateValue(ary1(1) & "/" & ary1(0) & "/" & ary1(2))
d2 = DateValue(ary2(1) & "/" & ary2(0) & "/" & ary2(2))
IsD1LessThanD2_E = d1 < d2
End Function

You can format both strings to the Date format
Dim date1, date2 As Date
' string1 in the format 5/30/2016
date1 = Format(string1, "mm/dd/yyyy")
' string2 in the format 30/5/2016
date2 = Format(string2, "dd/mm/yyyy")
And then you can simply compare the dates.

Related

Read the correct week number from a calendar date

I have below dates in an Excel column, as you can see.
Sprint 1 takes from 10.04 to 21.04 this means 2 weeks and between brackets they are specified week 15 and 16 which is correct but for Sprint 2, who also starts in 10.04 but takes until 05.05 it means 7 weeks, but are displayed also the weeks from the Sprint1.
"Sprint1 (CW15-16/2017)
[10.04.2017 - 21.04.2017]
Sprint2 (CW15-16/2017)
[10.04.2017 - 05.05.2017]"
What I have until now is:
'reading the first CW of the sprint based on the date
SprintFristCW = Left(planning_wb.Worksheets(SprintPlanningTable).Cells(2, i + 1).Value, 9)
'reading the last CW of the Sprint based on the date
SprintEndCW = Right(planning_wb.Worksheets(SprintPlanningTable).Cells(2, i + Sprintlength).Value, 9)
SprintCW = Left(SprintFirstCW, 4) & "-" & Right(SprintEndCW, 7)
But SprintEndCW is not reading correct the week number.
So I need to read the correct week number in which each sprint ends and print it.
Don't create huge procedures. Small is beautiful. Create functions that feed into your Main procedure. Here is an example. The procedure TestExtraction calls the function ExtractWeeks. Therefore ExtractWeeks needs not be part of the procedure that calls it, making the code easier to understand and maintain.
Private Sub TestExtraction()
Dim Fun As Long
Dim DateString As String
Dim StartDate As Date, EndDate As Date
DateString = ActiveCell.Value
' the DateString is re-defined here for testing purposes
DateString = "[10.04.2017 - 05.05.2017]"
Fun = ExtractWeeks(DateString, StartDate, EndDate)
If Fun < 0 Then
Debug.Print "Invalid date"
Else
With Application
DateString = "(CW" & .WeekNum(StartDate)
If Year(StartDate) <> Year(EndDate) Then _
DateString = DateString & "/" & Year(StartDate)
DateString = DateString & " - " & .WeekNum(EndDate) & "/" & Year(EndDate) & ")"
End With
Debug.Print DateString
Debug.Print Fun & " weeks"
End If
End Sub
Private Function ExtractWeeks(ByVal DateString As String, _
StartDate As Date, _
EndDate As Date) As Long
' 24 Oct 2017
' return the number of weeks between dates (rounded up)
' return -1 if one of the dates is unreadable
Dim Dates() As String
Dim i As Integer
Dates = Split(Mid(DateString, 2, Len(DateString) - 2), "-")
On Error Resume Next
For i = 0 To 1
Dates(i) = Replace(Trim(Dates(i)), ".", Application.International(xlDateSeparator))
Next i
StartDate = DateValue(Dates(0))
EndDate = DateValue(Dates(1))
If Err Then
ExtractWeeks = -1
Else
ExtractWeeks = Int((StartDate - EndDate) / 7) * -1
End If
End Function
The point is that not everything that looks like a date is a date Excel can understand. The Function ExtractWeeks converts the "dates' from your worksheet into real dates and returns these dates to the calling procedure. It also returns -1 in case of error which you can use to trap such errors. In my example, the function returns the number of weeks (or -1). You might let it return the CW string my calling procedure constructs. You will find it easy to move the process of constructing that string to the function and let the function return "" in case of error instead of -1. Perhaps you can exclude the possibility of errors in the dates. This is a question of how you integrate the function into your Main.

VBA - Checking date string validity

I have a string in the following format in Excel.
07/12/2015 08:00 - 08/12/2015 09:00
I want to check if the current date fits between the two (these dates are validity dates, meaning I have to check if the current date is bigger than the first date and smaller than the second date).
I sometimes also have this string without hours, so like:
07/12/2015 - 08/12/2015
so I have to check that as well (just without the hours).
I split the dates using the Split function to split by the "-" character. However, I'm not sure how to do the check because I've never worked with dates.
Can anyone show me how to do this? It seems that it'd be complicated with the check for the hours.
You can try this :
Dim mydate as String, splitdate as Variant
mydate = "07/12/2015 08:00 - 08/12/2015 09:00"
splitdate = Split(mydate, "-")
If Date < splitdate(0) And Date > splitdate(1) Then MsgBox "Is Between"
In case there will be some issues with understanding date formats, you can still use Cdate function -
If Date < CDate(splitdate(0)) ...
Assuming, that you String is located in A1, and the Date you want to check for is in B1, then put this formula in C1:
=IF(AND(B1>=DATEVALUE(LEFT(A1,10)),B1<=DATEVALUE(MID(A1,FIND("-",A1)+2,10))),TRUE,FALSE)
This works for both cases, if you are only interested if the date lies between the dates (thus excluding the time).
Use cdate function. You wrote you already used the split function, so all you need to do is put the separate date strings into date variables using cdate ('c' stands for cast).
So
Dim d1 as Date
Dim d2 as Date
d1 = CDate(splitstring(0))
d2 = CDate(splitstring(1))
Then you can check the given date.
With the CDate() conversion function and Trim (to get rid of useless spaces), here is a boolean function that you can easily use to test if you are in the time lapse described by your string.
Here is how to use it :
Sub test_Gilbert_Williams()
Dim TpStr As String
TpStr = "08/12/2015 08:00 - 08/12/2015 09:00"
'TpStr = "07/12/2015 - 08/12/2015"
MsgBox Test_Now_Date_Validity(TpStr)
End Sub
And the function :
Public Function Test_Now_Date_Validity(Date_Lapse As String) As Boolean
Dim A() As String, _
Date1 As Date, _
Date2 As Date
If InStr(1, Date_Lapse, "-") Then
A = Split(Date_Lapse, "-")
Debug.Print Trim(A(0)) & " " & CDate(Trim(A(0)))
Debug.Print Trim(A(1)) & " " & CDate(Trim(A(1)))
If CDate(A(0)) > CDate(A(1)) Then
Date1 = CDate(A(1))
Date2 = CDate(A(0))
Else
Date1 = CDate(A(0))
Date2 = CDate(A(1))
End If
If Now > Date1 And Now < Date2 Then
Test_Now_Date_Validity = True
Else
Test_Now_Date_Validity = False
End If
Else
Exit Function
End If
End Function

How can I convert a long date with time to a different format in VBA?

I have data for a date that looks like this: "2015-02-11T19:41:50-08:00"
I would like to know if there is already a function that exists in VBA which can convert the above data to the format of something like "02/11/2015 11:41 AM PST"
I attempted the following code playing around with the format function but was unable to get VBA to recognize the format as a date:
testdate = "2015-02-12T22:57:05-08:00"
newdate = Format(testdate, "mm/dd/yyyy hh/nn/ss AM/PM")
Debug.Print newdate
The output was still "2015-02-12T22:57:05-08:00"
Thanks for the help.
Edit:
I was able to resolve the problem by taking your suggestions to use the mid() function since the dates are in fixed format. I decided to keep the military time in the final version.
Here is my code for anyone curious:
Function convertDate(orderdate)
'takes the date formatted as 2015-02-06T08:26:00-08:00
'and converts it to mm/dd/yyyy hh/nn/ss UTC format
'2015-02-06T08:26:00-08:00
orderyear = Mid(orderdate, 1, 4)
ordermonth = Mid(orderdate, 6, 2)
orderday = Mid(orderdate, 9, 2)
orderhour = Mid(orderdate, 12, 2)
orderminute = Mid(orderdate, 15, 2)
ordersecond = Mid(orderdate, 18, 2)
newdate = ordermonth & "/" & orderday & "/" & orderyear
newtime = orderhour & ":" & orderminute & ":" & ordersecond
'Debug.Print newdate
convertDate = newdate & " " & newtime & " UTC"
End Function
Because your input isn't a true date none of Excel or VBA's date methods will work with it. Your best bet is to break the string down into parts, work with them individually, and then join it all back up again - for example:
testdate = "2015-02-12T22:57:05-08:00"
'// The letter T is redundant, so let's split the string here into an array:
dateArr = Split(testdate, "T")
'// Part 1 of the array can be easily converted with CDate() and Format()
dateArr(0) = Format(CDate(dateArr(0)), "mm/dd/yyyy")
'// Part 2 of the array will need to be broken down further:
dateArr(1) = Format(TimeValue(Split(dateArr(1), "-")(0)) - _
TimeSerial(Left(Split(dateArr(1), "-")(1), 2), _
Right(Split(dateArr(1), "-")(1), 2), 0), "hh:mm:ss")
'// The above line does the following:
'// 1) Split the second part of the array again, using the "-" as the delimiter
'// 2) Convert the first part of this (22:57:05) to a time using TimeValue()
'// 3) Convert the second part (08:00) to hours & minutes using TimeSerial()
'// 4) Minus the latter from the former (which can only be done if both are a valid time)
'// 5) Wrap all that into a Format() method to show "hh:mm:ss" instead of a Double.
'// Join the two parts back together and add "PST" on the end.
newdate = Join(dateArr, " ") & " PST"
Debug.Print newdate
'// Output will display "02/12/2015 14:57:05 PST"
N.B. I have chosen not to include "AM" or "PM" because your time is in 24hr format anyway so I don't see the relevance...
It's not converting because of the "T" and because of the tacked on time range at the end. You can ditch the "T" and truncate off the trailing range and it will convert.
Public Sub Example()
Const testValue As String = "2015-02-12T22:57:05-08:00"
Dim dateValue As Date
Dim stringValue As String
Dim subVal As Date
Dim hyphenPos As Long
stringValue = testValue
Mid(stringValue, 11&, 1&) = " "
hyphenPos = InStrRev(stringValue, "-")
subVal = Mid$(stringValue, hyphenPos + 1&)
dateValue = CDate(Left$(stringValue, hyphenPos - 1&)) - subVal
End Sub
Couple of ideas:
The sample date you have 2015-02-12T22:57:05-08:00 is not a real date (I think)
I think the following will give you the closest format to what you are looking for (you will need to define the range.Range.NumberFormat = "[$-409]h:mm:ss AM/PM"
Your best bet is concating "PST" to a date datatype formatted to your needs.
Sub DebugPrintDate()
Dim testdate As Date: testdate = Now
newdate = Format(testdate, "mmm/dd/yyyy hh:mm AM/PM") & " PST"
Debug.Print newdate
End Sub
Ouput:
Never mind the "févr". My system locale is France.
If you want to define a particular date, make sure to wrap the date in two #s.
Example:
Dim someDateAndTime As Date = #8/13/2002 12:14 PM#

query in Vba using cdate function with variable

Using the following query in microsoft access sql view works nice and easy with a hard coded date
SELECT Salary.First, Salary.Last,FROM Salary, allowances
WHERE Salary.PayThroughDate = CDate("2014-05-06") AND Salary.SSN = allowances.SSN
but embedding this query in Vba using a variable instead of a hard coded date is another business. It is just not working:
Dim ddate As Variant
Dim getDay As Integer
Dim getMonth As Integer
Dim getYear As Integer
getDay = Day(Me.DTPicker2.Value)
getMonth = Month(Me.DTPicker2.Value)
getYear = Year(Me.DTPicker2.Value)
ddate = getDay & "/" & getMonth & "/" & getYear
ddate = Format(ddate, "dd/mm/yyyy")
query1 = "SELECT Salary.First, Salary.Last FROM Salary, allowances WHERE Salary.PayThroughDate = " & CDate(ddate) & " AND Salary.SSN =
allowances.SSN
Any ideas in this Vba Sql mix? Am I missing single or double quotes?
When you send the SQL directly to JET and not running it from the normal user-interface of MS Access, you will need to make the date-format in the American format. I have had this problem a lot long time ago, but solved it by using this function to format my date in to text, the way that JET expects it to be:
Function SQLDate(varDate As Date) As String
'---------------------------------------------------------------------------------------
'Purpose Formats a date in the american way so that it can be used in
' SQL (by the JET-engine)
'Accepts varDate - the date that should be converted to text
'Returns The date converted to text, in american format with both the day and
' the month using 2 characters. (01 is january)
'---------------------------------------------------------------------------------------
'Changelog
'HANY 20100407: Stopped using the FORMAT-function for the date-value, as I found some
' cases where the format did not return the date as specified.
'---------------------------------------------------------------------------------------
'SQLDate = "#" & Format$(varDate, "mm\/dd\/yyyy") & "#"
SQLDate = "#" & Format(Month(varDate), "00") & "/" & Format(Day(varDate), "00") & "/" & Format(Year(varDate), "0000") & "#"
End Function
In your example above, you now add the date like this & SQLDate(CDate(ddate)) & instead of & CDate(ddate) &
The equivilant query is:
query1 = "SELECT Salary.First, Salary.Last
FROM Salary, allowances
WHERE (Salary.PayThroughDate =Cdate(" & ddate & ") )
AND (Salary.SSN = allowances.SSN)"
The problem you had is that when you constructed the sql string, the cdate value was converted into a string value first. It was just the same as
WHERE (Salary.PayThroughDate =" & format(ddate,"general date") & ")
If you do the cdate conversion later it works. Another almost equivilant query is
...
WHERE Salary.PayThroughDate =#" & ddate & "#
...
Both Cdate and the # tags take a string date, and convert to a date type (using slightly different rules). Since a date type is actually stored as the integer part of a double, you can also do:
WHERE Salary.PayThroughDate =cdbl(#" & ddate & "#)
or
WHERE Salary.PayThroughDate =clng(#" & ddate & "#)
or
WHERE Salary.PayThroughDate =" & clng(cdate(ddate) & "
--the number will be converted into a string to be part of the sql string, but numbers work correctly in SQL: they don't need to have # tags or conversion functions to make them work.
but you started out with a date value:
v =Me.DTPicker2.Value
so you can convert that directly to a number without converting it to a string first:
d = clng(Me.DTPicker2.Value)
...
WHERE (Salary.PayThroughDate = " & d & ")
which is the fastest and least error prone of handling dates in Access/VBA, but comes undone when you start working with SQL server, which stores dates differently.
Also, I see that you correctly used ISO date format when constructing your test example, but switched to American date format when constructing a string from the date value. That was a mistake. To avoid errors and 'evil date guessing' in SQL, you should stick to the ISO format:
v =Me.DTPicker2.Value
sdate = format(v,"yyyy-mm-dd")

Display date in dd/mm/yyyy format in vb.net

I want to display date in 09/07/2013 format instead of 09-jul-13.
Dim dt As Date = Date.Today
MsgBox(dt)
First, uppercase MM are months and lowercase mm are minutes.
You have to pass CultureInfo.InvariantCulture to ToString to ensure that / as date separator is used since it would normally be replaced with the current culture's date separator:
MsgBox(dt.ToString("dd/MM/yyyy", CultureInfo.InvariantCulture))
Another option is to escape that custom format specifier by embedding the / within ':
dt.ToString("dd'/'MM'/'yyyy")
MSDN: The "/" Custom Format Specifier:
The "/" custom format specifier represents the date separator, which
is used to differentiate years, months, and days. The appropriate
localized date separator is retrieved from the
DateTimeFormatInfo.DateSeparator property of the current or specified
culture.
Try this.
var dateAsString = DateTime.Now.ToString("dd/MM/yyyy");
// dateAsString = "09/07/2013"
and also check this link for more formatting data and time
Like this ..
MsgBox(format(dt,"dd/MM/yyyy"))
You could decompose the date into it's constituent parts and then concatenate them together like this:
MsgBox(Now.Day & "/" & Now.Month & "/" & Now.Year)
Dim formattedDate As String = Date.Today.ToString("dd/MM/yyyy")
Check link below
I found this catered for dates in 21st Century that could be entered as dd/mm or dd/mm/yy. It is intended to print an attendance register and asks for the meeting date to start with.
Sub Print_Register()
Dim MeetingDate, Answer
Sheets("Register").Select
Range("A1").Select
GetDate:
MeetingDate = DateValue(InputBox("Enter the date of the meeting." & Chr(13) & _
"Note Format" & Chr(13) & "Format DD/MM/YY or DD/MM", "Meeting Date", , 10000, 10000))
If MeetingDate = "" Then GoTo TheEnd
If MeetingDate < 36526 Then MeetingDate = MeetingDate + 36526
Range("Current_Meeting_Date") = MeetingDate
Answer = MsgBox("Date OK?", 3)
If Answer = 2 Then GoTo TheEnd
If Answer = 7 Then GoTo GetDate
ExecuteExcel4Macro "PRINT(1,,,1,,,,,,,,2,,,TRUE,,FALSE)"
TheEnd:
End Sub
if you want to display date along with time when you export to Excel then you can use this
xlWorkSheet.Cells(nRow, 3).NumberFormat = "dd/mm/yy h:mm AM/PM"