ADO text file query - results split by comma - vba

I am querying a text file using ADO to bring the data into Excel.
cn.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & filePath & ";" & _
"Extended Properties='text';"
rs.Open "SELECT * FROM " & fileName, cn
wsImport.Range("A1").CopyFromRecordset rs
The issue I'm facing is that the query results are being split, by comma as a delimiter. This means that when I write the data to the worksheet, it's being output across several columns.
I've confirmed that it's being split at the query stage, and not at the writing of the data to the worksheet stage. I have to use rs.Fields(0) and rs.Fields(1) to access some rows of data, when I want all of the data to be accessible within the first field of the created recordset (allowing the data to be written to column A of the worksheet).
Can anyone clarify how I can query the text file, whilst not splitting the data by any delimiter?
I've also tried using the below within the Extended Properties.
Extended Properties='text;HDR=Yes;FMT=Delimited';
and
Extended Properties='text;HDR=Yes;FMT=FixedLength';

Here's a simple example of reading the text file:
Sub foo(filePath As String)
Dim sDataIn As String
Dim sDataTemp() As String
Dim sDataOut() As String
Dim n As Long
Open filePath For Binary As #1
sDataIn = Space$(LOF(1))
Get #1, , sDataIn
Close #1
sDataTemp() = Split(sDataIn, vbNewLine)
ReDim sDataOut(1 To UBound(sDataTemp) + 1, 1 To 1)
For n = LBound(sDataTemp) To UBound(sDataTemp)
sDataOut(n + 1, 1) = sDataTemp(n)
Next n
ActiveSheet.Range("A1").Resize(UBound(sDataOut), 1) = sDataOut
End Sub

If you turn on the macro recorder and let it record you doing all the steps one time to import a file, you should have your answer.
I just tried it and got this.
Sub Macro1()
'
' Macro1 Macro
'
' Keyboard Shortcut: Ctrl+s
'
With ActiveSheet.QueryTables.Add(Connection:= _
"TEXT;C:\Users\your_path_here\test.txt", Destination:=Range("$A$1"))
.CommandType = 0
.Name = "test"
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.RefreshStyle = xlInsertDeleteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.TextFilePromptOnRefresh = False
.TextFilePlatform = 437
.TextFileStartRow = 1
.TextFileParseType = xlDelimited
.TextFileTextQualifier = xlTextQualifierDoubleQuote
.TextFileConsecutiveDelimiter = False
.TextFileTabDelimiter = False
.TextFileSemicolonDelimiter = False
.TextFileCommaDelimiter = False
.TextFileSpaceDelimiter = False
.TextFileColumnDataTypes = Array(1)
.TextFileTrailingMinusNumbers = True
.Refresh BackgroundQuery:=False
End With
End Sub

Related

How can VBA read CSV with breakline inside double quote?

I'm trying to upload a CSV file with breaklines inside quotes (data.csv) but instead of putting all the text inside the quote in one cell, it still considers it as a new row.
When I open the CSV directly, everything works fine but when I run it through VBA, everything is getting messed up.
data.csv sample
cases,"variant:
option1: 0333102
option2: 1133202
option3: 4234442"
make-shift,"variant:
option1: shift iron
option2: workload
option3: network map
option4: lesson map"
Import_CSV Function
Function import_CSV(location As String, row As Integer, col As String) As Variant
Dim ws As Worksheet, strFile As String
Sheets("data").Visible = True
Sheets("data").UsedRange.ClearContents
Set ws = Sheets("data")
strFile = location
With ws.QueryTables.Add(Connection:="TEXT;" & strFile, Destination:=ws.Range("A1"))
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.RefreshStyle = xlInsertDeleteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.TextFilePromptOnRefresh = False
.TextFilePlatform = 850
.TextFileStartRow = 1
.TextFileParseType = xlDelimited
.TextFileTextQualifier = xlTextQualifierDoubleQuote
.TextFileConsecutiveDelimiter = False
.TextFileTabDelimiter = False
.TextFileSemicolonDelimiter = False
.TextFileCommaDelimiter = True
.TextFileSpaceDelimiter = False
.TextFileColumnDataTypes = Array(1, 1, 1, 1)
.TextFileTrailingMinusNumbers = True
.Refresh BackgroundQuery:=False
End With
import_CSV = Sheets("data").Range(col & "1:" & Get_C(Last_C(row, "data")) & Last_R(Get_C(Last_C(row, "data")), "data"))
Sheets("data").Visible = False
End Function
Assuming your import_CSV() returns the range in data worksheet with same size as the imported CSV, try below. Don't really need the row integer and col string, so I have omitted it.
Option Explicit
Function ImportCustomCSV(location As String) As Range
Dim oWbCSV As Workbook, oRngCSV As Range, oRngData As Range
ThisWorkbook.Worksheets("data").UsedRange.ClearContents
' Range to start pasting csv data
Set oRngData = ThisWorkbook.Worksheets("data").Range("A1")
' Assumes file availability is already checked
Set oWbCSV = Workbooks.Open(Filename:=location, ReadOnly:=True)
Set oRngCSV = oWbCSV.Worksheets(1).UsedRange
' Copy the CSV range to data worksheet
oRngCSV.Copy oRngData
' Make the data range the same rows and cols as imported csv
Set oRngData = oRngData.Resize(oRngCSV.Rows.Count, oRngCSV.Columns.Count)
' Cleanup
Set oRngCSV = Nothing
oWbCSV.Close SaveChanges:=False
Set oWbCSV = Nothing
' Return the updated data range
Set ImportCustomCSV = oRngData
End Function

