linking an access database to excel (without importing the whole table) - excel

Is there any way to link tables in an Access database to Excel without importing the entire table? I need to reference/lookup cells in the Access table but don't want to import the whole table into the excel workbook (tables are too big).
My second option is to export the Access tables into a separate excel workbook, then just reference this new workbook instead of the Access database itself. When I try to do this only around 65,000 rows of data from any Access table actually export to Excel, as the rest 'couldn't be copied to the clipboard'. Is there a simple way around this? (I want to actually have a connection between the excel/access files, so the data can be refreshed, not just copy and paste the rows over)

See this ancient article, which should help you get the data you actually need rather than everything:
http://dailydoseofexcel.com/archives/2004/12/13/parameters-in-excel-external-data-queries/

You can work with Access database tables from Excel without importing the table into an Excel worksheet:
Dim cnn As ADODB.Connection ' Needs a reference to the Microsoft ActiveX
Dim rs As ADODB.Recordset ' Data Objects Library
Set cnn = CreateObject("ADODB.Connection")
cnn.Open "DRIVER={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=database-path\Data.accdb;"
Set rs = cnn.Execute("SELECT * FROM MyTable")
While Not rs.EOF
Debug.Print rs(1)
rs.MoveNext
Wend
You may need the Microsoft Access Database Engine 2010 Redistributable which you should install with the /passive option if you are using a x86 Access version on a x64 OS.

Try the following script. This should give you what you want.
Option Compare Database
Private Sub Command0_Click()
Dim InputFile As String
Dim InputPath As String
InputPath = "C:\your_path_here\Desktop\"
InputFile = Dir(InputPath & "*.xlsx")
Do While InputFile <> ""
DoCmd.TransferSpreadsheet acLink, , InputFile, InputPath & InputFile, True '< The true is for column headers
InputFile = Dir
Loop
End Sub

Related

How to export data from Excel to Access via Excel Macro when multiple instances of Excel are open

I am using an Excel macro to define a data range in Excel and then call "objAccess.DoCmd.TransferSpreadsheet" to import the data from this range into an Access table. This import does not work all of the time.
I have come to the conclusion that the macro works fine when there is only one instance of Excel open. However, the data import fails when another instance is already open. In the latter case the Access database opens up and the Excel file from which I run the macro is being reopened (in read-only mode) in the other Excel instance. There is no actual error but the desired import is not being carried out. Why does this happen?
Sub Excel_2_Access()
Dim strPath As String
Dim strwbPath As String
Dim strRange As String
Dim objAccess As Access.Application
Dim wbActive As Workbook
'get database path
strPath = Worksheets("error").Range("Access_DB_Path").Value & "\" & Worksheets("error").Range("Access_DB").Value
'open database
Set objAccess = New Access.Application
Call objAccess.OpenCurrentDatabase(strPath)
objAccess.Visible = True
'access import
Worksheets("error").Columns("P:P").Calculate
Set wbActive = ActiveWorkbook
strwbPath = Application.ActiveWorkbook.FullName
strRange = "error!M2:M" & (Worksheets("error").Range("WKN_count").Value + 2)
Call objAccess.DoCmd.TransferSpreadsheet(acImport, 8, "WKN_Mapping", strwbPath, True, strRange)
objAccess.Forms("MX_Import").Refresh
End Sub
As the macro is fairly short I have included the entire code for your reference. However, I don't think the way the range is specified or names are provided is really relevant to the question.
The desired outcome would be to have an Excel macro in place that carries out the transfer from Excel to Access no matter if there are other instances of Excel open or not.
Is there such a thing as the primary instance of Excel (the first one that was opened) which has a special status? Is there a way to provide the specific Excel instance the workbook is in when calling the Access function from Excel? Or is there a more reliable way to transfer the data which generally avoids this problem with multiple instances?
I tested approach that opens Access db and runs TransferSreadsheet. Don't need to set a workbook object (your code sets but then doesn't even utilize). It ran without error every time. I tried setting the Access object Visible but the database appears and immediately closes anyway, although the data import does happen. Set reference libarary: Microsoft Access x.x Object Library.
Sub test()
Dim ac As Access.Application, strRange As String
Set ac = New Access.Application
strRange = "Sheet1!A1:E3"
ac.OpenCurrentDatabase "C:\Users\June\LL\Umpires.accdb"
ac.DoCmd.TransferSpreadsheet acImport, acSpreadsheetTypeExcel12Xml, "Rates", ThisWorkbook.FullName, True, strRange
End Sub
Example Excel VBA code that exports all rows of worksheet to existing table in Access without opening Access file. Setting an ADODB connection makes the Execute method available. This approach runs faster. Set reference library: Microsoft ActiveX Data Objects x.x Library.
Sub test()
Dim cn As ADODB.Connection
Set cn = New ADODB.Connection
cn.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ThisWorkbook.FullName & ";Extended Properties=Excel 8.0"
cn.Execute "INSERT INTO Rates(RateLevel, Rate, Pos, EffDate) IN 'C:\Users\June\LL\Umpires.accdb' " & _
"SELECT RateLevel,Rate,Pos,EffDate FROM [Sheet1$];"
cn.Close
Set cn = Nothing
End Sub

