Catching error message from SQL Server in VBA in Excel - sql-server

I am doing an excel macro in order to automate some query what eventually I run in SQL Server. My problem is that I don't know how the server could alert excel if a query did not succeed.
For example, I am importing a file, and there is no syntax error, but it might result in error if bulk insert statement is not set properly. For the SQL connection I use the following:
Dim conn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim sConnString As String
' Create the connection string.
sConnString = "Provider=SQLOLEDB;Data Source=localhost;" & _
"Initial Catalog=" & MyDatabase & ";" & _
"Integrated Security=SSPI;"
' Create the Connection and Recordset objects.
Set conn = New ADODB.Connection
Set rs = New ADODB.Recordset
conn.Open sConnString
Set rs = conn.Execute(Myquery)
If I have a syntax error while compiling the code it stops which is good. But if I have another problem, e. g. the database name is not good, the table already exists, then the program runs with no error, I only can detect when I check it in SQL Server. I really want to know somehow whether the query run has resulted in error and then code some alerting message then into my macro. How can I do that?
Every help is much appreciated!

The ADO connection object has an Errors collection, which you can check after running your SQL:
conn.Errors.Clear
Set rs = conn.Execute(Myquery)
If conn.Errors.Count > 0 Then
For i = 0 To conn.Errors.Count
Debug.Print conn.Error(i).Number
Debug.Print conn.Error(i).Source
Debug.Print conn.Error(i).Description
next i
End If
That should get you started. You may find that you're seeing an 'error zero' that's actually a status message; if so, you'll have some additional coding to to do.

I found this helpful but needed to use:
Debug.Print conn.Errors.Item(i).Description
Debug.Print conn.Errors.Item(i).Source
Debug.Print conn.Errors.Item(i).NativeError
I might be using a different connection type

Related

how to connect VBScript (Excel) to SQL Server web database (via IP)

I'm at my job trying to do some unknow stuff for me, you see, we're trying to connect an excel document with a VBScript Macro to a databse stored in web server but for some reason doesn't recognizes the user and throws an error repeatedly, i discarded a connection issue since it returns an SQL error instead of something like a timeout or server doesn't exists or something like that, we're trying to connect to the server using the ip address, we also checked that the logging method is on mixed (win and sql) and remotes connections to the server are enabled as well, also if i use the credentials provided in the connection string (username and password) i can actually log in to SQL Server without any issue, we also tried a direct connection (external vpn) because we thought it could be our firewall, but got the same error anyway, so we have no clue what it could be and we're kinda running out of ideas on how to do this, i'll post down below the code i'm using to trying the connection (obviously test data but similar to reality)
picture of the error i'm getting (don't post the original since it's in spanish but is very similar to this):
code i'm currently trying:
Sub excel_sqlsrv()
Set rs = CreateObject("ADODB.Recordset")
Set conn = CreateObject("ADODB.Connection")
strConn = "Driver={ODBC Driver 17 for SQL Server};Server=10.20.30.5;Database=mydb;UID=sa;PWD=abcd12345;"
conn.Open strConn
strSqL = "SELECT * FROM USERS"
rs.Open strSqL
End Sub
Any advice, tip or trick could be of tremendous help for me, i'll be looking forward to any kind of comment, thanks in advance
Use the ODBC Data Source Administrator to create a connection named mydb and test it works. Then use
Sub excel_sqlsrv()
Const strConn = "mydb" ' ODBC source
Const strsql = "SELECT * FROM USERS"
Dim conn As Object, rs As Object
Set rs = CreateObject("ADODB.Recordset")
Set conn = CreateObject("ADODB.Connection")
On Error Resume Next
conn.Open strConn
If conn.Errors.Count > 0 Then
Dim i, s
For i = 0 To conn.Errors.Count - 1
s = s & conn.Errors(i) & vbLf
Next
MsgBox s
Else
On Error GoTo 0
Set rs = conn.Execute(strsql)
Sheet1.Range("A1").CopyFromRecordset rs
End If
End Sub
You can try using OLEDB provider instead of ADODB.

Error: Row cannot be located for updating. Some values may have been changed since it was last read. On changing provider from SQLOLEDB to MSOLEDBSQL

