VBA Execute Access Query error: database or object read only - sql

I have tried executing this code:
Dim cn As ADODB.Connection
Set cn = New ADODB.Connection
Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset
Dim strConn As String
Dim strAcc As String
'Connecting to the DB
cn.ConnectionTimeout = 7200
cn.CommandTimeout = 7200
strConn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=d:\Documents\proof.accdb;Mode=Share Deny None; Persist Security Info=False"
cn.Open strConn
'Creating the query string
strAcc = "SELECT * " _
& " INTO Table1 " _
& " FROM [Excel 8.0;HDR=YES;DATABASE=D:\Documents\database.xlsm].[Sheet1$];"
'Executing the query
rs.Open strAcc, cn, adOpenDynamic
When executing it gets the error: "Can't refresh. Database or object read only" on the line:
rs.Open strAcc, cn, adOpenDynamic
I don't know how to fix this problem. Curious thing is that when executing a different query (selecting from an existing table) it works perfectly. That's why I guess the problem is related to the fact that a new table is being created with the SELECT INTO command. I also tried writing "Mode=Share Deny None" (as you may see) in the connection but didn't solve the problem.

Your having this issue most likely because the directory the back end database Located at: "d:\Documents\proof.accdb" is sitting within a directory you do not have Write Permissions to. Thus you are only able to read from the DB/ File and not "Write" i.e. perform INSERTS or UPDATES Like you are currently trying to do.
Navigate to and right click that directory, Select "Properties". Looking at the Security tab assign yourself permissions to that directory if you are able to.

Related

PostgreSQL & Access -- Connecting at start vs. Connect when needed

I have a PostgreSQL 9.5 database with an Access 2016 front-end, using an ODBC driver to connect the two. If I wanted to query data, I would start with the following commands:
Dim conn As New ADODB.Connection
conn.Open "Driver={PostgreSQL ANSI};Server=localhost;Database=[name];User Id=[UID];Password=[pass];"
Dim cmd As New ADODB.Command
cmd.ActiveConnection = conn
My question is this: Is there any reason why I shouldn't establish this connection the moment the application opens, using that connection whenever I need to run a query, as opposed to opening and closing the connection each time I run a query?
I'm unsure what, if any, overhead is involved in establishing such a connection in Access, and I've been unable to find any information on the topic. Apologies if this is a naive question.
I the connection is cached by Access anyway.
Once you touch, or open any linked table, then the connection is now active, and re-used by Access.
In general if the query is against a single table, then there little reason to not just code against the linked table.
Eg:
Dim rst As DAO.Recordset
Dim strSQL As String
strSQL = "select * from tblInvoices where invoiceNum = 13355"
Set rst = CurrentDb.OpenRecordset(strSQL)
If you using a pass-though query, then this works well:
Sub Test555()
Dim rst As DAO.Recordset
With CurrentDb.QueryDefs("qryPass")
.SQL = "select * from tblInvoices where invoiceNum = 13355"
Set rst = .OpenRecordset
End With
End Sub
The reason for above is you thus don’t mess or have to bother with connection strings in your code.
Just ensure that you table re-link code also re-links any pass-through query.

VBA: Querying data in dynamic named range

I create named range that covers data I need to query using ADODB
SourceWB.Names.Add Name:=SOME_RANGE_NAME, RefersTo:=SOME_RANGE
I setup a connection run SQL query
sConn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & sSourceName_ & "; Extended Properties=""Excel 12.0 Macro;HDR=YES"";"
Set oConn_ = New ADODB.Connection
oConn_.Open sConn
Dim oRs As New ADODB.Recordset
oRs.Open sSQL, oConn_, adOpenStatic, adLockReadOnly, adCmdText
The SQL query is
SELECT * FROM [SOME_RANGE_NAME] WHERE ....
The problem is: these commands are in cycle, where every time there may be other range referenced by SOME_RANGE_NAME. If the range is changing within one sheet, everything is ok. As soon the SOME_RANGE_NAME references range in other sheet I get the following error:
no value given for one or more required parameters
The solution was proper closing of connections!

Unable to connect to DB from VBA but able to connect from Access

I'm able to connect to a database using Access, but not from VBA. In Access, I use the server name, Windows NT Integrated Security,and the database name. In VBA, I've tried many variations of variable names and values in the connection string, and the db.Open command always fails. I generally get an error about not being able to find an installable ISAM, or Multiple-step OLE DB operation generated errors. Is there a way to determine what I can use as a connection string from the working Access connection? One example of code that fails with the latter error:
Dim db As Object
Dim adoRS As Object
Set db = CreateObject("ADODB.Connection")
Set adoRS = CreateObject("ADODB.recordset")
db.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Server=sql03;" & _
"Database=db1;" & _
"Integrated Security=SSPI;"
The provider you as using in the connection string is for MS Access.
If thats the correct database then do the following.
Add the refrence "Microsoft Office 14.0 Access Database Engine object library.
Dim cnString, query As String
Dim rs As New ADODB.Recordset
'If older version of MS access then try Provider=Microsoft.Jet.OLEDB.4.0;'
cnSTring= "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=<Path>;Jet OLEDB:Database Password=<Pass>;"
query = "SELECT * FROM TABLE"
rs.Open query, cnString, adOpenStatic, adLockOptimistic

Weird ODBC error

