Excel VBA to force numeric value into time format - vba

There are two columns copied into a workbook from a Access database.
I want to ensure that the data is formatted correctly so I added this code:
'DateTime Column
Sheets("Sheet1").Columns("A:A").Select
Selection.NumberFormat = "m/d/yyyy hh:mm"
'Time Column
Sheets("Sheet1").Columns("B:B").Select
Selection.NumberFormat = "hh:mm"
The datetime column formats correctly.
The time column is initially copied as a numeric equivalent (ie 0.595277777777778) instead of the time value (14:17).
Running the macro code does nothing to the visual display and it isn't until I hit F2 and enter on the cell that the format applies.
Is there a method (short of a loop) to force Excel to apply the formatting?

You can use VBA to accomplish the same effect as Steve Homer's answer by setting the range's value property to itself:
Dim r As Range
Set r = Sheets("Sheet1").Columns("B:B")
r.Value = r.Value

If you copy the column and paste as values (through a macro if needs be) then Excel should re-interpret the data type and the above should work correctly.

You can do this with out declare TMP as DATE:
TMP = CDate(Range("A1").Value) ' we suppose A1 value is 12:45:00
TMP = "" & TMP ' convert to char
TMP = Left(TMP, 5) ' extract the first 5 char
MsgBox TMP ' for displaying 12:45

Related

"Runtime error 13 - Type mismatch" when parsing date from a text cell

