VBA Convert date to string - vba

I have tried the following but not working,
Dim my_date_string As String
Dim my_date_date As Date
my_date_string = "22.10.2020"
my_date_date = CDate(my_date_string)
Debug.Print my_date_string
Debug.Print my_date_date
Also tried with,
my_date_date = Format(my_date_string, "DD.MM.YYYY")

CDate does not understand periods as separators.
If you need them to be periods in your String variable for some reason, just replace them like this:
my_date_date = CDate(Replace(my_date_string, ".", "/"))
If your variable does not have periods in it, the Replace function will simply do nothing.

Related

Extracting Date/Time from comment cell

I have a comment field with cells containing text like this:
Cancelled by user at 2018-01-03 03:11:57 without charge
I want to get the date and time information, but it may not always be in the 3rd/4th from last spaces, otherwise I might try to do some sort of complicated split of the cell. Is there an "in cell" way extract the date time information? Or will this need a VBA script? I prefer the former, but I'm trying to make a macro to simplify my life anyway, so VBA would work too.
I'd propose the following formula:
=MID(A1,FIND("at 20",A1)+3,19)
This would require that the date is always preceded by the word 'at' and the date string starts with 20.
You can try this function. It splits the string checking for items that have the first letter numeric, and builds a result string of just the date information.
Public Function ParseForDate(sCell As String) As String
Dim vSplit As Variant
Dim nIndex As Integer
Dim sResult As String
vSplit = Split(sCell, " ")
For nIndex = 0 To UBound(vSplit)
If IsNumeric(Left$(vSplit(nIndex), 1)) Then
sResult = sResult & vSplit(nIndex) & " "
End If
Next
ParseForDate = Trim$(sResult)
End Function
If you wanted to use it in a formula it would look something like this:
=ParseForDate(A1)
To use it in a VBA routine:
Dim s as String
s = ParseForDate(Range("A1"))
Non-VBA solution: (this is assuming the date format is always the same for all cells)
= MAX(IFERROR(DATEVALUE(MID(A1,ROW(INDEX($A:$A,1):INDEX($A:$A,LEN(A1)-19)),20)),0))
+MAX(IFERROR(TIMEVALUE(MID(A1,ROW(INDEX($A:$A,1):INDEX($A:$A,LEN(A1)-19)),20)),0))
Note this is an array formula, so you must press Ctrl+Shift+Enter instead of just Enter when typing this formula.
You will obviously then need to format the cell as a date and time, but this formula gets the numerical value that Excel uses for its internal date and time system.
Using a regex will enable you to fetch the date and time, irrespective of its placement in the string. The following solution will work if the date and time are of the same format as shown in the example string.
Code:
Sub getDateTime()
Dim objReg, matches, str
str = Sheet1.Cells(1, 1).Value 'Change this as per your requirements
Set objReg = CreateObject("vbscript.regexp")
objReg.Global = True
objReg.Pattern = "\d{4}(?:-\d{2}){2}\s*\d{2}(?::\d{2}){2}"
If objReg.test(str) Then
Set matches = objReg.Execute(str)
strResult = matches.Item(0)
MsgBox strResult
End If
End Sub
Click for Regex Demo
Regex Explanation:
\d{4} - matches 4 digits representing the year
(?:-\d{2}){2} - matches - followed by 2 digits. {2} in the end repeats this match 2 times. Once for getting MM and the next time for DD
\s* - matches 0+ whitespaces to match the space between the Date and Time
\d{2} - matches 2 digits representing the HH
(?::\d{2}){2} - matches : followed by 2 digits. The {2} in the end repeats this match 2 times. First time for matching the :MM and the next time for matching the :SS
Screenshots:
Output:
This will be good for about 90 years (using cell C3 for example):
Sub GetDate()
Dim s As String
s = Range("C3").Comment.Text
arr = Split(s, " ")
For i = LBound(arr) To UBound(arr)
If Left(arr(i), 2) = "20" Then
msg = arr(i) & " " & arr(i + 1)
MsgBox msg
Exit Sub
End If
Next i
End Sub

