MS Access - execute a saved query by name in VBA - sql

How do I execute a saved query in MS Access 2007 in VBA?
I do not want to copy and paste the SQL into VBA. I rather just execute the name of the query.
This doesn't work ... VBA can't find the query.
CurrentDb.Execute queryname

You can do it the following way:
DoCmd.OpenQuery "yourQueryName", acViewNormal, acEdit
OR
CurrentDb.OpenRecordset("yourQueryName")

You should investigate why VBA can't find queryname.
I have a saved query named qryAddLoginfoRow. It inserts a row with the current time into my loginfo table. That query runs successfully when called by name by CurrentDb.Execute.
CurrentDb.Execute "qryAddLoginfoRow"
My guess is that either queryname is a variable holding the name of a query which doesn't exist in the current database's QueryDefs collection, or queryname is the literal name of an existing query but you didn't enclose it in quotes.
Edit:
You need to find a way to accept that queryname does not exist in the current db's QueryDefs collection. Add these 2 lines to your VBA code just before the CurrentDb.Execute line.
Debug.Print "queryname = '" & queryname & "'"
Debug.Print CurrentDb.QueryDefs(queryname).Name
The second of those 2 lines will trigger run-time error 3265, "Item not found in this collection." Then go to the Immediate window to verify the name of the query you're asking CurrentDb to Execute.

To use CurrentDb.Execute, your query must be an action query, AND in quotes.
CurrentDb.Execute "queryname"

Thre are 2 ways to run Action Query in MS Access VBA:
You can use DoCmd.OpenQuery statement. This allows you to control these warnings:
BUT! Keep in mind that DoCmd.SetWarnings will remain set even after the function completes. This means that you need to make sure that you leave it in a condition that suits your needs
Function RunActionQuery(QueryName As String)
On Error GoTo Hell 'Set Error Hanlder
DoCmd.SetWarnings True 'Turn On Warnings
DoCmd.OpenQuery QueryName 'Execute Action Query
DoCmd.SetWarnings False 'Turn On Warnings
Exit Function
Hell:
If Err.Number = 2501 Then 'If Query Was Canceled
MsgBox Err.Description, vbInformation
Else 'Everything else
MsgBox Err.Description, vbCritical
End If
End Function
You can use CurrentDb.Execute method. This alows you to keep Action Query failures
under control. The SetWarnings flag does not affect it. Query is executed always without warnings.
Function RunActionQuery()
'To Catch the Query Error use dbFailOnError option
On Error GoTo Hell
CurrentDb.Execute "Query1", dbFailOnError
Exit Function
Hell:
Debug.Print Err.Description
End Function
It is worth noting that the dbFailOnError option responds only to data processing failures. If the Query contains an error (such as a typo), then a runtime error is generated, even if this option is not specified
In addition, you can use DoCmd.Hourglass True and DoCmd.Hourglass False to control the mouse pointer if your Query takes longer

Related

MS Access - Use VBA to automatically select yes for "access was unable to append all the data" error message

I am using MS access where I click a button and it will upload a large number of files to my database. I want the user to be able to click the button and then minimise the application and when they come back all files are uploaded. However for a few of the files I get the error message "access was unable to append all the data to the table". This needs a user input and will not continue unless yes or no is selected.
For all these I always select yes, as I have a validation piece after this steps that will point out any issues.
Is there a way using VBA to build this yes selection into my code?
I already have the following in my code:
DoCmd.SetWarnings = False
DoCmd.RunSQL ...
DoCmd.SetWarnings = True
Thanks in advance,
Here is a function I use to execute sql, it returns the number of records effected by the SQL statement. It uses the 'On Error Resume Next' to handle any errors raised (not the best of coding practices). The function returns a 0 - it failed, if more then that's the number of recs effected by the SQL statement.
Function execSQL(vSQL) As Long
On Error Resume Next
Dim dbF As DAO.Database
Dim lngRecs As Long
DoCmd.SetWarnings False
Set dbF = CurrentDb
dbF.Execute vSQL
lngRecs = dbF.RecordsAffected
execSQL = lngRecs
DoCmd.SetWarnings True
dbF.Close
Set dbF = Nothing
End Function
Failing that, it may be better to use dao to execute the sql instead and then you can error trap properly on that and move on to the next record.
You could do something like this:
Sub MySub()
Dim strSql As String, fileName As String
On Error GoTo Err_MySub
'loop thru all files
strSql = "...'" & fileName & "' ...."
CurrentDb.Execute strSql
'end of loop
Exit Sub
Err_MySub:
Debug.Print fileName & " gives this error:" & Err.Description
End Sub
Press Ctrl-G to show the debug window. Maybe you should do something more clever in the error handler.
Action queries should be run using the Execute() method. No warnings of any kind are raised.
No parameters:
Currentdb().QueryDefs("QueryName").Execute dbFailOnError
With parameters:
With Currentdb().QueryDefs("QueryName")
.Parameters("ParameterName").Value = ParameterValue
.Execute dbFailOnError
End With
The dbFailOnError option will generate a run-time error if the query fails for whatever reason, so make sure your method handles errors. Lastly, if you need to see the records affected, check the RecordsAffected property of the query.

