Opening CSV as worksheet with VBA - incorrect parsing - excel

I have some file.csv. If I open it by double-click, it opens in Excel with the proper setup (there are no semicolons and each "line" of data is correctly showing up in the expected columns).
Example result:
However, in VBA:
'Workbooks.OpenText Filename:=f, StartRow:=2, DataType:=xlDelimited, Semicolon:=True, ConsecutiveDelimiter:=True, TextQualifier:=xlTextQualifierNone
'Workbooks.OpenText Filename:=f, DataType:=xlDelimited, Semicolon:=True
'Workbooks.OpenText Filename:=f, DataType:=xlDelimited
'Workbooks.Open Filename:=f, Format:=xlDelimited, Delimiter:=Chr(34)
'Workbooks.Open Filename:=f, Format:=xlDelimited, Delimiter:=";"
Workbooks.Open Filename:=f, Format:=xlDelimited
Dim s As String
s = """" & ";" & """"
Workbooks.Open Filename:=f, Format:=xlDelimited, Delimiter:=s
'Workbooks.OpenText Filename:=f, DataType:=xlDelimited, OtherChar:=s
'Workbooks.OpenText Filename:=f, DataType:=xlDelimited, OtherChar:=";"
I've tried the lines above (and a number of others before I started keeping all my attempts) as well as without any arguments at all, but no matter what I do, the file will open without the text being split as it does when I double-click the file.
Example result:
So in summary; double-clicking the file parses the file correctly, Open and OpenText does not. Surprisingly, the worksheet looks identical regardless of using Open or OpenText.
A similar problem is described in this question, though it remains without a proper answer. The difference between our cases is that Excel won't parse anything for me, where it seems like it does parse large parts of the file for OP.
I just want to open the workbook and iterate over one of the columns, then close it. I have a couple of workarounds in mind, so I will be able to solve it one unnecessarily roundabout way or another.
So far I have found these ideas:
Renaming .csv to .txt and using OpenText
Using QueryTable import
Iterating over the borked file as it appears using OpenText and using LEFT/MID/RIGHT to get at the desired column(s)
Binary Open and Split each line into an array
Desired answers:
How to achieve this solution using Workbooks.OpenText or similar native function.
Explanations (or maybe even ideas) as to why Workbooks.OpenText and/or the most appropriate native function similar to it cannot achieve the desired result when Excel itself does seem to be capable of it.
Other workarounds.

If you are going to use VBA to import the file, just use VBA to parse the records:
Sub ImportFile()
Dim j As Long, k As Long
Close #1
Open "C:\TestFolder\whatever.csv" For Input As #1
j = 1
Do While Not EOF(1)
Line Input #1, TextLine
ary = Split(TextLine, ";")
k = 1
For Each a In ary
Cells(k, j) = a
k = k + 1
Next a
j = j + 1
Loop
Close #1
End Sub
Doing it this way stops VBA from assigning special meaning to the .csv extension.
Once the core code is working to your satisfaction, you can decorate it with other features like double-quote encapsulation, etc.

Thanks to #GarysStudent for inadvertently tipping me off as to the one attribute I had not been smart enough to try. They said "assigning special meaning to the .csv extension".
Turns out that localization impacts this "special meaning" in the .csv context. I am using a localized version of Excel and setting Local:=True enables both Open and OpenText to parse the file correctly, even without specifying ; as a delimiter.

Related

Selecting cell in Excel VBA used to work but now generates Run-time error '1004': Method 'Range' of object '_Global' failed