Want to import bits (a couple of rows) of an .txt to excel

Hey so i found a specific query to import a file into excel from a specific row and delete the following datga each time you open it again. but is it also pssible to stop adding rows at a specific line? and is it possible to leave some rows out if there for example is a specific word in that line?
Sub Sample()
With ActiveSheet.QueryTables.Add(Connection:= _
"TEXT;C:\Users\sample.txt", Destination:=Range("$A$1") _
)
.Name = "Sample"
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.RefreshStyle = xlInsertDeleteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.TextFilePromptOnRefresh = False
.TextFilePlatform = 437
.TextFileStartRow = 1
.TextFileParseType = xlDelimited
.TextFileTextQualifier = xlTextQualifierDoubleQuote
.TextFileConsecutiveDelimiter = False
.TextFileTabDelimiter = True
.TextFileSemicolonDelimiter = False
.TextFileCommaDelimiter = True
.TextFileSpaceDelimiter = False
.TextFileColumnDataTypes = Array(1, 1, 1, 1, 1, 1, 1)
.TextFileTrailingMinusNumbers = True
.Refresh BackgroundQuery:=False
End With
End Sub
You can do it, but not with a Querytable.
Try this code:
Private Sub Open_Click()
Dim fn As Variant, myLine As Long, txt As String, x As Variant, ouput As String
Dim i As Integer, j As Integer: j = 1
Dim sht As Worksheet
Set sht = Worksheets("Sheet1") 'Modify Sheet Name
fn = Application.GetOpenFilename("Text Files (*.txt),*.txt", , _
"Open File")
If fn = False Then Exit Sub
txt = CreateObject("Scripting.FileSystemObject").OpenTextFile(fn).ReadAll
x = Split(txt, vbNewLine)
For i = 0 To UBound(x)
If x(i) <> "SomeCriteria" Then 'Check for some criteria
sht.Cells(j, 1).Value = x(i)
j = j + 1
End If
Next i
End Sub
So what it does basically, it opens a user selected txt file and stores it in the variable txt. Do seperate the rows you can use the split-function. Now each line is stored in an array x. You could go trough the array/each line and take out the ones you want. To check if a specific word is in a line, use the InStr-function.

How to read from a text (.txt) file and place data into an excel 2016 document using VBA Macros editor?

I need to read the following text document (see first picture):
and place data into an excel document in the pictured manner (see second image):
I want to do this with an Excel VBA macros but I do not have the slightest idea on how to do so. I am very new to excel VBA and I do not have the slightest idea on where to begin.
Use following sub.
Sub txtImport()
With ActiveSheet.QueryTables.Add(Connection:= _
"TEXT;C:\Users\HARUN\Documents\Test.txt", Destination:=Range("$A$1"))
.Name = "Test"
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.RefreshStyle = xlInsertDeleteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.TextFilePromptOnRefresh = False
.TextFilePlatform = 437
.TextFileStartRow = 1
.TextFileParseType = xlDelimited
.TextFileTextQualifier = xlTextQualifierDoubleQuote
.TextFileConsecutiveDelimiter = True
.TextFileTabDelimiter = False
.TextFileSemicolonDelimiter = False
.TextFileCommaDelimiter = False
.TextFileSpaceDelimiter = True
.TextFileColumnDataTypes = Array(1, 1, 1)
.TextFileTrailingMinusNumbers = True
.Refresh BackgroundQuery:=False
End With
This code will do that without looping and regardless of number of spaces between the columns.
Sub Test()
Dim Fn As String, WS As Worksheet, st As String
Fn = "D:\tttt\test.txt" ' the file path and name
Set WS = Sheets("Sheet1")
'Read text file to st string
With CreateObject("Scripting.FileSystemObject")
If Not .FileExists(Fn) Then
MsgBox Fn & " : is missing."
Exit Sub
Else
If FileLen(Fn) = 0 Then
MsgBox Fn & " : is empty"
Exit Sub
Else
With .OpenTextFile(Fn, 1)
st = .ReadAll
.Close
End With
End If
End If
End With
'Replace every one or more space in st string with vbTab
With CreateObject("VBScript.RegExp")
.Pattern = "[ ]+"
.Global = True
.Execute st
st = .Replace(st, vbTab)
End With
'Put st string in Clipboard
With CreateObject("New:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}")
.SetText st
.PutInClipboard
End With
'Paste Clipboard to range
WS.Range("A1").PasteSpecial
End Sub
Let's suppose you have csv file (like you have shown, just difference is in delimiters), then the code should be:
Sub ReadData()
Dim line, array() As String
Set FSO = CreateObject("Scripting.FileSystemObject")
Set rfile = FSO.OpenTextFile(*your full path to the file*, 1) 'connection for reading
Dim i As Integer
i = 1
Do Until rfile.AtEndOfStream
line = rfile.ReadLine
array = Split(line, ",") 'I assumed that delimiter is comma
For j = 0 To UBound(array)
Cells(i, j + 1).Value = array(j)
Next j
i = i + 1
Loop
rfile.Close
End Sub

