I have a column of date time. I have to remove the date part. I simple want to run a macro that will do that. WHen I record macro, do the delete and then stop, then run it on the next row, it gives the value below. How does one globalize so I can run on all rows this task?
2017-06-26 14:41:00
the macro is this:
Sub Macro9()
'
' Macro9 Macro
'
'
ActiveCell.FormulaR1C1 = "2:41:00 PM"
ActiveCell.Offset(1, 0).Range("A1").Select
End Sub
Here is a simple macro to accomplish what you are looking to do. I assumed that you wanted to convert from military time to AM/PM. You will have to adjust the locations of cells to fit your spreadsheet. This is just going through all of the values in column A and turning them into just AM/PM time and spitting them out in coulmn B. Instead of looping through all of the rows you could also define your own single input function with the same logic.
Sub test()
Dim dt As String
Dim tm As String
Dim hr As String
Dim row_ct As Integer
row_ct = Range("A1").End(xlDown).Row
For i = 1 To row_ct
dt = Cells(i, 1)
tm = Right(Cells(i, 1), 8)
hr = Left(tm, 2)
If hr < 12 Then
tm = tm & " AM"
ElseIf hr = 12 Then tm = tm & " PM"
ElseIf hr > 12 and hr - 12 < 10 then tm = 0 & (Left(tm, 2) - 12) & Right(tm, 6) & " PM"
Else: tm = left(tm, 2) - 12 & right(tm, 6) & " PM"
End If
Cells(i, 2) = tm
Next i
End Sub
Here is how you can make a custom function that handles this:
Function tm(date_time)
If Left(Right(date_time, 8), 2) < 12 Then
tm = Right(date_time, 8) & " AM"
ElseIf Left(Right(date_time, 8), 2) = 12 Then tm = Right(date_time, 8) & " PM"
ElseIf Left(Right(date_time, 8), 2) > 12 Then tm = Left(Right(date_time, 8), 2)- 12 & Right(date_time, 6) & " PM"`
End If
End Function
Depending on the application, one will probably work better than the other.
Related
I have a button, which when clicked will give the current date and time in a text box.then I used another program to move that to cell.but this are not considered as the date until I double-clicked it.during filtering,this entered date are excluded from other dates
i have done formatting for date(ddmmyy HHmm)
Private Sub CommandButton5_Click()
If Not TextBox6.Value = "" Then
ans = msgbox(" Date already exits.Do you want to continue", vbYesNo + vbQuestion)
If ans = vbYes Then
TextBox6.Value = Format(Now(), ddmmyyHHmm)
End If
End If
If TextBox6.Value = "" Then
TextBox6.Value = Format(Now(), ddmmyyHHmm)
End If
End Sub
and for copying value to cell ,i used
cells(i,"A").value = textbox6.value
Format returns a Variant/String. You want to enter an actual date/time into the cell, not a formatted one that Excel no longer recognizes as a date.
One option is to use DateSerial and TimeSerial to build up a true date/time from that string. There's probably a simpler way to achieve this though, but anyway, here's an example:
Dim x As String
x = TextBox6.Value
Dim yy As Integer, dd As Integer, mm As Integer, hh As Integer, min As Integer
yy = CInt(Mid(x, 5, 2)) ' year
mm = CInt(Mid(x, 3, 2)) ' month
dd = CInt(Mid(x, 1, 2)) ' day
hh = CInt(Mid(x, 7, 2)) ' hour
min = CInt(Mid(x, 9, 2)) ' minute
Cells(i, "A").Value = DateSerial(yy, mm, dd) + TimeSerial(hh, min, 0)
If you want to format the cell with that date/time formatting:
Cells(i, "A").NumberFormat = "ddmmyyHHmm"
Could you please help me to obtain the difference between 2 dates (working hours only, that's very important)
Take a look at this image:
First response is calculated by the difference between: Date First Response and Date of the problem
Elapsed time is calculated by the difference between: Date Last Response and Date of the problem
This is my macro so far (it is not working properly):
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
Const WORKING_DAY_START As String = "09:00"
Const WORKING_DAY_END As String = "18:00"
Const FORMULA_WORKING_TIME As String = _
"=(INT(E2-D2)*(""" & WORKING_DAY_END & """-""" & WORKING_DAY_START & """)" & _
"+MEDIAN(MOD(E2,1),""" & WORKING_DAY_END & """,""" & WORKING_DAY_START & """)" & _
"-MEDIAN(MOD(D2,1),""" & WORKING_DAY_END & """,""" & WORKING_DAY_START & """))"
Const FORMULA_ELAPSED_TIME As String = "=F2-D2"
Dim lastrow As Long
On Error GoTo ws_bdc_exit
Application.ScreenUpdating = False
Application.EnableEvents = False
With Me
lastrow = .Cells(.Rows.Count, "A").End(xlUp).Row
'input Elapsed Time
.Range("H2").Resize(lastrow - 1).Formula = FORMULA_ELAPSED_TIME
'input First Response time
.Range("G2").Resize(lastrow - 1).Formula = FORMULA_WORKING_TIME
With .Range("G2:H2").Resize(lastrow - 1)
.Value = .Value
.NumberFormat = "##0.00"
End With
End With
ws_bdc_exit:
Target.Offset(1).Select
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
EDIT #1: I should obtain working hours from Monday to Friday (weekend not included, but i dont know how to do it)
EDIT #2: The difference should be displayed in hours
EDIT #3: Before, i was using this macro (everything was working fine BUT i was not getting the working hours)
Public cVal
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
Dim LastRow
LastRow = Range("A" & Rows.Count).End(xlUp).Row
For i = 2 To LastRow
t1 = TimeValue(CStr(Cells(i, "D").Value))
t2 = TimeValue(CStr(Cells(i, "E").Value))
t3 = TimeValue(CStr(Cells(i, "F").Value))
'input First Response time
If Hour(t2) - Hour(t1) = 0 Then
Cells(i, "G").Value = Round((Minute(t2) - Minute(t1)) / 60, 2)
Else
Cells(i, "G").Value = Hour(t2) - Hour(t1) + Round((Minute(t2) - Minute(t1)) / 60, 2)
End If
'input Elapsed Time
If Hour(t3) - Hour(t1) = 0 Then
Cells(i, "H").Value = Round((Minute(t3) - Minute(t1)) / 60, 2) '- Cells(i, "J").Value - Cells(i, "J").Value
Else
Cells(i, "H").Value = Hour(t3) - Hour(t1) + Round((Minute(t3) - Minute(t1)) / 60, 2) '- Cells(i, "J").Value
End If
Next i
Target.Offset(1).Select
End Sub
I wrote a function which should calculate the working hours, Mon-Fri, only.
Note that in your posted example, some of the dates are on Sat/Sun, so will calculate as zero.
The algorithm:
Calculate workhours for each day that is Mon-Fri as being WORKING_DAY_START -WORKING_DAY_END` hours.
Make an adjustment if the day happens to be the first or last day being calculated.
You can use this function either on the worksheet itself, you can call if from a Macro that fills in the cells with just the value.
Below I will show your original data, plus some extra lines altering your weekend work dates.
Option Explicit
Function elapsedWorkTime(startDT As Date, endDt As Date) As Date
Const WORKING_DAY_START As Date = #9:00:00 AM#
Const WORKING_DAY_END As Date = #6:00:00 PM#
Dim adjTimeStart As Date, adjTimeEnd As Date, totTime As Date
Dim D As Date
For D = DateValue(startDT) To DateValue(endDt)
Select Case Weekday(D)
Case 2 To 6
'Adj for first and last days
If D = DateValue(startDT) Then
If TimeValue(startDT) <= WORKING_DAY_START Then
adjTimeStart = 0
ElseIf TimeValue(startDT) >= WORKING_DAY_END Then
adjTimeStart = WORKING_DAY_START - WORKING_DAY_END
Else
adjTimeStart = WORKING_DAY_START - TimeValue(startDT)
End If
End If
If D = DateValue(endDt) Then
If TimeValue(endDt) >= WORKING_DAY_END Then
adjTimeEnd = 0
ElseIf TimeValue(endDt) <= WORKING_DAY_START Then
adjTimeEnd = WORKING_DAY_START - WORKING_DAY_END
Else
adjTimeEnd = TimeValue(endDt) - WORKING_DAY_END
End If
End If
totTime = totTime + WORKING_DAY_END - WORKING_DAY_START
End Select
Next D
elapsedWorkTime = totTime + adjTimeStart + adjTimeEnd
End Function
EDIT Corrected formatting on screenshot
Note that the formula in the worksheet cell, since you want the output expressed as hours, is something like:
=elapsedWorkTime(C2;D2)*24
Note the discrepancy for 5541. In your example, you show a value of 8,52 for elapsed time. But in your requirements statement you write you want to include working hours only. Working hours end at 18:00 so time spent after that should not be counted.
Maybe there is no need to use VBA.
Use NETWORKDAYS function to count workdays between dates.
Multiply them by working hours a day
Substract work hours from begin and end date (e.g. work started later than workday begins and so on)
Calculate totals.
I'd recommend to do every step in a single cell, in order to check step-by-step logics.
I have 2 cells with time data that format as follows:
"A1" = Sep 01 2018 00:01:33.707
"A2" = Sep 01 2018 00:01:49.917
I need to create a button and method within excel VBA that will set "A3" cell to true if the time "A2" is more than "A1" by 90 seconds.
This is what i have so far but it does not work:
Sub Macro2()
Dim str1 As String, str2 As String
With Worksheets("sheet5")
str1 = .Cells(1, "A").Text
str2 = .Cells(2, "A").Text
'greater than 90m seconds in A3
.Cells(3, "A") = CBool(Abs((DateValue(Left(str1, 6) & "," & Mid(str1, 7, 5)) + _
TimeValue(Mid(str1, 13, 8)) + TimeSerial(0, 0, 1) * CDbl(Right(str1, 4))) - _
(DateValue(Left(str2, 6) & "," & Mid(str2, 7, 5)) + _
TimeValue(Mid(str2, 13, 8)) + TimeSerial(0, 0, 1) * CDbl(Right(str2, 4)))) > _
TimeSerial(0, 0, 90))
'actual absolute difference in A4
.Cells(4, "A") = Abs((DateValue(Left(str1, 6) & "," & Mid(str1, 7, 5)) + _
TimeValue(Mid(str1, 13, 8)) + TimeSerial(0, 0, 1) * CDbl(Right(str1, 4))) - _
(DateValue(Left(str2, 6) & "," & Mid(str2, 7, 5)) + _
TimeValue(Mid(str2, 13, 8)) + TimeSerial(0, 0, 1) * CDbl(Right(str2, 4))))
End With End Sub
The above gives error because Date functions works with system Locale, which in my case is Hebrew, while the Data is in English.
Another way that could help is to convert all the column "A" (which holds the dates) to a system local date that can be used with Date and time functions on VBA (don't know how to do that).
Please help
I have split your task into 3 functions.
a) a helper function converts the 3 characters of the month into an integer. It looks a little clumsy, there might be other approaches but the advantage of using a large Select Case is it is easy to understand and easy to adapt if month names in a different language arise:
Function getMonthFromName(monthName As String) As Integer
Select Case UCase(monthName)
Case "JAN": getMonthFromName = 1
Case "FEB": getMonthFromName = 2
Case "MAR": getMonthFromName = 3
Case "APR": getMonthFromName = 4
(...)
Case "SEP": getMonthFromName = 9
(...)
End Select
End Function
b) a function that converts the string into a date. It assumes the date format in the form you provided, but it is easily adapted if the format changes (for simplicity, the seconds are rounded)
Function GetDateFromString(dt As String) As Date
Dim tokens() As String
tokens = Split(Replace(dt, ":", " "), " ")
Dim day As Integer, month As Integer, year As Integer
month = getMonthFromName(CStr(tokens(0)))
day = Val(tokens(1))
year = Val(tokens(2))
Dim hour As Integer, minute As Integer, second As Double
hour = Val(tokens(3))
minute = Val(tokens(4))
second = Round(Val(tokens(5)), 0)
GetDateFromString = DateSerial(year, month, day) + TimeSerial(hour, minute, second)
End Function
c) A function that calculated the difference of the 2 dates in seconds. A date in VBA (and many other environments) is stored as Double, where the Date-Part is the integer part and the date is the remainder. This makes it easy to calculate with Date values.
Function DateDiffInSeconds(d1 As String, d2 As String) As Long
Dim diff As Double
diff = GetDateFromString(d2) - GetDateFromString(d1)
DateDiffInSeconds = diff * 24 * 60 * 60
End Function
Update to deal with milliseconds: Change the GetDateFromString-function. In that case, DateDiffInSeconds should return a double rather than a long.
Function GetDateFromString(dt As String) As Date
Const MillSecPerHour As Long = 24& * 60 * 60 * 1000
Dim tokens() As String
tokens = Split(Replace(Replace(dt, ".", " "), ":", " "), " ")
Dim day As Integer, month As Integer, year As Integer
month = getMonthFromName(CStr(tokens(0)))
day = Val(tokens(1))
year = Val(tokens(2))
Dim hour As Integer, minute As Integer, second As Integer, milli As Integer
hour = Val(tokens(3))
minute = Val(tokens(4))
second = Val(tokens(5))
milli = Val(tokens(6))
GetDateFromString = DateSerial(year, month, day) _
+ TimeSerial(hour, minute, second) _
+ milli / MillSecPerHour
End Function
For your information, I've done what you are doing in a slightly different (and easier) way:
In cell B2, I put the value 13/11/2018 11:44:00.
In cell B3, I put the value 13/11/2018 11:45:01.
(For both cells, the cell formatting has been set to d/mm/jjjj u:mm:ss).
In another cell, I put following formula:
=IF((B3-B2)*86400>90;TRUE;FALSE)
The formula is based on the idea that a datetime value is set, based on the idea that one day equals 1, and there are 86400 seconds in one day.
Like this, you can calculate time differences without needing VBA.
I think you are over-complicating it, try this to get an idea how to do it:
Sub Macro2()
Dim str1 As String, str2 As String
With Worksheets("sheet5")
.Range("b1:e1") = Split(Range("A1"), " ")
.Range("B2:e2") = Split(Range("A2"), " ")
End Sub
Use UDF.
Sub Macro2()
Dim str1 As String, str2 As String
Dim mySecond As Double, t1 As Double, t2 As Double, t3 As Double
mySecond = TimeSerial(0, 0, 90)
With Worksheets("sheet5")
str1 = .Cells(1, "A").Text
str2 = .Cells(2, "A").Text
t1 = ConvertTime(str1)
t2 = ConvertTime(str2)
t3 = t2 - t1
.Cells(3, "a") = Abs(t3) >= mySecond
End With
End Sub
Function ConvertTime(s As String)
Dim vS
vS = Split(s, " ")
ConvertTime = DateValue(vS(0) & "-" & vS(1) & "-" & vS(2)) + TimeValue(Split(vS(3), ".")(0))
End Function
I have a document with the following:
FullDateTime FullDate FullTime Day Month Year Hour Minute Second
dd/mm/yyyy hh:mm:ss AM/PM
and I would like to fill in the other columns using macros to split the first column and place the whole date, whole time, day, month, year, hour, minute and second in the other columns. FullDateTime is every five minutes and I want to the DateTime to run for a whole year. I imagine the code to look something like:
Sub Func()
Dim 5mindays as Integer = 12*24*365
Dim x As Integer
Dim date
Dim time
For x = 1 To 5mindays
Split(," ")
Split(,"/")
Split(,":")
.Offset(0,1) = date(0)
...
.Offset(0,8) = time(2)
Add the next FullDateTime field below the existing one (adding 5 minutes)
Next
But have no idea how to actually do it. Please give me some ideas on how to solve this. Thanks!
Try after setting the correct worksheet name and year to process,
Option Explicit
Sub funk()
Dim dt As Long, yr As Long, tm As Long, dttm As Double
yr = 2018
dt = DateSerial(yr, 1, 1)
With Worksheets("sheet6")
Do While Year(dt) = yr
Do While TimeSerial(0, tm * 5, 0) < 1
dttm = dt + TimeSerial(0, tm * 5, 0)
.Cells(tm + 1 + (dt - DateSerial(yr, 1, 1)) * 288, "A").Resize(1, 9) = _
Array(dttm, dt, dttm - dt, _
Day(dt), Month(dt), yr, _
Hour(dttm), Minute(dttm), 0)
tm = tm + 1
Loop
tm = 0
dt = dt + 1
Loop
With .Range(.Cells(1, "A"), .Cells(.Rows.Count, "I").End(xlUp))
.Columns("A").NumberFormat = "dd/mm/yyyy hh:mm:ss AM/PM"
.Columns("B").NumberFormat = "dd/mm/yyyy"
.Columns("C").NumberFormat = "hh:mm:ss"
.Columns("D:I").NumberFormat = "0"
End With
End With
End Sub
I'm trying to calculate the time elapsed with the total amount of months, Days and Hours together using Datediff function. Is it not possible?
DateDiff("d hh", datein, Now)
What can I do?
That's not possible as the interval parameter can only be a single string.
You will have to do a bit more work like get the difference in hours and if it's above 24 convert the part before decimal separator into days
Sub Main()
Dim d1 As Date
d1 = "15/10/2014 08:00:03"
Dim d2 As Date
d2 = Now
Dim hrsDiff As Long
hrsDiff = DateDiff("h", d1, d2)
MsgBox IIf(hrsDiff >= 24, _
hrsDiff \ 24 & " days " & hrsDiff Mod 24 & " hours", _
hrsDiff & " hours")
End Sub
This is rough and ready, but is just directional. You could make a user defined function. This one returns 1:2:22:15 as a string (but you could return a custom class instance with variables for months, days, hours, minutes). It doesn't account for date2 being before date1 (not sure what happens then), nor does it account for date1 only being a partial day (assumes date1 is midnight).
Function MyDateDiff(date1 As Date, date2 As Date) As String
Dim intMonths As Integer
Dim datStartOfLastMonth As Date
Dim datStartOfLastHour As Date
Dim datEndOfMonth As Date
Dim intDays As Integer
Dim intHours As Integer
Dim intMinutes As Integer
Dim strResult As String
' Strip of any time
datStartOfLastMonth = DateSerial(Year(date2), Month(date2), Day(date2))
' check the dates arent in the same month
If Not ((Month(date1) = Month(date2) And Year(date1) = Year(date2))) Then
' how many months are there
intMonths = DateDiff("m", date1, date2)
Debug.Print (intMonths)
' how many days difference are there
intDays = DateDiff("d", DateAdd("m", intMonths, date1), date2)
Debug.Print (intDays)
' how many hours difference are there
intHours = DateDiff("h", datStartOfLastMonth, date2)
Debug.Print (intHours)
' how many minutes different are there
datStartOfLastHour = datStartOfLastMonth + (DatePart("h", date2) / 24)
intMinutes = DateDiff("n", datStartOfLastHour, date2)
Debug.Print (intMinutes)
Else
' Dates are in the same month
intMonths = 0
Debug.Print (intMonths)
' how many days difference are there
intDays = DateDiff("d", date1, date2)
Debug.Print (intDays)
' how many hours difference are there
intHours = DateDiff("h", datStartOfLastMonth, date2)
Debug.Print (intHours)
' how many minutes different are there
datStartOfLastHour = datStartOfLastMonth + (DatePart("h", date2) / 24)
intMinutes = DateDiff("n", datStartOfLastHour, date2)
Debug.Print (intMinutes)
End If
strResult = intMonths & ":" & intDays & ":" & intHours & ":" & intMinutes
MyDateDiff = strResult
End Function
Testing this:
?MyDateDiff("01-SEP-2014", "03-Oct-2014 22:15:33")
Gives:
1:2:22:15
i.e. 1 month, 2 days, 22 minutes and 15 seconds.
Reverse testing this by adding the components back onto date1 gives:
?DateAdd("n",15,DateAdd("h",22,DateAdd("d",2,DateAdd("m",1,"01-SEP-2014"))))
= "03-Oct-2014 22:15:33"
If we try with 2 dates in the same month:
?MyDateDiff("01-SEP-2014", "03-SEP-2014 22:15:33")
We get:
0:2:22:15
Reverse testing this:
?DateAdd("n",15,DateAdd("h",22,DateAdd("d",2,DateAdd("m",0,"01-SEP-2014"))))
Gives:
03/09/2014 22:15:00
But you may want to account for dates being the wrong way round...and you may only want date1 to be counted as a partial date if it starts later in the day....as I say, just a thought.
Regards
i
This may give you some ideas to correct for days in month or leap year Feb
Private Sub CommandButton1_Click()
DoDateA
End Sub
Sub DoDateA()
Dim D1 As Date, D2 As Date, DC As Date, DS As Date
Dim CA: CA = Array("", "yyyy", "m", "d", "h", "n", "s", "s")
Dim Va%(7), Da(7) As Date, Ci%
D1 = Now + Rnd() * 420 ' vary the * factors for range of dates
D2 = Now + Rnd() * 156
If D1 > D2 Then
[b4] = "Larger"
Else
[b4] = " smaller"
DS = D1
D1 = D2
D2 = DS
End If
[d4] = D1
[e4] = D2
DC = D2
For Ci = 1 To 6
Va(Ci) = DateDiff(CA(Ci), DC, D1)
DC = DateAdd(CA(Ci), Va(Ci), DC)
Va(Ci + 1) = DateDiff(CA(Ci + 1), DC, D1)
If Va(Ci + 1) < 0 Then ' added too much
Va(Ci) = Va(Ci) - 1
DC = DateAdd(CA(Ci), -1, DC)
Cells(9, Ci + 3) = Va(Ci + 1)
Cells(8, Ci + 3) = Format(DC, "yyyy:mm:dd hh:mm:ss")
End If
Da(Ci) = DC
Cells(5, Ci + 3) = CA(Ci)
Cells(6, Ci + 3) = Va(Ci)
Cells(7, Ci + 3) = Format(Da(Ci), "yyyy:mm:dd hh:mm:ss")
Cells(10, Ci + 3) = DateDiff(CA(Ci), D2, D1)
Next Ci
End Sub