VBA Double to Time - vba

I have a VBA user form which when I press save after input data it writes to a spread sheet and set my time and date to Now() that is being written to a spread sheet where I split the now() value into time and date, when I read it back I get the date but my time in decimal format I would like to convert that decimal number back to time what is the formula for that thank you in advance my decimal number is something like '0.12425576899' so far I found this but it converts that to '00:the minutes on the double:00' here is the code
Public Function FromDecimalTime(ByVal t As Double) As Date
FromDecimalTime = TimeSerial(0, Fix(t), (t - Fix(t)) * 60)
End Function

The following will convert the Double into the Date Format. In order to only show the time portion of the date format, use the Format function:
Sub trythis()
Dim t As Double
t = Now()
Debug.Print CDate(t)
Debug.Print Format(t, "hh:mm:ss")
End Sub

Related

How to make a spreadsheet formula execute every day

I have the following formula which fetches data from the same day from table UniqueLast:
=IFERROR(QUERY(UniqueLast!$A$3:X;"select * where dateDiff(A, now())=0"))
It runs correctly but sometimes the table where this formula is executed keeps the result from the previuos day which is already old. How can I make a regulation for running the formula in 00:00?
Create a macro function and include the above expression. Use VBExpress and create a script (.exe) to open the spreadsheet and run the macro. Add it in the Windows scheduled tasks.
Function to call in Macro
Function getNextRunTime() As Date
Dim curDate As Date
Dim curTime As Date
Dim chkTime As Date
Dim runTime As Date
curDate = Date
curTime = TimeValue(Now)
runTime = curDate + TimeValue("15:59:00")
chkTime = curDate + curTime
If chkTime > runTime Then 'schedule for next day'
runTime = DateAdd("d", 1, runTime)
End If
getNextRunTime = runTime
End Function
The SQL statement parameter of the QUERY function should be a single value of type TEXT. NOW() it not valid Google Query Language function. Google Sheets magnes dates on the background as numbers with a different EPOCH date so we should convert it to a date with the proper format. Try
=QUERY(
UniqueLast!$A$3:X,
"select * where dateDiff(A, date """&TEXT(now(),"yyyy-mm-dd")&""")=0"
)
Removed IFERROR in order to make it easy to check if change proposed works with the OP data. You could add it later once you are sure that it does.

Declare either .Text, .Value, .Value2 using array to fetch data from excel

I use Excel automation with Excel interop. My code takes excel sheet using array fetch. As you can see below i take all of them as .Value2, however i would like to specify for example that one of my excel column to be taken as .Text. How to achieve that?
'Convert from interop object to native vb.net object, indexed 1 to length
Dim data As Object(,) = DirectCast(_xlWorkSheet.UsedRange.Value2, Object(,))
For row As Integer = 2 To data.GetUpperBound(0) - 1
Dim newDataRow As DataRow = dt.NewRow()
Dim dattime As DateTime = DateTime.FromOADate(data(row, 11))
Next
i have one column in excel that has format: [h]:mm:ss means hours could exceed clock hour so means there could be e.g 783:34:12. When i tried to use formatting for instance: NumberFormat ="#" or whatever else i always got wrong result.
Based on that description, I will assume that the value is entered into Excel as a numeric Double. i.e.: 783:34:13 equals 32.64875.
In VB.Net, you could generate a TimeSpan structure to yield the resulting day, hour, minutes and seconds components. In the following, rng is an Excel.Range representing a single cell.
Dim val As Double = CDbl(rng.Value2)
Dim ts As TimeSpan = DateTime.FromOADate(val) - DateTime.FromOADate(0)
Now if you wanted to format this TimeSpan as a string similar to that displayed in Excel, you could do something like this:
Dim s As String = String.Format("{0}:{1:00}:{2:00}", (ts.Days * 24) + ts.Hours, ts.Minutes, ts.Seconds)
The reason I am recommending this technique over getting the Text property of an Excel.Range is that the Text property will return exactly what you would see in Excel including the ever helpful "###" when the column is not wide enough to display the formatted value.
Edit To Address Comments:
can you explain why you do this: - DateTime.FromOADate(0) ?
Excel encodes a date-time value as a decimal number of 24 hour periods (days) from a specified date-time that has the value of zero. Your data is apparently making use of this fact to allow you to have a cell with a value of 783:34:12 (783 hours, 34 minutes, 12 seconds) or 32.64875 as a decimal value.
In order to retrieve the offset in (days, hours, minutes, seconds) the original value represents, you need to subtract date-time represented by its basis value (zero).
i saw mismatch e.g: in excel : 0:04:07 (real value behind is: 12:04:07 AM) after your function i get this: 0:04:06 (so 1 sec diffrence why is that?
I can not reproduce this issue. It is likely a rounding issue due too the limitations of floating point value representation.
Also, be advised that Excel supports two different date basis systems; the 1900 Date System (the default) and the 1904 Date System. The DateTime.FromOADate function does its conversion based on the 1900 Date System. The difference between these two systems is the date that is treated as zero. You should check the WorkBook.Date1904 property to see if you need to add addition days (1462 days) to the value retrieved from Excel when converting to a .Net DateTime.
This could effect the result of this code:
Dim dattime As DateTime = DateTime.FromOADate(data(row, 11))
See: Differences between the 1900 and the 1904 date system in Excel for more information.

Values vary after conversion from excel

I am trying to get values from one of the column from excel and i am facing strange issue that i cannot overcome so far.
Excel cells text we working on
Column format is set to: [h]:mm:ss so means hours could exceed 12/24.
When i am getting that values they are in double format as excel probbaly stores it in that way therefore i decided to write function to convert it back again to hours, minutes and seconds so i did that function:
Public Shared Function parseExcelHour(cellInput As String) As String
Dim excelHour As Double = 0
Dim hour As Integer
Dim min As Integer
Dim sec As Integer
Try
excelHour = [Double].Parse(cellInput)
Catch
End Try
sec = CInt((excelHour * 1440 * 60) Mod 60)
min = CInt((excelHour * 1440) Mod 60)
'mod (%) takes only the remainder as an int (if 5/4 = 1.25 , % only takes the number 1 that cannot be divided into an integer)
hour = CInt((excelHour * 1440) / 60)
' with the int cast you get only an integer.
Return hour & ":" & min & ":" & sec
End Function
However when i see the results, they are vary between excel and what i get after conversion. For three of them hours are either -1 or +1 if you compare. Also in one case we have additional + 1 minute. I suppose there is wrong hour calculation but i could be in wrong. See on screeshoot:
Results
Does anyone knows why i got those differences? Is that because i am missing something within my method or something else.
Excel stores a full Datetime equivalent as one double. The part before the decimal point is the days (since 1.1.1900; 1.1.1904 on Mac; note the bug that 1900 is faultily cosnider a leap year in Excel).
The part after is the time of the day, wich is what you apparently want:
https://stackoverflow.com/a/981865/3346583
What you are seeing in excel is meerely a ToString Foramting of the double value. Same way DateTime.ToString() would give you a string representation of whatever value is actually stored (most often a realy big unsigned int, with the ticks since a date).
A difference in full hours sounds like it might be a Timezone issue. But I am not aware that Excel stores Timezones in the first place (or what default timezone it asumes).

How to convert VBA Now() into seconds to determine total program runtime

I'm working on a problem where I need to determine the total time my program takes to execute. First line of code needs to write the current "Start time" and last lines of code need to write the current "End time". Then I'm subtracting "Start time" - "End Time" = Total Time.
I'm confused how I would use the FORMAT() function within VBA on the value of C2 to convert into seconds? Is there an other function that would work better than FORMAT? Basically I'm confused about Excel's Date Serial values and what they represent.
Code is below
EDIT: Thanks for the responses everyone. Both answers below work for what I'm trying to do.
sub ExecutionTime()
Worksheets("Table").Range("A2").Value = Now()
'All my executable code goes here. It's a relatively small program compiling a table so it
runs very quick.
Worksheets("Table").Range("B2").Value = Now()
Worksheets("Table").Range("C2").Value = Worksheets("Table").Range("A2").Value - Worksheets("Table").Range("B2").Value
end Sub
Do not use a Date data member or the Now method to analyze run time of your program. Instead, the Timer function is the most appropriate solution as it returns a Single representing seconds. It will require no type conversion and yields a more accurate result than an integer amount of seconds.
Using LimaNightHawk's answer as a template as you should be storing these in local variables instead of writing directly to the worksheet.
Dim startTime as Single
startTime = Timer()
' Do stuff
Dim endTime as Single
endTime = Timer()
Dim runTime as Single
runTime = endTime - startTime
Results should be written at the end of the routine.
With Worksheets("Table")
.Range("A2").Value = startTime
.Range("B2").Value = endTime
.Range("C2").Value = runTime
End With
Documentation on the timer function
In the first line of your program get the date (no need to format):
Dim startTime as Date
startTime = Now()
At the end of your program, get the date again:
Dim endTime as Date
endTime = Now()
Then use the DateDiff
Dim timeInSeconds as long
timeInSeconds = DateDiff("s", startTime, endTime)
DateDiff() is what you are looking for. The "s" defines that you are looking for the difference in seconds.
Worksheets("Table").Range("C2").Value = DateDiff("s", Worksheets("Table").Range("A2").Value, Worksheets("Table").Range("B2").Value)
EDIT: http://www.likeoffice.com/28057/excel-date to learn more about working with dates and times in Excel VBA. It is important to understand that dates work differently within the context of VBA, and have their own unique set of syntax functions for manipulating.
2nd EDIT: A cleaner version of this would be:
StartDateTime = Now()
'Run Code
Worksheets("Table").Range("C2").Value = DateDiff("s", StartDateTime, Now())
There's a few ways you can use VBA to format cells / variables.
In no particular order, firstly you can format ranges with the NumberFormat property which can be applied like so:
Worksheets("Table").Range("C2").Value = Now()
Worksheets("Table").Range("C2").NumberFormat = "ss"
The other way is that you could format Now() using the Format() function:
Worksheets("Table").Range("C2").Value = Format(Now(), "ss")
See the documentation from Microsoft to implement different formats:
NumberFormat: http://msdn.microsoft.com/en-us/library/office/ff196401%28v=office.15%29.aspx
Format: http://msdn.microsoft.com/en-us/library/office/gg251755%28v=office.15%29.aspx
How i generally go about bragging my process time to user
Sub Process()
Dim startTime as Date
Dim endTime as Date
startTime = Now
'Logic for what your process must do
endTime = Now
MsgBox "Process completed in : " & Format(endTime - startTime, "hh:mm:ss")
End Sub

How to compare dateformat rather than using of time

How can I compare the last characters using of month, day, and year or the completedate rather than using datetime, Example case is Textbox3 is greater than textbox9 because Textbox3 day = 26 and textbox9 day = 25.
Mycode:
'in my case I have 2 Textbox.
'Date format: hh.mm MM/DD/YYYY
'Textbox3= 02.02 03/26/2014
'TextBox9= 21.01 03/25/2014
If Val(Strings.Left(TextBox9.Text.Trim, 5)) < Val(Strings.Left(Textbox3 .Text.Trim, 5))Then
TimeError.ShowDialog()
End If
Really, the fastest, most reliable, and most effective way to do this is to parse the values into a DateTime. And taking a step back from there, the fastest, most effective way to get a date time from a textbox is to use a DateTimePicker control.
But if that's not an option, we can build on the code I gave you last time:
Dim temp1() As String = Textbox3.Text.Trim().Split(" .".ToCharArray())
Dim temp2() As String = Textbox9.Text.Trim().Split(" .".ToCharArray())
If DateTime.Parse(temp2(2)) < DateTime.Parse(temp1(2)) Then
TimeError.ShowDialog()
End If
I'll add that you probably want to also have code to compare the time values in the case where the date portions are equal. Given this as a starting point, you should be able to write that code on your own.
in vb.net you can comopare dates like this:
dim date1 as date = cdate(Textbox1.text)
dim date2 as date = Date.now()
if date1.date=date2.date then ....
and months like this
if date1.month=date2.month then ...