Obtaining the correct date using VBA - vba

01/02/2018 12:25:00 PM
I have the above date which is in an Excel spreadsheet's B1 cell. The date is 01 February 2018 but the VBA code below
thedate = CDate(Application.Cells(linecount, 2))
converts this to 02 January 2018
What VBA code do I use to have this remain 01 February 2018?

If you want to use VBA to return a Date data type value of string 01/02/2018 12:25:00 PM representing 01 February 2018 in your local regional date settings (in a message box), you could use:
Dim dt as String
dt = "01/02/2018 12:25:00 PM"
MsgBox DateSerial(Mid(dt, 7, 4), Mid(dt, 4, 2), Left(dt, 2))
† This is how it displays for me. See note below.
If you actually want a string to be returned (in a messages box) in the specific format you mentioned, "dd MMMM yyyy", you could use:
Dim dt as String
dt = "01/02/2018 12:25:00 PM"
MsgBox Format(DateSerial(Mid(dt, 7, 4), Mid(dt, 4, 2), Left(dt, 2)), "dd MMMM yyyy")
If you wanted to store this data (including the time), or use it for calculations, then the proper way to do it would be more like:
Dim strMyDate as String, dtMyDate as Date
strMyDate = "01/02/2018 12:25:00 PM"
dtMyDate = DateSerial(Mid(strMyDate, 7, 4), Mid(strMyDate, 4, 2), _
Left(strMyDate, 2)) + TimeValue(Mid(strMyDate, 11))
MsgBox dtMyDate
† Note that these MsgBox's are displaying date/time's based on my system's Windows settings (shown below), shown here, where they could be adjusted if required. (Hence, the results above will appear differently for you.)
Open these settings by hitting type region, and hit ᴇɴᴛᴇʀ.
(Click to enlarge)
The DateTime is actually stored in Excel as a number where 0 = December 30, 1899 and +1 = +1 day, so your example date of 01 February 2018 12:25:00 PM is actually only a formatted representation of the DateTime serial number, in this case, 43132.5173611.
More Information:
MSDN : DateSerial function (VBA)
MSDN : Format function (VBA)
MSDN : TimeValue function (VBA)
Microsoft.com : How to use dates and times in Excel

Related

Default date in datetimepicker in visual studio

