Automate response to Run-time error 3146 ODBC--call failed - sql

I have a number of Excel dashboards running in my factory that refresh each minute, by connecting to a local Access Db and running a number of queries.
The Db itself has ODBC connections to a couple of different SQL database tables. They run fine most of the time but I have a problem with random 3146 ODBC--call failed errors popping up.
I have worked with my IT people and have not really been able to nail down the root cause.
I can click OK on the error popup and the dashboard may refresh fine for anther day or more or it may pop the 3146 error again 10 minutes later. There does not seem to be any real consistency to it.
I have read several posts about missing primary keys in the linked tables as to root cause. That may be true here as well but unfortunately these tables are from a third party vendor and I cannot modify them without creating issues with their software functionality.
Short of an actually fix for the root cause, I am wondering if there is a way through my VBA that I can automate clicking the OK button on the 3146 error popup so that this error is automatically acknowledged and the dashboard can go on about it's business.

One way to handle the situation is to trap the error. I can only suggest a general approach, one that I use in similar situations. Without knowing more about your app, it is hard to be very specific. This answer assumes you are using ADO to connect to Access, and pulling back a Recordset to populate the Dashboard. It further assumes you are not trapping errors currently. Here is a template to illustrate the idea:
Public Sub Dashboard()
On Error GoTo error
Dim e As ADODB.error
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Set cn = "however you are connecting"
Set rs = "however you are retrieving data" 'assuming an error with this line
Do While Not rs.EOF
rs.MoveNext
Loop
cleanup:
'any code that always has to happen
Exit Sub
error:
If Err.Number = 3146 Then
'do nothing and continue where you left off
Resume Next
End If
'possibly check connection errors, too
For Each e In cn.Errors
If e.Number = 3146 Then
'do nothing and continue where you left off
Resume Next
End If
Next
'show error and exit sub (which is what it is doing now)
MsgBox Err.Description
Resume cleanup
End Sub
Here's another option if you don't care to catch a specific error:
Public Sub Dashboard()
Dim rs As ADODB.Recordset
On Error Resume Next
Set rs = "however you are retrieving data" 'assuming an error with this line
On Error GoTo 0
Do While Not rs.EOF
rs.MoveNext
Loop
End Sub

Related

VBA ADO: Could Not Use <Filename>; file already in use

It's been a long time since I've had to do any development in Access, so hoping I can get some help. I have a split Front End/Back End solution that I've built. The Back End resides on a server, the front end gets copied down to user's desktops (and they use runtime Access 2013). I'm using Access with VBA and ADO connections/recordsets in order to do all record actions (Select, inserts, updates mostly).
Two intermittent issues have cropped up and I'm at a loss - this is one of them. From time to time, some users will get the error "Could not use "(back end Filename)"; file already in use." (where (back end filename) is my back end db name & location". When users get this message, they close out, re-open and try the same data entry and it works without a hitch. Here's the code:
Private Sub SetProblemCode()
On Error GoTo ErrorHandler
strSQL = "SELECT Problem_Code_ID, Problem_Code, Problem_Description FROM Problem_Code ORDER BY Problem_Description"
con.Open strConString
rstProblemCode.CursorLocation = adUseClient
rstProblemCode.Open strSQL, con, adOpenForwardOnly, adLockReadOnly
cboProblemCode.RowSourceType = "Table/Query"
Set cboProblemCode.Recordset = rstProblemCode
rstProblemCode.Close
con.Close
Exit Sub
ErrorHandler:
CriticalError Err.Description, Err.Number, Me.Name, "SetProblemCode"
End Sub
The rst and con objects are defined at the global level, a practice I've used in other solutions before but I'm questioning if that's some of the problem. I'm also questioning the cursor location, type and lock type I'm using, although it seems correct - I'm not altering data, just copying a recordset to the Access combo box.
I'm hesitant to make sweeping changes when it seems like the user closes out and tries again and it works just fine. Any thoughts?

VBA Excel won't connect to Access DB on another computer

A colleague of mine is trying to use an excel tool that pulls data from an access database. The tool works perfectly on my computer but he is having the issue that the tool is unable to connect with the Access database.
I've tried solving the problem by checking that the excel options are correct i.e. making sure macros are enabled etc. but I'm still getting the problem.
The problem must be something in my colleagues settings that hasn't been configured because the tool works without any issues for me. Here are some of the parts of the code that read the Access DB:
Public Const pActuarialPWD = "password2"
Public Const QuoteDB = "N:\DWH\Commercial Ins\Fleet\Databases\Quote DB.accdb"
If bDBOpen = False Then
'Connect to database
If openQuotedb() = False Then
MsgBox "Connection to database failed - contact Actuarial"
Exit Sub
End If
End If
Function openQuotedb()
On Error GoTo ErrorHandler
openQuotedb = False
Set db = OpenDatabase(QuoteDB, False, False, "MS Access;PWD=" & pActuarialPWD)
openQuotedb = True
Exit Function
ErrorHandler:
MsgBox "Couldn't connect to database. Please contact actuarial. Tool should not be used, as quote information will be lost", vbCritical
End Function
I've stepped through the program both in my computer and my colleagues a number of times and I can't see what the problem is. When I step past the line of code "db = ..." on my colleagues PC and hover over db it reads "db = Nothing" whereas on mine it successfully connects to the database.
Have you any ideas what might be going wrong here. It just seems exces is not setup properly to connect to Access on my colleagues PC.
The only thing I can think of is that I am using Excel 2013 and my colleague is on 2010.
The function below have saved me a lot of trouble. I don't know if it will solve your problem but in general will help.
I have tested it in many applications and with a variety of changes and variables and it worked every time and has never failed me. Maybe will help you.
Public Function db_connect(Optional sel_db As Variant = "", Optional pass_be As Variant = ";PWD=<password>") As DAO.Database
Dim db As DAO.Database
If sel_db = "" Then
sel_db = "<database_path>"
End If
On Error GoTo db_locked:
Set db = DBEngine.OpenDatabase(sel_db, True, False, pass_be)
GoTo DBclose:
db_locked:
Sleep 100
Set db = DB_Connection.db_connect(sel_db, pass_be)
DBclose:
Set db_connect = db
End Function
To call the function just do:
Dim db As DAO.Database
Set pers = DB_Connection.db_connect("full_path or your path with the N drive mapped", ";PWD=<db_password>")
WARNING-DISCLAIMER!!!
Be careful. The function has a waiting mechanism and tries to connect without never stoping. If you have wrong parameters or the database doesn't exist then it will stuck in an infinite loop. I never bothered to fix it because I knew the problem and avoid it. However, you can make improvements if you want.

