I have an Access 2002 application which links an Oracle table via ODBC with this code:
Set HRSWsp = CreateWorkspace("CONNODBC", "", "", dbUseODBC)
Set HRSConn = HRSWsp.OpenConnection("HRSCONN", dbDriverPrompt, , "ODBC;")
DoCmd.TransferDatabase acLink, "Database ODBC", HRSConn.Connect, acTable, "SCHEMA.TABLE", "TABLE", False, True
Unfortunately, Access 2007 doesn't accept this syntax anymore, saying that ODBCDirect is no more supported (Runtime error 3847) and suggesting to use ADO instead of DAO.
Could someone please tell me how can I modify this code to satisfy Access 2007?
I found that I could solve my problem in a very simple way, by deleting the first two statements and modifying the third this way:
DoCmd.TransferDatabase acLink, "ODBC Database", "ODBC;DRIVER=Microsoft ODBC for Oracle;SERVER=myserver;UID=myuser;PWD=mypassword", acTable, "SCHEMA.TABLE", "TABLE", False, True
This way the table would be linked without prompting for anything. If I leave the connect string a simple "ODBC", instead, Access will ask to specify the odbc connection and the other missing parameters, thus obtaining the same thing I tried to perform with the previous statements.
Try this:
Dim tbl As New ADOX.Table
Dim cat As New ADOX.Catalog
cat.ActiveConnection = _
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=[x:\your_access_db.mdb];Jet OLEDB:Engine Type=4"
tbl.NAME = "[Access_table_name]"
Set tbl.ParentCatalog = cat
tbl.Properties("Jet OLEDB:Create Link") = True
tbl.Properties("Jet OLEDB:Link Provider String") = "ODBC;Driver={Microsoft ODBC For Oracle};Server=OracleServerName;Uid=[user];Pwd=[password];"
tbl.Properties("Jet OLEDB:Cache Link Name/Password") = True
tbl.Properties("Jet OLEDB:Remote Table Name") = "[Oracle_Schema].[Table]"
cat.Tables.Append tbl
cat.ActiveConnection.Close
Replace text in brackets ([]) with your info.
Related
I have an Access database for a client who wants to connect to and query the database using vbscript (so they can automate without actually opening the Access 2000 MDB). I can't figure out how to make the database connection.
I've tried several scripts, using both DAO and OLEDB. Below I've pasted the closest I've got, using an ODBC File DSN (I'm afraid using a System DSN would require extra work on the client's end, I'm trying to keep it simple).
Set objConnection = CreateObject("ADODB.Connection")
Set objRecordset = CreateObject("ADODB.Recordset")
'ERROR OCCURS HERE
objConnection.Open "FileDSN=D:\RLS.dsn;"
objRecordset.CursorLocation = adUseClient
objRecordset.Open "SELECT County FROM CountyTBL" , objConnection, adOpenStatic, adLockOptimistic
Here is the contents of RLS.dsn (I created this using Windows Control Panel so I am confident it's correct):
[ODBC]
DRIVER=Microsoft Access Driver (*.mdb)
UID=admin
UserCommitSync=Yes
Threads=3
SafeTransactions=0
PageTimeout=5
MaxScanRows=8
MaxBufferSize=2048
FIL=MS Access
DriverId=25
DefaultDir=D:\
DBQ=D:\RLS_be.mdb
The error message I got (and this was similar with the other 2 scripts I tried as well) was:
"Line 5, Char 4 Error: [Microsoft][ODBC Driver Manager] Data source name not found and no default driver specified. Source: Microsoft OLE DB Provider for ODBC Drivers"
You can simply use ADO to connect to the file without setting up a DSN. This will be simpler for your client.
For Access 2000, 2002-2003 MDB, use the following connection string:
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=D:\RLS_be.mdb"
For Access 2007, 2010, 2013 ACCDB:
"Provider=Microsoft.ACE.OLEDB.12.0; Data Source=D:\RLS_be.accdb"
The overall connection code:
' Build connection string
Dim sConnectionString
sConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=D:\RLS_be.mdb"
' Create connection object
Dim objConnection
Set objConnection = CreateObject("ADODB.Connection")
' Open Connection
objConnection.open sConnectionString
' Get recordset from SQL query
Dim objRecordset
Dim sQuery
sQuery = "SELECT County FROM CountyTBL"
Set objRecordset = CreateObject("ADODB.Recordset")
objRecordset.CursorLocation = adUseClient
objRecordset.Open sQuery, objConnection, adOpenStatic, adLockOptimistic
Here is another version using the connection string for a MS-Access 2016 database. The example connects to the 'clients.accdb' database and retrieves the value of the 'ClientID' field of the record where the 'ClientName' is equal to 'Joe Smith', then it loops through the records returned by the SQL statement.
Note that the extra quotations in the SQL statement are used in order to handle the scenario in which the name might contain a single quot ('), for example O'Connor.
Dim oConn, oRS
Dim ClientName : ClientName = "Joe Smith"
Set oConn = WSH.CreateObject("ADODB.Connection")
oConn.Open "Provider=Microsoft.ACE.OLEDB.16.0; Data Source=C:\test\clients.accdb"
Set oRS = oConn.Execute("Select ClientID From Clients Where ClientName=""" & ClientName & """")
Do While Not(oRS.EOF)
'Do something with the record.
oRS.MoveNext
Loop
oRS.Close
oConn.Close
I need to import tables from various databases on a monthly basis. Once the tables are imported, the databases are archived and not looked at again.
I have the following VBA code which works fine when a DB is not password protected:
Private Sub ImportTheData(ByVal dbImport As String)
DoCmd.SetWarnings False 'Turn OFF display alerts
'Import the full activity & comments table from the Import DB to a temporary table
DoCmd.TransferDatabase acImport, "Microsoft Access", dbImport, acTable, "tbl_Activity", "tbl_TempActivity", True
DoCmd.TransferDatabase acImport, "Microsoft Access", dbImport, acTable, "tbl_Comments", "tbl_TempComments", True
'code continues ...
The last parameter (storelogin) is set to true, but there seems to be no way to programmatically set those login parameters (password).
When I run the code, the user is prompted to enter the password (despite the SetWarnings = False). As I'm importing dozens of files each time this is not a viable solution.
Is there a way to programatically import tables using DoCmd.TransferDatabase when a file is password protected and if so how?
Open the database with DAO, supplying the password, then you can import the tables.
Public Sub ImportEncr()
Const dbImport = "D:\DbEncr.accdb"
Const sPassword = "foobar"
Dim DB As DAO.Database
Set DB = DBEngine.OpenDatabase(Name:=dbImport, Options:=False, ReadOnly:=False, Connect:=";PWD=" & sPassword)
DoCmd.TransferDatabase acImport, "Microsoft Access", dbImport, acTable, "tblEncr", "tblEncr", False
DB.Close
Set DB = Nothing
End Sub
StoreLogin applies to linking tables from ODBC databases.
You can use SQL and build a SQL statement and .RunSQL that I believe.
An example SQL would be
SELECT * into tblIMPORT
FROM xyz IN '' '; database=C:\Workspace\Database1.accdb;PWD=test';
Hope this helps.
Actually I use a ODBC-Connection to connect Ms Acces to tables of a PostgreSQL-DB. I connect them by using the External Data/Import ODBC-Link command. It works fine.
But how can I use VBA to link my tables?
When using VBA to link a table with ODBC, you can add and APP= argument to specify an application name that will generally show in the properties of the connection on your database server.
For example, here is a sample ODBC Connection string for a linked table:
ODBC;Driver={SQL Server};Server=MyServer\SQLExpress;Database=MyDatabase;APP=My App Title;Trusted_Connection=Yes;
My App Title is the string that will be your Application Name for that connection.
Update 1 In response to further comment by the OP:
Here is sample code to link a table via ODBC in VBA. To facilitate this, you also should always delete the ODBC linked table each time before re-linking it to make sure that your options are respected, and that Microsoft Access updates the schema for the linked table. This example shows a connection string for a SQL Server database, so all you would need to change is the connection string for your PostgreSQL-DB. The remaining VBA code would be the same.
Dim db As DAO.Database
Dim tdf As DAO.TableDef
Dim strConn As String
Dim ODBCTableName as String
Dim AccessTableName as String
Set db = CurrentDb()
ODBCTableName = "dbo.YourTable"
AccessTableName = "YourTable"
strConn = "ODBC;Driver={SQL Server};Server=YOURSERVER\SQLINSTANCE;Database=MYDATABASE;Trusted_Connection=No;UID=MyUserName;PWD=MyPassword"
db.TableDefs.Refresh
For Each tdf In db.TableDefs
If tdf.Name = AccessTableName Then
db.TableDefs.Delete tdf.Name
Exit For
End If
Next tdf
Set tdf = db.CreateTableDef(AccessTableName)
'===============================
'If your connection string includes a password
'and you want the password to be saved, include the following 3 lines of code
'to specify the dbAttachSavePWD attribute of the TableDef being created
'If you don't want to save the password, you would omit these 3 lines of code
'===============================
If InStr(strConn, "PWD=") Then
tdf.Attributes = dbAttachSavePWD
End If
tdf.SourceTableName = ODBCTableName
tdf.Connect = strConn
db.TableDefs.Append tdf
For some reason this code gives Run time error 3170 - Could not find installable ISAM. However, when you add ODBC; at the beginning of the connection string, then it works. So the connection string should look something like:
strConn = "ODBC;DRIVER={MySQL ODBC 5.2 Unicode Driver};" _
& "SERVER=servername;" _
& "DATABASE=databasename;" _
& "UID=username;PWD=password; OPTION=3"
I have a remote ODBC data source 'A' whose values is to be updated according to the table 'B' in the local access database. How can I do the same ?. I tried using pass through queries, however I am not able to access both the remote and local source in ONE SINGLE query. How should I do the same?
How does link tables work? Can I link my local table to the ODBC database dynamically using VBA?
In your Access database simply create a Linked Table for your ODBC data source:
For detailed instructions, see
About importing and linking data and database objects
Once that is done, you can use the linked table and the local table(s) in the same query from within Access:
You can't create a link dynamically that I am aware, though you could refresh a link that already existed.
What sort of joining is required? If you're just updating a single or a few rows, you might do this: (I can only write this using ado (means adding a reference to microsoft.activex data objects)
dim ss as string 'tempstr, sqlstr whatever you want to call it
dim cn as object: set cn = createobject("adodb.connection")
cn.Connection = [connection string required for ODBC datasource]
cn.Open
dim rst as object: set rst = createobject("adodb.recordset")
rst.open "SELECT required_data_column_list FROM localTable [WHERE ...]" _
, currentproject.connection, adOpenStatic, adLockReadOnly
do while not rst.eof
ss = "UPDATE ODBC_TableName SET ColumnA = '" & rst.Fields(3) & "' [, ... ]
ss = ss & " WHERE ... "
cn.Execute ss
do while cn.State = adStateExecuting
loop
rst.movenext
loop
set rst = nothing 'these statements free up memory,
set cn = nothing 'given that these objects are unmanaged
Hope this helps
I have an Access 2003 database with linked tables to a SQL Server 2005 database. The user information (the password) that is used to create an ODBC connection between Access and SQL Server was recently updated.
When I open the Access database, and try to edit the Linked table information I am then able to open the tables and see my data. However, when I close Access and and reopen the Access database it appears the password informtion has revereted back and I get an ODBC connection error.
Anyone know what I am doing incorrectly?
As a follow up, it appears we have about a dozen Access databases with numerous linked tables that all need this update. Is this the best way to update this information? The linked tables seem to have been created using different machines as the Workstation-ID specified in the ODBC connection is different.
Write a routine, that update the Connect Property from the TableDef and save the change with RefreshLink.
The problem with Linked Table Manager (LTM), is when you have linked tables that are in fact links to SQL Views. In that case, LTM will relink the "tables" without reassigning them the proper PK, and they will become non updatable.
I have written some code that I used to start from VBE, it is a quick and dirty thing, but you could surely adapt that if you need it.
There are 2 subs, one for the tables, and one for the passthru queries.
Option Compare Database
option explicit
Const kOld = "remote.g" 'string to identify old server
'new server odbc string
Const kConnLux = "ODBC;DRIVER=SQL Server Native Client 10.0;SERVER=xxxx;UID=yyyy;PWD=zzzz;"
Sub UpdateTables()
Dim db As Database, td As TableDef
Dim hasIndex As Boolean, strSql As String
Set db = CurrentDb
For Each td In db.TableDefs
If InStr(1, td.Connect, kOld) > 0 Then 'lien vers CE serveur ?
If td.Name Like "dbo_vw*" And td.Indexes.count = 1 Then 'table = vue attachee --> pbl de clef primaire
strSql = "CREATE INDEX " & td.Indexes(0).Name & " ON [" & td.Name & "](" & td.Indexes(0).Fields & ")"
' convert field list from (+fld1;+fld2) to (fld1,fld2)
strSql = Replace(strSql, "+", "")
strSql = Replace(strSql, ";", ",")
hasIndex = True
Else
hasIndex = False
End If
td.Connect = kConnLux
td.RefreshLink
Debug.Print td.Name
If hasIndex And td.Indexes.count = 0 Then
' if index now removed then re-create it
CurrentDb.Execute strSql
End If
End If
Next td
Debug.Print "Done"
End Sub
Sub UpdateQueries()
Dim db As Database
Dim td As QueryDef
Set db = CurrentDb
For Each td In db.QueryDefs
If InStr(1, td.Connect, kOld) > 0 Then
td.Connect = kConnLux
Debug.Print td.Name, td.Connect
End If
Next td
End Sub