I'm looking for a way to convert strings to Date data type in VBA. I can use CDate() function for this purpose, but it uses its own implicit algorithm for parsing strings and I would like to specify my own format to differentiate between "DD/MM/YY" and "MM/DD/YY", for example.
Please notice that unlike Visual Basic, VBA has no DateTime.TryParseExact function.
ADD: As some answers suggest, I can write my own parser. If there is no built-in solution, it will be my choice.
Do something like this...
strDate = Split(strDate,"/")
newstrDate = strDate(1) & "/" & strDate(0) & "/" & strDate(2)
strDate = CDate(newstrDate)
In this case I would avoid CDate alltogether and instead split the date string into year, month and day and use DateSerial(year, month, day). This way you have full control.
Can you use the below code
Msgbox Format("24/01/2017","MMM, DD, YYYY")
This will give you output as Jan, 24, 2017 . You can use other format which is easily available when you click on the Format cells. Thanks
Related
I have a value like this2015-12-18 11:14:20.72+05:30 and i would like to convert it to yyyy/dd/mm format. I would like to know what format is the date I mentioned above.
Thank you
This appears to be an ISO date with more information than VBA is designed to handle. For example, at the end it appears to have the difference to GMT for the configuration on which it was generated. VBA wasn't designed to work with milliseconds or GMT information - the programming language hasn't been updated for over a decade, except for new objects in the Office applications.
If you cut off the .72+05:30 VBA can work with the rest of the information. For example:
year = DatePart("yyyy", "2015-12-18 11:14:20") 'returns 2015
hour = DatePart("h", "2015-12-18 11:14:20") 'returns 11
You can trim off the end using string manipulation, for example:
sDateInfo = "2015-12-18 11:14:20.72+05:30"
sDateTrimmed = Left(sDateInfo, Instr(sDateInfo, ".")-1)
sDateFormatted = Format(sDateTrimmed, "yyyy/dd/mm")
It seems that VBA could not directly convert this timestamp. What I did is just to get the first 10 characters and then convert it to Date.
Regional settings in Windows are MM/DD/YYYY
Now look at these two lines, and the change in the MONTH:
Sub DateBug()
Debug.Print Format(CDate("11/4/1999"), "MMMM D, YYYY")
Debug.Print Format(CDate("30/4/1999"), "MMMM D, YYYY")
End Sub
OUTPUT:
November 4, 1999
April 30, 1999
Great, huh? What is going on?
In the 2nd line, I want an error, not "guessing".
Is this a bug? Any idea how this can be circumvented ?
Same in Excel 2007, 2010, 2013
Not a bug. VB will convert strings to date literals using the default regional settings, if it can. Which it did in the first date. But on the second date, that would have given an invalid date, so it tried DD/MM/YYYY and that worked. Solution, put use date literals instead of strings. Put # signs around both date literals (ex: '#4/30/1999#') to ignore regional setting and force use of the MM/DD/YYYY format. '#30/4/1999#' would have given you the error you want. This will make your code independent of the regional setting of the computer - ie, it will work regardless. Or else use DateTime(1999, 4, 30, 0, 0, 0). Look here... Date Data Type (Visual Basic)
In Excel, you would use the literal without the single quotes:
Sub Macro1()
Range("D2").Select
ActiveCell.FormulaR1C1 = CDate(#4/30/1999#)
End Sub
This is not a bug, its a "feature"
CDate() will interpret the string according to fixed rules. If the date is valid as m/d/y, that will be returned. If the date is not valid as m/d/y, but is valid as d/m/y, then that will be returned. If the date is not valid as either m/d/y or d/m/y, then an error will be returned.
Sub dural()
Dim st As String
st = CStr(CDate("12/4/2012")) & vbCrLf & CStr(CDate("13/4/2012"))
MsgBox st
End Sub
Very stupid thing but need to achieve in VB.net. I was trying to do this in VB.Net VS2008 .Net Framework 3.5
Dim str As String = "25/05/2014"
Dim dt As Date
dt = DateTime.ParseExact(str, "dd/MM/yyyy", CultureInfo.InvariantCulture)
Console.WriteLine(dt)
And I am getting output as
25-05-2014 00:00:00
Any idea?
This has nothing to do with the conversion, which is OK. When the date is written to the console it is formatted (i.e. converted to a string) with a default format that happens to include the time part.
Specify the desired format when printing:
Console.WriteLine("{0:dd/MM/yyyy}", dt)
or
Console.WriteLine(dt.ToString("dd/MM/yyyy"))
Note: the Date structure (which is the same as the DateTime structure) stores the date and time in a format neutral way, i.e. you cannot format the Date structure. However, when you output it to the user, the date will have to be converted into human readable form, i.e., it will have to be converted to a string. Whenever you convert some binary data (numeric, date/time and so on) into a string, a format will determine how the result will look.
If you're in a hurry, this is a simple way to get the data you want:
Dim sFormatted As String = dt.Day.ToString() & "/" & dt.Month.ToString() & "/" & dt.Year.ToString()
MessageBox.Show(sFormatted)
I have a problem in converting mm/dd/yyyy to dd/mm/yyyy date format using VBA.
I have a table like this:
fyi, the table is auto generated from a reporting tool.
Can "string manipulation" or any excel function help? Hope anyone who know how to solve this problem can give me some idea.
Well, from the way you've worded your question I'm not convinced you actually want or need VBA.
Looking at the image you posted it would appear the first cell contains the string 05/06/2013 - 05/10/2013 not the date 05/06/2013. So the first thing you need to do is split out the parts so the built in Excel or VBA functions can convert it.
By Excel Formulas
So we could use SEARCH or FIND to find the "-" and do things dynamically. But I'm feeling lazy so I'll just assume the first 10 characters of the string are the first date and the last 10 characters are the second date. A TRIM function on the source string should make this a bit safer in case of extra spaces before or after.
So if our string 05/06/2013 - 05/10/2013 is in cell A2, we can put =LEFT(TRIM(A2),10) in B2 and =RIGHT(TRIM(A2),10) in C2.
Now these are still strings. Normally I'd use DATEVALUE to convert the strings to dates, but my copy of Excel doesn't like those crazy nonsense* date formats. So we will parse the dates into the DATE function. Putting =DATE(RIGHT(B2,4),LEFT(B2,2),MID(B2,4,2)) and =DATE(RIGHT(C2,4),LEFT(C2,2),MID(C2,4,2)) into cells C2 and D2 respectively.
From here we can recombine them using the TEXT function (much like the format function in VBA) and some string concatenation into your original single-cell date range format. Assuming that's the desired result.
So our final cell, F2, would be =TEXT(D2,"dd/MM/yyyy") & " - " & TEXT(E2,"dd/MM/yyyy"). We could of course combine all those formulas into one big mess like so:
=TEXT(DATE(RIGHT(LEFT(A2,10),4),LEFT(LEFT(A2,10),2),MID(LEFT(A2,10),4,2)),"dd/MM/yyyy") & " - " & TEXT(DATE(RIGHT(RIGHT(TRIM(A2),10),4),LEFT(RIGHT(TRIM(A2),10),2),MID(RIGHT(TRIM(A2),10),4,2)),"dd/MM/yyyy")
By Visual Basic for Applications
It's the same process here, just using VBA functions and syntax instead of Excel formulas.
Now for whatever reason the VBA version of DateValue will accept those dates in my copy of Excel. So I'll use it.
Public Function ChangeDateFormat(inputString As String) As String
Dim firstDate As Date
Dim secondDate As Date
Dim trimmedInput As String
trimmedInput = Trim$(inputString)
firstDate = DateValue(Left$(trimmedInput, 10))
secondDate = DateValue(Right$(trimmedInput, 10))
ChangeDateFormat = Format(firstDate, "dd\/MM\/yyyy") & " - " & Format(secondDate, "dd\/MM\/yyyy")
End Function
Public Sub Test()
Sheet1.[B2] = ChangeDateFormat(Sheet1.[A2])
End Sub
This can be tested either by running the provided Test sub, or ChangeDateFormat can be used as a user defined function in an excel formula =ChangeDateFormat(A2).
Note, in the date formats passed to Format, I escaped the date separator \/ instead of just putting / in. This is because the Format function will automatically replace / with the date separator from your Windows settings. And since I use a modern computer friendly date format, my seperators are dashes...
Footnote
* Life would be so much easier if people would just use ISO 8601. It exists for a reason, a good reason.
Hey all i have 2 dates that i need to see the days that are different.
Problem being is that the server date is not in the normal MM/DD/YYYY format. It is in the format YYYYMMDD.
I've tried the following:
Dim curDate As Date = Format(Now, "yyyyMMdd")
Dim srDate As Date = dr(6)
Dim M As Long = DateDiff(DateInterval.Weekday, curDate, srDate)
The curDate has the error of:
Conversion from string "20110325" to type 'Date' is not valid.
Any help would be great! :o)
David
Try not to hammer a square string peg into a round date hole, that just has way too many ways to break your mallet. The Now function already returns a date:
Dim curDate As Date = Now.Date
Option Strict On at the top of the source code file helps you find these kinds of mistakes.
If you get the string from the server (pray you don't) then use ParseExact() to convert the date:
Dim curDate As Date = Date.ParseExact(serverValue, "yyyyMMdd", Nothing)
Why are you formatting Now like that? You could just do this:
Dim curDate As Date = DateTime.Now.Date
As the other posters have said, you don't need to format DateTime.Now.
But there's something else going wrong here: Format returns a string, and you're trying to assign that to a Date. It's trying to implicitly convert a string, and failing.
In future, when you do have a date-string like "yyyyMMdd" to turn into a DateTime type, use DateTime.Parse
Your problem is the first line; it seems you have Option Strict off in your project (FOR SHAME!), as it would otherwise not compile at all.
Format(Now, "yyyyMMdd") will produce the current date formatted in that manner as a string. The trouble is that you're attempting to assign that output (the string) to a Date variable. Because you have Option Strict off, the compiler indicates this conversion implicitly, and the runtime is attempting to convert your non-standard date string back into a date. This is what's failing.
Changing as little as possible about your code, it should read:
Dim curDate As Date = Now.Date
Dim srDate As Date = DateTime.ParseExact(dr(6).ToString(), "yyyyMMDD", CultureInfo.InvariantCulture).Date
Dim M As Long = DateDiff(DateInterval.Weekday, curDate, srDate)
Step 0: TURN OPTION STRICT ON
There's no reason that new code should be written with this option turned off. There's too much potential for runtime errors that are easily caught at compile time (like this one) with it off. It's a feature that should be banished from the language entirely.
Step 1: Adopt standard .NET types and functions
While this isn't required, it will make your code more readable to other developers and other developers' code more readable to you. Things like Format, DateDiff, Now, etc. are all VB-specific functions that exist primarily to make it easier for classic VB6 applications to be ported over to .NET. Unless there's a particular reason to use the language-specific versions, it's a good idea to use standard .NET functions instead.
Firstly:
"MM/DD/YYYY" is not normal in most of the world, only North America.
China uses "YYYY-MM-DD".
Europe uses "DD/MM/YYYY"
Secondly, if you are parsing a known date format, you can pass a format string to DateTime.Parse. In your case that is what you need to do.
Try
Dim curDate As Date = Now
Dim srDate As Date = mid(dr(6),5,2) & "/" & right(dr(6),2) & "/" & left(dr(6),4)