Error parsing CSV to XLS with VBA script

This function is designed to open a CSV file, and import all the data into a specific Sheet on an Excel Workbook.
But I think there is some kind of problem I can't resolve in some cases with delimiters.
This is my function:
Sub LoopAllExcelFilesInFolder_Invenotry()
Dim strFilename As String
Dim wsMstr As Worksheet: Set wsMstr = ThisWorkbook.Sheets("ALL_ACTIUS")
If MsgBox("Erase sheet before start importing?", vbYesNo, "Delete?") _
= vbYes Then wsMstr.UsedRange.Clear
strFilename = Application.GetOpenFilename _
(FileFilter:="CSV File (*.csv), *.csv", _
Title:="Select CSV file: ")
Worksheets("ALL_MACHINES").Activate
With ActiveSheet.QueryTables.Add(Connection:= _
"TEXT;" & strFilename, _
Destination:=Range("A1"))
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.RefreshStyle = xlInsertDeleteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.TextFilePromptOnRefresh = False
.TextFilePlatform = 1252
.TextFileStartRow = 1
.TextFileParseType = xlDelimited
.TextFileTextQualifier = xlTextQualifierDoubleQuote
.TextFileConsecutiveDelimiter = False
.TextFileTabDelimiter = True
.TextFileSemicolonDelimiter = True
.TextFileCommaDelimiter = False
.TextFileSpaceDelimiter = False
.TextFileColumnDataTypes = Array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
.TextFileTrailingMinusNumbers = True
.Refresh BackgroundQuery:=False
End With
End Sub
This is part of the source code (CSV file), containing a line that is not beeing "translted" as expected:
Here you can see how this line is translated to the Excel. The 12X5" string should'nt be there. The first column should only contain IP addresses.
I'm pretty sure It's a delimiter character issue, but I can't find the solution.
The Workbooks.Open command worked for me with that issue.
Dim wb As Workbook
strFilename = "yourfilename.csv"
Set wb = Workbooks.Open(Filename:=strFilename, local:=True)

Very strange Find/Replace behaviour