I'm importing a .csv file from another program into Excel. The date format is text, formatted as follows :
mm/dd/yy or
07/03/17
The imported file is very unstructured, with more than just dates in the first field.
I want to write 2017-07-03 into the cell (2,13)
Here is the code I'm using
ActiveSheet.Cells(2, 13).Select
ActiveCell.FormulaR1C1 = "=IF(LEN(RC[-12]))=8, _ 'How I identify date
20&MID((RC[-12]),7,2)&" - "& 'To get 2017 4 digit Year
MID((RC[-12]),1,2)&" - "& 'To extract 2 digit month
MID((RC[-12]),4,2)),"""")" 'To extract 2 digit day
This gives me Runtime error 13 - Type mismatch.
I think that my code is causing the error by mixing values and text, but I cannot see where.
The reasons for your error message is due to the formula not being properly created.
It should look like:
Cells(2, 13).FormulaR1C1 = "=IF(LEN(RC[-12])=8, 20 & MID(RC[-12],7,2) & ""-"" & MID(RC[-12],1,2) & ""-"" & MID(RC[-12],4,2),"""")"
Instead of writing formulas to the worksheet, I suggest doing the conversion within VBA and then writing the results to the worksheet. This can make your code easier to understand, debug, and maintain in the future.
The code below could be shortened, but purposely is not so as to provide more clarity. It is written as a macro that will process everything in column A, and write the dates to column M, in the format you specify.
I note that in your question, you specify a format of 2017-07-03, but in your code, you generate a format of 2017 - 07 - 03. I generated the former in the code, but it should be obvious how to change to the latter if that is what you really want.
Also note that in the code I used the default conversion for Excel for 2-digit years, where two digit years are assumed to be in the range 1930 - 2029. That can be changed if necessary.
The code uses a more involved method of assuring the value being converted is truly a date. But it does not check for "illegal" dates and will convert, for example 2/31/17 to 2017-03-03. Your formula method would return the string 2017-02-31 It would be trivial, in the VBA macro, to add code to flag this kind of problem, if it might be an issue.
There are other ways to check for valid dates, including seeing if CDate or VBA's DateValue functions return a date or an error. But these may not work properly across workbooks in different locale's, with different default short date formats in the windows Regional Settings.
Instead of writing the results as text, the results could be written as a real date formatted as you wish with the .numberformat property of the cell (which could be used in future calculations), and that option is in the comments in the macro.
If you require that the result be dynamic, with a formula, the macro could be easily converted into a User Defined Function, but you would have to assure that the cell format is "text" else Excel will try to convert the resultant date into a "real date" (depending on which of the two formats you really want).
Post back with any questions about the code.
Option Explicit
Sub ConvertOnlyDates()
Dim V As Variant
Dim YR As Long, MN As Long, DY As Long
Dim DT As Date
Dim WS As Worksheet
Dim rSrc As Range, C As Range
'Define the range to check: Columns A
'Always best to explicitly define worksheets and cells
' and not rely on ActiveSheet, Activate, Select, etc
Set WS = Worksheets("sheet2")
With WS
Set rSrc = .Range(.Cells(1, 1), .Cells(.Rows.Count, 1).End(xlUp))
End With
For Each C In rSrc
'check if a date
V = Split(C.Text, "/")
If UBound(V) = 2 Then
If V(0) > 0 And V(0) <= 12 _
And V(1) > 0 And V(1) <= 31 _
And V(2) >= 0 And V(2) <= 99 Then
MN = V(0)
DY = V(1)
'note that this is Excel's default (at least for now)
YR = V(2) + IIf(V(2) < 30, 2000, 1900)
DT = DateSerial(YR, MN, DY)
'Can be written as text
' or as a real date with proper formatting
' REAL DATE
'With C.Offset(0, 12) 'write in column M
' .NumberFormat = "yyyy-mm-dd"
' .Value = DT
'End With
With C.Offset(0, 12)
.NumberFormat = "#"
.Value = Format(DT, "yyyy-mm-dd")
End With
End If
End If
Next C
End Sub
You haven't appropriately closed your strings with double quotes for each line. Using the continuation character _ doesn't allow you to break a string in the middle. You can do this if you properly concatenate:
ActiveCell.FormulaR1C1 = "=IF(LEN(RC[-12]))=8," & _ 'How I identify date
"20&MID((RC[-12]),7,2)&" - " & _ 'To get 2017 4 digit Year
"MID((RC[-12]),1,2)&" - " & _ 'To extract 2 digit month
"MID((RC[-12]),4,2)),"""")" 'To extract 2 digit day
(Your code will be far more readable if you take the time to indent continued lines in the fashion shown above. You can more quickly and easily pick out the destination variable and the assignment if you follow this format.)

VBA - Converting a mixed row ( Data Type wise) to Date

I have an excel sheet, one of the columns is mixed with Dates and Dates that has been copied to it as text ( see below ).
I dont manage to convert the text type to Date type, i need to do it though VBA to add it to some automation im working on. is there a way to do this at all ?
I noticed excel is looking for format like this 03/09/2016 23:39:57 and it doesn't like 3/21/16 11:07:22 PM, apparently this is my case :) every look i run i get ( obviously data mismatch ), in the image bellow the spoken column is "C"
thx :)
ExcelSheet bad Date format
Assuming wvery bad dates are MM/DD/YYYY, then you could use the following code that I wrote for you:
Sub main()
Dim celda As Range
Dim s_date As String
Dim s_time As String
Dim validate_date As String
Dim valid_date As String
Dim date_arr() As String
Dim rango As Range
Dim limit As Long
limit = Columns("B").Find("", Cells(Rows.Count, "B")).Row - 1
Set rango = ActiveSheet.Range("B2:B" & limit)
' works only for date values, another value would return non expected values
For Each celda In rango
validate_date = Left(celda.Value, 1)
If validate_date <> "" Then
If Not celda.Rows.Hidden Then
If validate_date <> "0" Then
s_date = Trim(Mid(celda.Value, 1, InStr(1, celda.Value, " ") - 1))
s_time = Trim(Mid(celda.Value, InStr(1, celda.Value, " "), Len(celda.Value) - InStr(1, celda.Value, " ")))
date_arr = Split(s_date, "/")
valid_date = date_arr(1)
valid_date = valid_date & "/0" & date_arr(0)
valid_date = valid_date & "/" & date_arr(2)
valid_date = valid_date & " " & s_time
celda.Offset(0, 1).Value = CDate(valid_date)
End If
End If
End If
Next celda
End Sub
In order to use this code you should insert one empty column to the right from target. Second, you should to select entire C column and run the macro.
Edit 1. Ok, this macro autoselect column B. Select column dates is not necessary now.
Excel has parsed the dates according to your Windows Regional Settings short date format. Those that it could not parse (where the month>12) it left as text. Since there was initially a difference between the date format in the text file, and the date format in your Windows Regional settings, it is likely that many of the dates that appear as dates (or as unformatted numbers) were converted incorrectly.
You have a few options:
Import the text file using the Get External Data tab From Text option on the Data Ribbon. This will open up the text import wizard and allow you to specify the date format of the data being imported.
Change your Windows Regional settings short date format to match that in the text file.
Those are probably the two simplest options. The first can be automated through VBA. The second, not so much.

Excel VBA Application.Match between Long Time and Custom format

I can't for the life of me get this to work.
I have a column r of time values formatted as "yyyy-mm-dd hh:mm:ss.000 AM/PM" (this format is one of the Custom formats one can choose for a cell).
I also have a cell c containing a time value formatted as "*hh:mm:ss" (the first Time format).
I now want to find on which row i the c.Value is in range r. I do this using
i = Application.Match(c.Value, r, 1)
On this row I get the 'Run-time error '13': Type mismatch' and my guess is that it is because the cells in r has a Custom format, or because there is no date in c.Value.
How can I get this to work? Is there some other way I can get the placement of c.Value in the range r?
Code:
Sub test()
Dim r As Range
Set r = Range("A1:A10")
Dim c As Range
Set c = Range("B1")
Dim i As Integer
i = Application.Match(c.Value, r, 1) 'ERROR!
End Sub
SOLVED:
I didn't know Excel treats dates and times as numbers, so I got it to work when saving c.Value as a type Double before using it in the function.
SOLVED:
I didn't know Excel treats dates and times as numbers, so I got it to work when saving c.Value as a type Double before using it in the function.

sumif code returns error when using column number?

I have a quick question... not sure what I am doing wrong.
I would like to have a named range (single cell) updated with the value from a sumif based on data in another tab of excel. the formula should go through column 2 look for the date and sum any values in column 10.
even when I substitute out the columns with actual hard column letters, I am getting error 1004 method range of object worksheet failed. how can I re-code this to pick up sumif data from another tab?
here is my code
with data_ws
date = #5/13/2014#
[named_range] = worksheetfunction.sumif(.range(.columns(2)), date, _
.range(.columns(10))
end with
You are close and may have an idea from below why yours are not working:
Sub TestSumIf()
Dim oRngA As Range, oRngB As Range
With ActiveCell
.ClearContents
Set oRngA = .Columns(2).EntireColumn ' 1st EntireColumn on the right
Set oRngB = .Columns(3).EntireColumn ' 2nd EntireColumn on the right
.Value = WorksheetFunction.SumIf(oRngA, Date, oRngB)
End With
End Sub
Sample:

How to convert multiple column from text to date?

In my excel file, there are hundred columns. I want to convert some columns (eg. Column A, C,F, G..) from text to date. It really take time if manually change each column one column by one.
How can I do it ? By using VBA ?
The original text column format just like '31-Dec-2011 00:00:00'. I want to convert to 'dd/mm/yyyy' 31/12/2011
Thanks
If you actually want to chop the time off in each of the cells then this might be an approach:
If the target times are in column A of a sheet called "target" and the column header in A1 is "StartTime"
You could amend the below and add an argument so that it takes the column address. Then it could be called several times to carry out this operation on several columns.
Sub ChopOffTime()
dim mySheetName as string
mysheetname = "target" '<<<<change to your sheet name
myLstRow = Excel.ActiveWorkbook.Sheets(mysheetname ).Cells(Excel.ActiveWorkbook.Sheets(mysheetname ).Rows.Count, Excel.ActiveWorkbook.Sheets(mysheetname).Range("A2").Column).End(Excel.xlUp).Row
With Excel.ActiveWorkbook.Sheets(mysheetname)
.Columns("B:B").Insert Excel.xlToRight
.Range("B2:B" & myLstRow).FormulaR1C1 = "=TIME(HOUR(RC[-1]),MINUTE(RC[-1]), SECOND(RC[-1]))"
.Range("B1") = "StartTime" '<<<<<change to appropriate header
.Columns("B:B").Copy
.Columns("A:A").PasteSpecial Excel.xlPasteValues
.Columns("B:B").Delete Excel.xlToLeft
End With
End Sub
Thanks all.
To simplified the procedure, I just developed some macro for user to run to change the column format, and then they can import the excel the mdb without error.
Use the following for the columns in question:
Columns("A:A").Select
Selection.NumberFormat = "m/d/yyyy"