I understand this is a fairly common problem, but I'm yet to find a reliable solution.
I have data in a csv file with the first column formatted dd/mm/yyyy. When I open it with Workbooks.OpenText it defaults to mm/dd/yyyy until it figures out that what it thinks is the month exceeds 12, then reverts to dd/mm/yyyy.
This is my test code, which tries to force it as xlDMYFormat, and I've also tried the text format. I understand this problem only applies to *.csv files, not *.txt, but that isn't an acceptable solution.
Option Base 1
Sub TestImport()
Filename = "test.csv"
Dim ColumnArray(1 To 1, 1 To 2)
ColumnsDesired = Array(1)
DataTypeArray = Array(xlDMYFormat)
' populate the array for fieldinfo
For x = LBound(ColumnsDesired) To UBound(ColumnsDesired)
ColumnArray(x, 1) = ColumnsDesired(x)
ColumnArray(x, 2) = DataTypeArray(x)
Next x
Workbooks.OpenText Filename:=Filename, DataType:=xlDelimited, Comma:=True, FieldInfo:=ColumnArray
End Sub
test.csv contains:
Date
11/03/2010
12/03/2010
13/03/2010
14/03/2010
15/03/2010
16/03/2010
17/03/2010
I had the same problem with the .OpenText method. My Regional Settings are English - AU rather than NZ.
I found another thread that suggested using .open,
( http://www.pcreview.co.uk/forums/date-format-error-csv-file-t3960006.html )
so I tried that
Application.Workbooks.Open Filename:=strInPath, Format:=xlDelimited, Local:=True
and it worked.
I had the exact same problem. This is a function that coverts dd/mm/yyyy to mm/dd/yyyy. Just feed it one date at a time. Hope it helps.
Function convertDate(x As String) As Date
'convert a dd/mm/yyyy into mm/dd/yyyy'
Dim Xmonth
Dim XDay
Dim XYear
Dim SlashLocation
Dim XTemp As String
XTemp = x
SlashLocation = InStr(XTemp, "/")
XDay = Left(XTemp, SlashLocation - 1)
XTemp = Mid(XTemp, SlashLocation + 1)
SlashLocation = InStr(XTemp, "/")
Xmonth = Left(XTemp, SlashLocation - 1)
XTemp = Mid(XTemp, SlashLocation + 1)
XYear = XTemp
convertDate = Xmonth + "/" + XDay + "/" + XYear
End Function
At the end of your "Workbooks.OpenText" line, add Local:=True
Workbooks.OpenText filename:=filename, DataType:=xlDelimited, Comma:=True, FieldInfo:=ColumnArray, Local:=True
This worked on my pc when I changed my region to English(NZ).
EDIT: And now I see somebody else gave the same answer. :-)
Realise this is a little late, but if you combine the local and array qualifiers it should work correctly:
Workbooks.OpenText Filename:=FileName, _
FieldInfo:=Array(Array(1, 4), Array(2, 1)), Local:=True
I am trying to read in a txt file and use Australian date format dd/mm/yyyy but I do know if you are opening a text file with the Workbooks.Open function you can set the date to local.. by adding Local:=True
Ex
Workbooks.Open Filename:=VarOpenWorkbook, Local:=True
this works for me...
This seems to do the trick, but is still a hack. I will add a check that no dates in the range are more than one day apart, to make sure that data imported correctly as dd/mm/yyyy isn't reversed.
Question still open for a solution, rather than a method of patching up the problem.
Thanks to posts thus far.
Function convertDate(x As String) As Date
' treat dates as mm/dd/yyyy unless mm > 12, then use dd/mm/yyyy
' returns a date value
Dim aDate() As String
aDate = Split(x, "/")
If UBound(aDate) <> 2 Then
Exit Function
End If
If aDate(0) > 12 Then
d = aDate(0)
m = aDate(1)
Else
d = aDate(1)
m = aDate(0)
End If
y = aDate(2)
d = Lpad(d, "0", 2)
m = Lpad(m, "0", 2)
If Len(y) = 4 Then
Exit Function ' full year expected
End If
uDate = y & "-" & m & "-" & d & " 00:00:00"
convertDate = CDate(uDate)
End Function
Function Lpad(myString, padString, padLength)
Dim l As Long
l = Len(myString)
If l > padLength Then
padLength = l
End If
Lpad = Right$(String(padLength, padString) & myString, padLength)
End Function
The solutions i've used are;
Change the file name from .csv to .txt and then try importing again (but it sounds like this isn't appropriate
Change the region settings on your PC. If you're English, Australian, New Zealand etc and typically use dd/mm/yyyy then maybe Windows was installed incorrectly as US date formats etc.
Either import it all as text and then convert, or write some code to parse the file. Either way you'll need to ensure you're getting the right dates.This is where the Universal Date format and CDATE() can help you out.
The function below reads a string and changes it to a dd/mm/yyyy date. You'll have to format the cell as a date though. Please note that this will not help if you have imported the values as dates already.
You can use this in code or as a function (UDF) if you through it into a module.
Function TextToDate(txt As String) As Date
Dim uDate As String
Dim d, m, y As String
Dim aDate() As String
aDate = Split(txt, "/")
If UBound(aDate) <> 2 Then
Exit Function
End If
d = Lpad(aDate(0), "0", 2)
m = Lpad(aDate(1), "0", 2)
y = aDate(2)
If Len(y) = 2 Then ''# I'm just being lazy here.. you'll need to decide a rule for this.
y = "20" & y
End If
''# Universal Date format is : "yyyy-mm-dd hh:mm:ss" this ensure no confusion on dd/mm/yy vs mm/dd/yy
''# VBA should be able to always correctly deal with this
uDate = y & "-" & m & "-" & d & " 00:00:00"
TextToDate = CDate(uDate)
End Function
Function Lpad(myString As String, padString As String, padLength As Long) As String
Dim l As Long
l = Len(myString)
If l > padLength Then
padLength = l
End If
Lpad = Right$(String(padLength, padString) & myString, padLength)
End Function
Here is the code... My first column is a DD/MM/YYYY date and the second column is text... The Array(1,4) is the key...
Workbooks.OpenText Filename:= _
"ttt.txt", Origin:=437, StartRow _
:=1, DataType:=xlDelimited, TextQualifier:=xlDoubleQuote, _
ConsecutiveDelimiter:=False, Tab:=False, Semicolon:=False, Comma:=True _
, Space:=False, Other:=False, FieldInfo:=Array(Array(1, 4), Array(2, 1)), _
TrailingMinusNumbers:=True
The value is recognised as a proper date... You need apply the format of DD/MM/YY to the first column after this.
What I just found out is, you have to assign your local date to variable type of Date. I don't understand why it helps, but it sure does.
dim xDate As Date
xDate = PresDate.Value ' it is my form object let say it has 03/09/2013
curRange.Value = xDate ' curRange is my cur cell
While transfering dd/mm/yyyy to xDate it remains dd/mm/yyyy and after putting it in excel doesn't change it. Why? I have no idea. But after many tries it helped. Hope it will help for many of people =)
Try this:
Workbooks.OpenText Filename:=Filename, DataType:=xlDelimited, Comma:=True
Excel should correctly interpret those date values as dates, even if you prefer a different formatting. After executing the OpenText method, determine which column contains the date values and change the formatting so that it suits you:
CsvSheet.Columns(1).NumberFormat = "dd/mm/yyyy"
Related
I use a macro to load an Excel file, pull data, and paste it into a log file. Each of the source Excel files are named by the sample date time it was created.
For instance, a sample created November 25th, 2021 at 3:30 PM would have the file name "11-25-21 1530". I want to pull the file name, assign it to a variable, and format that string into the date time format recognized by Excel for plotting (11/25/21 15:30). I cannot change the file names to include the "/" or ":" since these are not valid in file names.
I have something similar using a userform for time only where it autoformats into a 24hr time variable:
Private Sub TextBox2_AfterUpdate()
'Input would be HHMM or HMM
Dim a As String
a = Len(Me.TextBox2)
If a <= 2 Then 'This is for cases with H or HH
On Error Resume Next
Me.TextBox2 = Left(Me.TextBox2, a) & ":" & 0
ElseIf a = 3 Then
Me.TextBox2 = Left(Me.TextBox2, 1) & ":" & Right(Me.TextBox2, 2) 'This is for cases with HMM
Else
If Me.TextBox2.Value >= 2400 Then
MsgBox ("Incorrect Value")
Call CommandButton1_Click
Else
Me.TextBox2 = Left(Me.TextBox2, 2) & ":" & Right(Me.TextBox2, 2) 'This is for cases with HHMM
End If
End If
Me.TextBox2 = Format(Me.TextBox2, "HH:MM")
End Sub
How do I take the file name and split it into a date and then a time, format both to the proper Excel date time format, then combine them again for MM/DD/YY HH:MM output to log the results?
Use simple string handling to split the name into it's pieces. Then use DateSerial and TimeSerial to create a real Date out if it.
Once that is done, you can do whatever you want with the Date. I don't understand your request "into the date time format recognized by excel for plotting (11/25/21 15:30)", I do know that my Excel will have a hard time to understand 11/25/21 correctly (I am not located in the US...). When you write the date into a cell, write it as date and format the cell. If you need it in your code as string, use the Format-command.
The following function will split a filename, just note that there is no error handling or plausability test.
Function FilenameToDate(filename As String) As Date
Dim fileYear As Long, fileMonth As Long, fileDay As Long, fileHour As Long, fileMinute As Long
fileDay = Val(Mid(filename, 4, 2))
fileMonth = Val(Mid(filename, 1, 2))
fileYear = Val(Mid(filename, 7, 2))
fileHour = Val(Mid(filename, 10, 2))
fileMinute = Val(Mid(filename, 13, 2))
FilenameToDate = DateSerial(fileYear, fileMonth, fileDay) + TimeSerial(fileHour, fileMinute, 0)
End Function
I have dates formatted as text. I want to change these dates' format from
"dd.mm.yyyy hh:mm" to "yyyy.mm.dd". (eg. "04.05.2020 10:33" to "2020.05.04") I use the following code (the original dates are in column "K"):
Dim cell As Range
For Each cell In Range(Range("K2"), Range("K2").End(xlDown))
cell.Offset(0, 7).Value = Mid(cell.Value, 7, 4) & "." & Mid(cell.Value, 4, 3) & Left(cell.Value, 2)
Next
The newly created dates cannot be formatted, though and so when I try to use a vlookup function on them, the function fails, saying it couldn't find the value in the lookup table. (dates are ok in the lookup table)
I need to manually enter every cell and hit enter and only after that will excel start recognizing the format.
I also found that if I use the manual "replace" function of excel like this: https://i.stack.imgur.com/U3k5e.png, and replace the dots with dots, excel will once again start to recognize the format, however it won't recognize any format when I use the following code:
Range(Range("R2"), Range("R2").End(xlDown)).Replace What:=".", Replacement:=",", LookAt:=xlPart, SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, ReplaceFormat:=False, FormulaVersion:=xlReplaceFormula2
Can someone help? How can I convert the format of these concatenated values in vba so that vlookup will recognize them?
Thanks!
Try this:
cell.Offset(0, 7).Value = Format(Mid(cell.Value, 7, 4) & " " & Mid(cell.Value, 4, 3) & " " & Left(cell.Value, 2), "yyyy.mm.dd")
The yyyy.mm.dd at the end tells it how you want it formatted. You also need to use a space or a slash (/) between the 3 functions because it doesn't recognize a period as a separator for it.
For example formatting the month. Take January:
m = 1
mm = 01
mmm = Jan
mmmm = January
Edit:
The only way I could see really doing it then is:
Dim cell as range
For Each Cell in Range(Range("K2"), Range("K2").End(xlDown))
Cell.Value = Format(Replace(Cell.Value,".","/"), "yyyy.mm.dd")
Next
Convert Date & Time As String to Date
Option Explicit
Sub createDate()
Dim Data As Variant
Dim currString As String
Dim currDate As Date
Dim i As Long
With Range(Range("K2"), Range("K2").End(xlDown))
Data = .Value
For i = 1 To UBound(Data, 1)
currString = Data(i, 1)
currDate = DateSerial(CLng(Mid(currString, 7, 4)), _
CLng(Mid(currString, 4, 2)), CLng(Left(currString, 2)))
Data(i, 1) = currDate
Next i
With .Offset(, 7)
.Value = Data
.NumberFormat = "yyyy.mm.dd"
'.Columns.AutoFit
End With
End With
End Sub
I ended up using the following code:
For Each cell In Range(Range("K2"), Range("K2").End(xlDown))
cell.Offset(0, 7).Value = Mid(cell.Value, 7, 4) & "/" & Mid(cell.Value, 4, 2) & "/" & Left(cell.Value, 2)
Next
Turns out I just had to use slashes to separate the concatenated parts, this allowed me to freely change the formatting of the newly created dates.
Special thanks to Simon, his answers helped a lot!
I have a sheet with tens of thousands of dates in the following format :-
31.01.2018 (so, dd.mm.yyyy)
The cell format of each of these is General. I need to convert each of these to UK date format.
To do so, I am using :-
With ThisWorkbook.Worksheets("Report")
For i = 2 To Lastrow
DateString = .Range("J" & i).Value
Year = Right(DateString , 4)
Month = Mid(DateString , 4, 2)
Day = Left(DateString , 2)
With .Range("J" & i)
.Value = CDate(Day & "/" & Month & "/" & Year)
.NumberFormat = "dd/mm/yyyy"
End With
Next i
End With
This takes quite a while, and I wanted to know if there was a more effective way of converting the dates?
If i understand correctly and I am not missing something, you don't need VBA to do that.
Just select column J and find and replace . with /.
If you want to do it using VBA anyway, you can do this:
Sub test()
Dim sht As Worksheet
Dim rng As Range
Set sht = ThisWorkbook.Worksheets("Report")
Set rng = sht.Columns("J")
rng.Replace what:=".", replacement:="/"
End Sub
It takes less than a second to execute for around 10k dates.
EDIT:
When it's done the values will be recognized by excel as dates.
The format of these dates can be set to the European one. Select column J press CTRL+1, in the Number tab, under Category choose Date and set it to European format.
Or simply add this line to he code above:
rng.NumberFormat = "dd/mm/yyyy"
I was able to resolve this using the answer supplied here :-
https://stackoverflow.com/a/30609676/1936588
Changing
.TextToColumns Destination:=.Cells(1), DataType:=xlFixedWidth, FieldInfo:=Array(0, xlYMDFormat)
To
.TextToColumns Destination:=.Cells(1), DataType:=xlFixedWidth, FieldInfo:=Array(0, xlDMYFormat)
I need to split data [1...M] gathered in columns [A...N] into separate text files named as first cell of each column.
Data arranged in excel:
FileName_A |FileName_B |FileName_C |… |FileName_N
Data_A1 |Data_B1 |Data_C1 |… |Data_N1
Data_A2 |Data_B2 |Data_C2 |… |Data_N2
Data_A3 |Data_B3 |Data_C3 |… |Data_N3
… … … … …
DataA_AM DataA_BM DataA_CM DataA_AM DataA_NM
____________________________________________________________________________
shall be written into FileNames
FileName_A.tex should look like:
_____________
Data_A1
Data_A2
Data_A3
…
DataA_AM
____________
I´ve tried, but...
Altough it seems an easy task for an expert, it is quite a huge obsticle for me becouse I am not familiar with coding.
Thank You very much for support in advance.
So, I assumed that M is an Integer Variable that you already defined and N just the Column Name (So column number 14). The code would then be
Dim i As Integer
Dim LastRow As Integer
For i = 1 To 14
Range(Cells("2", i), Cells(M, i)).ExportAsFixedFormat _
Type:=xlTypeXPS, _
Filename:=Sheets(1).Cells("1", i), _
Quality:=xlQualityStandard, _
IncludeDocProperties:=True, _
IgnorePrintAreas:=False, _
OpenAfterPublish:=False
Next
You might want to replace Filename:=Sheets(1).Cells("1", i), _ with Filename:="C:/Your_Path/ & Sheets(1).Cells("1", i), _
Try Code below.
Sub export_data()
Dim row, column, i, j As Integer
Dim fullPath, myFile As String
fullPath = "C:\Workspace"
row = 21
column = 5
For i = 1 To column
myFile = Cells(1, i).Value + ".txt"
myFile = fullPath + "/" + myFile
Open myFile For Output As #1
For j = 2 To row
Print #1, Cells(j, i).Value
Next j
Close #1
Next i
End Sub
You can change Row number and Column number. Your First row is always Header.
See Image below for Excel
Excel Image
This is super frustrating and it doesn't make sense to me.
This is in Excel 2010.
I've recorded a macro to format some data, containing date (DD/MM/YYYY). I import it, Excel sees it as text. So I use the "text to date" macro I have recorded, store into a VBA sub.
Here's the recorded macro:
Sub DateFormatting()
Sheets("Donnees").Select
Columns("H:H").Select
Selection.TextToColumns Destination:=Range("H1"), DataType:=xlDelimited, _
TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=False, Tab:=True, _
Semicolon:=False, Comma:=False, Space:=False, Other:=False, OtherChar _
:="/", FieldInfo:=Array(1, 4), TrailingMinusNumbers:=True
End Sub
When I import my data, at first I have this. You can see it's seen as TEXT by Excel because it is left-aligned (Column H and I confirm it actually is):
Then I run the macro, and get this (column H):
You can see Excel sees it as Date, as it is right-aligned. If I convert it to "number" I see the underlying serial, as expected. So one would think it's fine. But it's really not:
If I run the macro AGAIN (and I would, because more data will be added to it later, so I need to make sure the newly imported data at the bottom of these will be correctly formatted as well), I get this:
So basically it changed the format from DD/MM/YYYY (which it is SUPPOSED to be) to MM/DD/YYYY (which is wrong). If I run that macro again on that data set, it switches back to DD/MM/YYYY.
But the WORST thing is that if I MANUALLY do the exact same thing (e.g. instead of running the macro, I manually go to "Data", "Text to columns" and select the EXACT same options), then it doesn't change. If the date is formatted as DD/MM/YYYY, it stays this way, and if it is formatted as MM/DD/YYYY (because of this stupid quirk), then it stays that way as well. I repeat it enough (and even re-recorded the macro a couple times) to be SURE I do the exact same things.
I know this is because of regional settings, but the file won't always be use on my computer, and I have no way of ensuring that the end user will have any specific regional settings. I need this file to be region-settings independant, basically.
MY QUESTION IS: How can I make sure that those dates are:
Formatted & recognized as date by Excel
Independant of the local regional settings of the users?
I know I could either to an intermediary import step (and format the data there, instead of in the main file), or then tweak the code so that only newly imported data have the macro applied.... But then I feel it's not reliable because how do I know Excel won't mess up the format?
Oh, because the Macro is a bit cryptic looking at the VBA:
I go to Data, Text to Column, choose "Delimited" (doesn't matter because I don't actually split it into columns), then "Delimiters" as default (doesn't matter again I'm not actually splitting the text into columns), then "Date" and in the dropdown "DYM" for DD/MM/YYYY
EDIT: Please see Ron Rosenfield's answer for full details. For completedness, here's the code I'll be running to import the data & format it at import, as opposed to importing it and then formatting it:
Sub importData()
Dim myFile As String
myFile = Sheet5.Cells(2, 5).Value 'My metadata sheet, containing name of file to import
Sheet1.Select 'Setting target sheet as active worksheet
With ActiveSheet.QueryTables.Add(Connection:="TEXT;C:\ChadTest\" & myFile, _
Destination:=Sheet1.Cells(Sheet5.Cells(2, 1).Value, 1))
.Name = "ExternalData_1"
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.RefreshStyle = xlOverwriteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.TextFilePromptOnRefresh = False
.TextFilePlatform = 1252
If Sheet1.Cells(1, 1).Value = "" Then
.TextFileStartRow = 1
Else
.TextFileStartRow = 2
End If
.TextFileParseType = xlDelimited
.TextFileTextQualifier = xlTextQualifierDoubleQuote
.TextFileConsecutiveDelimiter = False
.TextFileTabDelimiter = True
.TextFileSemicolonDelimiter = False
.TextFileCommaDelimiter = True
.TextFileSpaceDelimiter = False
.TextFileColumnDataTypes = Array(1, 1, 1, 4, 1, 1, 1, 4, 1, 1, 1, 1)
.TextFileTrailingMinusNumbers = True
.Refresh BackgroundQuery:=False
End With
Sheet1.Select
Application.WindowState = xlMinimized
Application.WindowState = xlNormal
End Sub
From what you write, it seems you are getting your data from a TEXT or CSV file which you OPEN in Excel, and then try to process the date. A common problem.
Instead, what you can do is IMPORT the file. If you do this, the Text Import Wizard (same as the text-to-columns wizard), will open BEFORE the data gets written to the worksheet, and give you the opportunity to specify the format of the dates being imported.
That option should be on the Get External Data tab of the Data Ribbon:
I'm a bit hazy on the exact process you are using to get data from the source to the Excel worksheet, but the whole process could surely be automated with VBA. And there should be no need to run the macro on the already imported data.
This is what I came up with, using what I mentioned in my comment above:
Sub DateFormatting()
On Error Resume Next
Application.ScreenUpdating = False
Dim wbCurrent As Workbook
Dim wsCurrent As Worksheet
Dim nLastRow, i, nDay, nMonth, nYear As Integer
Dim lNewDate As Long
Set wbCurrent = ActiveWorkbook
Set wsCurrent = wbCurrent.ActiveSheet
nLastRow = wsCurrent.Cells.Find("*", LookIn:=xlValues, SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
For i = nLastRow To 2 Step -1
If InStr(1, wsCurrent.Cells(i, 8), "/", vbBinaryCompare) > 0 Then
nYear = Right(wsCurrent.Cells(i, 8), 4)
nMonth = Mid(wsCurrent.Cells(i, 8), InStr(1, wsCurrent.Cells(i, 8), "/", vbBinaryCompare) + 1, 2)
nDay = Left(wsCurrent.Cells(i, 8), 2)
lNewDate = CLng(DateSerial(nYear, nMonth, nDay))
wsCurrent.Cells(i, 8).Value = lNewDate
End If
Next i
wsCurrent.Range("H:H").NumberFormat = "dd/mm/yyyy"
Application.ScreenUpdating = True
End Sub
This code assumes that the original raw data will always be imported as text in the format dd/mm/yyyy, leading zeros included.
It won't touch any real dates (i.e. where the actual value of the cell is a serial) except to format them.
Here I will assume that your dates will always be written in the format dd/mm/yyyy.
If I only had one cell to check, I would do this:
Dim s() As String
With Range("A1")
If .NumberFormat = "#" Then
'It's formatted as text.
.NumberFormat = "dd/mm/yyyy"
s = Split(.Value, "/")
.Value = DateSerial(CInt(s(2)), CInt(s(1)), CInt(s(0)))
Else
'It isn't formatted as text. Do nothing.
End If
End With
However, this does not scale well if you have many cells to check; looping through cells is slow. It's much quicker to loop through an array, like this:
Dim r As Range
Dim v As Variant
Dim i As Long
Dim s() As String
Set r = Range("H:H").Resize(GetLastNonblankRowNumber(Range("H:H"))) 'or wherever
v = r.Value ' read all values into an array (could be strings, could be real dates)
For i = 1 To UBound(v, 1)
If VarType(v(i, 1)) = vbString Then
s = Split(v(i, 1), "/")
v(i, 1) = DateSerial(CInt(s(2)), CInt(s(1)), CInt(s(0)))
End If
Next i
With r
.NumberFormat = "dd/mm/yyyy"
.Value = v 'write dates back to sheet
End With
where I make use of:
Function GetLastNonblankRowNumber(r As Range) As Long
GetLastNonblankRowNumber = r.Find("*", r.Cells(1, 1), xlFormulas, xlPart, _
xlByRows, xlPrevious).Row
End Function
Actually we had this problem quite a lot at work.
we figured out that the best way to work around this problem is to make sure the dates in the base data are in format "YYYY/MM/DD", this way it's recognized as the same date in either American or normal date format and it will actually correctly follow your regional settings to put a correct date in Excel...
if you are opening a text file (eg csv) then use vba to force it to open using the local date formatting
Workbooks.Open Filename:=strPath & strFile, Local:=True
avoids all the workarounds