Else Portion of Code keeps timing out - vba

I have a code to check the connection between access and sql server upon opening the form. If there is a connection a message box pops up and says so. If not there is supposed to be a message box indicating there is no connection. Instead I get the error:
Run Time Error '-2147467259 (80004005)':
[DBNETLIB][ConnectionOpen (Connect()).]Specified SQL Server Not Found
Which is not what I am wanting it to do, is it something in my coding or is there no way to get this to work?
Public Sub AutoExec()
Dim cnn As ADODB.Connection
Dim localrst As New ADODB.Recordset
Dim remoterst As New ADODB.Recordset
Set cnn = New ADODB.Connection
cnn.Open "Provider=SQLOLEDB; Data Source=DB; Initial Catalog=HRLearnDev;" _
& "User Id=ID; Password=PW;"
If cnn.State = adStateOpen Then
MsgBox ("You have an established connection with the L&TD SQL Server Database.")
Else
MsgBox ("Cannot connect to remote server. Data will be stored locally to CDData Table until application is opened again.")
End If
cnn.Close
End Sub

In situations like these, you typically want to use an On Error GoTo construct - then send the code to your error handler if an error occurs (you can test to make sure the error number is what you expect with Err.Num).
However, in your case it may be even easier to use On Error Resume Next. This tells the interpreter "If an error occurs, go to the next line. I will figure out what went wrong and deal with it."
You usually do this when you have a single function call that either produces an error or a sensible value. I often do something like this:
On Error Resume Next
returnValue = -1
returnValue = functionThatReturnsPositiveValue()
If returnValue < 0 Then
MsgBox "oops - the function failed!"
Else
' <<<< do whatever needs doing >>>>
End If
In your case that's almost exactly what you would do. Complete example:
Public Sub AutoExec()
Dim cnn As ADODB.Connection
Dim localrst As New ADODB.Recordset
Dim remoterst As New ADODB.Recordset
On Error Resume Next ' <<<<<< add this line so an error doesn't stop the code
Set cnn = New ADODB.Connection
cnn.State = 0 ' <<<<< not sure if you need something like this, or if the New command
already set it to some sensible value other than "adStateOpen"
cnn.Open "Provider=SQLOLEDB; Data Source=DB; Initial Catalog=HRLearnDev;" _
& "User Id=ID; Password=PW;"
If cnn.State = adStateOpen Then ' <<<<<< this will only be true if no error occurred
MsgBox ("You have an established connection with the L&TD SQL Server Database.")
Else
MsgBox ("Cannot connect to remote server. Data will be stored locally to CDData Table until application is opened again.")
End If
On Error GoTo 0 ' <<<<<<<< turn off error handling - we have passed the "tricky" spot.
' <<<<<< lots more code goes here >>>>>>
If cnn.State = adStateOpen Then cnn.Close ' <<<<<<<< only close connection if it was open!!
End Sub

Related

VBA SQL: Runtime Error 3704, how can I fix this?

