Excel 2010 to Sql Server 2008 Insert Statment - sql

I am going from Excel to Sql. I have the connection established. I can create a simple select statment and obtain values from a table in Sql into Excel. Now, I want to go the other way. I am trying to insert a value from excel into Sql. I keep getting a "Operation not allowed when object is closed" error # 3704. Below is my code.
Option Explicit
Private Conn As ADODB.Connection
Private Sub CommandButton1_Click()
Dim Conn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim sConnString As String
'This will create the string to connect.
sConnString = "Driver={SQL Server};Data Source=**;Initial Catalog = **;Trusted_Connection =yes;"
'Create Connection and the Recordset Objects.
Set Conn = New ADODB.Connection
Set rs = New ADODB.Recordset
'Open the Connection in Order to Execute.
Conn.Open sConnString
Set rs = Conn.Execute("insert into TestTable(TestColumn) Values('50');")
'Check for the Data.
If Not rs.EOF Then
Sheets(1).Range("A1").CopyFromRecordset rs
'Close Connection
rs.Close
Else
MsgBox "Error: No Records Returned.", vbCritical
End If
'Clean
If CBool(Conn.State And adStateOpen) Then Conn.Close
Set Conn = Nothing
Set rs = Nothing
End Sub
How do I properly execute this statement? As I said earlier the select statment worked fine. all I did was
("Select * From KpiSetupOee;")
Any thoughts? Thank you for your time

An INSERT statement doesn't return any records, so why are you trying to assign its results to a recordset? Change this line:
Set rs = Conn.Execute("insert into TestTable(TestColumn) Values('50');")
to just execute:
Conn.Execute("insert into TestTable(TestColumn) Values('50');")
Then clean up your code to get rid of unneeded recordset references.

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

connecting to sql server via vba/odbc

I'm not sure what is wrong with my code here, it is not throwing any errors and is compiling successfully. However, the recordset is not grabbing any data. Nothing is being pasted into the sheet. The query itself runs fine from command line/sqlserver. Do I need to add a dsn somewhere in the connection string?
Sub queryTest()
Dim connection As New ADODB.connection
Dim recordset As ADODB.recordset
Dim strSQL As New ADODB.Command
connection.Open "DRIVER={SQL Server};SERVER=xxx;" & _
"trusted_connection=yes;DATABASE=xxxx"
strSQL.ActiveConnection = connection
strSQL.CommandText = "SELECT TOP (50) [CalendarSK] ,[CalendarMonthSK] ,[CalendarDate] FROM [xxxx].[dbo].[tblCalendar]"
strSQL.CommandType = adCmdText
Set recordset = strSQL.Execute
Sheets("Sheet1").Range("a1").CopyFromRecordset recordset
recordset.Close
connection.Close
End Sub

If i create a disconnected ADO recordset from scratch in VBA how do i set the base table information for UpdateBatch?

