I am working with an Access 2003 database that has a subroutine using DAO code. This code loops through the table definitions and refreshes the ODBC connection string. I would like to convert this to ADO so I do not have to reference the DAO object library. Here is the code ...
Public Sub RefreshODBCLinks(newConnectionString As String)
Dim db As DAO.Database
Dim tb As DAO.TableDef
Set db = CurrentDb
For Each tb In db.TableDefs
If Left(tb.Connect, 4) = "ODBC" Then
tb.Connect = newConnectionString
tb.RefreshLink
Debug.Print "Refreshed ODBC table " & tb.Name
End If
Next tb
Set db = Nothing
MsgBox "New connection string is " & newConnectionString, vbOKOnly, "ODBC Links refreshed"
End Sub
The part I am unsure of is how to loop through the tables and get/set their connection strings.
DAO is really best for that, you cannot refresh the link with ADO rather you would need to use ADOX (Some relevant code here).
You can acces the connection string via Jet OLEDB:Link Provider String
If avoiding a reference for DAO is your goal, you could just modify your existing procedure to use late binding for DAO. As an example, this sub should work without a reference set for DAO.
Public Sub DAO_without_reference()
Dim db As Object
Dim td As Object
Set db = CurrentDb
For Each td In db.TableDefs
Debug.Print td.Name
Next td
Set db = Nothing
End Sub
You would not have Intellisense to help you with DAO properties, methods, and constants while writing the code, but the code can still work with late binding.
I think this would be your easiest alternative if you are determined to avoid a DAO reference. However, I have never developed an Access project without a DAO reference, and I don't understand why you are opposed to adding it.
Edit: Also if you use late binding and any DAO constants, your code must use the constant value rather than the name.
Related
I am trying to insert some records into MS Access Table with the help of below VB Script. But when am trying to execute it, it's throwing Compilation error: Expected end of statement. Could someone please help me figure out where am I going wrong.
Private Sub Form_Click()
Dim dbs As DAO.Database
Dim DbFullNAme As String
DbFullName = "D:\G\Diamond\FINAL MS-Access\MS-Access project.accdb"
Set dbs = OpenDatabase(DbFullName)
dbs.Execute "INSERT INTO [2014_Status] ( Prompt, Project_Name, STATUS,Release_Name )SELECT RoadMap.SPRF_CC, RoadMap.SPRF_Name, RoadMap.Project_Phase,RoadMap.Release_Name FROM RoadMap WHERE (((Exists (select 1 FROM [2014_Status] where RoadMap.SPRF_CC = [2014_Status].[Prompt]))=False));"
dbs.Close
End Sub
VBScript (as opposed to VBA or other dialects) does not support typed Dims. So
Dim dbs As DAO.Database
Dim DbFullNAme As String
need to be
Dim dbs
Dim DbFullNAme
VBscript has no native OpenDatabase() function. You need to use ADO to connect to your Access 'database'. First create a connection
Set dbs = CreateObject("ADODB.Connection")
Then determine the connection string and
dbs.Open cs
The rest of your code should work.
Update wrt comment:
The error message:
D:\G\Diamond\FINAL MS-Access\query1.vbs(2, 9) Microsoft VBScript compilation error: Expected end of statement
prooves that the OT tried to write a VBScript (the addition of the misleading vba/access tags is (C) Pankaj Jaju).
So lets break down the real reason why this code doesn't work.
You copied and pasted Visual Basic for Applications(VBA) into a .VBS(Visual Basic Script) file and expected it to work, I assume.
The problem with this is that VBA and VBScript are slightly different languages. Review the info section for both tags on stackoverflow when you get the opportunity.
For now lets just patch your code and maintain your DAO object so you don't have to reconstruct your Database usage with ADODB.
ExecuteInsert
Sub ExecuteInsert()
Dim dbs, DbFullName, acc
Set acc = createobject("Access.Application")
DbFullName = "D:\G\Diamond\FINAL MS-Access\MS-Access project.accdb"
Set dbs = acc.DBEngine.OpenDatabase(DbFullName, False, False)
dbs.Execute "INSERT INTO [2014_Status] ( Prompt, Project_Name, STATUS,Release_Name )SELECT RoadMap.SPRF_CC, RoadMap.SPRF_Name, RoadMap.Project_Phase,RoadMap.Release_Name FROM RoadMap WHERE (((Exists (select 1 FROM [2014_Status] where RoadMap.SPRF_CC = [2014_Status].[Prompt]))=False));"
dbs.Close
msgbox "done"
End Sub
Changes made.
Blocked your dim'd variables and removed As *** statements for vbscript compatibility
Set an access object so you could maintain the remainder of your code.
Added the acc.DBEngine. before OpenDatabase with additional parameters.
Renamed your Sub from Form_Click to ExecuteInsert, then placed ExecuteInsert at the top of the code so that the vbscript activates the sub. If you just place a sub in a vbscript file, it will not necessarily run, you have to activate it directly.
This code is tested and functions. Best of luck to you.
Adding to Ekkehard.Horner
http://www.csidata.com/custserv/onlinehelp/vbsdocs/vbs6.htm
VBScript has only one data type called a Variant. A Variant is a
special kind of data type that can contain different kinds of
information, depending on how it's used. Because Variant is the only
data type in VBScript, it's also the data type returned by all
functions in VBScript.
Am trying to create an empty DAO recordset rs2 whose structure is similar to an existing recordset rs1 (which has more than 200 fields). But I am facing an error which does not happen when I use ADO recordset:
dim rs2 as recordset
With rs2.Fields
For Each fld In rs.Fields
.Append fld, adVariant
Next
End With
Error is wrong number of arguments.
ADO allows you to add a field to the Recordset.Fields collection under certain circumstances. That is why the ADO version of your code runs without error.
However, the DAO Fields.Append method can not be used with a Recordset. Instead you would have to add a field to the table, or field expression to the query, which is used as the recordset's data source.
I know that this solution is not good for performance, but you can give it a try anyway.
First, clone the recordset:
Set rs2 = rs.clone
And then, if you only need the structure, empty it:
Do until rs2.EOF
rs2.Delete
Loop
I had a form with some VB code that was using Access 2003. Recently we wanted to use the same form as a small front end interface for another database that has a SQL Server backend. However, the file type for this project in Access is .adp and not all of the vb code is working properly. If you could help me fix the bugs in this code:
Private Sub SurveyNameCombo_AfterUpdate()
Dim db_CFC As DAO.Database
Set db_CFC = CurrentDb
Dim rst As DAO.Recordset, query As String, count As Integer
query = "SELECT DISTINCT SurveyID FROM tbl_SurveyMeta WHERE SurveyName = " & Chr(34) & Me.SurveyNameCombo.Value & Chr(34)
Set rst = db_CFC.OpenRecordset(query)
count = rst.RecordCount
If count > 1 Then
Me.SurveyIDCombo.RowSource = query
Else
rst.MoveFirst
Me.SurveyIDCombo.Value = rst.Fields(0).Value
Call SurveyIDCombo_AfterUpdate
End If
End Sub
It is throwing errors in the for the DAO.Database and DAO.Recordset.
Thank you for your help!
The error message "User-defined type not defined" on a line such as this ...
Dim db_CFC As DAO.Database
... means your application doesn't include a reference to the Microsoft DAO Object Library.
Open a code module, then check from the main menu in the VBE editor: Tools->References
Ordinarily the cure would be to place a check mark in the box next to Microsoft DAO Object Library, then click OK. However, your application is an ADP, and I don't know whether DAO can even be used in ADP. You can try. :-)
Sorry I can't tell you more. I quit using ADP a few years ago. Instead I use the MDB format with ODBC links to SQL Server database objects. Perhaps you could consider the same approach if you're unable to get the ADP version working as you need.
I am trying to retrieve an ADODB recordset from a function in MS-Access 2007 but get a very annoying error message thrown in my face saying: "Argument not optional (Error 449)".
I really can't figure out what I am doing wrong, please help!
Regards,
Stefan
FUNCTION:
Function Rs(sourceSQL As String) As ADODB.Recordset
' Create New Disconnected Recordset
Dim rsConnection As ADODB.Connection
Dim rsRecordset As ADODB.Recordset
Set rsConnection = New ADODB.Connection
rsConnection.Open CurrentProject.Connection
Set rsRecordset = New ADODB.Recordset
rsRecordset.CursorLocation = adUseClient
rsRecordset.Open sourceSQL, rsConnection
Set Rs = rsRecordset
Set rsRecordset.ActiveConnection = Nothing
End Function
FUNCTION CALL:
Private Sub Form_Load()
Call Rs("tblDocumentCode")
Debug.Print Rs.txtDocumentCode(0).Value
End Sub
You are using rs twice, once as a function, once as the name of a recordset:
Private Sub Form_Load()
Set Myrs= Rs("tblDocumentCode")
Debug.Print MyRs(0).Value
End Sub
Assuming that "txtDocumentCode" is a field in the recordset, this:
Private Sub Form_Load()
Call Rs("tblDocumentCode")
Debug.Print Rs.txtDocumentCode(0).Value
End Sub
...should be changed to this:
Private Sub Form_Load()
Debug.Print Rs("tblDocumentCode").Fields("txtDocumentCode").Value
End Sub
So far as I can tell, that should work without needing to assign the recordset returned by the function to a variable.
But let me step back a bit and suggest that fixing this syntactical error begs the question: what's being done her is pretty inadvisable. Every time this function is called, you're opening a new connection, but Access works better with a single connection that is used over and over again. That's true of both Jet/ACE back ends and server back ends. The overhead required to initialize the connection is going to make your forms load really slowly.
But even worse, this is not Access programming -- this is "refugee from a programming environment that lacks bound forms/controls" programming. You should be using ODBC with linked tables and then you can assign recordsources to your forms without having to muck about with ADO recordsets. If you insist on doing what you're doing, you might as well not be using Access at all, because you're discarding 75% or more of the advantages of Access, and you're getting no performance or concurrency benefits from doing so (and buying yourself a world of problems).
Of course, now that I look at it again, you're using the CurrentProject.Connection, and I'm not sure how this interacts with ODBC linked tables. Indeed, I guess it's possible this is an ADP and not an MDB/ACCDB, but that makes even less sense, since you don't need to do anything extra at all in an ADP to populate your forms with ADO recordsets -- it's the default.
So, in general, something is wrong beyond the syntax error -- what you are doing simply doesn't make a lot of sense.
Can anyone give me details of
runtime error 3734
in Access vba.
For reference i am getting it from a code in the following thread
How to run a loop of queries in access?
Sub plausibt_check()
Dim rs As DAO.Recordset
Dim rs2 As ADODB.Recordset
Dim db As database
Dim strsql As String
Dim tdf As TableDef
Set db = opendatabase("C:\Codebook.mdb")
Set rs = db.OpenRecordset("querycrit")
Set rs2 = CreateObject("ADODB.Recordset")
rs2.ActiveConnection = CurrentProject.Connection
For Each tdf In CurrentDb.TableDefs ' in this line the error occurs
I don't understand what you're trying to do. Why are you using one DAO recordset and one ADO? This makes no sense at all. If you have saved queries in an Access front end, then even if your back end is, say, SQL Server with ODBC table links, there is really no utility whatsoever in using ADO.
There is no evidence of a loop in your code, so unless your code is being called by a loop, it doesn't seem to me that the KB article explanation would apply.
I don't know what it is you want to do, but the point about opening your database once, rather than in each repetition of your loop, should be pretty obvious to anyone who thinks about it. If you're running a loop and repeatedly opening the same database in each repetition of the loop, it should be obvious that the operation belongs outside the loop.
That would be something like this:
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
Set db = CurrentDB()
For Each qdf in db.QueryDef
[do whatever here]
Next qdf
Set qdf = Nothing
Set db = Nothing
In that code, you're using the MDB currently open in the user interface, but it doesn't matter -- whichever database you're opening and looping through its objects should be opened only once, outside the loop.
If you want to have your loop be in a subroutine called from your main code, then pass the database variable as an argument to your subroutine. The subroutine would be something like this:
Public Sub ProcessQueries(db As DAO.Database)
Dim qdf As DAO.QueryDef
For Each qdf in db.QueryDef
[do whatever here]
Next qdf
Set qdf = Nothing
End Sub
And you would call that thus:
Dim db As DAO.Database
Set db = CurrentDB()
Call ProcessQueries(db)
Set db = Nothing
Now, if you insist on getting source data from DAO and then doing something with it via ADO, you'd have a DAO loop and inside it, and ADO loop. Because of that, you'd want to define your ADO connection outside your DAO loop, rather than inside it. The only exception to that would be if the data you're pulling from your DAO loop defines which database you're opening with ADO. As we don't know what you're actually trying to accomplish, it's pretty much impossible to give good advice on exactly what you should change in your code.
It seems that you are using ADO in the current database without saving. You must save before running code that contains ADO.