I am trying to run a SQL Query through VBA. (I'm new to VBA)
P.s I have searched so much online but no solution has helped just yet.
I have copied the code from another excel (which works flawlessly) but my SQL Query involves temp tables and the other doesn't (this used to work on previous files that had temp tables). For some reason it just fails and I get the following error on the following line:
Error: 3704 Operation is not allowed when the object is closed'
' Check we have data for OrderIDs.
If Not rsfswdata.EOF Then
My full VBA code;
Dim conn As ADODB.Connection
Dim rsfswdata As ADODB.Recordset
Dim sConnString As String
' Create the connection string.
sConnString = "Provider=SQLOLEDB;Data Source=server001;" & _
"Initial Catalog=Dev;" & _
"Integrated Security=SSPI;"
' Create the Connection and Recordset objects.
Set conn = New ADODB.Connection
Set rs = New ADODB.Recordset
'To wait till the query finishes without generating error
conn.ConnectionTimeout = 0
'To wait till the query finishes without generating error
conn.CommandTimeout = 0
' Open the connection and execute.
conn.Open sConnString
Set rsfswdata = conn.Execute(Sheets("SQL Query").Range("A1").Value)
' Check we have data for OrderIDs.
If Not rsfswdata.EOF Then
' Transfer result.
Sheets("test").Cells(3, 2).CopyFromRecordset rsfswdata
' Close the recordset
rsfswdata.Close
Else
MsgBox "Error: No records returned.", vbCritical
End If
' Clean up
If CBool(conn.State And adStateOpen) Then conn.Close
Set conn = Nothing
Set rsfswdata = Nothing
End Sub

Check the permission of user when calling `ADODB.connection.open`

I was stucked for many week on the following :
I need to delete and insert to SQL database using VBA Excel.
The code used to connect to database is :
sConnString= "string for the connexion to the database"
conn.Open sConnString, "username", "password"
Debug.Print conn.State
Here the answer is 1, which according to the Microsoft documentation, means that the connexion is opened.
Then I try to execute an SQL query, using the following code :
varSQL = "DELETE FROM mytable WHERE specificColumn = '" & specificVariable & "'"
Set Command1 = New ADODB.Command
With Command1
.ActiveConnection = conn
.CommandType = adCmdText
End With
With Command1
.CommandText = varSQL
.Execute NbRecordsAffected
End With
This returns access denied for the DELETE query
I want to know if the user with username has the permission to do the query, so I can be sure that the error comes form another thing
Thank you in advance
Consider capturing the more informative error via the ADO error collections using VBA error handling where you may receive if using an SQL Server database:
The DELETE permission was denied on the object 'mytable', database 'mydatabase' schema dbo
Sub Run_SQL()
On Error GoTo ErrorHandle
Dim conn As ADODB.Connection, Command1 AS ADODB.Command
'...your full code...
ExitHandle:
' RELEASE RESOURCES
Set Command1 = Nothing: Set conn = Nothing
Exit Sub
ErrorHandle:
' RAISE EVERY CONNECTION ERROR
Dim myError As ADODB.Error
For Each myError In conn.Errors
Msgbox myError.Number & " - " & myError.Description, "RUNTIME ERROR", vbCritical
Next myerror
Resume Exit_Handle
End Sub

Executing a stored procedure on pervasive server

I have a stored procedure on my Pervasive Server called EGC_Expl_BOM_TT and I can execute it with "CALL EGC_Expl_BOM_TT('B-8579-K')" in my SQL query window within Excel, however it will perform the function and then through me an error forcing me to back out of the query window. I found the below VBA code which is designed to execute a stored procedure. I need help adapting it to me specific need. My stored procedure has only one variable input, which I will put in sheet 1 cell A1.
This is my connection string from my Excel query window. I need help formatting it in the VBA code:
Provider=MSDASQL.1;Persist Security Info=True;Extended Properties="DSN=global_EGC;ServerName=fah2.1583;UID=UserIDName;PWD=password;ArrayFetchOn=1;ArrayBufferSize=8;TransportHint=TCP;DBQ=GLOBALEGC;ClientVersion=11.31.017.000;CodePageConvert=1252;PvClientEncoding=CP1252;PvServerEncoding=CP1252;AutoDoubleQuote=0;"
Function Sproc()
Dim cnn As ADODB.Connection
Dim rst As ADODB.Recordset
Dim cmd As ADODB.Command
Dim ConnectionString As String
Dim StrSproc As String
Set cnn = New ADODB.Connection
cnn.ConnectionString = "Provider=MSDASQL.1;DSN=global_EGC;ServerName=fah2.1583;UID=Myusername;PWD=mypassword;ArrayFetchOn=1;ArrayBufferSize=8;TransportHint=TCP;DBQ=GLOBALEGC;ClientVersion=11.31.017.000;CodePageConvert=1252;PvClientEncoding=CP1252;PvServerEncoding=CP1252;AutoDoubleQuote=0;"
'Opens connection to the database
On Error GoTo SQL_ConnectionError
cnn.Open ConnectionString
On Error GoTo 0
'Timeout error in seconds for executing the entire query; this will run for 15 minutes before VBA timesout, but your database might timeout before this value
cnn.CommandTimeout = 900
Set rst = New ADODB.Connection
StrSproc = "set nocount on; "
StrSproc = "CALL EGC_Expl_BOM_TT" + Cells(1, 1)
rst.ActiveConnection = cnn
On Error GoTo SQL_StatementError
rst.Open StrSproc
On Error GoTo 0
If Not rst.EOF And Not rst.BOF Then
Sproc = IIf(IsNull(rst.Fields(0).Value), "(BLANK)", rst.Fields(0).Value)
End If
Exit Function
SQL_ConnectionError:
MsgBox "Error connecting to the server / database. Please check the connection string."
Exit Function
SQL_StatementError:
MsgBox "Error with the SQL syntax. Please check StrSproc."
Debug.Print StrSproc
Exit Function
SQL_ConnectionError:
Msgbox "Error connecting to the server / database. Please check the connection string."
Exit Function
SQL_StatementError:
Msgbox "Error with the SQL syntax. Please check StrSproc."
Debug.Print StrSproc
Exit Function
End Function
The connection string would be something like:
cnn.ConnectionString = "Provider=MSDASQL.1;DSN=global_EGC;ServerName=fah2.1583;UID=UserIDName;PWD=password;ArrayFetchOn=1;ArrayBufferSize=8;TransportHint=TCP;DBQ=GLOBALEGC;ClientVersion=11.31.017.000;CodePageConvert=1252;PvClientEncoding=CP1252;PvServerEncoding=CP1252;AutoDoubleQuote=0;"
Your statement would be something like:
StrSproc = "EXEC EGC_Expl_BOM_TT" + Cells(1,1)

Excel VB Database connection test

I have an excel spreadsheet with a bit of VB code that copies the data across to a access database. This copies the data from one sheet to a cache sheet and then from the cache sheet to the db using a flag to identify new data, This works ok but we would like to add a connection test to check if the connection to the database is ok.
This is the code i have below for the connection test:
Dim cnn As ADODB.Connection
Dim canConnect As Boolean
Set cnn = New ADODB.Connection
cnn.Open "Provider=Microsoft.Jet.OLEDB.4.0; " & _
"Data Source=\\G-FILE1\Common_Files\All Users\Robert T\Cash Sheets\CashSheets.mdb;"
If cnn.State = adStateOpen Then
canConnect = True
cnn.Close
MsgBox "Connection UP", vbOKOnly
Else
cnn.Open "Provider=Microsoft.Jet.OLEDB.4.0; " & _
"Data Source=\\G-FILE1\Common_File\All Users\Robert T\Cash Sheets\CashSheets.mdb;"
cnn.Close
If cnn.State = adStateClosed Then
canConnect = False
cnn.Close
MsgBox "Connection DOWN!", vbOKOnly
End If
End If
So what I want to do is this:
When button clicked > data is sent to cache sheet (Working) > Test DB connection > If not available, then msgbox user informing them > carry on caching sheet
I dont want the error window to appear, rather a msgbox and let the rest of the code carry on..
Hope this edit is a bit clearer..
Regards
It is enough if the file is available:
If Dir(accessFilePath) = "" Then
'file not found!
else
'file found!
end if

ADO with KDB+/qodbc.dll in VBA

I have an Excel based application reliant on several different databases which I connect to using ADO (Microsoft ActiveX Data Objects 6.1 Library). The databases reside on regional servers and there is an overhead in establishing the initial connection so I cache the connections in a Scripting.Dictionary object for reuse.
Private moConnCacheDict As Scripting.Dictionary
When I use the kdb+ qodbc.dll database drivers I get unexpected behavior. I can connect and reuse multiple data sources (Oracle,Sybase,Access) and one KDB database instance as expected. However, if I create a second KDB database connection and execute a query on the new dataset, no data is returned despite the fact the query is legitimate.
Recordset.BOF = TRUE and Recordset.EOF = TRUE
It appears to execute fine and the fields are visible. The connection to the previous regional server seems to persist and I can successfully retrieve data which resides on the original server despite the fact that if I look at,
Recordset.ActiveCommand.ActiveConnection.Properties.Item("Extended Properties")
, is the new connection string.
The KDB+ connection string uses the following syntax:
DRIVER=kdb+;DBQ=XXXXX;UID=XXXXX;PWD=XXXXX;
I have included the core VBA functions used as an example:
Private Function ExecuteQuery(sDBName As String, ByRef oRst As ADODB.Recordset, Optional bDeleteConnection As Boolean) As Boolean
Dim oDBConn As ADODB.Connection
Dim sSql As String
'delete connection
If bDeleteConnection Then Call DropConnection(sDBName)
'get cached or new connection
Call GetConnection(sDBName, oDBConn)
Select Case sDBName
Case "MAIN_US"
sSql = mSQL_MAIN
Case "MD_ASIA"
sSql = mSQL_MDASIA
End Select
Set oRst = New Recordset
oRst.Open sSql, oDBConn, adOpenKeyset, adLockPessimistic
If Not oDBConn.State = adStateOpen Then Err.Raise vbObjectError + 1024, "ExecuteQuery", sDBName & ": Recordset Closed. Unable to execute query ->" & sSql
ExecuteQuery = True
End Function
Private Function GetConnection(sDBName As String, ByRef oDBConn As ADODB.Connection) As Boolean
If moConnCacheDict Is Nothing Then Set moConnCacheDict = New Dictionary
If moConnCacheDict.Exists(sDBName) Then
'get existing connection
Set oDBConn = moConnCacheDict.Item(sDBName)
Else
'create connection
Set oDBConn = New Connection
With oDBConn
.Mode = adModeRead
Select Case sDBName
Case "MAIN_US"
.Mode = adModeReadWrite
.ConnectionString = mCONN_MAIN
Case "MD_ASIA"
.Mode = adModeRead
.ConnectionString = mCONN_MDASIA
End Select
.CursorLocation = adUseServer
.Open
End With
moConnCacheDict.Add sDBName, oDBConn
End If
GetConnection = True
End Function
Private Function DropConnection(Optional sDBName As String) As Boolean
Dim oDBConn As ADODB.Connection
Dim i As Integer
'delete object directly from cache
If Not moConnCacheDict Is Nothing Then
If sDBName = vbNullString Then
'close all connections
For i = 0 To moConnCacheDict.Count - 1
If Not IsEmpty(moConnCacheDict.Items(i)) Then
Set oDBConn = moConnCacheDict.Items(i)
If Not oDBConn Is Nothing Then
If oDBConn.State = adStateOpen Then oDBConn.Close
Set oDBConn = Nothing
Debug.Print Now, "Dropping Database Connection - " & moConnCacheDict.Keys(i)
End If
End If
Next i
Set moConnCacheDict = Nothing
Else
If moConnCacheDict.Exists(sDBName) Then
If Not IsEmpty(moConnCacheDict.Item(sDBName)) Then
Set oDBConn = moConnCacheDict.Item(sDBName)
If Not oDBConn Is Nothing Then
If oDBConn.State = adStateOpen Then oDBConn.Close
Set oDBConn = Nothing
Debug.Print Now, "Dropping Database Connection - " & "Dropping Database Connection - " & sDBName
End If
End If
moConnCacheDict.Remove (sDBName)
End If
End If
End If
DropConnection = True
End Function
(Note the ADO.Recordset is always closed and set to nothing by the caller).
The only way to resolve the issue is to close all database connections (regardless of the provider) and then reconnect to the desired regional server. This is horrendously inefficient as I have to reopen all the existing connections. Also note that it is not sufficient to do this purely in the current workbook. This must be done at the application level. If ANY ADO connections to ANY database are still open, I can create a new KDB+ ADO Connection but it will still point to the previous instance.
I have looked at the error properties of the KDB+ connection object and there are two errors:
Multiple-step OLE DB operation generated errors. Check each OLE DB status value, if available. No work was done.
Provider does not support the property.
This appears to be documented in http://support.microsoft.com/kb/269495 but I am unable to locate any CLSID in the registry so am unable to experiment with the suggested change.
If I turn on ODBC logging I see the following message:
EXCEL 8dc-22d0 EXIT SQLGetInfoW with return code -1 (SQL_ERROR)
HDBC 0x02131EA8
UWORD 151 <SQL_KEYSET_CURSOR_ATTRIBUTES2>
PTR 0x003C4FB0
SWORD 4
SWORD * 0x00000000
DIAG [S1096] [Microsoft][ODBC Driver Manager] Information type out of range (0)
Would this be responsible for the error anyway?
As always, any help and suggestions would be much appreciated.
What you're seeing is a bug in the driver, and you should look for more recent drivers.
I shouldn't really give a full answer (instead of a comment) if I haven't run and tested the code myself, but I would recommend that you enumerate the properties collection of the connection object and look for connection pooling.
Setting connection pooling to 0 (or to false, depending on what you can guess from viewing the vartype of the property's value) is a promising workaround. Your other option is to use a forward-only recordset: that may or not work, but its worth trying.
NB: There was an open-source project a couple of years ago to write a proper OLEDB drive, but that seems to have faded from view.