I have been using disconnected recordsets for a few weeks now, typically retrieving data from SQL Server, disconnecting the rs and filtering/formatting in VBA. Now i'm trying to do the reverse and create a new ADO recordset from scratch, and then connect it to my database and use UpdateBatch to insert the recordset into the database without using a loop. I have a fully populated recordset at this point, hooked it back up to my connection string, and try UpdateBatch. Understandably, it has no information at this point about what table I'm trying to update (only Data Source and Initial Catalog via the connection string). Is there a recordset property that I use to provide the table in question? Additionally, the table I'm trying to import into has a GUID field (first field) that I have left blank on purpose in my disconnected recordset assuming that upon import, SQL Server would assign this GUID/primary key automatically.
The specific error I'm getting after "rs.UpdateBatch" is
Run-time error '-2147467259 (80004005)'"
Insufficient base table information for updating or refreshing.
I know I could use a loop and a SQL command "INSERT INTO ...". I'd like to use a recordset object though since those provide much more functionality as a container for data. One thing I haven't tried is to first retrieve a recordset from the table in question, then clear it and re-populate it with the new data so that the recordset itself retains all of the original database and table properties. If that's the only/best approach I can try that route too. I just wanted to see if it was possible to create an ADO recordset, populate it, and then insert it into a matching table of my choice.
dim rs as ADODB.Recordset
set rs = New ADODB.Recordset
With rs.Fields
.append "alias", adVarChar, 255
.append "textA", adVarChar, 255
.append ......
End With
rs.Open
rs.AddNew Array(0, 1, 2, ..., n), Array(val0, val1, val2, ..., valn)
rs.Update
call importRS(rs)
rs.close
set rs = nothing
After rs.update above some recordsets may need to go to a database, other recordset objects are just used to expedite filtering and sorting so I just use them as a convenient container and they'd never go to importRS()
However, IF I need to send the disconnected recordset to a database, i'd like to just pass the recordset object to another function that serves the purpose of opening the connection, sending the update, and closing the connection. The code below would serve that purpose which is why i'd like to wait to establish a connection until this point, right at the end after my rs is populated.
sub importRS(byref rs as ADODB.Recordset)
dim cn as ADODB.Connection
set cn = New ADODB.Connection
cn.ConnectionString = strConnection 'my connection string variable'
cn.Open
rs.ActiveConnection = cn
rs.UpdateBatch '-------error message appears on this line
cn.close
set cn = nothing
You can get the data, (wherever it may be) into an array and add to the recordset using a loop. Then then when the loop is finished, you do rs.updatebatch as follows:
Private Sub SaveToSQLSever()
Dim lngLastRow As Long
Dim arrySheet As Variant
Dim rs As ADODB.Recordset
Dim cn As ADODB.Connection
Dim strCn As String
Set cn = New ADODB.Connection
Set rs = New ADODB.Recordset
strCn= "Provider=VersionOfSQL;User ID=*********;Password=*********;"
& _ "Data Source=ServerName;Initial Catalog=DataBaseName"
cn.Open strCn
On Error Goto exiting
'*********************************************************
'If the data is coming from a sheet
'Set to your Range
With Sheets("SheetName")
lngLastRow = .Range("A2").CurrentRegion.Rows _
(.Range("A2").CurrentRegion.Rows.Count).Row
arrySheet = .Range("A1:G" & lngLastRow).Value2
End With
'Else populate the array and pass it to this Sub
'*************************************************************
'Note the property parameters
'.Source = Table That you want to populate
With rs
.ActiveConnection = cn
.Source = "Select * from TableName"
.CursorType = adOpenDynamic
.CursorLocation = adUseClient
.LockType = adLockBatchOptimistic
.Open
End With
For i = LBound(arrySheet,1) To UBound(arrySheet,1)
rs.AddNew
For j = LBound(arrySheet,2) To UBound(arrySheet,2)
rs.Fields(j).Value = arrySheet(i,j)
Next j
rs.MoveNext
Next i
rs.UpdateBatch 'Updates the table with additions from the array
i = 0
'******************************************************************
'Note that you can also refer to the Field Names Explicitly Like So:
For i = LBound(arryData,1) To UBound(arryData,1)
With rs
.AddNew
.Fields("FieldName1").Value = arryData(i,1)
.Fields("FieldName2").Value = arryData(i,2)
.Fields("FieldName3").Value = arryData(i,3)
.Fields("FieldName4").Value = arryData(i,4)
.Fields("FieldName5").Value = arryData(i,5)
.Fields("FieldName6").Value = arryData(i,6)
.Fields("FieldName7").Value = arryData(i,7)
End With
Next i
rs.UpdateBatch
'******************************************************************
MsgBox "The data has successfully been saved to the SQL Server", _
vbInformation + vbOKOnly,"Alert: Upload Successful"
exiting:
If cn.State > 0 Then cn.Close
If rs.State > 0 Then rs.Close
Set cn = Nothing
Set rs = Nothing
End Sub
Edit: As per OP's request to pass an existing recordset to a SQL table, below should do so:
Private Sub SendRcrdsetToSQL(ByRef rsIn As ADODB.Recordset)
Dim arrySheet As Variant
Dim rsSQL As ADODB.Recordset
Dim cn As ADODB.Connection
Dim strCn As String
Set cn = New ADODB.Connection
strCn= "Provider=VersionOfSQL;User ID=*********;Password=*********;"
& _ "Data Source=ServerName;Initial Catalog=DataBaseName"
cn.Open strCn
On Error Goto exiting
Set rsSQL = New ADODB.Recordset
With rsSQL
.ActiveConnection = cn
.Source = "Select * from TableName"
.CursorType = adOpenDynamic
.CursorLocation = adUseClient
.LockType = adLockBatchOptimistic
.Open
End With
'disconnect the recordset and close the connection
Set rsSQL.ActiveConnection = Nothing
cn.Close
Set cn = Nothing
rsIn.MoveFirst
rsSQL.MoveLast
'Add the records from the passed recordset to the SQL recordset
Do While Not rsIn.EOF
With rsSQL
.AddNew
.Fields("FieldName1").Value = rsIn.Fields("FieldName1").Value
.Fields("FieldName2").Value = rsIn.Fields("FieldName2").Value
.Fields("FieldName3").Value = rsIn.Fields("FieldName3").Value
.Fields("FieldName4").Value = rsIn.Fields("FieldName4").Value
.Fields("FieldName5").Value = rsIn.Fields("FieldName5").Value
.Fields("FieldName6").Value = rsIn.Fields("FieldName6").Value
.Fields("FieldName7").Value = rsIn.Fields("FieldName7").Value
End With
rsIn.MoveNext
Loop
rsSQL.UpdateBatch
MsgBox "The data has successfully been saved to the SQL Server", _
vbInformation + vbOKOnly,"Alert: Upload Successful"
exiting:
If cn.State > 0 Then cn.Close
If rsIn.State > 0 Then rsIn.Close
If rsSQL.State > 0 Then rsSQL.Close
Set cn = Nothing
Set rsIn = Nothing
Set rsSQL = Nothing
End Sub
The only way I was able to get this to work was by running a query to build the structure of my Recordset. So your code becomes something like this:
Private Sub Command1_Click()
Dim cn As ADODB.Connection
Set cn = New ADODB.Connection
cn.ConnectionString = "<your connection string>"
cn.CursorLocation = adUseClient
cn.Open
Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset
Set rs.ActiveConnection = cn
rs.Open "select * from states where 1<>1", , adOpenStatic, adLockBatchOptimistic
rs.AddNew Array("Abbrev", "Name", "Region", "SchoolDataDirect"), Array("TN", "TestName", "MyRegion", 1)
Set rs.ActiveConnection = Nothing
cn.Close
ImportRS rs
End Sub
Private Sub ImportRS(ByRef rs As ADODB.Recordset)
Dim cn As ADODB.Connection
Set cn = New ADODB.Connection
cn.ConnectionString = "<your connection string>"
cn.CursorLocation = adUseClient
cn.Open
Set rs.ActiveConnection = cn
rs.UpdateBatch
Set rs.ActiveConnection = Nothing
cn.Close
End Sub

