Operation invalid when trying to open Recordset from SQL linked Table - vba

I am trying to open to a recordset of a linked table but i keep getting invalid operation error. it works fine with local table.
I have tried to remove dbOpenTable but the error changed to 'Operation is not supported for this type of object'
It is important to note that i have a very shallow knowledge of vba access.
I would really appreciate any help I can get from this forum
Dim db As DAO. Database
Dim rst As Recordset
Set db=CurrentDb
Set rst = db.OpenRecordset("myTable",dbOpenTable)
rst.Index = "PRODUCT_CODE"
rst.Seek "=", Me!Combo_Product_number
If Nz(Me!Combo_Product_number) = "" Then
DoCmd.OpenForm "Not_found_Inventory"
ElseIf rst.NoMatch Then
DoCmd.OpenForm "Not_found_Inventory"
Else
DoCmd.OpenForm "FRM_Inventory_A01", WhereCondition:="[PRODUCT_CODE]='" & Me!Combo_Product_number & "'"
End If

The Seek method is only valid on a table local to the opened database.
Use the FindFirst method on a linked table.

Related

Changing Linked Table Source Access 2016

I am trying to change the links in an Access 2016 database, but the method I've used in the past is not working as required.
I am using the
t.connect="new connection"
t.refreshlink
method, where t is a the table.
I have seen in the linked table manager that the tables are now grouped by a data source. I can create the new source and link it to the desired table, but I have many as migrating, so would like to do this in code.
I get no errors the current way, but immediately after the .refreshlink the table's .connect is still the same.
Is this still possible?
I currently populate a dictionary with the table name and it's existing connection, but only if non ODBC.
I am then looping through this dictionary, getting the table and changing its connection
CurrentDb.TableDefs(strTableName).Connect = strNewConnection
CurrentDb.TableDefs(strTableName).RefreshLink
Debug.Print CurrentDb.TableDefs(strTableName).Connect
Existing connection = ;DATABASE=\\app01\Access\CRM_Data.mdb
New connection =;DATABASE=C:\CRM_TEST\CRM_DATA_BE_2016.accdb
Many thanks
You should not use CurrentDb.TableDefs when changing tables, as that changes between calls and makes the reference to the tabledef where you change the connection string be a different one than the one where you refresh the link.
Dim d As DAO.Database
Set d = CurrentDb
d.TableDefs(strTableName).Connect = strNewConnection
d.TableDefs(strTableName).RefreshLink
AFAIK this behaviour is not version-dependent, so the code you provided should never have worked.
I am using this code in Access 2016 and it works just fine:
Public Function RelinkTables(environment As Integer)
On Error Resume Next
Dim tblDef As DAO.TableDef
For Each tblDef In CurrentDb.TableDefs
If tblDef.Connect <> "" Then
tblDef.Connect = GetConnectionString(environment)
tblDef.RefreshLink
End If
Next
End Function
Public Function GetConnectionString(environment As Integer) As String
Select Case environment
Case 1 ' connection to Test db
GetConnectionString = "your connection string to Test"
Case 2 ' connection to Prod db
GetConnectionString = "your connection string to Production"
End Select
End Function
If this would not work with your db than may be the path is wrong.

Calling scalar UDF function from ms access

I am trying to call a scalar function from my database in ms access.
This function should return one row of my salted and hashed parameters.
My initial attemt looked like this and returned the following error: "undefined function 'dbo.SaltAndHashPassword' in expression"
Dim rs As Recordset
Set rs = CurrentDb.OpenRecordset("SELECT dbo.SaltAndHashPassword('" & Me.txtWW & "','" & Me.salt & "') as salted", dbOpenSnapshot, dbReadOnly)
I tried the solution from this question but I got the error "object required"
I also tried the solution from this question but I can't get it to work(probably due to wrong parameters)
Can anybody help me with this problem?
Thanks in advance.
You can't use CurrentDbin that case. You have to set a Connection object to the server/db where the dbo.SaltAndHashPassword function is stored (the example you mention uses a connection, even if the code to set it up is not shown), since it is totally unknown from Access.
Alternatively you can create a passthru query in Access and use DAO. I find it easier and it avoids creating yet another external reference.
Something like:
Set db = CurrentDb()
'Create a temporary passthrough query '
Set ptq = db.CreateQueryDef("")
'set ODBC connection '
ptq.Connect = "your connect string"
ptq.SQL = "SELECT * from your SQL"
ptq.ReturnsRecords = True
Set rs = ptq.OpenRecordset(dbOpenSnapshot)

Run-time Error 2498 for Append and Make Table Queries Created in VBA