I have a Firebird database stored in Windows-1251 codepage and managed using IBExpert. I have to get some billing info using SQL, edit it and then send it to clients. I export query results into .csv (comma-separated values) format and then process a bunch of csvs into a pretty xls (with borders, fonts, etc.) using Microsoft Excel 2010. I have NO idea why, but IBExpert places a strange symbol everywhere in numeric values between decades (64 731 instead of 64731). Asc() method from VBA tells me that it's the #160 symbol in ASCII codepage.
NOW, the strangest observation I made: if you copy this symbol manually and delete it from everywhere using find/replace function of Excel, everything is OK. If you do the same thing in any text editor (e.g. good old notepad) everything is still OK. But when you try to automate the replacement using VBA, everything goes very, very wrong. No matter if you use a manually copied #160 from the csv itself or you generate it using Chr(160), if you try to delete all those, VBA also deletes half of the commas. By comma I mean generally known symbol #44, you can google "ascii" pictures and check it out. I have to mark that again, the replacement affects half the commas, however all of them actually ARE the very same symbol, I rechecked that twice.
You can look for a link to a csv below, so you can reassure yourself with the fact that I'm not crazy.
Here is the code you can use to reproduce the magic
Sub test()
Worksheets(1).UsedRange.Replace What:=Chr(160), Replacement:=""
End Sub
I'll be very thankful to someone who will clarify this phenomenon, because I just can't believe that VBA is that buggy, I think I missed something somewhere
UPDATE: Guys, I am terribly sorry. I'm so dumb that I've uploaded the wrong csv. Here's the right one
I've imported the CSV to Range("A1"). Here's what I've found:
$F$2 = 4 708,200
That value is not detected as a numeric. This is due to the CHR(160) existing in the 2nd place (the "space" after 4).
If you want that value to become 4708200 (four million...), replace CHR(160) like you've done. This removes the comma because now excel detects those values as numerics.
Since you haven't provided correct info, Excel thinks the comma is a thousands separator.
If it should rather be 4708,2 (four thousand...), correct it during your CSV import:
To import the CSV correctly, you have to put CHR(160) as a thousands separator.
The comma will act as a decimal sign.
This way, Excel will interpret 4 708,200 as the numeric value 4708,2 during import.
When using REPLACE in VBA, Excel assumes the comma is a thousands separator. Why? Hard to say. However, you haven't provided that it's NOT. :)
Below is the code for importing the file correctly.
With ActiveSheet.QueryTables.Add(Connection:= _
"TEXT;H:\testfile2.csv", Destination:=Range("$A$1"))
.Name = "testfile2.csv"
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.RefreshStyle = xlInsertDeleteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.TextFilePromptOnRefresh = False
.TextFilePlatform = 1251
.TextFileStartRow = 1
.TextFileParseType = xlDelimited
.TextFileTextQualifier = xlTextQualifierDoubleQuote
.TextFileConsecutiveDelimiter = False
.TextFileTabDelimiter = False
.TextFileSemicolonDelimiter = True
.TextFileCommaDelimiter = False
.TextFileSpaceDelimiter = False
.TextFileColumnDataTypes = Array(1, 1, 1, 1, 1, 1, 1)
.TextFileThousandsSeparator = Chr(160) ' Here's that thousands separator!
.TextFileTrailingMinusNumbers = True
.Refresh BackgroundQuery:=False
End With
Update: Here's the code that replaces your previous Workbooks.OpenText macro.
Sub eyecandy()
Dim SelectedItem
Dim Wb As Workbook, Sh As Worksheet
Dim WbName As String, WbFullName As String
With Application.FileDialog(msoFileDialogFilePicker)
.Title = " "
.InitialFileName = ThisWorkbook.Path & Application.PathSeparator & "*.csv"
.AllowMultiSelect = True
If .Show = False Then Exit Sub
Application.ScreenUpdating = False
For Each SelectedItem In .SelectedItems
Set Wb = Workbooks.Add
' Get the file name
WbFullName = Replace(SelectedItem, ThisWorkbook.Path & Application.PathSeparator, "")
WbName = Replace(WbFullName, ".csv", "")
' Deletes unnecessary sheets
Do Until Wb.Sheets.Count = 1
Application.DisplayAlerts = False
Wb.Sheets(1).Delete
Application.DisplayAlerts = True
Loop
Set Sh = Wb.Sheets(1)
With Sh.QueryTables.Add(Connection:= _
"TEXT;" & SelectedItem, Destination:=Sh.Range("$A$1"))
.Name = WbName
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.RefreshStyle = xlInsertDeleteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.TextFilePromptOnRefresh = False
.TextFilePlatform = 1251
.TextFileStartRow = 1
.TextFileParseType = xlDelimited
.TextFileTextQualifier = xlTextQualifierDoubleQuote
.TextFileConsecutiveDelimiter = False
.TextFileTabDelimiter = False
.TextFileSemicolonDelimiter = True
.TextFileCommaDelimiter = False
.TextFileSpaceDelimiter = False
.TextFileColumnDataTypes = Array(1, 1, 1, 1, 1, 1, 1)
.TextFileThousandsSeparator = Chr(160)
.TextFileTrailingMinusNumbers = True
.Refresh BackgroundQuery:=False
End With
Sh.Activate
ActiveWindow.DisplayGridlines = False
With Sh.UsedRange
.Borders.LineStyle = xlContinuous
.Rows(1).Font.Bold = True
.Rows(1).Borders.Weight = xlThick
End With
Sh.Name = WbName
Wb.SaveAs Filename:=WbName, FileFormat:=56
Wb.Close SaveChanges:=False
Next SelectedItem
Application.ScreenUpdating = True
End With
End Sub
So, as #takl suggested, the solution was to modify thousand separator property.
It's .TextFileThousandsSeparator if you are using ActiveSheet.QueryTables.Add method and .ThousandsSeparator if you are using Workbooks.OpenText method.
I really appreciate his help, but I just have to use the Workbooks.OpenText method because it supports Local property. So, here's the edited file-processing loop from my script
'walk through selected files
For Each SelectedItem In .SelectedItems
Workbooks.OpenText _
Filename:=SelectedItem, _
Origin:=xlWindows, _
StartRow:=1, _
DataType:=xlDelimited, _
TextQualifier:=xlTextQualifierNone, _
ConsecutiveDelimiter:=False, _
Semicolon:=True, _
ThousandsSeparator:=Chr(160), _
Local:=True