Connection String for MS Access Database incorrect

I am trying to extrapolate data from an MS Access 2007/2010 Database.
I have the following code in VBA but the connection string is incorrect. I have added the relevant REFERENCES libraries
Private Sub btnGetMsAccessData_Click()
Dim sConn As String
Dim oConn As ADODB.Connection
Dim oRs As ADODB.Recordset
Dim sSQL As String
sConn = "Provider=Microsoft.ACE.OLEDB.12.0;User ID=Admin;Data Source=\\MyNetworkPath\BP-MasterDashboard Source\BP_Planning_by_PT_dept_be.accdb;Mode=Read"
Set oConn = New ADODB.Connection ' Open a connection.
oConn.Open
sSQL = "SELECT * FROM Tbl_Start_Leaver" ' Make a query over the connection.
Set oRs = New ADODB.Recordset
oRs.Open sSQL, , adOpenStatic, adLockBatchOptimistic, adCmdText
MsgBox oRs.RecordCount
oConn.Close ' Close the connection.
Set oConn = Nothing
End Sub
It fails saying Unknown Application error on the oConn.Open line.
I have tried to link a Workbook to one of the tables and this works fine.
I then looked at the "Connection" and copied it into my code but still no joy.
Keeps saying :
Automation Error
Unexpected Error
Any ideas would be appreciated.
Thanks in advance.
While the connection string was incorrect, there were other issues as well. Such as, not assigning the connection String to the ADODB Connection object as well as others. Here is the updated code that I hope will get you operational
Private Sub btnGetMsAccessData_Click()
'Ensure you add a reference to Microsoft ADO Objects
Dim oConn As New ADODB.Connection
Dim oRs As New ADODB.Recordset
Dim sSQL As String: sSQL = "SELECT * FROM Tbl_Start_Leaver"
'Corrected Connection String from Thomas Inzina
Dim sConn As String: sConn = "Provider=Microsoft.ACE.OLEDB.12.0;UID=Admin;Data Source=" & _
"\\MyNetworkPath\BP-MasterDashboard Source\BP_Planning_by_PT_dept_be.accdb;Mode=Read"
With oConn
.ConnectionString = sConn ' You need to assign the connection string to the ADODB.Connection Object
.Open
End With
'Make sure the connection isn't open before opening the recordset
'You also need to specify which connection you want to use as the second parameter (this was missed)
If oRs.State <> adStateOpen Then oRs.Open sSQL, oConn, adOpenStatic, adLockBatchOptimistic, adCmdText
'Close Connection and RS
If oConn.State = adStateOpen Then oConn.Close
If oRs.State = adStateOpen Then oRs.Close
'Clean Up
Set oRs = Nothing
Set oConn = Nothing
End Sub