I'm getting a 2498 error and really don't understand why. I'm building a string in VBA and am getting the error with the following line of code...
DoCmd.OpenQuery qdfNew, acNormal
It happened with a very long string created to create the query so I simplified the code as much as possible and am still getting the error.
Here's the code...
Option Compare Database
Option Explicit
Dim dbsFootball As Database
Dim strInsertSQL, strSelectSQL, strIntoSQL, strFromSQL, strOrderSQL, strSQL As String
Dim qdfNew As QueryDef
Sub CreateFormattedData()
Set dbsFootball = CurrentDb()
strSelectSQL = ""
strIntoSQL = ""
strFromSQL = ""
strOrderSQL = ""
strSQL = ""
strSelectSQL = "SELECT [tbl_Raw_League_Data].[Season]"
strIntoSQL = "INTO [tbl_Manip Data]"
strFromSQL = "FROM [tbl_Raw_League_Data]" _
+ "LEFT JOIN Referees ON [tbl_Raw_League_Data].[Referee] = Referees.[Referee from Source Data]"
strSQL = strSelectSQL + " " + strIntoSQL + " " + strFromSQL + " " + strOrderSQL
On Error Resume Next ' If query doesn't exist, error won't stop execution
DoCmd.DeleteObject acQuery, "pgmqry_Create Table tbl_Manip"
On Error GoTo 0 ' Reset error handler
Set qdfNew = dbsFootball.CreateQueryDef("pgmqry_Create Table tbl_Manip", strSQL)
DoCmd.OpenQuery qdfNew, acNormal
End Sub
The source field, [tbl_Raw_League_Data].[Season], is a "Short Text" data type (field size = 7).
If I terminate the VBA code and run the query that was created by the code, it works fine with no apparent errors. However, it will never run the query from within the VBA code.
I was originally getting the error 2498 when using "INSERT INTO" for an append query, but realized that the table could as easily be recreated at code execution time.
I'm lost and would sure appreciate some ideas!
Thanks in advance,
Jason
You are passing the querydef object to DoCmd.OpenQuery when it expects a string referencing name of a stored query object. Consider using the querydef's Name property:
DoCmd.OpenQuery qdfNew.Name, acNormal
Alternatively, use .Execute command from database object using the SQL string variable, bypassing any need for querydef:
dbsFootball.Execute strSQL, dbFailOnError
Or with querydef object, as #HansUp suggests, where you simply execute directly since it is an action query:
qdfNew.Execute dbFailOnError
Do note above two options bring up the regular MS Access discussion, of using stored vs VBA string query. While the former is precompiled and runs through query optimizer caching best plan, the latter can have sql dynamically created (structural components that is like SELECT, FROM and JOIN clauses as both can use passed in parameters). From your code snippet consider saving SQL query beforehand without needing to build it in VBA on the fly, and call it with DoCmd.OpenQuery.

Excel VBA Late Bind to Access and SQL Insert

