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
Related
I created many spreadsheets which use stored procedures. I have a custom VBA code which works fine when I try to get data from SQL. However, today I wanted to execute parametrized stored procedure which inserts and updates data on a database table. When I run macro no errors show up, however there's no insert/update action on database. I have no idea why. I established SQL connection in my workbook (myConn) as I do everytime I need to connect with SQL so it's correct for sure. This is my standard VBA code:
Sub SaveData()
Dim myValue As Double
myValue = Sheets("XYZ").Range("valueToSave").Value
With ActiveWorkbook.Connections("myConn").OLEDBConnection
.CommandText = Array( _
"EXEC DB.[dbo].[myProc] '" & myValue & "'")
End With
ActiveWorkbook.Connections("myConn").Refresh
End Sub
I need to insert data into column of decimal(6,4) type (in SQL table). myProc does it perfectly when I run it manually via SSMS but not here using VBA code. valueToSave is an Excel range which stores one decimal value (for example: 23,56, 11,21 etc.). When I run macro nothing happens. When I run macro and go to 'Connection Properties' > 'Definitions' > 'Command Text' then I can see there's a procedure with parameter (EXEC DB.[dbo].[myProc] '11,23'). So my acode above seems working but not executing stored procedure.
Has it something to do with data type? Honestly, I tried with other VBA types: String, Variant, Integer but it's not working. I also changed data type of that column in SQL table (to varchar, int etc.) but it also doesn't work. The most interesting thing is that the code above works fine when I withdraw data from db, it doesn't work when need to insert/update data.
PS. I guess I added all required refrences:
Using ADODB
Option Explicit
Sub SaveData()
Const PROC_NAME = "DB.dbo.myproc"
Dim wb As Workbook
Dim ado As ADODB.Connection, cmd As ADODB.Command
Dim sCon As String, v As Single
Set wb = ThisWorkbook
v = wb.Sheets("XYZ").Range("valueToSave").Value
' get connection string
sCon = wb.Connections("myConn").OLEDBConnection.Connection
sCon = Replace(sCon, "OLEDB;", "")
' open connection
Set ado = New ADODB.Connection
ado.Open sCon
Set cmd = New ADODB.Command
With cmd
.ActiveConnection = ado
.CommandType = adCmdStoredProc
.CommandText = PROC_NAME
.Parameters.Append .CreateParameter("P1", adDecimal, adParamInput)
With .Parameters(0)
.NumericScale = 2
.Precision = 18
.Value = v
End With
.Execute
End With
ado.Close
MsgBox PROC_NAME & " " & v, vbInformation, "Done"
End Sub
I am trying to pass a parameter from Excel to a SQL Server Stored Procedure. The parameter is a date, the aim is to pass the date into the query then the query return results for said date. I have included pictures of how I have currently connected to the database.
Picture 1 (Irrelevant really but thought I'd include it anyway): https://imgur.com/TgRKOkc
Picture 2: https://imgur.com/FkH34qQ - Here I am currently hardcoding the parameter in the .CommandText area to check whether the functionality is working OK if the parameter were to be passed correctly. The data returned is correct with the hard coded value. This is where I am hoping to replace the '2018-08-19' with a dynamic parameter entered into cell A14 of the spreadsheet by the client.
Picture 3: https://imgur.com/3LGTP3I - This is where I feel like I am messing up, I am brand new to VBA so I am unaware how to declare the value entered in a particular cell (A14 in this case) as the parameter to pass to the stored procedure on refresh of the excel document. Worth noting I am aware that I am point to "PreDealingFormA" in the VBA code and the connection is "PreDealingFormA1" this is just an anomaly in the screen shots, I have since changed this and it hasn't solved the problem. I am aware that the code pictured in screenshot three is on the command of a button being clicked, I previously thought this was the route to go down, however due to requirements a button cannot be implemented. The aim is to instead pass the parameter entered into cell A14 and execute the stored procedure on refresh of the excel document.
Any help is appreciated on this as I am brand new to VBA so as basic as this may seem, it's hard for me to get my head around at the moment.
You can do it like this.
Sub RunSProc()
Dim cn As ADODB.Connection
Dim cmd As ADODB.Command
Dim rs As ADODB.Recordset
Dim strConn As String
Set cn = New ADODB.Connection
strConn = "Provider=SQLOLEDB;"
strConn = strConn & "Data Source=Server_Name;"
strConn = strConn & "Initial Catalog=DB_Name;"
strConn = strConn & "Integrated Security=SSPI;"
cn.Open strConn
Set cmd = New ADODB.Command
cmd.ActiveConnection = cn
cmd.CommandText = "MyOrders"
cmd.CommandType = adCmdStoredProc
cmd.Parameters.Refresh
cmd.Parameters(1).Value = ActiveSheet.Range("E1").Text
cmd.Parameters(2).Value = ActiveSheet.Range("E2").Text
Set rs = cmd.Execute()
If Not rs.EOF Then
Worksheets("sheet2").Range("A5:D500").CopyFromRecordset rs
rs.Close
End If
End Sub
In this case, the setup looks like this.
The process is run in the environment of Excel VBA 2010 and MS SQL Server 2008.
Assume that there is a simple one column data with 1500 rows in an Excel-sheet and we want to export it to the database with SQL-queries in VBA code (SQL procedure in VBA exports maximum 1000 rows at once in default mode).
There is one limitation in this problem: the export procedure must be with dbclass-connection instead of ADODB connection. (The code-owner is not me. The code-owner is using dbclass for a quite big VBA code, so probably he wouldn't accept to change the whole code).
I found an option like lngRecsAff for ADODB.Connection which is used like:
Sub test()
Dim cn As ADODB.Connection
Dim strSQL As String
Dim lngRecsAff As Long
Set cn = New ADODB.Connection
cn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\test.xls; Extended Properties=Excel 8.0"
strSQL = "Insert INTO [odbc;Driver={SQL Server};Server=SQL09;Database=Tom;UID=userID;PWD=password].tbl_test1 Select * FROM [Sheet1$]"
cn.Execute strSQL, lngRecsAff
cn.Close
Set cn = Nothing
End Sub
I tried to implement that lngRecsAff in my dbclass execution like:
Sub test()
Dim connOk As Boolean
Dim rs As New ADODB.Recordset
Set dbclass = New clsDB
Dim Value1() As Variant
Dim lngRecsAff As Long
Dim strSQL as String
Dim mstrErr as Boolean
dbclass.Database = "database_name"
dbclass.ConnectionType = SqlServer
dbclass.DataSource = "server_name"
dbclass.UserID = Application.UserName
connOk = dbclass.OpenConnection(False, True)
If connOk = False Then
MsgBox "Unsuccessful connection!"
Else
MsgBox "Successful connection"
End If
strSQL = "INSERT INTO [dbo].[table1](Column1) Values('" & Value1 & "')"
mstrErr = dbclass.ExecuteSQL(strSQL, lngRecsAff) ' The result mstrErr is a Boolean
' Some closing options here
End Sub
I got en error like lngRecsAff is not suitable for my ExecuteSQL procedure. Normally my execution mstrErr = dbclass.ExecuteSQL(strSQL) works without any problem.
Maybe I can do the SQL-procedure with a for-loop, then I can send the data in small pieces. But I want to find a more efficient, "nicer" solution which sends the whole array at once.
So is there any special option for dbclass which can send more than 1000 rows from Excel to the database?
You can query the Excel-Sheet directly using liked server.
In your Management Studio click to "Server Objects" and then right click onto "linked server". There you'll be able to add a new linked server.
If you need further help you can find tuorials easily. One is here:
https://www.mssqltips.com/sqlservertip/2018/using-a-sql-server-linked-server-to-query-excel-files/
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
I'm trying to build a VBA form that runs a SQL Server stored procedure to cache data before it does anything else. Ideally I'd prefer not to use an Excel data connection because then I can't export it to a new workbook with a minimum of fuss - it'd be nice to contain all of the information in the form's file.
The main way I know to connect VBA to a database is using code along these lines:
Dim cnn As New ADODB.Connection
Dim rst As New ADODB.Recordset
cnn.Open ConnectionString
rst.Open QueryText, cnn, adOpenDynamic
/*Whatever you're doing to the data goes here*/
rst.Close
cnn.Close
The problem I'm running into is that the caching proc doesn't return a dataset (not even a blank one), and this type of connection seems to throw a tizzy if there is no data returned. And I'd prefer not to modify the proc if I don't have to.
Is there a feasible solution, within these constraints? Or am I just being too whiny and should suck it up and use an Excel data connection or something?
I think you are looking for an ADODB.Command. Try something like this:
Dim cnn As New ADODB.Connection
Dim cmd As ADODB.Command
cnn.Open ConnectionString
Set cmd = New ADODB.Command
With cmd
.ActiveConnection = cnn
.CommandText = "EXEC spNameHere param1"
.CommandType = adCmdText
.Execute
End With