I have a recordset that contains all of the data needed to import into an Excel file. Is there a way I can clone my live recordset into the one created when I open an Excel file?
Here is what I'm trying right now with no luck.
Dim connection : Set connection = Server.CreateObject("ADODB.Connection")
connection.Open "Driver={Microsoft Excel Driver (*.xls)}; DriverId=790;
Dbq=c:\MyExcel.xls;" & _
"DefaultDir=c:\; ReadOnly=False;"
Dim excelRecordset : Set excelRecordset = Server.CreateObject("ADODB.Recordset")
excelRecordset.Open "[SHEET1$]", connection, 2, 3
excelRecordset.AddNew
Set excelRecordset = recordset.clone
excelRecordset.Update
excelRecordset.Close
Thank you.
When you do this:-
Set excelRecordset = recordset.clone
You replace the reference to the recordset opened on the excel spreadsheet (and it closes) with a reference to new recordset. This new recordset is not in anyway connected to the excel spreadsheet.
Using recordsets you don't really have much choice but to For Each through the source recordset, AddNew on the destination, assign each field from source to destination and Update.
Excel Range objects have a CopyFromRecordset method that should do the job. If you can create an Excel.Application object and open the workbook you want to write to then you should be able to use this.
So if your existing recordset is named rs and has already been populated, the code in VBA would be:
Worksheets("SHEET1").Cells(2, 1).CopyFromRecordset rs
You can then iterate over rs.Fields to fill in the field names
Dim fld As Field
Dim i As Integer
i = 1
With Worksheets("SHEET1")
For Each fld in rs.Fields
.Cells(1, i).Value = fld.Name
i = i + 1
Next fld
End With
Not sure how easy that would be to translate to your scenario though.
Alternatively, if it is available with the driver you are using, you may want to look into the SELECT INTO and INSERT INTO syntax described in this Knowledge Base article
Related
I'm using Excel and Access 365 for the record.
I have information on around 100,000 account numbers, far too many for Excel to handle efficiently. I put them into Access.
In Excel, I have a list of about 10 account numbers. This list changes daily. How do I get the account information from Access into Excel? If I was able to keep everything in Excel I would use INDEX MATCH, what is the equivalent to get information from Access?
I would suggest setting up a linked table to Excel within Access, and running an SQL statement. Much simpler than loops in VBA.
Open Access
Create a linked table to the Excel worksheet, which is nothing more than connection information to the worksheet; it doesn't actually store the records from the worksheet.
This allows the following:
From within Access -- run queries that join data between Access tables and the linked Excel table. You can save such queries, use them as RecordSource for a form or report etc.
From within Excel -- you can open an ADO connection from within Excel and run an SQL statement joining Access tables and the linked Excel worksheet. You can then use the Excel Range.CopyFromRecordset method to paste those results into an Excel worksheet.
It sounds like you need to use the 'In' clause. I have the following data points on Sheet2 in Range A1:A5.
Ryan
Sam
Timmy
Tommy
Teddy
Paste the code below into a Module and set a reference to 'Microsoft Active X Data Objects 2.8 Library' under Tools in the VBE Window.
Sub Import()
Dim connect As ADODB.Connection
Dim rec1 As ADODB.Recordset
Dim wb As Worksheet
Dim Wb2 As Worksheet
Dim Param() As ADODB.Parameter
Dim Command1 As ADODB.Command
Dim lrow As Integer
Dim i As Integer
Dim ConcatSQL As String
Set wb = ActiveWorkbook.Sheets("Sheet1")
Set Wb2 = ActiveWorkbook.Sheets("Sheet2")
lrow = Wb2.Range("A" & Wb2.Rows.Count).End(xlUp).Row
'Concatenate desired range into one cell
For i = 0 To lrow
ConcatSQL = ConcatSQL & "'" & Wb2.Cells(i + 1, 1) & "'" & ","
Next i
ConcatSQL = "(" & Left(ConcatSQL, Len(ConcatSQL) - 1) & ")"
'Open Command Object with One Paramter
Set Command1 = New ADODB.Command
With Command1
.CommandText = " Select ID, Price from TABLE where ID IN " & ConcatSQL
.CommandType = adCmdText
.CommandTimeout = 600
End With
'Connect to Data Source
Set connect = GetNewConnection 'Represents Private Function with Connection String
Command1.ActiveConnection = connect
Set rec1 = New ADODB.Recordset
Set rec1 = Command1.Execute()
'Paste Results
wb.Activate
With wb.QueryTables.Add(Connection:=rec1, Destination:=wb.Range("A1"))
.Name = "data"
.FieldNames = True
.Refresh BackgroundQuery:=False
End With
'Close Connections
rec1.Close
connect.Close
Set rec1 = Nothing
Set connect = Nothing
End Sub
Here is a screen shot to show how the variables are created.
I'm 100% certain that you can run a simple query in Access and export the results of said query to Excel. Or, save that query, and import the records in the object to Excel. When you get into larger data sets like you described, you may want to consider using different tools for the job. Python and R come to mind.
This will probably require VBA to do efficiently.
Loop through the account numbers, and for each account number query the Access database (using ADO) and return only the required data for each account.
I've got some queries I have connected to an excel sheet that I refresh in order to get the latest data.
Is it possible to make excel "ask" for input parameters for one column lets say?
I am looking to get data by company so wondering if it's possible to do it as in access (type [company]:) in the field criteria
If I save the query like that in access it won't let me connect it to excel
Thanks
Alright another edit.
Here it is, I created a database, its simple.
The database is called "Database1.accdb"
There are more records than shown in the screen shot.
I created a workbook with one sheet, its name is "AccessDBtest.xlsm"
I created a button on Sheet1 and entered the field parameter I wanted in the cell beside it, C3 or (3,3) in (row,col) format.
This is the code that works returning the data set (without field names) based on the input criteria. I made a msgBox before the SQL query execution so that I could look at it first. You don't need that if you do not want it, good for testing.
Private Sub CommandButton1_Click()
Dim inputSheet As Worksheet
Dim fieldSTR As String
Dim placementRange As Range
Dim rs As Object 'record set
Dim conn As Object
Dim strQuery As String
Dim myDB As String
Set inputSheet = ThisWorkbook.Worksheets("Sheet1")
Set placementRange = inputSheet.Range("E2")
fieldSTR = CStr(inputSheet.Cells(3, 3).Value) 'C3 cell
myDB = "C:\Users\Documents\0_Excel Projects\Testing\Database1.accdb"
Set conn = CreateObject("ADODB.Connection")
With conn
.Provider = "Microsoft.ACE.OLEDB.12.0" 'For *.ACCDB Databases
.ConnectionString = myDB
.Open
End With
strQuery = "SELECT * FROM " & _
"tbl_test WHERE tbl_test.Color = " & "'" & fieldSTR & "'" & ";"
'The below gives the same result as * but you could limit the fields returned as well
'tbl_test.ID, tbl_test.Color, tbl_test.number
'just using Color also works you do not need to reference the table directly
MsgBox (strQuery)
Set rs = conn.Execute(strQuery)
placementRange.CopyFromRecordset rs
rs.Close
Set rs = Nothing
conn.Close
Set conn = Nothing
End Sub
See if you can map what you want to do using that.
I wanted to capture a string from a cell and then use that string in the query.
Here is the MsgBox before the query executes (what access will see):
I tested it with * for all fields and below you can see that I called up specific fields, they both work.
And here is what happens after I clear the msgBox, the recordset is pulled and pasted starting in the range I specified Range.("E3") on the sheet I specified (Sheet1)
As you can see, we can pull queries from a database using input that is found on a current sheet.
Let me know if this helps your situation.
We can dig deeper if required.
-WWC
I have a database with different values. It is object based, so object "A" will have certain data and so on for other objects. It has almost 200,000 lines, but I only need the data from one object that is given as input in my tool's database. I want my tool to look in the huge database and pull the required data into its own database.
This huge database is also in the same workbook of my tool, but it has to be updated regularly and makes my tool open too slowly. I want the database in a different workbook, and the required data to be copied, according to an input object, into a sheet of my tool, where I will work on it.
Suppose the huge database (let's call it Workbook A) is as follows:
object var1 var2 var3 var4 var5
A
B
C
D
E
Input workbook is B
sheet 1 where we give input
lets say input is A
The input database is in Sheet2:
object var1 var2 var3 var4 var5
A
You can either use VLOOKUP and reference your other workbook or you can use VBA and ADO to access the data. The VBA ADO method is shown below. You must set a reference to Microsoft ActiveX Data Objects.
Dim DBWorkbook As String
Dim rs As ADODB.Recordset
Dim con As New ADODB.Connection
Dim wb As Workbook
Dim ws As Worksheet
Sub get_data() 'set reference to Microsoft ActiveX Data Objects
Set wb = ThisWorkbook
Set con = New ADODB.Connection
Set rs = New ADODB.Recordset
DBWorkbook = "C:\MyHugeDatabaseWorkbook.xlsx"
'lets assume everything is happening on Sheet2, Row2
Set ws = wb.Sheets("Sheet2")
LookupObject = ws.Cells(2, 1)
'connect to huge database workbook
con.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & DBWorkbook & ";Extended Properties=""Excel 8.0;"""
'get data for object
rs.Open "Select * from [Sheet1$] WHERE [object]='" & LookupObject & "'", con, adOpenStatic
'fill in sheet with data, if it exists in the database worksheet
If Not rs.EOF Then
ws.Cells(2, 2) = rs("var1")
ws.Cells(2, 3) = rs("var2")
ws.Cells(2, 4) = rs("var3")
ws.Cells(2, 5) = rs("var4")
ws.Cells(2, 6) = rs("var5")
End If
'cleanup
rs.Close
con.Close
Set rs = Nothing
Set con = Nothing
'this needs error trapping once you have it working
End Sub
You would also do yourself a huge favor by putting your database into Access or SQL Server and referencing it from there.
I am building a form in Access that will allow a user to select an excel file, and then select a worksheet to import. I have code that allows a user to select an Excel file and it stores the filename in a control on the form.
Now I want to display the names of the worksheets that are in that file. I know how to do the import, what I don't know is how to get the worksheet names in the file and store them either in a table, or a listbox on the form so the user can select one. Sadly, although all the Excel files are supposed to have standard names for the worksheets, some of the sheets are off and that is why I want to display them.
I am using Office 2007.
Set oWkb = oXLApp.Workbooks.Open(FileName)
For Each oSh In oWkb.Worksheets
MsgBox oSh.Name
Next
oXLApp would be an instance of the Excel application, which you can get using Set oXLApp = CreateObject("Excel.Application").
Make sure you close your workbook when you are done getting the sheet names. I would probably store them in a collection or an array (instead of the MsgBox oSh.Name) so that you can collect them, close the workbook, and display them on your form using the contents of the collection.
In my testing, using an ADOX Catalog to retrieve the worksheet names appears significantly faster than opening an Excel application instance to enumerate the WorkSheets collection.
Public Sub List_WorksheetsAdox(ByVal pWorkBook As String)
Dim cat As Object 'ADOX.Catalog
Dim cn As Object 'ADO.Connection
Dim strConnect As String
Dim tbl As Object 'ADOX.Table
strConnect = "Provider=" & _
CurrentProject.Connection.Provider & ";" & _
"Data Source='" & pWorkBook & "';" & _
"Extended Properties=Excel 8.0;"
Set cn = CreateObject("ADODB.Connection")
cn.Open strConnect
Set cat = CreateObject("ADOX.Catalog")
Set cat.ActiveConnection = cn
For Each tbl In cat.Tables
Debug.Print tbl.Name
Next tbl
Set tbl = Nothing
Set cat = Nothing
cn.Close
Set cn = Nothing
End Sub
This approach will include the dollar sign after each sheet name, which may not be what you want. You could strip it off easily.
I tested using Excel 8.0 for my xls 2003 format workbook. It appears the Excel 2007 format would require "Excel 12.0" for Extended Properties. You can find more details at ConnectionStrings.com.
As in the other answers, you will want to do something more useful with tbl.Name other than Debug.Print it.
Note this approach will list both named ranges and worksheets. If that is an issue for you, you can distinguish between them based on whether or not the name includes a dollar sign ("$") on the end. Sheets have the dollar sign; named ranges do not.
Something like this?
Dim wb As Excel.Workbook
Dim ws As Excel.Worksheet
Set wb = Excel.Workbooks.Open("C:\MyBook.xls") ' Or whatever
For Each ws In wb.Worksheets
Debug.Print ws.Name
' This prints the name in the Immediate window.
' You'll want to do something useful with them instead.
Next ws
To use this, must set reference to Excel object library: Tools > References > set checkmark next to Microsoft Excel xx.0 Object Library.
What's the "best" way to read (just read) an Excel file from within an Access 2007 application. I only want to loop trough the rows and put the data into an Access table.
I don't want a manually import (Get External Data dialog) but by VBA. The user gets a Form with a Browse button and then points to a Excel file with a defined content/format. After that the VBA code reads the data and puts it into the Access database.
You could try the DoCmd.TransferSpreadsheet method.
DoCmd.TransferSpreadsheet acImport, , "from_excel","C:\Access\demo.xls", True
That imports spreadsheet data into a table named from_excel, and assumes the first row of the spreadsheet contains field names. See Access help for TransferSpreadsheet or online here, for more details.
If you want to read the entire spreadsheet in, you can import an Excel spreadsheet directly into Access. See here or here.
You can also choose to link to the Excel spreadsheet instead of importing it. That way any changes to the Excel spreadsheet will be reflected in the linked table. However, you won't be able to make changes from within Access.
A third option is to write some VBA code within Access to open a recordset and read the spreadsheet in. See the answers from KeithG in this thread. You can do something like this to open the spreadsheet in VBA:
Dim xl As Excel.Application
Dim xlsht As Excel.Worksheet
Dim xlWrkBk As Excel.Workbook
Set xl = CreateObject("Excel.Application")
Set xlWrkBk = GetObject("H:/ggg.xls")
Set xlsht = xlWrkBk.Worksheets(1)
Try something like this:
Dim excelApp As Excel.Application
Dim workbook As Excel.Workbook
Dim worksheet As Excel.Worksheet
Set excelApp = CreateObject("Excel.application")
Set workbook = excelApp.Open("C:\someFileName.xls")
Set worksheet = workbook.Worksheets(1)
And then loop through the rows and columns, pull the data from the cells, and insert it into the database. (You can use the worksheet.cells method.) Try searching on google for code samples.
Hereafter my method to read an excel file and all the worksheet names:
Function listOfWorksheet(filename As String) As Collection
Set dbExcel = OpenDatabase(filename, False, True, "excel 8.0")
For Each TableDef In dbExcel.TableDefs
Debug.Print TableDef.Name
Next
End Function
Now, you can use the name of the worksheet to read the whole content:
Function ReadMyObjects(filename as String, wsName as String) As Collection
On Error GoTo label_error
Set results = New Collection
Dim countRows As Integer
Set dbExcel = OpenDatabase(filename, False, True, "excel 8.0")
Set excelRs = dbExcel.OpenRecordset(wsName, dbOpenSnapshot)
Do While Not excelRs.EOF
'Data Rows
Dim item As MyObject 'a custom object defined by you.
Set item = New MyObject
item.ABC = Nz(excelRs.Fields("COLUMN_ABC").Value, "")
item.DEF = Nz(excelRs.Fields("COLUMN_DEF").Value, "")
results.Add item
excelRs.MoveNext
Loop
excelRs.Close
Set ReadMyObjects= results
GoTo label_exit
label_error:
MsgBox "ReadMyObjects" & Err.Number & " " & Err.Description
label_exit:
End Function