Link Table between MS Access files from MS Excel - 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

Related

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.

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

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

how to extract the content of excel document with devexpress

I would extract the content of excel document. It's possible with devexpress 13.2? Does anybody have any suggestion?
Thanks a lot in advance
Take a look at the DevExpress Spreadsheet Document Server (non-visual component with complete spreadsheet functionality available via its API). It allows developers to create, modify, save and print Excel documents, even when Microsoft Excel or Microsoft Office is not installed on the system. Supported File Formats - XLS, XLSX, XLSM, CSV and TXT;
Example: How to: Load a Document to a Workbook
I have done an import of an excel-file to update a SQL server table in the last days (with the DevExpress Grid only to show the imported data).
I my example, I:
ask the user for the filename (not necessary if you already know the
file name and path)
load the excel-file in a datatable (no devexpress needed for that)
show the datatable in a DevExpress Grid then
Note: in real live, I use the grid only to view/control the loaded data.
I then update an existing datatable on a SQL server from the loaded data in the datatable (code not included here).
Note: In the example, the sheet name always is "Sheet1" - maybe you want to make the sheet name also variable for your scenario...
Note: You don't need DevExpress, if you only want to import an Excel file into a DataTable (see ImportTable = ReadExcelIntoDataTable(cFileName, "Sheet1") and function ReadExcelIntoDataTable()) in code below.
' Chose the Excel-File over Open FileDialog()
' If you don't know the filename & path allready
Dim cFileName As String = ""
Dim filedialog As OpenFileDialog = New OpenFileDialog()
filedialog.Title = "Chose the File"
filedialog.DefaultExt = ".XLSX"
filedialog.ShowDialog()
cFileName = filedialog.FileName
'
If Not cFileName = "" Then
ImportTable = ReadExcelIntoDataTable(cFileName, "Sheet1")
If ImportTable.Rows.Count > 0 Then
Grid_Datenimport.DataSource = ImportTable
' Do some format (if you like)..
GridView2.Columns("ColumnX").DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime
GridView2.Columns("ColumnX").DisplayFormat.FormatString = "dd/MM/yyyy HH:mm:ss"
GridView2.Columns("ColumnX").Width = 160
End If
End If
Public Shared Function ReadExcelIntoDataTable(ByVal FileName As String, ByVal SheetName As String) As DataTable
Dim RetVal As New DataTable
Dim strConnString As String
strConnString = "Driver={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};DBQ=" & FileName & ";"
Dim strSQL As String
strSQL = "SELECT * FROM [" & SheetName & "$]"
Dim y As New Odbc.OdbcDataAdapter(strSQL, strConnString)
y.Fill(RetVal)
Return RetVal
End Function

Export Access database with multiple tables to Excel with multiple sheets

The title says it about all. I'm trying to write a VBA script that would allow me to run inside Access and it would export all database tables as separate sheets into and Excel file with the same name as the database:
Sub exportTablesToXLS()
Dim td As DAO.TableDef, db As DAO.Database
Dim out_file As String
out_file = CurrentProject.Path & "\" & db.DatabaseName & ".xls"
Set db = CurrentDb()
For Each td In db.TableDefs
If Left(td.Name, 4) = "MSys" Then
'We do not need MSys tables in excel file
Else
DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel9, _
td.Name, out_file, True, Replace(td.Name, "dbo_", "") 'We do not need dbo prefix in sheetnames
End If
Next
End Sub
Problems I'm having I would like your help on:
see line out_file -> db.DatabaseName return an error. How can I correctly get the database name of the current Access database?
I want to output a logfile (simple textfile) as well. How can I read, for each database table, the number of rows that have been exported and report eventual errors that occured?
Any help to improve this script is greatly appreciated :-)
Your db variable doesn't refer to the current database (yet - it is set in the following line), and the property is Name (I haven't encountered DatabaseName):
Sub Test()
Dim db As DAO.Database
Set db = CurrentDb
Dim sLast As String
MsgBox db.Name
'F:\Documents and Settings\student\My Documents\Staff Database.accdb
sLast = InStrRev(db.Name, "\")
MsgBox Right(db.Name, Len(db.Name) - sLast)
'Staff Database.accdb
End Sub
Name gives the full path and filename, the second MsgBox reduces this to just the filename.
(There may be another way to get the filename without having to parse Name..)
To get the number of rows exported you could open a Recordset for the table(s), reading the RecordCount property. A text file could be created using the FileSystemObject object. Sample code:
Set fso = CreateObject("Scripting.FileSystemObject")
Set oFile = FSO.CreateTextFile(strPath)
oFile.WriteLine "test"
oFile.Close
Or even just simple file (VBA) I/O:
Open pathname For mode [Access access] [lock] As [#]filenumber [Len=reclength]
(the FileSystemObject is easier to work with)
To report errors you'll need to create your own error-handling routines, and an error-logging procedure. This has been done before and a little searching will uncover some code. Essentially, each (important) event has error-handling code that calls a logging procedure. This procedure creates a record in a table to store all relevant information: date, time, which form was open, etc., etc.
A quick Google uncovered this page about logging Access errors.

Excel macro to change location of .cub files used by pivot tables? (to allow .xls files that depend on .cub files to be moved)

I often use Excel with pivot tables based on .cub files for OLAP-type analysis. This is great except when you want to move the xls and you realise internally it's got a non-relative reference to the location of the .cub file. How can we cope with this - ie make it convenient to move around xls files that depend on .cub files?
The best answer I could come up with is writing a macro that updates the pivot tables' reference to the .cub file location....so I'll pop that in an answer.
Here's the macro I ended up with. Clearly this makes some assumptions that might not be right for you, e.g. it updates all pivot tables in the workbook to use the same .cub file.
It loops through the workbook's Pivot Table connections to use a .cub file with
the same name as this .xls file, in the same directory. This assumes that the PivotCaches are not using LocalConnections - check that ActiveWorkbook.PivotCaches(1).UseLocalConnection = False.
Sub UpdatePivotTableConnections()
Dim sNewCubeFile As String
sNewCubeFile = ActiveWorkbook.Path & Replace(ActiveWorkbook.Name, ".xls", ".cub", , , vbTextCompare)
Dim iPivotCount As Integer
Dim i As Integer
iPivotCount = ActiveWorkbook.PivotCaches.Count
' Loop through all the pivot caches in this workbook. Use some
' nasty string manipulation to update the connection.
For i = 1 To iPivotCount
With ActiveWorkbook.PivotCaches(i)
' Determine which cub file the PivotCache is currently using
Dim sCurrentCubeFile As String
Dim iDataSourceStartPos As Integer
Dim iDataSourceEndPos As Integer
iDataSourceStartPos = InStr(1, .Connection, ";Data Source=", vbTextCompare)
If iDataSourceStartPos > 0 Then
iDataSourceStartPos = iDataSourceStartPos + Len(";Data Source=")
iDataSourceEndPos = InStr(iDataSourceStartPos, .Connection, ";", vbTextCompare)
sCurrentCubeFile = Mid(.Connection, iDataSourceStartPos, iDataSourceEndPos - iDataSourceStartPos)
' If the PivotCache is using a different cub file then update the connection to use the new one.
If sCurrentCubeFile <> sNewCubeFile Then
.Connection = Left(.Connection, iDataSourceStartPos - 1) & sNewCubeFile & Right(.Connection, Len(.Connection) - iDataSourceEndPos + 1)
End If
End If
End With
Next i
End Sub

Resources