I have cells that can either contain time in this format:
1625 (16 for 2016 and 25 for week 25)
Or in this format
2016-Q2 (Q2 means quarter 2 if the year)
When converting I want quarters to be the mid week of the quarter
2016-Q1 = 1608
2016-Q2 = 1620
2016-Q3 = 1633
2016-Q4 = 1646
I dont want to convert the times in the cell its in. I want to convert it to YYWW format for a formula for a timeline in another sheet. So I use help cells with the converted value and reference those instead of the values in the other sheet.
I have done this with nested if functions resulting in mile long formulas because the timeline needs to be very long and the time can very well be 2025-Q3.
a =IF('Gulpilspuls NT'!U4="2016-Q1";1608;IF('Gulpilspuls NT'!U4="2016-Q2";1620;IF('Gulpilspuls NT'!U4="2016-Q3";1633;IF('Gulpilspuls NT'!U4="2016-Q4";1646;IF('Gulpilspuls NT'!U4="2017-Q1";1708;IF('Gulpilspuls NT'!U4="2017-Q2";1720;IF('Gulpilspuls NT'!U4="2017-Q3";1733;IF('Gulpilspuls NT'!U4="2017-Q4";1746;IF('Gulpilspuls NT'!U4="2018-Q1";1808;IF('Gulpilspuls NT'!U4="2018-Q2";1820;IF('Gulpilspuls NT'!U4="2018-Q3";1833;IF('Gulpilspuls NT'!U4="2018-Q4";1846;IF('Gulpilspuls NT'!U4="2019-Q1";1908;IF('Gulpilspuls NT'!U4="2019-Q2";1920;IF('Gulpilspuls NT'!U4="2019-Q3";1933;IF('Gulpilspuls NT'!U4="2019-Q4";1946;IF('Gulpilspuls NT'!U4="2020-Q1";2008;IF('Gulpilspuls NT'!U4="2020-Q2";2020;IF('Gulpilspuls NT'!U4="2020-Q3";2033;IF('Gulpilspuls NT'!U4="2020-Q4";2046;IF('Gulpilspuls NT'!U4="2021-Q1";2108;IF('Gulpilspuls NT'!U4="2021-Q2";2120;IF('Gulpilspuls NT'!U4="2021-Q3";2133;IF('Gulpilspuls NT'!U4="2021-Q4";2146;IF('Gulpilspuls NT'!U4="2022-Q1";2208;IF('Gulpilspuls NT'!U4="2022-Q2";2220;IF('Gulpilspuls NT'!U4="2022-Q3";2233;IF('Gulpilspuls NT'!U4="2022-Q4";2246;IF('Gulpilspuls NT'!U4="2023-Q1";2308;IF('Gulpilspuls NT'!U4="2023-Q2";2320;IF('Gulpilspuls NT'!U4="2023-Q3";2333;IF('Gulpilspuls NT'!U4="2023-Q4";2346;IF('Gulpilspuls NT'!U4="2024-Q1";2408;IF('Gulpilspuls NT'!U4="2024-Q2";2420;IF('Gulpilspuls NT'!U4="2024-Q3";2433;IF('Gulpilspuls NT'!U4="2024-Q4";2446;IF('Gulpilspuls NT'!U4="2025-Q1";2508;IF('Gulpilspuls NT'!U4="2025-Q2";2520;IF('Gulpilspuls NT'!U4="2025-Q3";2533;IF('Gulpilspuls NT'!U4="2025-Q4";2546;IF('Gulpilspuls NT'!U4="2026-Q1";2608;IF('Gulpilspuls NT'!U4="2026-Q2";2620;IF('Gulpilspuls NT'!U4="2026-Q3";2633;IF('Gulpilspuls NT'!U4="2026-Q4";2646;IF('Gulpilspuls NT'!U4="2027-Q1";2708;IF('Gulpilspuls NT'!U4="2027-Q2";2720;IF('Gulpilspuls NT'!U4="2027-Q3";2733;IF('Gulpilspuls NT'!U4="2027-Q4";2746;IF('Gulpilspuls NT'!U4="2028-Q1";2808;IF('Gulpilspuls NT'!U4="2028-Q2";2820;IF('Gulpilspuls NT'!U4="2028-Q3";2833;IF('Gulpilspuls NT'!U4="2028-Q4";2846;IF('Gulpilspuls NT'!U4="2029-Q1";2908;IF('Gulpilspuls NT'!U4="2029-Q2";2920;IF('Gulpilspuls NT'!U4="2029-Q3";2933;IF('Gulpilspuls NT'!U4="2029-Q4";2946;IF('Gulpilspuls NT'!U4="2030-Q1";3008;IF('Gulpilspuls NT'!U4="2030-Q2";3020;IF('Gulpilspuls NT'!U4="2030-Q3";3033;IF('Gulpilspuls NT'!U4="2030-Q4";3046;IF('Gulpilspuls NT'!U4="2031-Q1";3108;IF('Gulpilspuls NT'!U4="2031-Q2";3120;IF('Gulpilspuls NT'!U4="2031-Q3";3146;IF('Gulpilspuls NT'!U4="2031-Q4";3146;IF('Gulpilspuls NT'!U4="2032-Q1";3208;IF('Gulpilspuls NT'!U4="2032-Q2";3220;IF('Gulpilspuls NT'!U4="2032-Q3";3233;IF('Gulpilspuls NT'!U4="2032-Q4";3246;IF('Gulpilspuls NT'!U4="2033-Q1";3308;IF('Gulpilspuls NT'!U4="2033-Q2";3320;IF('Gulpilspuls NT'!U4="2033-Q3";3333;IF('Gulpilspuls NT'!U4="2033-Q4";3346;IF('Gulpilspuls NT'!U4="2034-Q1";3408;IF('Gulpilspuls NT'!U4="2034-Q2";3420;IF('Gulpilspuls NT'!U4="2034-Q3";3433;IF('Gulpilspuls NT'!U4="2034-Q4";3446;IF('Gulpilspuls NT'!U4="2035-Q1";3508;IF('Gulpilspuls NT'!U4="2035-Q2";3520;IF('Gulpilspuls NT'!U4="2035-Q3";3533;IF('Gulpilspuls NT'!U4="2035-Q4";3546;IF('Gulpilspuls NT'!U4="2036-Q1";3608;IF('Gulpilspuls NT'!U4="2036-Q2";3620;IF('Gulpilspuls NT'!U4="2036-Q3";3633;IF('Gulpilspuls NT'!U4="2036-Q4";3646;IF('Gulpilspuls NT'!U4="2037-Q1";3708;IF('Gulpilspuls NT'!U4="2037-Q2";3720;IF('Gulpilspuls NT'!U4="2037-Q3";3733;IF('Gulpilspuls NT'!U4="2037-Q4";3746;IF('Gulpilspuls NT'!U4="2038-Q1";3808;IF('Gulpilspuls NT'!U4="2038-Q2";3820;IF('Gulpilspuls NT'!U4="2038-Q3";3833;IF('Gulpilspuls NT'!U4="2038-Q4";3846;'Gulpilspuls NT'!U4))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
As you can clearly see this method is not the best. I cant make it this long because nested if functions can only contain 64 levels of nesting. Do you guys have a better suggestion for this?
The formula has to work with both formats of time entry and I need it to be able to convert all the cells 1:1 meaning 1 cell in the calendar has to be 1 converted cell in the other spot that I can use for the formula. If the cell in the calendar does not have YYYY-Q1234? it should just show what it is instead as you can see at the end of my formula.
Here is your formula.
=IF(AND(LEN(C6)=4,ISERROR(FIND("-",C6))),C6,MID(C6,3,2)&INDEX({"08",20,33,46},RIGHT(C6,1)))
Make sure there is no excess space in your data. Not like this "2016-Q1 ", but like this "2016-Q1".
EDIT: I just realized that if the original is in the format of YYWW, that you do NOT want it changed to the mid quarter week number. So we simplify the formulas:
=IF(ISNUMBER(-A1),A1,MID(A1,3,2) & CHOOSE(RIGHT(A1,1),"08",20,33,46))
and if you want YYWW to always be rendered as numeric:
=1*IF(ISNUMBER(-A1),A1,MID(A1,3,2) & CHOOSE(RIGHT(A1,1),"08",20,33,46))
And here are the results for various samples:
EDIT: If you need to check for blanks, you can do this simply:
=IF(LEN(A1)=0,"",1*IF(ISNUMBER(-A1),A1,MID(A1,3,2) & CHOOSE(RIGHT(A1,1),"08",20,33,46)))
However, if a 0 will not result in a downstream problem, you can use the original, shorter formula, and merely use a custom format to suppress zero returns: 0;;
And if you need to check for other conditions for which you don't want to process, you can perform similar actions.
something like this should do it, however, mid way through Q1, is week 6, so you'll need to adjust if your year doesn't start at 1/1
Function get_week(strInput As String) As String
Dim strQ As String
Dim bytQ As Byte
Dim dblMultiplier As Double
Dim intWeekNumber As Integer
strQ = Split(strInput, "-")(0)
bytQ = CByte(Right(strQ, 1))
dblMultiplier = (bytQ - 1) / 4
intWeekNumber = (dblMultiplier * 52)
intWeekNumber = intWeekNumber + (13 / 2)
get_week = Split(strInput, "-")(1) & "-" & CStr(intWeekNumber)
End Function
Let me try again
="20"&LEFT(N5,2)&IF(MOD(N5,100)<=8,"-Q1",IF(MOD(N5,100)<=20,"-Q2",IF(MOD(N5,100)<=33,"-Q3",if(MOD(N5,100)<=46,"-Q4","-Q1"))))
Should work for everything past year 2000 ;)
Related
I am writing a function which takes a date and converts into a string of characters so i can use that string of characters to save an export file. so 12/10/2019 becomes 12102019.
I ran into a problem and i believe I may not be using the len() function correctly.
I wanted to ensure that single digit months and days, ie 1/1/2019 appeared as this 01012019
I created a loop to go through an entire calendar year to test my function.
dim x as date
if len(x) = 8 then
debug.print x
elseif len(x) = 9 then
debug.print x
end if
imagine this is in a loop.
when len(x) = 8, no problem. i get the date ie 1/1/2019
when len(x) = 9, ie 1/10/2019, it won't process the elseif.
am i using the len() function correctly? is there something else i should be using?
thanks
Groundhog
len() in VBA will give you the length of the date. In VBA many data types are actually stored as doubles under the hood. That's why you're not seeing the String length of the date, but the length of the number of digits in the doubles value.
You can test this in excel, these dates:
1/1/2019
1/10/2019
When formatted as Numbers (5 digits length):
43466
43739
To fix it you can follow #braX & Ken's advice with Format$(x, "yyyymmdd"), you could enclose in quotes and deduct 2 from the length, or cast the dates and work with them as strings in VBA.
Goodafternoon all,
Currently, I'm trying to fill a table with the following in the first row, which is needed for the VLOOKUP. I would like to have this row defined as "yyyy-ww", so for this week "2016-15". This works fine, however when it is earlier in the year, the weeks will be only 1 digit, "2016-1" instead of the expected "2016-01". Formatting does not work unfortunately.
Can anyone please help me out?
The formula is basically putting year, "-", current week together, then shifting up to 12 weeks minus (so, we're in week 15 now, I would like to have week 03 to 15 displayed). How do I get the weeks displayed in the right format?
Range("A4").FormulaR1C1 = "=CONCATENATE(YEAR(TODAY()),""-"",INT((TODAY()-DATE(YEAR(TODAY()-WEEKDAY(TODAY()-1)+4),1,3)+WEEKDAY(DATE(YEAR(TODAY()-WEEKDAY(TODAY()-1)+4),1,3))+5)/7)-12)"
Range("A5").FormulaR1C1 = "=CONCATENATE(YEAR(TODAY()),""-"",INT((TODAY()-DATE(YEAR(TODAY()-WEEKDAY(TODAY()-1)+4),1,3)+WEEKDAY(DATE(YEAR(TODAY()-WEEKDAY(TODAY()-1)+4),1,3))+5)/7)-11)"
Range("A6").FormulaR1C1 = "=CONCATENATE(YEAR(TODAY()),""-"",INT((TODAY()-DATE(YEAR(TODAY()-WEEKDAY(TODAY()-1)+4),1,3)+WEEKDAY(DATE(YEAR(TODAY()-WEEKDAY(TODAY()-1)+4),1,3))+5)/7)-10)"
Range("A7").FormulaR1C1 = "=CONCATENATE(YEAR(TODAY()),""-"",INT((TODAY()-DATE(YEAR(TODAY()-WEEKDAY(TODAY()-1)+4),1,3)+WEEKDAY(DATE(YEAR(TODAY()-WEEKDAY(TODAY()-1)+4),1,3))+5)/7)-9)"
Range("A8").FormulaR1C1 = "=CONCATENATE(YEAR(TODAY()),""-"",INT((TODAY()-DATE(YEAR(TODAY()-WEEKDAY(TODAY()-1)+4),1,3)+WEEKDAY(DATE(YEAR(TODAY()-WEEKDAY(TODAY()-1)+4),1,3))+5)/7)-8)"
Range("A9").FormulaR1C1 = "=CONCATENATE(YEAR(TODAY()),""-"",INT((TODAY()-DATE(YEAR(TODAY()-WEEKDAY(TODAY()-1)+4),1,3)+WEEKDAY(DATE(YEAR(TODAY()-WEEKDAY(TODAY()-1)+4),1,3))+5)/7)-7)"
Range("A10").FormulaR1C1 = "=CONCATENATE(YEAR(TODAY()),""-"",INT((TODAY()-DATE(YEAR(TODAY()-WEEKDAY(TODAY()-1)+4),1,3)+WEEKDAY(DATE(YEAR(TODAY()-WEEKDAY(TODAY()-1)+4),1,3))+5)/7)-6)"
Range("A11").FormulaR1C1 = "=CONCATENATE(YEAR(TODAY()),""-"",INT((TODAY()-DATE(YEAR(TODAY()-WEEKDAY(TODAY()-1)+4),1,3)+WEEKDAY(DATE(YEAR(TODAY()-WEEKDAY(TODAY()-1)+4),1,3))+5)/7)-5)"
Range("A12").FormulaR1C1 = "=CONCATENATE(YEAR(TODAY()),""-"",INT((TODAY()-DATE(YEAR(TODAY()-WEEKDAY(TODAY()-1)+4),1,3)+WEEKDAY(DATE(YEAR(TODAY()-WEEKDAY(TODAY()-1)+4),1,3))+5)/7)-4)"
Range("A13").FormulaR1C1 = "=CONCATENATE(YEAR(TODAY()),""-"",INT((TODAY()-DATE(YEAR(TODAY()-WEEKDAY(TODAY()-1)+4),1,3)+WEEKDAY(DATE(YEAR(TODAY()-WEEKDAY(TODAY()-1)+4),1,3))+5)/7)-3)"
Range("A14").FormulaR1C1 = "=CONCATENATE(YEAR(TODAY()),""-"",INT((TODAY()-DATE(YEAR(TODAY()-WEEKDAY(TODAY()-1)+4),1,3)+WEEKDAY(DATE(YEAR(TODAY()-WEEKDAY(TODAY()-1)+4),1,3))+5)/7)-2)"
Range("A15").FormulaR1C1 = "=CONCATENATE(YEAR(TODAY()),""-"",INT((TODAY()-DATE(YEAR(TODAY()-WEEKDAY(TODAY()-1)+4),1,3)+WEEKDAY(DATE(YEAR(TODAY()-WEEKDAY(TODAY()-1)+4),1,3))+5)/7)-1)"
Range("A16").FormulaR1C1 = "=CONCATENATE(YEAR(TODAY()),""-"",INT((TODAY()-DATE(YEAR(TODAY()-WEEKDAY(TODAY()-1)+4),1,3)+WEEKDAY(DATE(YEAR(TODAY()-WEEKDAY(TODAY()-1)+4),1,3))+5)/7))"
you could have the desired format and shorten the code with the following
Range("A4").Resize(12).FormulaR1C1 = "=CONCATENATE(YEAR(TODAY()),""-"", TEXT( INT((TODAY()-DATE(YEAR(TODAY()-WEEKDAY(TODAY()-1)+4),1,3)+WEEKDAY(DATE(YEAR(TODAY()-WEEKDAY(TODAY()-1)+4),1,3))+5)/7)-(12-rows(R4:R)) ,""00""))"
You can format you integer to allways have 2 digits.
Format(iMyInt, "00")
If you're willing to bring your formula into VBA, you can use DatePart to more efficiently extract the week number, and then Format to get the leading zero you desire.
The last line of your formula would become as follows:
Range("A16").FormulaR1C1 = Year(Now()) & "-" & Format(DatePart("ww", Now()), "00")
while the first would be
Range("A4").FormulaR1C1 = Year(Now()) & "-" & Format(DatePart("ww", Now()) - 12, "00")
Calling DatePart("ww",Now()) tells VBA to return the week part of todays date, wrapping this in Format tells it to output it in the format you seek.
A word of warning, however - this seems to return a value of 16 for today's date, so you may need to check your week definition against that used in DatePart, if you choose to use it.
As you are adding the formulae in VBA, you may be better off getting the field value there instead:
range("A4").value = format(now,"yyyy") & "-" & format(format(dateadd("ww",-x,now),"ww"),"00")
where x is the number of weeks ago you want.
However, if you are intending to use the formula so that it will update without any interference then you can use the TEXT() function in the same way that VBA uses Format().
Range("A4").FormulaR1C1 = "=CONCATENATE(YEAR(TODAY()),""-"",TEXT((INT((TODAY()-DATE(YEAR(TODAY()-WEEKDAY(TODAY()-1)+4),1,3)+WEEKDAY(DATE(YEAR(TODAY()-WEEKDAY(TODAY()-1)+4),1,3))+5)/7)-12),"00"))"
A word of caution. VLookup works off the underlying field value, so if you are looking up from a date displayed as 2016-15, then the lookup will still fail. In this case, you might need to make sure that both dates are set to the first day of the working week to ensure a match.
I have a data import file that has dates on it without a comma (i.e. January 1 2015). Excel won't recognize this as a date, and I need to work with these dates to find other dates (i.e. Date + Length of trip to find the last day of the trip, etc.)
I'm trying to use VBA to accomplish this and have the logic down but I'm encountering an error.
I'm taking the length of the date (January 1 2015), the 5 right characters (2015), the left of the whole length minus the 5 right characters(JANUARY 1), and then combining these variables with a comma inserted: Left(value-5) & ", " & Right(value, 5)
I'm using this code:
'correct date from JANUARY 1 2000 to JANUARY 1, 2000 so excel can recognize as date
LengthTrpDpt = Len(wb1.Sheets("BL Import").Cells(ioi, TrpDepCol)) 'length of date
LengthRightTrpDPt = Right(wb1.Sheets("BL Import").Cells(ioi, TrpDepCol), 5) 'finds right 5 of date " 2015"
NewListedDate = Left(wb1.Sheets("BL Import").Cells(ioi, TrpDepCol), LengthTrpDpt - 5) & ", " & LengthRightTrpDPt
The problem is with the NewListedDate variable. I can change the part LengthTrpDpt - 5 to a number and it works fine. For some reason I can't have an equation here though. I tried perform the equation in a separately saved variable (LengthMath = LengthTrpDpt - 5) and using LengthMath instead, but that doesn't work either.
LengthTrpDpt works fine and MsgBox's the correct number. Any ideas? Thanks!
You should just Split() the date string to get your three parts, then piece them back together however you'd like:
Dim a
a = Split(wb1.Sheets("BL Import").Cells(ioi, TrpDepCol))
NewListedDate = a(0) & " " & a(1) & ", " & a(2)
Use Range.TextToColumns method on the column of text-that-look-like-dates.
with worksheets("Sheet1").columns(1) '<-change this to reflect the actual worksheet and column
.TextToColumns Destination:=.cells(1,1), DataType:=xlFixedWidth, FieldInfo:=Array(0, 3)
end with
The 0 tells T2C that it should just put everything back into the original column. The 3 is the MDY TextFileColumnDataTypes property.
imho, it is ALWAYS better to work with numbers and dates rather than a string representation approximating them.
I am currently learning VBA programming by doing, and have encountered the below situation with which I would appreciate your help. Ideally not just in finding a solution, but also to understand how and why the solution works.
Say that there is a database from which one can export a spreadsheet of data. One of the columns has date values, but they are badly formatted from the export. The system sends the dates as mm/dd/yyyy hh:mm AM/PM, for example, 04/11/2014 09:24 AM, but the spreadsheet has this identified as dd/mm/..., meaning it enters 04 as the day and 11 as the month.
Within this column, if the day is before or including 12 of the month, the cell is formatted as date. If the day is past the 12th, the cell is formatted with a general format.
My question is, could I write a VBA macro that could reverse the values for day and month and create the correct dates in a new column? I would think that it would first have to identify if a cell is formatted as date, and then somehow extract the date and month in the correct positions, or if it's formatted as a general format, and then use a different code to extract the correct date.
If this is too basic an issue for this community and there's another community more suited, I will gladly repost my question there.
EDIT:
After my comment below I played around with functions and looked for other similar functions that may help do what I need, switch the day value with the month value, and so far I have:
'for dates with general format: 04/14/2014 11:20 AM
=DATE(MID(A1,7,4),LEFT(A1,2),MID(A1,4,2)) 'in a column for the date
=TIME(MID(A1,12,2),MID(A1,15,2),"00") 'in a column for time, since I may need this
'for dates with a date format: 4/11/2014 7:35:00 PM
=DATE(TEXT(A1,"yyyy"),TEXT(A1,"dd"),TEXT(A1,"mm")) 'in a column for the date
=TEXT(A1,"hh:mm AM/PM") 'in a column for time
Now I just need to figure out a conditional function to identify when to apply each set of formulas according to the values or formatting or column A.
But are there equivalent functions to achieve this through VBA? I need these date and time columns to only hold values, not formulas, so that I may export the data out of them directly. And somehow putting this in VBA code seems more "clean" to me, using formulas feels to me like a volatile solution. I'm not sure how to explain this properly, but I'm somehow more confortable with proper coding behind my data manipulation.
EDIT2:
I've resolved the worksheet functions solution as below. It took me a while to figure out how to go around the FIND error with date formatted cells, and only found the IFERROR function by chance in the list Excel suggests when writing =IF.
'to get the correct date
=IF(IFERROR(FIND("/",A1),0)>0,DATE(MID(A1,7,4),LEFT(A1,2),MID(A1,4,2)),DATE(TEXT(A1,"yyyy"),TEXT(A1,"dd"),TEXT(A1,"mm")))
'to get the correct time
=IF(IFERROR(FIND("/",A1),0)>0,TIME(MID(A1,12,2),MID(A1,15,2),"00"),TEXT(A1,"h:mm AM/PM"))
Now at least I have a working solution, but I'm still interested in a VBA translation for these formulas and will continue searching for these.
Check this out. Let's take for example your formula:
=IF(IFERROR(FIND("/",A1),0)>0,DATE(MID(A1,7,4),LEFT(A1,2),MID(A1,4,2)),DATE(TEXT(A1,"yyyy"),TEXT(A1,"dd"),TEXT(A1,"mm")))
VBA equivalent functions:
Find = Instr
Date = DateSerial
Text = Format (not exactly the same but the nearest)
Code equivalent:
Dim mydate As Date
Dim myformat As String
myformat = "mm/dd/yyyy hh:mm AM/PM"
If InStr(1, [A1], "/") > 0 Then
mydate = DateSerial(Mid(Format([A1], myformat), 7, 4), _
Left(Format([A1], myformat), 2), Mid(Format([A1], myformat), 4, 2))
Else
mydate = DateSerial(Year([A1]), Month([A1]), Day([A1]))
End If
[B1] = mydate
Take note that [A1] is a shortcut Evaluate function which can also be written as Evaluate("A1").
I used that to refer to Cell A1 as in your formula. You can use the conventional Range Object reference like this: Range("A1"). I used the shortcut because it looks cleaner. But it is not advisable in huge data sets.
For your time formula:
=IF(IFERROR(FIND("/",A1),0)>0,TIME(MID(A1,12,2),MID(A1,15,2),"00"),TEXT(A1,"h:mm AM/PM"))
Code Equivalent:
Dim mytime As Date
If InStr(1, [A1], "/") > 0 Then
mytime = TimeValue([A1])
Else
'~~> myformat is declared above
mytime = TimeValue(Format([A1], myformat))
End If
[C1] = mytime
You can also check the format of the cell like below:
Select Case True
Case [A1].NumberFormat = "General"
mydate = DateSerial(Year([A1]), Month([A1]), Day([A1]))
mytime = TimeValue(Format([A1], myformat))
Case [A1].NumberFormat = myformat '~~> again this is declared above
mydate = DateSerial(Mid(Format([A1], myformat), 7, 4), _
Left(Format([A1], myformat), 2), Mid(Format([A1], myformat), 4, 2))
mytime = TimeValue([A1])
Case Else
MsgBox "Invalid Format. Cannot be evaluated"
End Select
[B1] = mydate: [C1] = mytime
Not sure if above will really solve your problem.
There are just many possibilities when you extract datetime stamp from a database.
If the scenarios you mentioned are only the problems you encounter, then above solutions might work.
This is now an old thread but in case anyone else stumbles upon it (as I did) with a similar problem, I'm just offering this up.
My suggested VBA function for this is shown below. Its style doesn't strictly follow purist programming practice (declaration of variables, etc); it's written, rather, to be relatively easily comprehensible.
Function Date_Text_Convert( _
date_text As String, _
return_with_month_letters As Boolean, _
return_as_date_time_value As Boolean)
' Patrick S., June 2018
' Intention: to enable mm/dd/yyyy[etc] imported text-string dates
' to be switched to dd/mm/yyyy[etc]. Can be adapted for other cases.
' Usage examples: if cell A2 contains the text-string:
' 06/26/2018 09:24 AM
' then in, for example, cell B2, type:
' =Date_Text_Convert(A2,TRUE,FALSE) or =Date_Text_Convert(A2,FALSE,FALSE)
' which returns:
' 26-Jun-2018 09:24 am or 26/06/2018 09:24 am
' To return a date-and-time value instead of a string, use, for example:
' =Date_Text_Convert(A2,TRUE,TRUE)
' establish the positions where the day and month digits start
daypos = 4
mthpos = 1
rempos = 7 ' starting position of remaining part of the string
' establish the length of the relevant text sections: 2 characters each, in this case
daylen = 2
mthlen = 2
' so that,
daytext = Mid(date_text, daypos, daylen)
mthtext = Mid(date_text, mthpos, mthlen)
remtext = Mid(date_text, rempos, 999) ' the remainder of the text string
' format the output according to 'return_with_month_letters'
' there are 2 options available, each using a different separator
sep_stroke = "/"
sep_hyphen = "-"
If return_with_month_letters = True Then
mthnum = mthtext * 1
mthindex = ((mthnum - 1) * 3) + 1
mthname = Mid("JanFebMarAprMayJunJulAugSepOctNovDec", mthindex, 3)
newtext = daytext & sep_hyphen & mthname & sep_hyphen & LCase(remtext) ' LCase optional
Else
newtext = daytext & sep_stroke & mthtext & sep_stroke & UCase(remtext) ' UCase optional
End If
' finally, return the output through the function name: either as a date, or as the text equivalent
If return_as_date_time_value = True Then
newdate = DateValue(newtext) + TimeValue(newtext)
Date_Text_Convert = newdate
Else
Date_Text_Convert = newtext
End If
End Function
I'm looking for a simple macro to specify cells as being of type "time" and typing only numbers (for example "955") will format that (and recognise as) "hh:mm" time. In other words, by typing "955", the cell would interpret to "09:55", whereas all I can have it do right now is interpret to "1902-08-12 00:00:00" (most likely 955 is the day number for 1902-08-12).
EDIT:
Part of the need for this is to allow calculation of times post typing (for example, substract two time values to get a timespan, or add several timespans to get a total).
VBA code:
Dim val As String
val = myCell.Value
Dim newval As String
If Len(val) = 2 Then
newval = "00:" & val
ElseIf Len(val) = 3 Then
newval = "0" & Left(val, 1) & ":" & Right(val, 2)
ElseIf Len(val) = 4 Then
newval = Left(val, 2) & ":" & Right(val, 2)
Else
newval = "Not a valid time"
End If
myCell.Value = newval
This code does not detect if the last two digits are a valid time (greater than 59 minutes), but otherwise it should handle most cases.
You'll also need to add a case if someone types in 1 digit, ie. 1 thru 9 minutes after midnight.
If you want it to be formatted as an actual time (date-time type), then change the formatting of the cell to hh:mm.
The value typed in, for example 955, must be manipulated to produce a fraction of a day.
pseudocode:
(left(myCell,len(myCell)-2) + (right(myCell,2)/60)) / 24
This produces the proper decimal value for how much of the day has elapsed and thus will display as a proper 'Time' in the cell with hh:mm formatting.
This isn't the VBA, but a formula that will change the formatting. You could incorporate this into VBA if you wanted to, but should help as a jumping point.
=TIMEVALUE(IF(LEN(A5)=3,"0"&LEFT(A5,1)&":",LEFT(A5,2)&":")&RIGHT(A5,2))
(If A5 is the cell where you enter 955)
(Also, make sure to format the formula cell as your desired time formatting.)
I can help with the code if needed. Just post back.
For some reason Excel does not allow to use ":" in your custom format.
But if you OK with another delimiter, say dash "-", then you can simply create a custom format like this: ##-##
Of course your time has to be in 24 hours format.
Alternatively, you may first enter all your times just like numbers (or better as text if you don't want to lose trailing zeros). And then run your script to insert semicolons between hours and minutes.