If the user selects the date in the DateTimePicker, it only picks up the date, which is what I need. However, if the user doesn't select any date and leaves the DateTimePicker as today's date, it shows date + time. The data is stored in an Access database. I want to store the date only in the Access store when the user leaves the DateTimePicker to today's date (without changing any date).
Me.DateTimePicker1.CustomFormat = "dd-MM-yyyy"
Me.DateTimePicker1.DataBindings.Add(New System.Windows.Forms.Binding("Value", Me.OrderdetailsBindingSource, "OrderDate", True))
Me.DateTimePicker1.DataBindings.Add(New System.Windows.Forms.Binding("Text", Me.OrderdetailsBindingSource, "OrderDate", True))
Me.DateTimePicker1.Font = New System.Drawing.Font("Tahoma", 10.2!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
Me.DateTimePicker1.Format = System.Windows.Forms.DateTimePickerFormat.Custom
Me.DateTimePicker1.Location = New System.Drawing.Point(158, 39)
Me.DateTimePicker1.Name = "DateTimePicker1"
Me.DateTimePicker1.Size = New System.Drawing.Size(294, 28)
Me.DateTimePicker1.TabIndex = 2
Me.DateTimePicker1.Value = New Date(2019, 6, 18, 0, 0, 0, 0)
Access does not have a short date format such as SQL Server. See this link for lists of data types.
Access:
Date/Time, Use for dates and times, 8 bytes
SQL Server:
datetime, From January 1, 1753 to December 31, 9999 with an accuracy of 3.33 milliseconds, 8 bytes
date, Store a date only. From January 1, 0001 to December 31, 9999, 3 bytes
So Access only has one date/time type which must be able to store time, which has the same number of bytes as SQL Server datetime. The date without a timestamp you see is actually 12 AM. This is what you are doing when you set the date/time on your DateTimePicker Me.DateTimePicker1.Value = New Date(2019, 6, 18, 0, 0, 0, 0). This is incidentally your best solution, to set the DateTimePicker to today's date (just the date portion using the DateTime.Date property I menioned).
To solve your problem, do this in Form_Load:
Me.DateTimePicker1.Value = Now.Date ' this makes it today at 12 AM
If you want to better understand what is going on, check out the value of your DateTimePicker at any time with this, to see that there is always a time in it, even if it's 12 AM:
MessageBox.Show($"{DateTimePicker1.Value:yyyy-MM-dd HH:mm:ss}")
And run this query on your database to see that there is also always a time in an Access Date/Time field, and that Access automatically hides the time when it is 12 AM:
select
orderdate
, format(orderdate, 'General Date') as GeneralDate
, format(orderdate, 'Short Time') as ShortTime
, format(orderdate, 'Medium Time') as MediumTime
, format(orderdate, 'Long Time') as LongTime
, format(orderdate, 'Short Date') as ShortDate
, format(orderdate, 'Medium Date') as MediumDate
, format(orderdate, 'Long Date') as LongDate
from orderdetails
Sorry, if I am not able to answer you perfectly in vb.net
i will give you an Answer in vb (how i mean it is correct)
and in correct c#
i understood that you want the code to save values in the database, if the date of the DateTimePicker is set today.
c#
if(dateTimePicker1.Value.Date == DateTime.Today)
{
//insert your code here
}
vb.net
if dateTimePicker1.Value.Date == DateTime.Today
//Code here
end if
this if asks, if the picket Date of the DateTime is the same Date as today
if you just want to save the whole value of the date in the DataBase if the picked date is today so like: "25.06.2019 17:25" then you will have a problem.
If you save it as String you could format it:
dateTimePicker1.Value.ToString("HH:mm dd.MM.yyyy")
or
dateTimePicker1.Value.ToString("HH:mm")
so put the second in the "else" braket.
if you only need Date or time, you can format it like the above.
(sorry i am not sure if i understood your question right, so if it doesn't help you, just comment. I will answer)

Conver Time from UTC to PST/PDT/CET and CEST with VBA

I have a cloumn (Col. A) of the time and date for one years based on UTC time as the follow format (in fact i have 30 mins Intervals) from first of the year until end of the year:
01.01.2019 00:00
01.01.2019 00:30
.
.
.
31.12.2019 11:00
31.12.2019 11:30
Now I want to convert the time from UTC to CET when it's winter Time and CEST when is Summer time (I want to have the information in Col.B). I could do it with Excel Formula Easily but as my file is big enough I have to use VBA code.
Do have any suggetion How can I do it? My problem is on switching summer time to winter time via versa.
Regarding the time zone conversion itself, Wikipedia says (https://en.wikipedia.org/wiki/Central_European_Summer_Time#Period_of_observation):
Since 1996, European Summer Time has been observed between 01:00 UTC
(02:00 CET and 03:00 CEST) on the last Sunday of March, and 01:00 UTC
on the last Sunday of October
If I'm reading that correctly, a datetime can only be CET if it:
is before (<) the last Sunday of March at 01:00 UTC (i.e. when CEST begins)
or is on or after (>=) the last Sunday of October at 01:00 UTC (i.e. when CET begins)
It's not clear to me what your source data is like. (It looks like two datetimes delimited by a space, meaning each row actually contains a string. If this is true, you'll likely need to split the string into two strings along the delimiting space, then convert the two strings into two datetimes. This can probably be done with LEFT, RIGHT, DATEVALUE functions in VBA.)
To give you an example, I've filled range A1:A17520 of my worksheet "Sheet1" with datetimes at half-hour intervals (similar to what you've shown):
and I then use the code below to convert my values in column A (and put the converted values in column B of the same sheet):
Option Explicit
Private Sub ConvertUtcDatesInColumnAToCETorCEST()
Dim sourceSheet As Worksheet
Set sourceSheet = ThisWorkbook.Worksheets("Sheet1")
Dim lastSourceRow As Long
lastSourceRow = sourceSheet.Cells(sourceSheet.Rows.Count, "A").End(xlUp).Row
Dim datesFromSheet() As Variant
datesFromSheet = sourceSheet.Range("A1", sourceSheet.Cells(lastSourceRow, "A"))
Dim outputArray() As Date
ReDim outputArray(1 To UBound(datesFromSheet, 1), 1 To 1)
Dim rowIndex As Long
For rowIndex = LBound(datesFromSheet, 1) To UBound(datesFromSheet, 1)
outputArray(rowIndex, 1) = ConvertUtcDateTimeToCETorCEST(datesFromSheet(rowIndex, 1))
Next rowIndex
sourceSheet.Range("B1").Resize(UBound(outputArray, 1), UBound(outputArray, 2)).Value = outputArray
End Sub
Private Function LastSundayOfSomeMonthAndYear(ByVal someMonth As Long, ByVal someYear As Long) As Date
Dim lastDateInMonth As Date
lastDateInMonth = Application.EoMonth(DateSerial(someYear, someMonth, 1), 0)
Dim lastSundayInMonth As Date
LastSundayOfSomeMonthAndYear = lastDateInMonth - Weekday(lastDateInMonth, vbSunday) + 1
End Function
Private Function ConvertUtcDateTimeToCETorCEST(ByVal someUtcDateTime As Date) As Date
Dim startOfCESTinUTC As Date
startOfCESTinUTC = LastSundayOfSomeMonthAndYear(someMonth:=3, someYear:=Year(someUtcDateTime)) + TimeSerial(1, 0, 0)
Dim endOfCESTinUTC As Date
endOfCESTinUTC = LastSundayOfSomeMonthAndYear(someMonth:=10, someYear:=Year(someUtcDateTime)) + TimeSerial(1, 0, 0)
Dim isCET As Boolean
isCET = someUtcDateTime < startOfCESTinUTC Or someUtcDateTime >= endOfCESTinUTC ' Not sure if end is inclusive or exclusive
Dim hoursToAdd As Date
If isCET Then hoursToAdd = TimeSerial(2, 0, 0) Else hoursToAdd = TimeSerial(3, 0, 0)
ConvertUtcDateTimeToCETorCEST = someUtcDateTime + hoursToAdd
End Function
which gives me something like this:
Something to note is that this approach is quite inefficient for a few reasons:
The variables startOfCESTinUTC and endOfCESTinUTC are re-calculated every single time the function ConvertUtcDateTimeToCETorCEST is invoked (~17.5k times in my case). Since all of our datetimes are during the same year, the values of startOfCESTinUTC and endOfCESTinUTC will not change (so really the variables startOfCESTinUTC and endOfCESTinUTC should be determined just once, before the For loop).
If you know in advance and for sure that your data is sorted and is at half-hour intervals, you can do some maths and work out on which row CEST must begin on and end on. With that knowledge, you no longer need to check if the datetime is CET or CEST inside the For loop. If you use three For loops (loop 1: first row to row CET ends on, loop 2: row CEST starts on to row CEST ends on, loop 3: row CET starts on to last row), you can convert all values to CET (loop 1, loop 3) and CEST (loop 2) without actually checking what the value is. This makes the code more specialised (and faster), but also less reusable.
Modern computers are (relatively) fast. The code above converted 17.5k datetimes for me in <2 seconds on my machine. You may also want to check if the code handles the boundaries of CET and CEST correctly.

Convert date type (Sun Apr 01 00:00:00 UTC 2018) in excel VBA as a custom function

I need to create a custom function based on the formula:
=DATEVALUE(CONCATENATE(MID(A2,8,3),MID(A2,4,4),RIGHT(A2,4)))
where A2= Sun Apr 01 00:00:00 UTC 2018
And the result should be: 43191
I also need that this function will be available anywhere in excel
Function MyDate(val As Variant)
MyDate = DateValue(Mid(val, 8, 3) & "-" & Mid(val, 4, 4) & "-" & Right(val, 4))
End Function
so you can type in any cell =MyDate(A2) (or whatever, cell reference you need)

VBA Code for name of previous month

I have added text in to my email that goes like:
"please provide numbers for MMMM month end" - where MMMM is the name of the previous month.
So it it's April today, MMMM will show March.
I have the following code:
Dim newDate: newDate = DateAdd("M", -1, Now)
But the result comes out to be 27/03/2017 16:37:58
I want it to show March.
Any suggestions?
Format the return as "MMMM":
Dim newDate: newDate = Format(DateAdd("M", -1, Now), "MMMM")
If set to True, the month name is abbreviated e.g. Apr
newDate = MonthName(Month(DateAdd("m", -1, Date)), False)
This will ensure the month is in English irrespective of the regional settings on the computer. This will be helpful for those who are releasing an Excel VBA tool worldwide.
previousmonth = WorksheetFunction.Text(DateAdd("m", -1, Date), "[$-409]mmmm")
For abbreviated months eg: Apr use
previousmonth = WorksheetFunction.Text(DateAdd("m", -1, Date), "[$-409]mmm")

Convert Text to Date

I have a text field in Access called "TempD"
which contains data like below
Mon, Oct 6, 2014
Mon, Nov 10, 2014
I need to convert this to proper date format using SQL and put it in Field "Emaildate"
I am using the sql query below:
UPDATE MissingT
SET MissingT.emaildate = format(cdate(Right([tempd],4) & "/" & Mid([tempd],6,3) & "/" & Mid([tempd],9,2)));
But the issue is that the TempD field varies in length if the day is single/double. When the day is in 2 digits
(Mon, Nov 10, 2014)
it is converting this text to 2014-11-01 instead of 2014-11-10
Any idea how can this be resolved?
Discard the abbreviated day name, comma, and space from the beginning of your date string ...
? Mid("Mon, Oct 6, 2014", 5)
Oct 6, 2014
The resulting substring can be converted directly to a Date/Time value using CDate() ...
? CDate(Mid("Mon, Oct 6, 2014", 5))
10/6/2014
Then if you want that Date/Time value as a string in yyyy/mm/dd format ...
? Format(CDate(Mid("Mon, Oct 6, 2014", 5)), "yyyy/mm/dd")
2014/10/06
If that is what you're after, you can do it in an UPDATE query like this ...
UPDATE MissingT
SET emaildate = Format(CDate(Mid(tempd, 5)), "yyyy/mm/dd");
It makes no sense to apply Format on a date value passed to a Date field.
This is how to solve it:
UPDATE
MissingT
SET
emaildate = DateValue(Mid([tempd], 5))