How do I match data in Excel with an Access database?

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.

Link Table between MS Access files from MS Excel

How can I create a Table link within a MS Access *.accdb file, linking to another table in an MS Access *.accdb file, but from VBA code within an MS Excel *.xlsx file.
Database1 in file1
Database2 in file2
Excel VBA Code in file3
Execute code in file3 to link a table of file2 to file1, so that it appears as linked table within file1.
Details:
I have a complex script creating a large table and join mappings based on a MS Excel Design, since it is more user friendly to design the things in an MS Excel Table. Everything works great so far, but I need the last step, LINK the original table.
Within MS Access I would do
DoCmd.TransferDatabase TransferType:=acLink, _
DatabaseType:="Microsoft Access", _
DatabaseName:=SRC_FILE_PATH, _
ObjectType:=acTable, _
Source:=SRC_TABLE_NAME, _
Destination:=DESTINATION_TABLE_NAME
But since I am executing VBA Code within Excel, only using the connection to the database via a DAO.Database object, this command doesn't work.
Using the DAO reference library in Excel
Dim wrkDAOWorkspace As DAO.Workspace
Dim dbsDAODatabase As DAO.Database
Dim tdfNewLinkedTable As DAO.TableDef
Set wrkDAOWorkspace = CreateWorkspace("WorkspaceForLinkCreation", "Admin", "", dbUseJet)
Set dbsDAODatabase = wrkDAOWorkspace.OpenDatabase("c:\file1.accdb")
Set tdfNewLinkedTable = New DAO.TableDef
With tdfNewLinkedTable
.Name = "TestTableLinked"
.Connect = ";DATABASE=c:\file2.accdb"
.SourceTableName = "TestTableLinkTo"
End With
dbsDAODatabase.TableDefs.Append tdfNewLinkedTable
Something like this should do it for you. Modify to suit your needs...
Private Sub Command1_Click()
DoCmd.SetWarnings False
Dim InputFile As String
Dim InputPath As String
InputPath = "C:\your_path_here\"
InputFile = Dir(InputPath & "*.xls")
Do While InputFile <> ""
DoCmd.TransferSpreadsheet acImport, , InputFile, InputPath & InputFile, True '< The true is for column headers
InputFile = Dir
Loop
End Sub

Access - Excel Integration