Index and length should refer to a location within the sequence

I need to break a variable to get the value of the database. Today my full return would be "2017-09-15T14: 01: 46" I only need 2017-09-15 and 14:01, I tried to do
.Substring (0.10) for the date and worked, already for the time I tried Substring (11,16) and the error that is in the title of the question occurs.
Assuming you always have the capital T in your result string
dim xValue as string = "2017-09-15T14: 01: 46"
dim xStr() as string = xValue.split("T")
dim xDate as string = ""
dim xTime as string = ""
if xstr.count>0 then
xDate = xStr(0)
xTime = xStr(1)
end if
or
dim xValue as string = "2017-09-15T14: 01: 46"
dim xDate as string = strings.left(xValue, 10)
dim xTime as string = strings.mid(xValue, 12)
So with VB.NET, you can use the DateTime method. From the DateTime, you can do something like DateTime.Date or DateTime.ToShortDateString for just the date and DateTime.ToShortTimeString for the time.
Your arguments to the function Substring are wrong.
The second argument to the function Substring (in your case 16) needs to be the amount of letters that the function will return and NOT the index it needs to end in.
It will work with something like Substring(11, 5), where the 5 is the length of the returned substring.
Dim temp_date As String = "2017-09-15T14: 01: 46"
Dim main_date As String = temp_date.Substring(0, 10)
Dim main_time As String = temp_date.Substring(11, 6)
OR
a better approach using the datetime object proposed by AustinS90 (this will support alot of time formatted strings):
Dim temp_date As DateTime = DateTime.Parse("2017-09-15T14: 01: 46")
Dim main_date As String = temp_date.Year() & "-" & temp_date.Month() & "-" & temp_date.Day
Dim main_time As String = temp_date.Hour & ":" & temp_date.Minute

Visual basic date object parsing from string with indexing

I would like to ask if in VBA there is a built in function which will parse a date object from a string based on a specified format.
For example:
dateString = "24-4-12"
VBADateFunc(dateString, "dd-m-yy")
to return a date object interpreting the dateString string by the provided format.
I will appretiate your ideas on this.
Thank you
Here you go:
Public Sub TestMe()
Dim dtMyDate As Date
dtMyDate = Format("24-4-12", "dd-mm-yy")
Debug.Print dtMyDate
Debug.Print Format(dtMyDate, "yyyy")
Debug.Print Format(dtMyDate, "dd-mmm-yy")
'For Non-Europeans:
dtMyDate = Format(DateSerial(2012, 4, 24), "dd-mm-yy")
Debug.Print dtMyDate
Debug.Print Format(dtMyDate, "yyyy")
Debug.Print Format(dtMyDate, "dd-mmm-yy")
End Sub
From the comments - in general, the date is a long value in MS Excel and VBA. Today's date can be seen like this in the immediate window:
?clng(now)
42935
If you want to do further something with the 42935 value, you may go like this:
?Format(42934,"dd-mm-yyyy")
Note: Today is 42934 for all those, who have ActiveWorkbook.Date1904 = False. For those, who are starting the calendar with 1904, today is 42935-4*365-1
I ended up writing my own function to scan a date. Leaving out error handling:
Function ScanDate(s As String, Optional order As String = "DMY", Optional separator As String = "-") As Date
Dim parts() As String
parts = Split(s, separator)
Dim day As Long, month As Long, year As Long
day = parts(InStr(order, "D") - 1)
month = parts(InStr(order, "M") - 1)
year = parts(InStr(order, "Y") - 1)
ScanDate = DateSerial(year, month, day)
End Function

Search for the character & rather than the converted & in mailItem.HTMLBody

I have a function which finds a string between to given strings. Here is an example:
midReturn("?sender=", "&to=", mailItem.HTMLBody)
The above should get the string between ?sender and &to but the & is converted to &.
Is there a way i can look for both occurrences? I did a statement to check this but it doesn't work:
Dim from = midReturn("?sender=", "&to=", mailItem.HTMLBody)
If from < 1 Then
from = midReturn("?sender=", "&to=", mailItem.HTMLBody)
End If

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#