The simplified sub below shows line XX1 started to fail yesterday with the above error message. I have tried it on another machine and it fails at the same point.
This code has run hundreds of times, albeit with frequent minor updates. I use this kind of method for selecting a range quite frequently and it usually works fine. It's code that I've written for my own use at work, but aiming to eventually share it with colleagues (for execution and possible ownership). It's part of a 2000-line VBA process.
I've included an earlier fragment of code with a similar line 'xx0' that works fine.
I've found that line XX1 works if I put in an arbitrary selection task beforehand like this: Range("A1").Select
Also, as a test I entered line XX2 and that works fine if I skip over line XX1.
Worse, after experiencing the error, the code continues to run (apparently normally) and then at a later point, it crashes catastrophically: Excel shuts down completely with no warning or message.
I can see that lines xx0 and xx1 are both giving Excel a task to create an address by appending a 'Long' variable to a string like "j2:j" and I guess this is not good practice (it kind of undermines the use of Option Explicit and my Dim statements), but I'm not sure how best to fix it (considering my code contains many subs / 2000 lines and is full of this kind of structure).
Option Explicit
Sub AlignTables()
Dim LastRow As Long
Dim RefColX As Integer
Sheets("shMAIN").Select
LastRow = Cells(999999, 1).End(xlUp).Row
RefColX = Rows("10:10").Find(What:="x1", LookAt:=xlWhole, MatchCase:=False).Column
'Sort shMAIN
Range("c11:c" & LastRow).CurrentRegion.Select
Selection.Sort Header:=xlYes, Key1:=Cells(10, RefColX), Order1:=xlDescending, Key2:=Range("c10"), Order2:=xlAscending
'Refresh index column
Range("c11:c" & LastRow).Select 'Line XX0
Selection.FormulaR1C1 = "=ROW()"
Selection = Selection.Value
'Prepare sort key in ShCleanData column J
Sheets("ShCleanData").Select
LastRow = Cells(999999, 1).End(xlUp).Row 'This sets LastRow to value 6981
Range("j2:j" & LastRow).Select 'Line XX1
Range("j2:j" & "6981").Select 'Line XX2
'(subsequent lines populate the column etc)
End Sub
One option could be to change all my referencing to style YY:
Range(Cells(2,10), Cells(LastRow, 10)).Select 'Style YY
Range("j2:j" & LastRow).Select 'Style XX (easier to follow)
... but I find style XX easier to follow (and easier to explain to people with no VBA knowledge who may need to run and support my code).
KEY QUESTIONS:
Would declaring LastRow as Variant (instead of Long) be a robust
solution to this? [Not only to maintain the 'readable' style, but
also to simplify modifying all my subs]
Or should I go through my code removing Range Selections of type XX and changing them all to style 'YY'?
Or is there some other better solution?
One other strange observation that may be relevant: I have a VBA Function: jStop ("Run this section stepwise if you're processing data of type XX") I use this function throughout my code with different messages. The jStop function simply displays the string in a msgbox together with 'Click OK to continue or Cancel to Stop' and handles the user's request to stop (or not). It has been working for many months, but yesterday just before I encountered the 'XX1' issue, I noticed that this function was ignoring the text argument (it behaved like jstop ("") ) ... perhaps this gives a clue about what's behind the XX1 issue? This odd behaviour of jStop did not persist after a reboot.

Copying lines from Wordpad into Excel using VBA