On change of provider from SQLOLEDB to MSOLEDBSQL in the ADODB connection string, we get the error:
-2147217864 Row cannot be located for updating. Some values may have been changed since it was last read.
The connection string is:
Provider=MSOLEDBSQL;SERVER=servername;APP=Applicationname;DATABASE=databasename;WSID=id;Trusted_Connection=yes;MARS Connection=True;DataTypeCompatibility=80
And the code looks like:
Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset
rs.CursorLocation = adUseClient
rs.Open("SELECT * FROM tableName WHERE 1 = 2", Adoconnection, adOpenStatic, adLockBatchOptimistic, CommandTypeEnum.adCmdText)
rs.AddNew
'Add the fields
...
...
rs.UpdateBatch ''this line throws error
Now, when in the connection string of provider is changed to SQLOLEDB, with the same code it works great without any issue.
Try adding a timestamp, or so called "rowversion" column to the table. (use type timestamp - which has ZERO to do with time).
Also, if you have any bit columns in that table, then make sure they are not null, and make sure a default value of (0) is set for that bit column.
And if the application has linked tables, then re-link your tables after you made the above change server side.
I found out the issue, it was in the SQL triggers.
The respective table had some update statements on the trigger. Adding SET NOCOUNT ON just before the update statement in the trigger helped me to avoid this error.
I found my way to this thread because I had a similar error. I am using Access 365 VBA 32-bit on Windows 10. Here's a snippet of my code (some details omitted):
Dim cmd As ADODB.Command
Set cmd = New ADODB.Command
cmd.ActiveConnection = GetCurrentConnection()
cmd.CommandText = sql
Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset
rs.CursorLocation = adUseClient
rs.Open cmd, , adOpenDynamic, adLockOptimistic
With rs
.Fields("FailedImport") = True
.Fields("ImportErrors") = ReadErrorsFromResponse(xmlDoc)
.Update
End With
I also encountered the same error as in the OP. In my case, I didn't get the error until I included the update to the boolean field called FailedImport. I found my way to this forum post from 2008, containing this comment (formatting mine):
Had same error, however had it with recordsets rather than data control.
From another forum, I learnt that if you are using a static cursor for the recordset, using adLockBatchOptimistic instead of adLockOptimistic solved the problem.
So, I changed this line:
rs.Open cmd, , adOpenDynamic, adLockOptimistic
to this:
rs.Open cmd, , adOpenDynamic, adLockBatchOptimistic
And my code worked again! Hope this helps someone else in the future!

Using excel to query sql server automatically when sheet is opened