On Error During Loop

I have this code setup which inserts data into a table from another, and it is setup on a loop. I would like for it to check to see if the record it was supposed to upload actually uploaded and if it didn't I would like for it to try again, then after the second try if it still cant I would like for it to terminated the code. Basically:
Before this code runs a connection check is run prior then if there is a connection the record uploads, then during the loop process I would like for it to run a select statement to find the record that was just uploaded on the new table. If it finds it, then it continues onto the next record, if it doesn't it tries one more time, then stops if it still cant. This is one way for me to verify the connection.
It is a way to kind of test the connection during the actual upload process so I don't have to build in a connection check after each record, thus saving time. I am just unsure how to build in an On Error in a loop, are there any ideas? The bottom of the code looks like:
qdf.ReturnsRecords = False
On Error GoTo Update_qdfError
qdf.Execute dbFailOnError
On Error GoTo 0
rs.MoveNext
Loop
rs.Close
Set qdf = Nothing
Set cdb = Nothing
Set rs = Nothing
Exit Function
Update_qdfError:
For Each err In DAO.Errors
MsgBox err.Description, vbCritical, "Error " & err.Number
Next
End Function
Since VBA doesn't have structured error handling, you would do the error testing one line at a time in your loop by setting the On Error property and then checking the ERR object. First, set it up so it falls over to the next line of code like this.
On Error Resume Next
Then, test.
Do While rs.EOF
rs.Fields("fieldName").value =value
if Err.Number >0 then
'you had an error
end if
Loop

What happens if you use .BeginTrans and don't use .CommitTrans or .Rollback

What happens if you use .BeginTrans and .Execute then you exit code before .CommitTrans or .Rollback in Access VBA.
Daniel's comment pretty much sums it up. When I run the following code...
Sub noCommit()
Dim cdb As DAO.Database, rst As DAO.Recordset
Set cdb = CurrentDb
Set rst = cdb.OpenRecordset("tblSampleData", dbOpenTable)
DBEngine.Workspaces(0).BeginTrans
rst.Edit
rst!Item = "Item1amended"
rst.Update
'' no Commit and no Rollback
End Sub
...and then open the table in Datasheet view any attempts to edit either of the two records results in a "beep" and the "no entry" icon on the record selector.
Attempts to add a new record are met with a "Could not update" error:
So, the changes made within the transaction are not written, and the table is left in a locked state until the connection is closed (or the transaction is cleared). Since my transaction was based on the default Access connection (DBEngine.Workspaces(0)) that means either closing and re-opening Access, or running the following:
Sub transRollback()
DBEngine.Workspaces(0).Rollback
End Sub

Run Time Error '2501'

I'm having the Run Time Error '2501' on a Form. Does anyone have ideas of why this happens and how to fix it?
The Report is called through this code:
Private Sub Command92_Click()
DoCmd.SetWarnings Off
''# get current reqid and version number
DoCmd.OpenQuery "NewReqVersion", acViewNormal
Dim NewReqID As Integer
Dim NewVerID As Integer
NewReqID = Me.Text58
NewVerID = Me.Version + 1
[Forms]![UWReviewForm].[StatusID] = 99
On Error Resume Next
**DoCmd.Save acForm, "UWReviewForm"**
DoCmd.OpenForm "NewReqVersionForm", acNormal
DoCmd.GoToRecord acDataForm, "NewReqVersionForm", acLast
End Sub
Private Sub StatusID_Change()
Me.LastModifiedTimeStamp = Now()
End Sub
The error 2501 can occur on calling OpenForm if there is a problem with the database. Can you please try following the steps in the link below under the headings "Recovering from corruption" and "Symptom: Cannot open a form or report"?
MS Access - Recovering from corruption
In my case, I had a table linked to an external data source, which was another Access database. I had experimented with splitting that database application into its database component and UI component, and had decided to revert the change. Somewhere along the line, this corrupted to the link between my original Access application and the external Access data source. I could verify this by attempting to open the linked table in my original Access application, and it gave an error.
My solution was to delete the linked table from my Access application and import it once again. After this, my problem resolved. The forms which could not open before were based on queries which included this external data source.