How to join two recordset created from two different data source in excel vba - sql

My Scenario is -
I have one set of data in .xls file and another set of data in oracle data base table. I want import both data using excel vba then perform join (sql like) and finally save the data in some workbook.
Problem -
I do not know how to get two different set of data in vba and then perform join.
In .Net there is DataSet object where we can save the imported data and then perform any query on it but vba How I can do this?

Consider the below example using ADO. The code allows to get data from several data sources within single SQL query (Jet SQL), particularly make unions from .xlsx files, and put result recordset to the worksheet. Unfortunately I have no available Oracle data source to test, though you can connect directly to Oracle also with ADO (like any other database) via Oracle ODBC driver.
The code is placed in Query.xlsm:
Option Explicit
Sub SqlUnionTest()
Dim strConnection As String
Dim strQuery As String
Dim objConnection As Object
Dim objRecordSet As Object
strConnection = _
"Provider=Microsoft.ACE.OLEDB.12.0;" & _
"User ID=Admin;" & _
"Data Source='" & ThisWorkbook.FullName & "';" & _
"Mode=Read;" & _
"Extended Properties=""Excel 12.0 Macro;"";"
strQuery = _
"SELECT * FROM [Sheet1$] " & _
"IN '" & ThisWorkbook.Path & "\Source1.xlsx' " & _
"[Excel 12.0;Provider=Microsoft.ACE.OLEDB.12.0;Mode=Read;Extended Properties='HDR=YES;'] " & _
"UNION " & _
"SELECT * FROM [Sheet1$] " & _
"IN '" & ThisWorkbook.Path & "\Source2.xlsx' " & _
"[Excel 12.0;Provider=Microsoft.ACE.OLEDB.12.0;Mode=Read;Extended Properties='HDR=YES;'] " & _
"UNION " & _
"SELECT * FROM [Sheet1$] " & _
"IN '" & ThisWorkbook.Path & "\Source3.xlsx' " & _
"[Excel 12.0;Provider=Microsoft.ACE.OLEDB.12.0;Mode=Read;Extended Properties='HDR=YES;'] " & _
"ORDER BY ContactName;"
Set objConnection = CreateObject("ADODB.Connection")
objConnection.Open strConnection
Set objRecordSet = objConnection.Execute(strQuery)
RecordSetToWorksheet Sheets(1), objRecordSet
objConnection.Close
End Sub
Sub RecordSetToWorksheet(objSheet As Worksheet, objRecordSet As Object)
Dim i As Long
With objSheet
.Cells.Delete
For i = 1 To objRecordSet.Fields.Count
.Cells(1, i).Value = objRecordSet.Fields(i - 1).Name
Next
.Cells(2, 1).CopyFromRecordset objRecordSet
.Cells.Columns.AutoFit
End With
End Sub
Note, ThisWorkbook.Path should not contain ' within path. Otherwise you have to escape them by replacing ' with ''.
Also there are three data source files in the same folder as Query.xlsm.
Source1.xlsx:
Source2.xlsx:
Source3.xlsx:
The resulting worksheet is as follows:
It works on 64-bit version Excel 2013 for me. To make it compatible with .xls and Excel 2003 (where the provider ACE.OLEDB.12.0 isn't installed) you have to replace Provider=Microsoft.ACE.OLEDB.12.0; with Provider=Microsoft.Jet.OLEDB.4.0;, and also in extended properties Excel 12.0 Macro; / Excel 12.0; with Excel 8.0;. You can easily add WHERE clause and other SQL stuff to the query. Actually data source for connection object isn't limited the only Query.xlsm file, which the code placed in. It could be another data source, compatible with one of the available providers, either file-based or server-based. Find more connection strings for your data source on http://www.connectionstrings.com/

Related

VBA - SQL Import From Excel Sheet To Access DB - EXECUTION ERROR 3343

I would like to build a SQL request in order to store all my sheet content into an access DB in order to do this I built the following request :
sSQL = "INSERT INTO Archive_FP21 (Date_Histo,Caisse,Libelle,Reference_Contrat,Date_de_Nego,Date_Valeur,Echeance_Finale,Libelle_Index,Taux_Actuel,Capital_Origine,Capital_Restant_Du,Marge,Taux_du_cap,Taux_du_Floor,Derniere_Echance_INT,Derniere_Echeance_AMO,Interet,Prochaine_Echeance) " & _
"SELECT * FROM [Feuil1$A:R] IN """ & WbPath & """"
But I am facing the following issue :
3343 unrecognized database format
[I feel like my issue is in FROM [Feuil1$A:R] IN """ & WbPath & """"]
Below is the my full code Sub :
Sub archiver()
Dim ws As DAO.Workspace
Dim db As DAO.Database
Dim sDb As String
Dim sSQL As String
Dim qdf As QueryDef
Dim WbPath As String
WbPath = "C:\******\Extraction FP21 Mise en Forme Auto\16102020 - Copie.xlsx"
sDb = "C:\******\BaseFp21.accdb"
Set ws = DBEngine.Workspaces(0)
Set db = ws.OpenDatabase(sDb)
sSQL = "INSERT INTO Archive_FP21 (Date_Histo,Caisse,Libelle,Reference_Contrat,Date_de_Nego,Date_Valeur,Echeance_Finale,Libelle_Index,Taux_Actuel,Capital_Origine,Capital_Restant_Du,Marge,Taux_du_cap,Taux_du_Floor,Derniere_Echance_INT,Derniere_Echeance_AMO,Interet,Prochaine_Echeance) " & _
"SELECT * FROM [Feuil1$A:R] IN """ & WbPath & """"
db.Execute sSQL
End Sub
Note The goal of this SQL request is to Add all data from the sheet 'Feui1.Range(A:R)` into my Access Table.
I can't do it row By Row since I have 37K line to fill in Access.
What Am I missing ? How would you do in order to fill 37K row from excel inside Access DB with VBA ?
To query from an Excel workbook inline with an Access connection does not use the IN operator but bracketed identifier with set parameters such as headers and workbook type. As used, IN would work if you were querying an external Access database but being an Excel workbook, the database format was not recognized.
sSQL = "INSERT INTO Archive_FP21 (Date_Histo, Caisse, Libelle, Reference_Contrat," _
& " Date_de_Nego, Date_Valeur, Echeance_Finale, " _
& " Libelle_Index, Taux_Actuel, Capital_Origine, " _
& " Capital_Restant_Du, Marge, Taux_du_cap, Taux_du_Floor, " _
& " Derniere_Echance_INT, Derniere_Echeance_AMO, Interet, " _
& " Prochaine_Echeance) " _
& " SELECT * FROM [Excel 12.0 Xml;HDR=Yes;Database=" & WbPath & "].[Feuil1$A:R]"
db.Execute sSQL
Also, be sure to avoid SELECT * FROM and explicitly select named columns especially in insert-select append queries for column-to-column mapping. SELECT Col1, Col2, Col3, ... FROM is more readable and maintainable in case Excel columns order should adjust or some columns are no longer present.

Is it possible to create a table from another table in Excel using SQL like syntax?

I have a table in excel that has multiple lines per date. I'd like to create a new table that groups by date as well as a few other dimensions and sums net_revenue.
In sql it would be simple:
SELECT send_date,
week_day,
after_hours,
discount_type,
sum(net_revenue
FROM this_table
GROUP BY send_date,
week_day,
after_hours,
discount_type
Is there a simple way to do this in excel? At first I thought pivot tables but I don't want each additional dimension on a new row.
This is what my current table looks like:
Consider the following strictly GUI interface solution:
Copy all your grouping fields as is into a separate sheet.
Under Data tab of ribbon, click Remove Duplicates, selecting all columns.
In the final column, run SUMIFS formula to calculate net_revenue sum, pointing to values in you original sheet.
=SUMIFS(<net_revenue_column>,
<1stgroup_column_in_first_sheet>, <1stgroup_value_in_second_sheet>,
<2ndgroup_column_in_first_sheet>, <2ndgroup_value_in_second_sheet>,
<3rdgroup_column_in_first_sheet>, <3rdgroup_value_in_second_sheet>,
...
)
Alternatively, actually run SQL (if using Excel for Windows) using the JET/ACE SQL Engine (same engine of MS Access that can query Excel workbooks even CSV files). Below assumes your data begins in A1 with named columns. Adjust sheet name in FROM clause.
Sub RunSQL()
Dim oConn, rs As Object
Dim strConnection, strSQL As String
Dim i As Integer
Set oConn = CreateObject("ADODB.Connection")
Set rs = CreateObject("ADODB.Recordset")
' CONNECTION STRING ON CURRENT WORKBOOK
strConnection = "DRIVER={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};" _
& "DBQ=" & ThisWorkbook.FullName & ";"
' OPEN DB CONNECTION
oConn.Open strConnection
strSQL = "SELECT send_date, " _
& " week_day, " _
& " after_hours, " _
& " discount_type, " _
& " sum(net_revenue) AS total_revenue " _
& " FROM [SheetName$] " _
& " GROUP BY send_date, " _
& " week_day, " _
& " after_hours, " _
& " discount_type "
' OPEN RECORDSET OF QUERY
rs.Open strSQL, oConn
' OUTPUT DATA TO EXCEL WORKSHEET (IN EMPTY TAB NAMED "RESULTS")
' HEADERS
For i = 0 To rs.Fields.Count - 1
ThisWorkbook.Worksheets("RESULTS").Cells(1, i) = rs.Fields(i).Name
Next i
' ROWS
ThisWorkbook.Worksheets("RESULTS").Range("A2").CopyFromRecordset rs
rs.Close: oConn.Close
Set rs = Nothing: Set oConn = Nothing
End Sub

Executing SQL query stored in an excel cell and then transfer the result set into a .txt file

I have a SQL query stored in one of my excel sheet cells that I execute using the below VBA Code:
Sub run()
Dim dtStart As Date
Dim dtEnd As Date
Dim MRC As Variant
'Get the SQL text(s)
MRC = "" & Worksheets("SQL Text").Range("D4").Value & ""
'Check for UNDF queries
If MRC = 0 Then
MsgBox ("Query has not yet been defined, please make a new selection")
Exit Sub
Else
End If
'Set up query
Application.StatusBar = "Data Refresh: 1 of 1 "
'Update subTabs
Sheets("Summary").Select
With ActiveWorkbook.Connections("connection1").OLEDBConnection
.CommandText = MRC
.CommandType = xlCmdSql
End With
ActiveWorkbook.Connections("connection1").Refresh
End Sub
In addition to the above VBA code, I also have another VBA code that executes the different SQL view and transfers the SQL view result-set to a .txt file and saves it into a specific folder. Please see below for that code
Sub TEXT()
Dim cn As New ADODB.Connection
Dim rs As New ADODB.Recordset
Dim strCon, strSQL As String
strCon = "Provider=SQLOLEDB.1;" & _
"Integrated Security=SSPI;Persist Security Info=True;" & _
"Initial Catalog=master;Data Source=VRSQLADHOC;" & _
"Use Procedure for Prepare=1;" & _
"Auto Translate=True;" & _
"Packet Size=4096;" & _
"Use Encryption for Data=False;" & _
"Tag with column collation when possible=False"
strSQL = "SELECT * FROM table1" 'Sql Query
Folder = "U:\" 'Path in U drive
Filename = "file_name_" & Format(Now(), "YYYYMMDD") & ".txt" 'Name of Text document
fpath = Folder & Filename
cn.Open strCon
rs.ActiveConnection = cn
rs.Open strSQL
Set fs = CreateObject("Scripting.FileSystemObject")
Set A = fs.CreateTextFile(fpath)
A.Write (rs.GetString(adClipString, , , vbCrLf, ""))
rs.Close
cn.Close
Set cn = Nothing
MsgBox ("file name " + fpath)
End Sub
Currently I am interested in applying the second VBA logic of transferring the result-set data into .txt file to my first VBA logic, which takes care of executing the SQL query stored in one of the excel sheet cells.
To put it shortly I want to execute a SQL query stored in an excel cell and then transfer the result set into a .txt file
If I'm understanding this right, both these subs use really different ways do query the database.
In the first example you've got a db connection in a sheet, and you're using a cell to update that connection.
In the second, you've got a vba /adodb connection to the database. If all you want to do is refer to a cell in excel for the query, then simply change the line:
strSQL = "SELECT * FROM table1" 'Sql Query
to something more like:
strSQL = Worksheets("SQL Text").Range("D4").Value

Excel VBA SQL - multiple data sources

I have a fairly simple problem which I cannot find an answer to.
I have the following SQL:-
Select a from filea where a in (select b from fileb)
I am attempting to run this in Excel using VBA.
The problem I have is that filea is a table on an AS/400 and fileb is a table in an Excel spreadsheet. That is, two different datasources.
I can't find a way to combine the two datasources in one SQL statement.
Anybody got any bright ideas.
The below example shows how to get data from two excel workbooks within single SQL query (since I haven't got any AS/400 data source), and put result recordset to the worksheet. The code is placed in Query.xlsm:
Option Explicit
Sub SqlWhereInTest()
Dim strConnection As String
Dim strQuery As String
Dim objConnection As Object
Dim objRecordSet As Object
strConnection = _
"Provider=Microsoft.ACE.OLEDB.12.0;" & _
"User ID=Admin;" & _
"Data Source='" & ThisWorkbook.FullName & "';" & _
"Mode=Read;" & _
"Extended Properties=""Excel 12.0 Macro;"";"
strQuery = _
"SELECT * FROM [Sheet1$] " & _
"IN '" & ThisWorkbook.Path & "\Src1.xlsx' " & _
"[Excel 12.0;Provider=Microsoft.ACE.OLEDB.12.0;Mode=Read;Extended Properties='HDR=YES;'] " & _
"WHERE Country IN " & _
"(SELECT CountryFilter FROM [Sheet1$] " & _
"IN '" & ThisWorkbook.Path & "\Src2.xlsx' " & _
"[Excel 12.0;Provider=Microsoft.ACE.OLEDB.12.0;Mode=Read;Extended Properties='HDR=YES;'])"
Set objConnection = CreateObject("ADODB.Connection")
objConnection.Open strConnection
Set objRecordSet = objConnection.Execute(strQuery)
RecordSetToWorksheet Sheets(1), objRecordSet
objConnection.Close
End Sub
Sub RecordSetToWorksheet(objSheet As Worksheet, objRecordSet As Object)
Dim i As Long
With objSheet
.Cells.Delete
For i = 1 To objRecordSet.Fields.Count
.Cells(1, i).Value = objRecordSet.Fields(i - 1).Name
Next
.Cells(2, 1).CopyFromRecordset objRecordSet
.Cells.Columns.AutoFit
End With
End Sub
Also there are two workbooks as data sources in the same folder as Query.xlsm.
Src1.xlsx containing Customers:
Src2.xlsx:
The resulting worksheet is as follows:
It works on 64-bit version Excel 2013 for me. To make it compatible with .xls and Excel 2003 (where the provider ACE.OLEDB.12.0 isn't installed) you have to replace Provider=Microsoft.ACE.OLEDB.12.0; with Provider=Microsoft.Jet.OLEDB.4.0;, and also in extended properties Excel 12.0 Macro; / Excel 12.0; with Excel 8.0;. Actually data source for connection object isn't limited the only Query.xlsm file (see ThisWorkbook.FullName part within strConnection), which the code placed in. It could be another data source, compatible with one of the available providers, either file-based or server-based. Find more connection strings for your data source on http://www.connectionstrings.com/

Use Excel VBA to change the value of a cell in a closed workbook?

I currently use this function in VBA to get the value of a cell in a closed workbook. I want to use a similar process to SET the value of the cell to whatever I want, without opening the file. Is that possible?
Private Function GetValue(path, file, sheet, ref)
Dim arg As String
If Right(path, 1) <> "\" Then path = path & "\"
If Dir(path & file) = "" Then
GetValue = "File Not Found"
Exit Function
End If
arg = "'" & path & "[" & file & "]" & sheet & "'!" & _
Range(ref).Range("A1").Address(, , xlR1C1)
GetValue = ExecuteExcel4Macro(arg)
End Function
Yes you can do this using ADO as Gary commented but only if your Excel Worksheet is arranged in a Database like structure.
Meaning you have valid fields arranged in columns (with or without headers).
For example:
Now, you see that ID number 12345 have a name John John and you want to update it to John Knight.
Using ADO you can try:
Edit1: You can actually do this without using Recordset. See below update.
Sub conscious()
Dim con As ADODB.Connection
Dim sqlstr As String, datasource As String
Set con = New ADODB.Connection
datasource = "C:\Users\UserName\Desktop\TestDataBase.xlsx" 'change to suit
Dim sconnect As String
sconnect = "Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Data Source=" & datasource & ";" & _
"Extended Properties=""Excel 12.0;HDR=YES"";"
With con
.Open sconnect
sqlstr = "UPDATE [Sheet1$] SET [Name] = ""John Knight"" WHERE [ID Number] = 12345"
.Execute sqlstr
.Close
End With
Set con = Nothing
End Sub
Result:
I'm not entirely sure if this is what you want but HTH.
Notes:
You need to add reference to Microsoft ActiveX Data Objects X.X Library (early bind).
But you can also do this using late bind (no reference).
Connection string used is for Excel 2007 and up.
Sheet1 is the name of the target sheet you want to update the value to.
Edit1: This is how to do it if your file have no header
First change the connection string HDR argument to NO:.
sconnect = "Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Data Source=" & datasource & ";" & _
"Extended Properties=""Excel 12.0;HDR=NO"";"
Then adjust your SQL string to:
sqlstr = "UPDATE [Sheet1$] SET F2 = ""John Knight"" WHERE F1 = 12345"
So that is F1 for field 1, F2 for field 2 etc.