Hey all, have been working on designing a new database for work. They have been using Excel for their daily reports and all the data is stored in there, so I decided to have the back-end of the database in Access and the front-end in Excel, so any analytical work can be easily performed once all the data has been imported into Excel.
Now I'm fairly new to VBA, slowly getting used to using it, have written some code to transfer one of the calculated tables from Access to Excel:
Option Explicit
Public Const DataLocation As String = "C:\Documents and Settings\Alice\Desktop\Database\TestDatabase21.accdb"
Sub Market_Update()
Call ImportFromAccessTable(DataLocation, "Final_Table", Worksheets(2).Range("A5"))
End Sub
Sub ImportFromAccessTable(DBFullName As String, TableName As String, TargetRange As Range)
Dim cn As ADODB.Connection, rs As ADODB.Recordset, intColIndex As Integer
Set TargetRange = TargetRange.Cells(1, 1)
' open the database
Set cn = New ADODB.Connection
cn.Open "Provider=Microsoft.ACE.OLEDB.12.0; Data Source=" & DBFullName & ";"
Set rs = New ADODB.Recordset
With rs
' open the recordset
' .Open TableName, cn, adOpenStatic, adLockOptimistic, adCmdTable
' all records
.Open "SELECT * FROM Final_Table", cn, , , adCmdText
' filter records
For intColIndex = 0 To rs.Fields.count - 1 ' the field names
TargetRange.Offset(0, intColIndex).Value = rs.Fields(intColIndex).Name
Next
TargetRange.Offset(1, 0).CopyFromRecordset rs ' the recordset data
End With
rs.Close
Set rs = Nothing
cn.Close
Set cn = Nothing
End Sub
Sub Company_Information()
Dim companyName As String
On Error GoTo gotoError
companyName = Application.InputBox(Prompt:="Enter Company Name", _
Title:="Company Name", Type:=2)
Exit Sub 'Don't execute errorhandler at end of routine
gotoError:
MsgBox "An error has occurred"
End Sub
The above code works fine and pulls up the desired calculated table and places it in the right cells in Excel.
I've got two problems that I'm having trouble with; firstly I have some cell-formatting already done for the cells where the data is going to be pasted into in Excel; I want it to apply the formatting to the values as soon as they are pasted in Excel.
Secondly; I have an add-on for Excel which updates some daily Stock Market values; these values need to be transferred into Access at the end of each working day, to keep the database maintained, I tried some code but have been having some problems with it running.
The code for this part can be seen following:
Sub UPDATE()
Dim cnt As ADODB.Connection
Dim stSQL As String, stCon As String, DataLocation As String
Dim stSQL2 As String
'database path - currently same as this workbook
DataLocation = ThisWorkbook.Path & DataLocation
stCon = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & DataLocation & ";"
'SQL code for GL Insert to Access
stSQL = "INSERT INTO Historical_Stock_Data SELECT * FROM [Portfolio] IN '" _
& ThisWorkbook.FullName & "' 'Excel 8.0;'"
'set connection variable
Set cnt = New ADODB.Connection
'open connection to Access db and run the SQL
With cnt
.Open stCon
.CursorLocation = adUseServer
.Execute (stSQL)
End With
'close connection
cnt.Close
'release object from memory
Set cnt = Nothing
End Sub
I get the following error with this.
Run-time Error '-2147467259 (80004005)'
The Microsoft Jet database engine cannot open the file 'Cocuments and Settings\Alice\Desktop\Database'. It is already opened exclusively by another user or you need permission to view its data.
I'm fairly new to databases, VBA and Access so any help would be greatly appreciated.
Also I have been told that the above method of having an Excel front-end and Access back-end is not recommended but alot of the analysis they conduct is done through Excel, and the charts feature in Excel is much better than Access in my experience atleast; and that is also one of the requirements for this project.
Thank you advance!
Solution to your first problem:
Sorry to be the bearer of bad news, but your entire first module is unnecessary. Instead, try:
Go to Data->Import External Data->Import Data, select your Access file, select your table, and presto! done!
Right-click on your new "External Data Range" to see a number of options, some related to formatting. You can even keep the original cell formatting and just update the values. I do this all the time.
To update the Excel data table later, there is a "External Data Range" toolbar that allows you to refresh it as well as a "refresh all" option to refresh every table in the Excel file. (You can also automate this thru code. It'll take some trial and error, but you're definitely up to the task)
Regarding your second problem
I've never used it, but there is also a "New Web Query" option in there as well. I assume it can be manipulated and updated the same way.
And lastly
Your choice of the Excel front-end and the Access back-end sounds good for your needs. It gets the data to your analysts in a medium they are familiar with (Excel) while keeping the calculations out of the way in Access. Technically, you could try putting all your calculations in Excel, but that might the Excel file much bigger and slower to open.
Do the data entry/updating/reviewing in Access. One of Access' strengths is using forms that allow you to update the tables without any code. Then allow the users to easily export the data to Excel such as by clicking on some command buttons.
Modules: Sample Excel Automation - cell by cell which is slow
Modules: Transferring Records to Excel with Automation
nothing wrong in principle with the excel/access pairing. I'm not familiar with ADO (I use DAO), but your error message seems to be indicating that the path to the datasource is not fully formed; or you already have it opened and hence are locking it.

Clone existing recordset to excel recordset

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

Resources