I am writing some code where I import some files under TMX (a form of xml).
I tried various options
a) using the Open FileName For input, but this messes up the character encoding
b) opening the file and copying the data using the msoDialog, but this return an error if the file is too large (which is often the case) and this put the data in an utterly messy manner.
c) opening the file using notepad, but there are the same limitations in so far as copying the entirety of the file into Excel as the previous option.
I am not trying to use a shell function calling onto Wordpad.
My issue right now, is that I need to copy the file line by line to treat its content according to my needs (hopefully without losing the character encoding
Would someone know how to copy every single line from the file opened in WordPad and paste it post treatment (selection of the relevant elements) into Excel?
Thank you
For large files you can use this solution:
Public Sub ImportTMXtoExcel()
Call Application.FileDialog(msoFileDialogOpen).Filters.Clear
Call Application.FileDialog(msoFileDialogOpen).Filters.Add("TMX Files", "*.tmx")
Application.FileDialog(msoFileDialogOpen).Title = "Select a file to import..."
Application.FileDialog(msoFileDialogOpen).AllowMultiSelect = False
intChoice = Application.FileDialog(msoFileDialogOpen).Show
If intChoice <> 0 Then
strFileToImport = Application.FileDialog(msoFileDialogOpen).SelectedItems(1)
Else
Exit Sub
End If
intPointer = FreeFile()
Open strFileToImport For Input Access Read Lock Read As #intPointer
intCounter = 0
Do Until EOF(intPointer)
Line Input #intPointer, strLine
intCounter = intCounter + 1
Worksheets(1).Cells(intCounter + 1, 1).Value2 = strLine
Loop
Close intPointer
End Sub
For other encodings you can use ADO's Stream as described in this solution:
VB6/VBScript change file encoding to ansi
If you have large files which require ADO's Stream then you might want to consider breaking down the large files first as described in this solution:
How to split a large text file into smaller files with equal number of lines?
The following website provides a tool which mimics the Unix command split for Windows in command prompt: https://www.fourmilab.ch/splits/

Trying to convert XLS to CSV and CSV to XLS using VBScript. Receiving error: 800A03EC (Unable to get the Open property of the Workbooks class)

I'm trying to open a CSV then use the SaveAs method to save it as an XLS. Also vice-versa in another script. I accidentally had the file format codes wrong before and was not getting this error. The CSV would in fact open. I accidentally had made the CSV format 2 (which is actually SYLK) and the XLS, 6 (which is actually CSV).
I've looked all over, and most of what I can find has to do with using an incorrect argument (which I have checked multiple times). The rest is for ASP, and suggests changing permissions in Component Services (which probably wouldn't be an issue anyway, since I can get the Open method to work with different formats).
So I'm at a loss as to how to proceed. If I can't even use the Open method, then I'm kind of stuck. If it was as simple as thee SaveAs method not working for this task, I could get around that. But I need to be able to open an XLS using the Open method (since I'm also trying to do XLS to CSV). CSV to XLS can be fixed another way, probably, since the Open method seems to work sometimes.
Anyway, my code for the CSV to XLS is below. The XLS to CSV is essentially identical to this. It just flips the format codes and uses different paths for the files.
strName = "MidCSVTemp.csv"
strSaveName = Month(Now) & "." & Day(Now) & "." & Year(Now) & ".xls"
strPath = "C:\Users\adam\Documents\" & strName
strSavePath = "C:\Users\adam\Documents\" & strSaveName
'Options for Workbook.Open
intUpdateLinks = 0
boolReadOnly = False
intFormat = 6
'Options for SaveAs
intFileFormat = 56
Set objExcel = CreateObject("Excel.Application")
Set objWorkBook = objExcel.Workbooks.Open(strPath,intUpdateLinks,boolReadOnly,intFormat)
Call objWorkBook.SaveAs(strSavePath,intFileFormat)
Call objWorkbook.Close
I think the issue is that you're using the Format parameter of the Workbooks.Open() method like it's the FileFormat parameter. It shouldn't be xlCSV (6), which is a FileFormat constant. According to the docs, Format should be one of the following values:
1 = Tabs
2 = Commas
3 = Spaces
4 = Semicolons
5 = Nothing
6 = Custom
Since you're passing a value of 6, it's expecting that you also include the Delimiter argument. And since you're not including it, you're getting an error.
You should be able to open a CSV without specifying the Format parameter (Excel seemed to guess the delimiter correctly for me without having to specify it). But, to be safe, pass a value of 2 for a comma-delimited (CSV) file.
intFormat = 2
Set objWorkBook = objExcel.Workbooks.Open(strPath,intUpdateLinks,boolReadOnly,intFormat)

Opening CSV in Excel using VBA causes data to appear in two columns instead of one