I'm using an Access front-end for an Microsoft SQL back-end.
The problem I'm facing, is that I'm inserting data with an adodb connection. I use this on multiple forms. On the first form it works, on the second form it works, on the third form it also works. But on the fourth form I get an: 'ODBC: Call failed' error.
You might think I made some kind of typing error, but that is not the issue. When I start with form four I can insert the data.
So long story short, after 3 inserts on different form, I get that odbc error. I don't know what the problem is.
Dim Query As String
Dim rs As ADODB.Recordset
Dim cn As ADODB.Connection
Set cn = New ADODB.Connection
Set rs = New ADODB.Recordset
Query = "SELECT MAX(ID) From dbo_Controle"
rs.Open Query, CurrentProject.Connection
rs.MoveFirst
ID = rs.Fields(0).Value
Query = "INSERT INTO dbo_Controle VALUES (" & ID + 1 & ",'" & Me.txtControleTime & "')"
Set cn = CurrentProject.Connection
Debug.Print (Query)
cn.Execute Query
rs.Close
cn.Close
Set rs = Nothing
Set db = Nothing
This is the code I am using on different forms with different queries.
I was having the same issue, and was able to fix it by using CurrentProject.AccessConnection

Execute Query from Access via Excel Query in VBA

Access has saved a query that was designed with the query builder called 'myQuery'. The database is connected to the system via ODBC connection. Macros are all enabled.
Excel Has makes a ADODB connection to connect to the database via
Dim con As ADODB.Connection
Dim rs As ADODB.Recordset
Set con = New ADODB.Connection
With con
.Provider = "Microsoft.ACE.OLEDB.12.0"
.Open "MyDatabase.accdb"
End With
Usually you would go ahead and just write your SQL, which is perfectly fine and then just do something like
Dim sqlQuery As String
sqlQuery = "SELECT * FROM myTable"
Set rs = New ADODB.Recordset
rs.Open sqlQuery, con, ...
But I want to access the query that I saved in the access database. So how do I call the saved query in the database that I just connected.
Tried already
con.Execute("EXEC myQuery") but that one told me it could not be find myQuery.
rs.Open "myQuery", con but that one is invalid and wants SELECT/etc statements from it
I think you can treat it like a stored procedure.
If we start right before Dim sqlQuery As String
Dim cmd as new ADODB.Command
cmd.CommandType = adCmdStoredProc
cmd.CommandText = "myQuery"
cmd.ActiveConnection = con
Set rs = cmd.Execute()
Then pickup your recordset work after this.
You were nearly there:
Dim con As ADODB.Connection
Dim rs As ADODB.Recordset
Set con = New ADODB.Connection
With con
.Provider = "Microsoft.ACE.OLEDB.12.0"
.Open "z:\docs\MyDatabase.accdb"
End With
con.Execute "MyQuery"
Just leave out Exec.
You can add parameters, too, this is a little old, but should help: update 2 fields in Access database with Excel data and probably a Macro
I was able to run an update query that was already saved in Access using:
Connection.Execute "My_Update_Query_Already_Saved_In_Access", adExecuteNoRecords, adCmdStoredProc
This gave me errors until I replaced spaces in the query name with underscores in both the Access database and the execute statement.
This is sort of a hack job, but you can query a query. That is, replace your sql string with the following:
sqlQuery = "SELECT * FROM QueryName;"
Before running this, one must ensure that the Access Database has been saved ie. press Ctrl+S (it is not sufficient that the query was run in Access).
Long time since this thread was created. If I understand it correctly, I might have something useful to add. I've given a name to what the OP describes, that being the process of using SQL from a query saved in an ACCDB to run in VBA via DAO or ADOBD. The name I've given it is "Object Property Provider", even with the acronym OPP in my notes, and for the object name prefix/suffix.
The idea is an existing object in an ACCDB (usually a query) provides a property (usually SQL) that you need to use in VBA. I slapped together a function just to suck SQL out of queries for this; see below. Forewarning: sorry, but this is all in DAO, I don't have much use for ADODB. Hope you will still find the ideas useful.
I even went so far as to devise a method of using/inserting replaceable parameters in the SQL that comes from these OPP queries. Then I use VBA.Replace() to do the replacing before I use the SQL in VBA.
The DAO object path to the SQL of a query in an ACCDB is as follows:
mySqlStatement = Access.Application.CurrentDb.QueryDefs("myQueryName").SQL
The way I use replaceable parameters is by evaluating what needs to be replaced, and choosing an unusual name for the paramater that cannot possibly exist in the real database. For the most part, the only replacements I've made are field or table names, or the expressions of WHERE and HAVING clauses. So I name them things like "{ReplaceMe00000001}" and then use the Replace() function to do the work...
sqlText = VBA.Replace(sqlText, "{ReplaceMe00000001}", "SomeActualParameter")
...and then use the sqlText in VBA. Here's a working example:
Public Function MySqlThing()
Dim sqlText as String
Dim myParamater as String
Dim myExpression as String
'Set everything up.
sqlText = getSqlTextFromQuery("myQuery")
myParameter = "{ReplaceMe00000001}"
myExpression = "SomeDateOrSomething12/31/2017"
'Do the replacement.
sqlText = VBA.Replace(sqlText, myParameter, myExpression)
'Then use the SQL.
db.Execute sqlText, dbFailOnError
End Function
Function getSqlTextFromQuery(ByVal oppName As String) As String
Dim app As Access.Application
Dim db As DAO.Database
Dim qdefs As DAO.QueryDefs
Dim qdef As DAO.QueryDef
Dim sqlText As String
Set app = Access.Application
Set db = app.CurrentDb
Set qdefs = db.QueryDefs
Set qdef = qdefs(oppName)
oppGetSqlText = qdef.SQL
End Function