trap access vba messages

I'm developing in Access 2007 after a period doing other things and am trying to trap messages to the user. One function in a form modifies a row in a table. The relevant bits of the code are
On Error GoTo PROC_ERR
...
DoCmd.RunSQL szSQL
...
PROC_ERR:
MsgBox "Error: (" & Err.Number & ") " & Err.Description, vbCritical
The SQL statement is correct and he system pops up with a "You are about to update 1 row ..." message (number 10505). I want to trap this and replace it with my own warning message. However, my function doesn't trap an error on this message. Nor does it do so on the message that appears if the user clicks "no": "Run-time error 2501. The RunSQL action was canceled."
In VBA options I have for the moment set Error Trapping to "Break on all errors".
What am I missing here? Have I failed to set some other option in Access?
I would recommend to do not use RunSQL. It requires DoCmd.SetWarnings False, which may affect further warnings in case if it won't be followed by DoCmd.SetWarnings True, for instance after error. Also you won't be able to read quantity of affected rows.
Use
db.Execute szSQL, dbFailOnError
instead, it will allow to trap errors and analyze database state after query execution. Without dbFailOnError option errors won't be raised.
That message is not an error.
You can silent it with
DoCmd.SetWarnings False
Remember to set them on again.

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.

ms-access - how to automatically select yes in warning message boxes

in ms-access i am running a macro that runs several queries, during the execution of a query a message box appears
"you are about to run an update.......... are you sure you want to run this query ? "
how can i automatically select for all such cases so that macro runs without human intervention.
You can turn off temporary the warnings like this:
DoCmd.SetWarnings = False
DoCmd.RunSQL ...
DoCmd.SetWarnings = True
It is generally best to use Execute in such cases in order to trap errors:
Dim db As Database, qdf As QueryDef, strSQL As String
Set db = CurrentDb
Set qdf = db.QueryDefs("Query17")
qdf.Execute dbFailOnError
Debug.Print qdf.RecordsAffected
Or
strSQL="UPDATE SomeTable SET SomeField=10"
db.Execute strSQL, dbFailOnError
Debug.Print db.RecordsAffected
Trapping errors with dbFailOnError and an error trap is more or less essential and there are a number of other useful aspects to the Execute Statement
To avoid having to write the code #Remou supplies every time you execute arbitrary SQL you could use my SQLRun function, which is designed as a dropin replacement for DoCmd.RunSQL and avoids all the problems therewith.

Getting a value from the update query prompt

When we run a update query we get prompt saying that 'these many records are going to be updated. do you want to continue' is it possible to capture the value in the prompt message to a variable i.e the number of records going to be updated.
If you run the query from code, you can use the records affected property:
Dim db As Database
Set db=CurrentDB
db.Execute "Some SQL here"
db.RecordsAffected
If you use a transaction, you can rollback.
Patrick Cuff proposed this function:
Function RowsChanged(updateQuery As String) As Long
Dim qry As QueryDef
Set qry = CurrentDb.QueryDefs(updateQuery)
qry.Execute
RowsChanged = qry.RecordsAffected
End Function
I don't understand why one would go to the trouble of assigning a QueryDef variable to execute a query when it can be done directly CurrentDB.Execute without initializing (or cleaning up) any object variables.
Obviously, a parameter query is going need to use the QueryDef approach, since you have to assign the values to the parameters before executing it. But without parameters, there's no reason to make it more complicated than necessary. With a generic function like this that isn't set up to handle parameter queries, it seems wrongly designed.
And, of course, it ought also to use dbFailOnError, so that you don't get unexpected results (dbFailOnError works with QueryDef.Execute, just as it does with CurrentDB.Execute). In that case, there really needs to be an error handler.
Rather than write an error handler every time you execute SQL, you can do this, instead. The following function returns the RecordsAffected and will recover properly from errors:
Public Function SQLRun(strSQL As String) As Long
On Error GoTo errHandler
Static db As DAO.Database
If db Is Nothing Then
Set db = CurrentDB
End If
db.Execute strSQL, dbFailOnError
SQLRun = db.RecordsAffected
exitRoutine:
Exit Function
errHandler:
MsgBox Err.Number & ": " & Err.Description, vbExclamation, "Error in SQLRun()"
Resume exitRoutine
End Function
It can also be used to replace DoCmd.RunSQL (you just call it and ignore the return value). In fact, this function was entirely designed for use as a global replacement for DoCmd.RunSQL.
Yes, you can get the number of records updated via the RecordsAffected property:
Function RowsChanged(updateQuery As String) As Long
Dim qry As QueryDef
Set qry = CurrentDb.QueryDefs(updateQuery)
qry.Execute
RowsChanged = qry.RecordsAffected
End Function
You can call this function with the name of your update query to get the number of rows updated:
Dim numRows as long
numRows = RowsChanged("UpdateQuery")