I need an excel sheet along with a batch file such that that: when the batch file runs, the excel sheet opens, runs a query on an SQL database, and saves the contents to a differently named excel file.
I know this is asking a lot, so I apologize for the long request. I know exactly the query that I need to perform and I know how the batch file is supposed to work.
What I am having trouble with is the VBA code inside of excel that runs when the file is opened and performs the query. So, while I know how to run sql queries in SAS and in Micorsoft SQL, I am having a hard time figuring out how to make excel perform these queries automatically in the VBA code. Here's what I have, but it *when I run the code, I get the error "Compile error: user-defined type not defined"
Steps to help
Create a WorkBook Open Event and place your code there.
Learn how to open other works books using VBA. The documentation section here on SO has examples
Learn to write results using Offset property and xlUp command (just in case you need to write results to a log which tends to be the next row/columns
I use like this
Sub getDAtaFromServer()
Dim con As New ADODB.Connection
Dim cmd As New ADODB.Command
Dim rst As New ADODB.Recordset
Dim strOldUDT As String
Dim strNewUDT As String
Dim aryTempUDT() As String
Dim strTempID As String
Dim i As Integer
con.ConnectionString = "Provider=SQLOLEDB.1;" _
& "Server=(local);" _
& "Database=TEST;" _
& "Integrated Security=SSPI;" _
& "DataTypeCompatibility=80;"
con.Open
Set cmd.ActiveConnection = con
cmd.CommandText = "SELECT * FROM [table] "
Set rst = cmd.Execute
Range("A1").CopyFromRecordset rst
con.Close
Set con = Nothing
End Sub

Excel 2003 VBA Write to SQL Server 2000 ADO

We are working on changing an existing excel form to deliver a record to our SLQ server.
We have been scuccessful with code that scrubs captures and writes the data to the server using a DSN and ODBC.
scn = dsn=ODBC123
Our target users (of wich there are many) are using excel 2003 and an ODBC connection on each terminal is not practical.
This is my first venture into using ADODB.
I was tripping my badSQL message but do not get an error from the server, until I added the UID and Pass.
Now I am getting
Run-time error '-2147467559(80004005)':
Automation error
Unspecified Error
Would one of you fine ladies and/or gentlemen take a look and provide some guidence?
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim ssql As String
Set cn = New ADODB.Connection
Set rs = New ADODB.Recordset
Const scn As String = "Provider=SQLOLEDB.1;Integrated Security=SSPI;" & _
"Persist Security Info=False;" & _
"Initial Catalog="DB on Server";" & _
"Data Source="Server Name" & _
"User ID=Form;Password=nope;"
ssql = "sql statment that writes a record to a table using info in the excel form," & _
" writen in vb that has worked through an odbc"
With cn
.CursorLocation = adUseClient
.Open scn
.CommandTimeout = 0
Set rst = .Execute(ssql)
End With
On Error GoTo badsql:
rs.Open ssql, cn, adOpenStatic, adLockOptimistic
On Error GoTo badsql:
rs.Close
cn.Close
Set rs = Nothing
Set cn = Nothing
MsgBox ("This record was updated in the database and documented for" & _
" processing. Please close this workbook.")
badsql:
MsgBox ("This record was not processed please resubmit.")
Exit Sub'
We seem to have both rst and rs as Recordset objects. I don't see a declaration for rst in the supplied code.
In any case, the query string in ssql is run twice. Once when it gets executed and the results (if any) returned into rst. The other time when rs is opened.
You probably only want to run the query string once and, as it seems to be an INSERT-type query, you probably want to use cn.Execute rather than rs.Open

Requested operation requires an OLE DB Session object... - Connecting Excel to SQL server via ADO

I'm attempting to take Excel 2003 and connect it to SQL Server 2000 to run a few dynamicly generated SQL Queries which ultimately filling certain cells.
I'm attempting to do this via VBA via ADO (I've tried 2.8 to 2.0) but I'm getting an error while setting the ActiveConnection variable which is inside the ADODB.Connection object. I need to resolve this pretty quick...
Requested operation requires an OLE DB Session object, which is not supported by the current provider.
I'm honestly not sure what this error means and right now I don't care. How can get this connection to succeed so that I can run my queries?
Here is my VB code:
Dim SQL As String, RetValue As String
SQL = " select top 1 DateTimeValue from SrcTable where x='value' " 'Not the real SQL
RetValue = ""
Dim RS As ADODB.Recordset
Dim Con As New ADODB.Connection
Dim Cmd As New ADODB.Command
Con.ConnectionString = "Provider=sqloledb;DRIVER=SQL Server;Data Source=Server\Instance;Initial Catalog=MyDB_DC;User Id=<UserName>;Password=<Password>;"
Con.CommandTimeout = (60 * 30)
Set Cmd.ActiveConnection = Con ''Error occurs here.
' I'm not sure if the rest is right. I've just coded it. Can't get past the line above.
Cmd.CommandText = SQL
Cmd.CommandType = adCmdText
Con.Open
Set RS = Cmd.Execute()
If Not RS.EOF Then
RetValue = RS(0).Value
Debug.Print "RetValue is: " & RetValue
End If
Con.Close
I imagine something is wrong with the connection string but I've tried over a dozen variations. Now I'm just shooting in the dark....
Note/Update: To make matters more confusing, if I Google for the error quote above, I get a lot of hits back but nothing seems relevant or I'm not sure what information is relevant....
I've got the VBA code in "Sheet1" under "Microsoft Excel Objects." I've done this before but usually put things in a module. Could this make a difference?
You have not opened your connection yet. I think you need a Con.Open before you assign it to the Command object.
Con.ConnectionString = "Provider=sqloledb;DRIVER=SQL Server;Data Source=Server\Instance;Initial Catalog=MyDB_DC;User Id=<UserName>;Password=<Password>;"
Con.CommandTimeout = (60 * 30)
Con.Open
Set Cmd.ActiveConnection = Con 'Error occurs here.
Cmd.CommandText = SQL
Cmd.CommandType = adCmdText

Resources