I created VBA code in Excel 2007/2010 to import data from a CSV file. Unfortunately, when I open the file programmatically, the data is split into two columns (A and B) for certain rows of data.
When I open the CSV File manually, everything displays fine!
Generally the CSV data looks like this (example header row):
TBWAKT;"TBWAKO";"TBSAIS";"TBSKU9 ";"TBSMOD";"TBLETT";"TBKBNR
";"TBBEZ2 ";"TBFAR2
";"TBSUGC";"TBSOGC";"TBEINK ";"TBKBGR ";"TBKBGF
";"TBVKPE ";"TBVKPR ";"TBEKPE
";"TBAUAN";"TBFAAN";"TBREAN";"TBSTAN";"TBRUAN";"TBKPAG";"TBERDT
";"TBDATV ";"TBDATB "
The data that causes problems includes a comma in the text. Here is an example:
JEAN 5 POCHES EXTENSIBLE+1,60M
Here is the code:
Private Sub OpenCSV(x As Integer, wkbDashboard As String, wkbCsvImport As String, wksDestination As Worksheet)
' Opens CSV and copies data to current workbook
Dim wkbCsvImportName As String
Dim r As Range
Workbooks(wkbDashboard).Activate
' Open and read CSV
Workbooks.Open Filename:=wkbCsvImport, Format:=xlDelimited, Delimiter:=";"
wkbCsvImportName = ActiveWorkbook.Name
Screenshot of the problem. The stuff in red is in column B after opening the file.
Add Local:=True as argument in Workbooks.Open
Hope this might help!
I still suspect it's because the extension is CSV. What happens if you rename the file as a .txt?
In order to import data with a separator that is not a comma, you should set the Format attribute to 6 in order to be able to define your delimiter, as described here.
It should also work if you directly set Format to 4
I think when you do it manually Excel is reading the delimiter as ";" and not just ;.
Try this:
Workbooks.Open Filename:=wkbCsvImport, Format:=xlDelimited, Delimiter:=""";"""
EDIT:
the only way I can get this to work is by changing the file extension from csv to txt and then run this code:
Workbooks.OpenText Filename:=wkbCsvImport, _
DataType:=xlDelimited, semicolon:=True
I know two possible workarounds:
1) Change the extension from .csv to for example .xxx and open it like this:
Workbooks.OpenText fileName:="file.xxx", _
Origin:=xlMSDOS, StartRow:=1, DataType:=xlDelimited, TextQualifier:=1, _
ConsecutiveDelimiter:=False, Tab:=False, Semicolon:=True, _
Comma:=False, Space:=False, Other:=False, OtherChar:="", _
TrailingMinusNumbers:=True, Local:=True
If you use .csv or .xls, then the excel overrides the settings by it's default values from the OS.
2) In Windows 10, change your locale setting from English - United States to English - United Kingdom. It's strange that it helps, it doesn't matter what the delimiter setting in advanced date/time is. In Windows 7 I think the delimiter setting worked.
Change the cell format to text.
e.g. Cells(1,1).NumberFormat = "#"

Date formats/values change when file is opened programmatically