runtime error '-2147217900' (80040e14)': automation error using where in the sql query from excel vba

I am trying to connect to my sqlserver express 2005 from excel vba using the following (copied from some forum routine as i am not very into databases). It works perfect. As soon as I use WHERE in the sqlquery variable (already verified quotes double and single) i get
runtime error '-2147217900' (80040e14)':
automation error
Similar routine that work pulling data from other people same thing. I appreciate deeply your help
Thanks
Sub ConnectTEST()
' Create a connection object.
Dim cnPubs As ADODB.Connection
Set cnPubs = New ADODB.Connection
Dim sqlquery As String
Dim rsPubs As ADODB.Recordset
Set rsPubs = New ADODB.Recordset
' Provide the connection string.
Dim strConn As String
'Use the SQL Server OLE DB Provider.
strConn = "PROVIDER=SQLOLEDB;"
sqlquery = "SELECT * FROM [Logisuite].[dbo].[EoWebStatus]"
'Connect to the Pubs database on the local server.
strConn = strConn & "Server=SERVITRANSMAIn\SQLEXPRESS;Database=logisuite;Trusted_Connection=True;"
'Use an integrated login.
strConn = strConn & "INTEGRATED SECURITY=sspi;"
'Now open the connection.
cnPubs.Open strConn
' Create a recordset object.
Set rsPubs = New ADODB.Recordset
With rsPubs
' Assign the Connection object.
.ActiveConnection = cnPubs
' Extract the required records.
.Open sqlquery
' Copy the records into cell A1 on Sheet1.
Sheet1.Range("A1").CopyFromRecordset rsPubs
' Tidy up
.Close
End With
cnPubs.Close
Set rsPubs = Nothing
Set cnPubs = Nothing
End Sub