I am having a frustrating issue with late binding to MS Access from Excel VBA to execute a DML statement like Insert or Update. All of the data I use in vba comes from user defined Classes. I can query just fine but writing to the DB gets different errors each time I try a different way to do the same thing. Below are some links to the same/similar issues, however each is slightly out of context and therefore I could not get passed my problem.
Microsoft.ACE.OLEDB.12.0 Current Recordset does not support updating error received when trying to update access
Operation must use an Updateable Query / SQL - VBA
Update an excel sheet using VBA/ADO
Operation must use an updatable query. (Error 3073) Microsoft Access
https://msdn.microsoft.com/en-us/library/bb220954%28v=office.12%29.aspx?f=255&MSPPError=-2147217396
http://www.access-programmers.co.uk/forums/showthread.php?t=225063
My end goal is to simply execute a DML string statement and it has to use late binding. Mainly I get the 3251 error saying my connection is 'Read Only' or a missing ISAM when I add ReadOnly=0 to the connection string. Fyi, getProjectFile just returns a path to a file starting from the parent folder of my project. I am pretty sure I can just use the connDB.Execute so I only need SQL Insert, I don't want to query first because the queries will get fat quick. I also think something might be wrong with the enum params because the ExecuteOptions want bitmasks instead of just a Long and I don't really know how to do that. From most of my research, I kept getting referred to the LockType and/or cursor not being right. For my environment; Windows 8.1 64bit, MS Office 2010 32bit(required). Does anyone see what is wrong here?
Sub ADO_Tester()
Dim strSQL, strFile, strConnection As String
Dim connDB As Object
'late bind to the ADODB library and get a connection object
Set connDB = CreateObject("ADODB.Connection")
'Connect to the DB
strFile = Application.ActiveWorkbook.Path & "\" & "PortfolioDB.accdb"
strConnection = "Provider = Microsoft.ACE.OLEDB.12.0; data source=" & strFile & ";"
connDB.Open strConnection
'insert statement for a test record
strSQL = "INSERT INTO underlying_symbol (symbol) VALUES ('xyz')"
'execute the
connDB.Execute strSQL, , 2, 1 + 128
'clear the object
connDB.Close
Set connDB = Nothing
End Sub
Edit:
Early binding:
connDB.Execute strSQL, , adCmdText + adExecuteNoRecords
Late Binding: How to enter the value for adExecuteNoRecords? On msdn it is 0x80 and another post says &H0001,either way it gives a syntax error. It says enter a bitmask for this enum value.
connDB.Execute strSQL, , 1 + 0x80
Edit: Now the correct way -
adExecuteNoRecords (the ADO enum value) = 0x80 (a binary value) = 128 (a decimal value)
connDB.Execute strSQL, , 1 + 128
Edit: Now the issue gets even deeper. When I execute the code in a test spreadsheet into a test database, it works. When I copy and paste into the actual project spreadsheet and point to actual project db, I get the error: operation must use an updateable query . . . again. Same db name, same dml, same table name. The only difference is the actual DB is a product of a split to separate it from the forms and code in Access. Could this have changed some setting to make it read only?
Edit: It just gets deeper and deeper. The issue causing it not to work in the project db is because I have some Excel Tables querying the db. I made these through the Excel UI, Ribbon -> External Data -> Access -> etc. . . It has now become obvious these are causing me to be unable to insert DML because they are probably set to read only. How can I change the tables connections permissions? Is there another way I could be making these tables so that I can provide the connection? How to get Tables to be friendly with DML in VBA?
This worked for me:
Option Explicit
Private Const acCmdText As Integer = 1
Sub ADO_Tester()
On Error GoTo ErrorHandler
Dim strSQL As String
Dim strFile As String
'Dim adoRecSet As Object
Dim connDB As Object
'late bind to the ADODB library and get a connection object
Set connDB = CreateObject("ADODB.Connection")
'Connect to the DB
strFile = getProjectFile("core", "PortfolioDB.accdb")
connDB.Open connectionString:="Provider = Microsoft.ACE.OLEDB.12.0; data source=" & strFile & ";"
'If State = 1, db connection is okay.
MsgBox "ADO Connection State is " & connDB.State & "."
'SQL to get the whole [underlying_symbol] table
'strSQL = "underlying_symbol" 'if options 2
'strSQL = "SELECT * FROM underlying_symbol" 'if options 1
strSQL = "INSERT INTO underlying_symbol (symbol) VALUES ('xyz')"
'late bind to adodb and get recordset object
'Set adoRecSet = CreateObject("ADODB.Recordset")
'&H0001 = bitmask for aCmdText
connDB.Execute strSQL, , acCmdText
'With adoRecSet
' .Open Source:=strSQL, _
' ActiveConnection:=connDB, _
' CursorType:=1, _
' LockType:=3, _
' Options:=&H1
'.AddNew
'.fields("symbol") = "XYZ"
'.Update
'End With
'------------------
'close the objects
'adoRecSet.Close
connDB.Close
'destroy the variables
'Set adoRecSet = Nothing
Set connDB = Nothing
ExitMe:
Exit Sub
ErrorHandler:
MsgBox Err.Number & ": " & Err.Description
GoTo ExitMe
End Sub
Added some error handling, a constant that defines acCmdText (Why just not add a reference to ADO library? Up to you, though.), and a message box to check the connection state to the database, as I can't test your getProjectFile function. Late binding doesn't seem to be the issue here, I think the key line is:
connDB.Execute strSQL, , 2, &H1
Can really say what's going on here as I've never done it like this (code doesn't even compile), but changing it to
connDB.Execute strSQL, , acCmdText
worked for me.

Rowset does not support scrolling backward

I am trying to query a MySQL database with the below code:
'declare the variables
Dim Connection
Dim Recordset
Dim SQL
'declare the SQL statement that will query the database
SQL = "SELECT * FROM CUSIP"
'create an instance of the ADO connection and recordset objects
Set Connection = CreateObject("ADODB.Connection")
Set Recordset = CreateObject("ADODB.Recordset")
'open the connection to the database
Connection.Open "DSN=CCS_DSN;UID=root;PWD=password;Database=CCS"
Recordset.CursorType=adOpenDynamic
'Open the recordset object executing the SQL statement and return records
Recordset.Open SQL,Connection
Recordset.MoveFirst
If Recordset.Find ("CUSIP_NAME='somevalue'") Then
MsgBox "Found"
Else
MsgBox "Not Found"
End If
'close the connection and recordset objects to free up resources
Recordset.Close
Set Recordset=nothing
Connection.Close
Set Connection=nothing
Whenever I execute the above I get an error 'rowset does not support scrolling backward', any suggestions?
adOpenDynamic is not declared in VBScript and therefore equals Empty, which gets converted to 0 when you assign the CursorType property.
0 is adOpenForwardOnly, and forward only does not support moving backwards, an ability the Find method wants.
You should replace adOpenDynamic with its literal value:
Recordset.CursorType = 2 'adOpenDynamic
To avoid this class of errors altogether, place Option Explicit as the first line of your script.
That is because the rowset does not permit backward moves; as the error message suggests. Your code is not using them; so you should replace the line
Recordset.CursorType=adOpenDynamic
with
Recordset.CursorType=adOpenForwardOnly (or the equivalent value 0)
Better leave the line altogether; the default is forward cursor.