I have .csv file which is a time series of daily data, with several data points associated with each date.
When I manually open the file, the dates open correctly, as the date format dd/mm/yyyy.
When I open the file programmatically, the dates up to the 12th of each month are opened as mm/dd/yyyy, although the format remains dd/mm/yyyy (e.g. the 1st of July 1983 (1/7/1983), would be opened as the 7th of January 1983 (7/1/1983) - this isn't just a formatting issue, the Julian Date (days since 1 Jan 1901) associated with these dates also changes), and the dates after the 12th of each month are opened correctly, although as text rather than a date.
The data coming in as text is not an issue, however, the dates changing as soon as the file is opened is problematic. I could try to import the entire .csv file as comma delimited text rather than opening the file, however, it would be easier and faster if I could stop the dates from changing when I open the file.
Flder = InputBox("Copy and Paste Folder path here:")
Set FSO = CreateObject("Scripting.FileSystemObject")
Set SourcePath = FSO.GetFolder(Flder)
For Each File In SourcePath.Files
Workbooks.Open (File)
FlNm = File.Name
StrtCol = Workbooks(FlNm).Worksheets(1).Range(Cells(4, 1), Cells(4, 30)).Find ("Mean").Column
Workbooks(FlNm).Worksheets(1).Range(Cells(1, 1), Cells(60000, 1)).Copy (Workbooks("Find Water Years V2.xls").Worksheets(1).Range("A3"))
Workbooks(FlNm).Worksheets(1).Range(Cells(1, StrtCol), Cells(60000, StrtCol + 1)).Copy (Workbooks("Find Water Years V2.xls").Worksheets(1).Range("B3"))
Workbooks(FlNm).Close
Next
The problem seems to occur at the line Workbooks.Open(File).
Since the question has already been answered by the OP in the comments but not posted as an official answer I'll put it here in case someone else misses it like I did.
workbook = workbooks.Open(filename, Local:= true)
By setting Local = true uses the local machines date format rather than assuming mdy so in locales such as Australia (dmy) it'll change the behavior of Open()
I experienced this problem with Office 365.
With importing an csv file with Excel some dates dd/mm/jjjj (European) where imported as American dates mm/dd/jjjj. The csv file doesn't have any formatting of dates closed in.
By opening as follows:
Set xla = CreateObject("Excel.Application")
Set xlb = xla.Workbooks.Open(sFilePath, ReadOnly:=False, Local:=True)
The local settings where used, and problem solved :-)
Other options with opening a file are:
expression.Open (FileName, UpdateLinks, ReadOnly,
Format, Password, WriteResPassword,
IgnoreReadOnlyRecommended, Origin,
Delimiter, Editable, Notify, Converter,
AddToMru, Local, CorruptLoad)
I could try to import the entire .csv file as comma delimited text rather than actually opening the file, however, it would be easier and faster if I could stop the dates from changing when I open the file.
It is still fast if you open it as CDT. You simply use .OpenText instead of .Open. Rest of the code remains same :)
Try recording a macro and you will see that the code looks somewhat like this.
Workbooks.OpenText Filename:= File, _
Origin:=437, StartRow:=1, DataType:=xlDelimited, TextQualifier:= _
xlDoubleQuote, ConsecutiveDelimiter:=False, Tab:=True, Semicolon:=False, _
Comma:=True, Space:=False, Other:=False, FieldInfo:=Array(1, 1), _
TrailingMinusNumbers:=True
I found that user2981639 had the right idea, but I got a syntax error with 'Local: true' so
I used 'local:=True' instead
This problem was driving me nuts because I also had 2 memo fields in the csv file.
If I tried to format the dates in any way the memo fields would not import correctly, they would either be truncated to 255 characters or any embedded CRLF characters would cut the record up into pieces depending on how many there were.
Thanks guys for posting
Here, you see a working code with example. This problem frustrated me as well for a while. I was opening a .txt file in excel and the date I had use for was converting from dd-mm-yyyy format to mm-dd-yyyy format. Below you see a solution. It lay in the last command (,Local := True). See below. Hope it helps.
Note that while trasferring .txt file to excel use File Origin as "xlWindows:
Workbooks.OpenText Filename:= _
ThisWorkbook.Worksheets("Reporting").Cells(3, 6), Origin:=xlWindows, _
StartRow:=1, DataType:=xlFixedWidth, FieldInfo:=Array(Array(0, 1), Array(49 _
, 1), Array(50, 1), Array(67, 1), Array(80, 1), Array(93, 1), Array(106, 1), Array(119, 1)) _
, DecimalSeparator:=",", ThousandsSeparator:=".", TrailingMinusNumbers:= _
True, Local:=True
NOTE: rest above settings for array and decimal separator are my work specific - may not apply to you.
I am also struggling to find an answer. However what resolves this problem is.:-
Local should be true.
and workbook close save changes must be false. That should work.
Just had this problem myself and found the above solution
workbook = workbooks.Open(filename, Local:= true)
to be problematic in that it generates an error message. The MS documentation doesn't mention brackets or Workbook =, so I used this:-
Workbooks.Open Path, local:=True
Worked form me, hope it helps you.

Resources