VBA Macro read user selected field names from CSV file - excel

I have a sample.csv file with four fields/columns:
Date
City
State
Amount
Below is my code which retrieves all four fields of the data:
Sub LoadFromFile()
Dim fileName As String, folder As String
folder = "d:\Sample.csv"
fileName = ActiveCell.Value
ActiveCell.Offset(1, 0).Range("A1").Select
With ActiveSheet.QueryTables _
.Add(Connection:="TEXT;" & folder & fileName, Destination:=ActiveCell)
.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
End Sub
My requirement is to display only three fields/columns: Date, City and Amount. How can I do that?

Sub CSVData()
Dim con As ADODB.Connection
Dim rs As ADODB.Recordset
Set con = New ADODB.Connection
Set rs = New ADODB.Recordset
Dim currentDataFilePath As String
Dim currentDataFileName As String
Dim nextRow As Integer
Dim emptystr As String
'"H:\projectfiles\csv\", "Book.csv"
currentDataFilePath = ("H:\projectfiles\csv\")
currentDataFileName = ("Book.csv")
emptystr = "NULL"
con.Provider = "Microsoft.Ace.OLEDB.12.0"
con.ConnectionString = "Data Source=" & currentDataFilePath & ";" & "Extended Properties=""text;HDR=Yes;FMT=Delimited;"""
'MsgBox currentDataFilePath
con.Open
rs.Open "SELECT * FROM [" & currentDataFileName & "] ", con
rs.MoveFirst
'nextRow = Worksheets("Sheet3").UsedRange.Rows.Count + 1
'Worksheets("Sheet3").Cells(nextRow, 1).CopyFromRecordset rs
'MsgBox rs.RecordCount
With rs
Do Until .EOF
'check the field is not null before process
If Not IsNull(rs(0)) Then
custordernum = rs(0)
End If
If Not IsNull(rs(1)) Then
ContactNAme = "" & Replace(rs(1), "'", " ")
Else
ContactNAme = emptystr
End If
If Not IsNull(rs(2)) Then
colladd1 = "" & Replace(rs(2), "'", " ")
Else
colladd1 = emptystr
End If
MsgBox colladd1
.MoveNext
Loop
End With
rs.Close
con.Close
End Sub

This is your alternative doing exactly what you want so you can copy and change to your specification
Sub CSVDataBok()
Dim con As ADODB.Connection
Dim rs As ADODB.Recordset
Set con = New ADODB.Connection
Set rs = New ADODB.Recordset
Dim currentDataFilePath As String
Dim currentDataFileName As String
Dim nextRow As Integer
Dim emptystr As String
'"H:\projectfiles\csv\", "Book.csv"
currentDataFilePath = ("H:\resources\")
currentDataFileName = ("Book2.csv")
emptystr = "NULL"
con.Provider = "Microsoft.Ace.OLEDB.12.0"
con.ConnectionString = "Data Source=" & currentDataFilePath & ";" & "Extended Properties=""text;HDR=Yes;FMT=Delimited;"""
'MsgBox currentDataFilePath
con.Open
rs.Open "SELECT Date,City,State,Amount FROM [" & currentDataFileName & "] ", con
rs.MoveFirst
nextRow = Worksheets("Sheet3").UsedRange.Rows.Count + 1
Worksheets("Sheet3").Cells(nextRow, 1).CopyFromRecordset rs
rs.Close
con.Close
End Sub

Related

How to read the second and third line of csv as one line

My Excel reads a CSV file to get data for a grid table.
"header", "header", "header", "header"
"value1",
"value2", "value3", "value4"
"value5", "value6", "value7", "value8"
"value9", "value10", "value11", "value12"
I want to read the second and third line of the CSV as the first row of the grid table.
Other lines are read one by one.
My code is:
Dim FileName As String, folder As String
folder = ThisWorkbook.Path & "\"
FileName = Dir(ThisWorkbook.Path & "\*.csv")
With ActiveSheet.QueryTables _
.Add(Connection:="TEXT;" & folder & FileName, Destination:=ActiveCell)
.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:=True
End With
My approach:
I am trying to modify the csv file with a new one that will have the second and third line merged as the second line.
filePath = folder & fileName
Dim fName As String, fso As Object, fsoFile As Object, txt As Variant
Set fso = CreateObject("Scripting.FileSystemObject")
Set fsoFile = fso.OpenTextFile(filePath, 1)
txt = fsoFile.ReadAll
fsoFile.Close
txt = Split(txt, vbNewLine)
txt(2 - 1) = "some text with special characters like & Char(44) & and & Chr(10) & and so on"
Set fsoFile = fso.OpenTextFile(filePath, 2)
fsoFile.Write Join(txt, vbNewLine)
fsoFile.Close
the problem is that the grid table displays the special characters as & Char(44) & and & Char(10) & inside the cells...
Three methods for combining 2nd and 3rd lines
Sub merge23()
Dim fso As Object, tsIn, tsOut
Dim s As String
Set fso = CreateObject("Scripting.Filesystemobject")
Set tsIn = fso.OpenTextFile("C:\temp\test.csv", 1)
Set tsOut = fso.CreateTextFile("C:\temp\test1.csv", 1)
' method 1
Do While tsIn.AtEndOfLine <> True
s = tsIn.readline
If tsIn.Line <> 3 Then
s = s & vbCrLf
End If
tsOut.write s
Loop
tsIn.Close
tsOut.Close
' method 2
Set tsIn = fso.OpenTextFile("C:\temp\test.csv", 1)
s = tsIn.readall
tsIn.Close
s = Replace(s, vbCrLf, "~#~#~", 1, 1) 'mark 1st crlf
s = Replace(s, vbCrLf, "", 1, 1) ' replace 2nd
s = Replace(s, "~#~#~", vbCrLf, 1, 1) ' replace 1st crlf
Set tsOut = fso.CreateTextFile("C:\temp\test2.csv", 1)
tsOut.writeline s
' method 3 regex
Dim regex
Set regex = CreateObject("vbscript.regexp")
With regex
.Global = False
.MultiLine = True
.Pattern = "^(.*\r\n.*)\r\n" ' 2nd crlf
End With
Set tsIn = fso.OpenTextFile("C:\temp\test.csv", 1)
s = tsIn.readall
tsIn.Close
Set tsOut = fso.CreateTextFile("C:\temp\test3.csv", 1)
s = regex.Replace(s, "$1")
tsOut.writeline s
tsOut.Close
End Sub

Copy Query from Access to Excel

I'm having some problems when I try to import a Query from Access to Excel.
Some days ago I programmed a code (with some help of Google haha) to import a Table from Access to Excel:
Sub importQuery(DBFullName As String, data_sht As Worksheet)
Dim cn As Object, rs As Object
Dim i As Integer
Dim TargetRange As Range
Dim rows As Long, cols As Long
Dim dataEmpty As Boolean
Dim lastColString As String
data_sht.Activate
Application.ScreenUpdating = False
Set TargetRange = data_sht.Range("A1")
Set cn = CreateObject("ADODB.Connection")
cn.Open "Provider=Microsoft.Ace.OLEDB.12.0; Data Source=" & DBFullName & ";" 'the Access file is .accdb
Set rs = CreateObject("ADODB.Recordset")
rs.Open "SELECT * FROM C_Paso2_SM_Cuplas", cn, , , adCmdUnspecified
cols = rs.Fields.Count
rows = data_sht.Range("A" & data_sht.rows.Count).End(xlUp).Row
' Copy titles of the Access Query
For i = 0 To (cols - 1)
TargetRange.Offset(0, i).Value = rs.Fields(i).Name
Next
' Copy data
TargetRange.Offset(1, 0).CopyFromRecordset rs
End Sub
That code works but when I do this:
rs.Open "SELECT * FROM C_Paso2_SM_Cuplas", cn, , , adCmdUnspecified
I'm importing another Query called C_Paso1_SM_Cuplas, from the same file. What can I do? Why am I importing C_Paso1_SM_Cuplas when I say C_Paso2_SM_Cuplas? Is there other possibility to import an Access Query to Excel?
Try this DAO solution.
Sub ImportFromAccessToExcel()
Dim db1 As Database
Dim db2 As Database
Dim recSet As Recordset
Dim strConnect As String
Set db1 = OpenDatabase("C:\Database1.mdb")
strConnect = db1.QueryDefs("Query3").Connect _
& "DSN=myDsn;USERNAME=myID;PWD=myPassword"
Set db2 = OpenDatabase("", False, False, strConnect)
db2.Close
Set db2 = Nothing
Set recSet = db1.OpenRecordset("Query3")
With ActiveSheet.QueryTables.Add(Connection:=recSet, Destination:=Range("$A$4"))
.Name = "Connection"
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.BackgroundQuery = True
.RefreshStyle = xlInsertDeleteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.PreserveColumnInfo = True
.Refresh BackgroundQuery:=False
End With
recSet.Close
db1.Close
Set recSet = Nothing
Set db1 = Nothing
End Sub

Using VBA to get MDX Data

I'm having a hard time getting results back in Excel connecting to an MDX database. Below is my code (I am incredibly new at this, so please be patient.) I did hijack someone's error code, so that part is not mine. The query runs through but I receive no data in Excel. Any help would be appreciated.
Sub Test()
Sheets("DataDump").Select
ActiveSheet.Range("A1").Value = "Department"
Set cn = New ADODB.Connection
cn.Open "provider=MSOLAP.3;Integrated Security=SSPI;Persist Security Info=True;Initial Catalog=XXX;Data Source=XXXXX;MDX Compatibility=1;Safety Options=2;MDX Missing Member Mode=Error"
Set rs = New ADODB.Recordset
strSQL = "select [product].[base color] on columns "
strSQL = strSQL & " From XXX "
strSQL = strSQL & " Where [Date].[Fiscal Week].&[2016]&[10] "
rs.Open strSQL, cn
Sheets("DataDump").Range("A2").CopyFromRecordset rs
rs.Close
Set rs = Nothing
Set Lists = Nothing
strSQL = vbNullString
StartDate = 0
EndDate = 0
SeasonYear = vbNullString
PriorYear = vbNullString
TXTYear = 0
With Application
.ScreenUpdating = True
.DisplayAlerts = True
.Calculation = xlCalculationAutomatic
.EnableEvents = True
.StatusBar = False
End With
Exit Sub
ErrorHandler:
Sheets("DataDump").Visible = xlVeryHidden
Set Lists = Nothing
strSQL = vbNullString
StartDate = 0
EndDate = 0
SeasonYear = vbNullString
PriorYear = vbNullString
TXTYear = 0
With Application
.ScreenUpdating = True
.DisplayAlerts = True
.Calculation = xlCalculationAutomatic
.EnableEvents = True
.StatusBar = False
End With
'Error Message
MsgBox "An Error occurred while retrieving data: " & Err.Description
End Sub
Here is an example of going straight to a cube via vba.
I've used this additional object ADOMD.Cellset to capture the results of the mdx.
Sub getFromCube()
Dim strConn As String
strConn = _
"Provider=MSOLAP.6;" & _
"Data Source=imxxxxxx;" & _ '<<<name of your server here
"Initial Catalog=AdventureWorksDW2012Multidimensional-EE;" & _ '<<<name of your Adv Wrks db here
"Integrated Security=SSPI"
Dim pubConn As ADODB.Connection
Set pubConn = New ADODB.Connection
pubConn.CommandTimeout = 0
pubConn.Open strConn
Dim cs As ADOMD.Cellset
Set cs = New ADOMD.Cellset
Dim myMdx As String
myMdx = _
" SELECT" & _
" NON EMPTY" & _
" [Customer].[Customer Geography].[State-Province].&[AB]&[CA] ON 0," & _
" NON EMPTY" & _
" [Measures].[Internet Sales Amount] ON 1" & _
" FROM [Adventure Works];"
With cs
.Open myMdx, pubConn
ActiveSheet.Range("A1") = cs(0, 0)
.Close
End With
End Sub

How to refresh table data on all sheets

I need to run a VBScript that can dynamically set a SQL Server connection string, taking server name and database name from Excel cells, and refresh tables in all worksheets of the file.
I currently have this script against a 'Refresh' button on the 'Setup' sheet (from where it takes the server and database names):
Sub Refresh_Click()
Dim Sh As Worksheet
Dim sServer As String
Dim sDatabase As String
Dim sTableName As String
Dim vDestinationRg As Variant
Dim sQuery(1 To 24) As String
Dim vQueryArray As Variant
Dim i As Integer
Dim j As Integer
Dim isSplit As Boolean
Dim sUsername As String
Dim sPassword As String
Set Sh = ActiveSheet
j = 1
isSplit = True
vQueryArray = Application.Transpose(Sh.Range("U1:U10"))
For i = LBound(vQueryArray) To UBound(vQueryArray)
If vQueryArray(i) <> "" Then
isSplit = False
sQuery(j) = sQuery(j) & Trim(vQueryArray(i)) & vbCrLf
ElseIf Not isSplit Then
isSplit = True
j = j + 1
End If
Next i
sServer = Sheets("Setup").Range("F5").Value
sDatabase = Sheets("Setup").Range("F7").Value
vDestinationRg = Array("$H$12")
sUsername = "username"
sPassword = "********"
For i = LBound(sQuery) To UBound(sQuery)
If sQuery(i) = "" Then Exit Sub
sTableName = "Result_Table_" & Replace(Replace(Sh.Name, " ", ""), "-", "") & "_" & i
On Error Resume Next
Sh.ListObjects(sTableName).Delete
On Error GoTo 0
With Sh.ListObjects.Add(SourceType:=0, Source:=Array( _
"OLEDB;Provider=SQLOLEDB.1;User Id=" & sUsername & "; Password=" & sPassword & ";Data Source=" & sServer & ";Initial Catalog=" & sDatabase & ""), Destination:=Sh.Range(vDestinationRg(i - 1))).QueryTable
.CommandText = sQuery(i)
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.BackgroundQuery = True
.RefreshStyle = xlInsertDeleteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.PreserveColumnInfo = True
.ListObject.DisplayName = sTableName
.Refresh BackgroundQuery:=False
End With
Next
End Sub
I have a select query written in cell "U1" of the 'Setup' sheet and it creates and populates the table into the destination range starting from "H12".
But instead of placing the query on the 'Setup' sheet I want to write queries on different worksheets which would populate tables in the respective worksheets, with only this one Refresh button click on the Setup sheet.
How can I do this?
I have been told it can be achieved without writing VBScript also, but no luck there! I tried adding SQL server connections to the workbook, but can't make it dynamic from there.

Graphs with various Y values and one X values in Excel VBA

This is the code i use to create a graph which searches for .csv {created using excel application} file in the path specified. It plots the column 'B' { Y axis } against column 'C' {X-axis}.. I want to one more column 'A' to my Y axis keeping column 'C' as the X axis.. How can i do that???
here is the code...
Sub Draw_Graph()
Dim strPath As String
Dim strFile As String
Dim strChart As String
Dim i As Integer
Dim j As Integer
strPath = "C:\PortableRvR\report\"
strFile = Dir(strPath & "*.csv")
i = 1
Do While strFile <> ""
With ActiveWorkbook.Worksheets.Add
With .QueryTables.Add(Connection:="TEXT;" & strPath & strFile, _
Destination:=.Range("A1"))
Parent.Name = Replace(strFile, ".csv", "")
TextFileParseType = xlDelimited
TextFileTextQualifier = xlTextQualifierDoubleQuote
TextFileConsecutiveDelimiter = False
TextFileTabDelimiter = False
TextFileSemicolonDelimiter = False
TextFileCommaDelimiter = True
TextFileSpaceDelimiter = False
TextFileColumnDataTypes = Array(1)
TextFileTrailingMinusNumbers = True
Refresh BackgroundQuery:=False
Files(i) = .Parent.Name
i = i + 1
End With
End With
strFile = Dir
Loop
numOfFiles = i - 1
chartName = "Chart 1"
For j = 1 To numOfFiles
strFile = Files(j)
Sheets(strFile).Select
Plot_y = Range("B1", Selection.End(xlDown)).Rows.Count
Plot_x = Range("C1", Selection.End(xlDown)).Rows.Count
Sheets("GraphDisplay").Select
If j = 1 Then ActiveSheet.ChartObjects(chartName).Activate
ActiveChart.SeriesCollection.NewSeries
ActiveChart.SeriesCollection(j).Name = strFile
ActiveChart.SeriesCollection(j).XValues = Sheets(strFile).Range("C1:C" & Plot_x)
ActiveChart.SeriesCollection(j).Values = Sheets(strFile).Range("B1:B" & Plot_y)
ActiveChart.SeriesCollection(j).MarkerStyle = -4142
ActiveChart.SeriesCollection(j).Smooth = False
Next j
ActiveSheet.ChartObjects(chartName).Activate
ActiveChart.Axes(xlValue).DisplayUnit = xlMillions
ActiveChart.Axes(xlValue).HasDisplayUnitLabel = False
End Sub
you can add 2 series for every file (j and j+1 inside for j = 1 to 2*numOfFiles step 2) and repeat everything for j+1 series except:
ActiveChart.SeriesCollection(j).Values = Sheets(strFile).Range("A1:A" & Plot_y)
ActiveChart.SeriesCollection(j+1).Values = Sheets(strFile).Range("B1:B" & Plot_y)
Not for points
I was planning to post this as a comment (and hence do not select this as an answer. All credit to #Aprillion) but the comment would not have formatted the code as this post would have done.
Whenever you add a series as Aprillion mentioned you have to also add one more line. I just tested this with small piece of data and it works.
'<~~ You have to call this everytime you add a new series
ActiveChart.SeriesCollection.NewSeries
ActiveChart.SeriesCollection(1).Values = "=Sheet1!$B$1:$B$6"
'<~~ You have to call this everytime you add a new series
ActiveChart.SeriesCollection.NewSeries
ActiveChart.SeriesCollection(2).Values = "=Sheet1!$A$1:$A$6"
Also since there is a huge difference between your Series 1 Data and Series 2 data (as per the snapshot), the 2nd series will be very close to X Axis.
Hope this is what you wanted?
FOLLOWUP
Is this what you are trying?
Dim files(1 To 20) As String
Dim numOfFiles As Integer
Dim chartName As String, shName as String
Sub Time_Graph()
Dim strPath As String, strFile As String, strChart As String
Dim i As Long, j As Long, n As Long
strPath = "C:\PortableRvR\report\"
strFile = Dir(strPath & "*.csv")
i = 1
Do While strFile <> ""
With ActiveWorkbook.Worksheets.Add
shName = strFile
ActiveSheet.Name = Replace(shName, ".csv", "")
With .QueryTables.Add(Connection:="TEXT;" & strPath & strFile, _
Destination:=.Range("A1"))
.Name = Replace(strFile, ".csv", "")
.TextFileParseType = xlDelimited
.TextFileTextQualifier = xlTextQualifierDoubleQuote
.TextFileConsecutiveDelimiter = False
.TextFileTabDelimiter = False
.TextFileSemicolonDelimiter = False
.TextFileCommaDelimiter = True
.TextFileSpaceDelimiter = False
.TextFileColumnDataTypes = Array(1)
.TextFileTrailingMinusNumbers = True
.Refresh BackgroundQuery:=False
files(i) = .Parent.Name
i = i + 1
End With
End With
strFile = Dir
Loop
numOfFiles = i - 1
chartName = "Chart 1"
For j = 1 To numOfFiles
If n = 0 Then n = j Else n = n + 2
strFile = files(j)
Sheets(strFile).Select
Plot_y = Range("B1", Selection.End(xlDown)).Rows.Count
Plot_x = Range("C1", Selection.End(xlDown)).Rows.Count
Sheets("GraphDisplay").Select
If j = 1 Then ActiveSheet.ChartObjects(chartName).Activate
ActiveChart.SeriesCollection.NewSeries
ActiveChart.SeriesCollection(n).Name = strFile & " - Col B Values"
ActiveChart.SeriesCollection(n).XValues = "=" & strFile & "!$C$1:$C$" & Plot_x
ActiveChart.SeriesCollection(n).Values = "=" & strFile & "!$B$1:$B$" & Plot_y
ActiveChart.SeriesCollection.NewSeries
ActiveChart.SeriesCollection(n + 1).Name = strFile & " - Col A Values"
ActiveChart.SeriesCollection(n + 1).XValues = "=" & strFile & "!$C$1:$C$" & Plot_x
ActiveChart.SeriesCollection(n + 1).Values = "=" & strFile & "!$A$1:$A$" & Plot_y
ActiveChart.SeriesCollection(j).MarkerStyle = -4142
ActiveChart.SeriesCollection(j).Smooth = False
ActiveChart.SeriesCollection(n + 1).MarkerStyle = -4142
ActiveChart.SeriesCollection(n + 1).Smooth = False
Next j
ActiveSheet.ChartObjects(chartName).Activate
ActiveChart.Axes(xlValue).DisplayUnit = xlMillions
ActiveChart.Axes(xlValue).HasDisplayUnitLabel = False
End Sub

Resources