Select data from mssql using excel vba and where statement - sql-server

I need select data from database, using Excel. I want to select only one column from database and I need use where statement (to select only data which have the same unique value as data in Excel sheet)
I tried this
Sub DB_RTVresult()
Dim Cn As ADODB.Connection
Dim Server_Name As String
Dim Database_Name As String
Dim User_ID As String
Dim Password As String
Dim SQLStr As String
Dim myRes As ADODB.Recordset
Server_Name = "123" ' Enter your server name here
Database_Name = "DBName" ' Enter your database name here
User_ID = "UserName" ' enter your user ID here
Password = "Pass" ' Enter your password here
Set myCon = New ADODB.Connection
Worksheets(2).Select
LastRow = GetRowCnt
For bl = LastRow To 5 Step -1
myCon.ConnectionString = "Driver={SQL Server};Server=" & Server_Name & _
";Uid=" & User_ID & ";Pwd=" & Password & ";Database=" & Database_Name & ";"
myCon.Open
SQLStr = "SELECT [RTV_RESULT]" & _
"FROM [WSCZWMS].[WSCZWMS].[OMEGA_E2E_REPORT] WHERE [SME_TRACK_NO] ='" & Cells(bl, "CC").Value & "'"
Set myRes = myCon.Execute(SQLStr)
Worksheets("HelpTables").Range("E2" & Rows.Count).End(xlUp).Offset (1)
StrQuery = "OMEGA_SPEQ_REPORT"
myCon.Close
Set myRes = Nothing
Set myCon = Nothing
Next
End Sub
But when I run it, it writes Application-define or object-define error.
and colored this line
Worksheets("HelpTables").Range("E2" & Rows.Count).End(xlUp).Offset(1).CopyFromRecordset myRes
This line dave the select data into first empty row in column E, (start on 3rd row)
Do you have any idea how to solve this?

The reason for your issue is, that you are already referring to the Row in your .Range("E2" & Rows.Count) .
If you modify the mentioned line to the following, it should work properly:
Worksheets("HelpTables").Cells(Rows.Count, 5).End(xlUp).Offset(1).CopyFromRecordset myRes
The 5 in .Cells(Rows.Count, 5) is for the fifth column ('E').

I am not sure, but it seems that your excel objects Cells dans Rows should be affected and your sheets selected.
I would have writen
For b1=...
Worksheets(2).select
...
... Worksheets(2).cells(b1,"CC").value
...
Worksheets("HelpTables").select
Worksheets("HelpTables").Range("E" & _
Worksheets("HelpTables").Range("E:E").Rows.Count).End(xlUp).Offset(1) ...
...
NB :
"CC" is the name of a Excel value ?
Do you want Range("E2" & rows.count) to go to E2100 if there are 100 rows ? That's why I wrote "E" and not "E2" in my proposition. But may be you wanted (... rows.count+2) ?
Hope it helps.
Pierre.

Related

VBA Access SQL Server table insert

I have some problem when I deal with MS Access. I am using SQL Server and MS Access together.
I try to insert data into a new table.
First, this program asks me to add an item to the list (it is like temporary table). And then, there is another submit button which confirms the data (this step is needed and it is not inefficient one. Please do not ask about this step).
To add data to the list, I use a stored procedure. But I do not know what do I need to do to submit the data again.
Here is my code:
Dim rs As ADODB.Recordset
strConn = "DRIVER=SQL Server;SERVER=CHU-AS-0004;DATABASE=RTC_LaplaceD_DEV;Trusted_Connection=Yes;"
Set conn = New ADODB.Connection
conn.Open strConn
cmd.ActiveConnection = conn
Set rs = New ADODB.Recordset
rs.Open "Insert into dbo.Blend values(List731.Column(1, introw),List731.Column(2, introw),TextRequestNo.Value, List731.Column(3, introw),List731.Column(4, introw),List731.Column(5, introw))"
conn.Close
Set rs = Nothing
MsgBox "Done"
When I run with this code, I get this error:
I think there is some missing in my code but I do not know how to proceed.
Is there anyone who can give me some information about this?
There are many ways to do this kind of thing. Something like this should get the job done.
Sub MoveDateFromAccessToSQLServer()
Dim adoCN As ADODB.Connection
Dim sConnString As String
Dim sSQL As String
Dim lRow As Long, lCol As Long
sConnString = "Provider=sqloledb;Server=servername;Database=NORTHWIND;User Id=xx;Password=password"
Set adoCN = CreateObject("ADODB.Connection")
'adoCN.Open sConnString
'Assumes that you have Field1, Field2 and Field3 in columns A, B and C
'Text values must be enclosed in apostrophes whereas numeric values should not.
sSQL = "INSERT INTO YOUR_TABLE (FIELD1, FIELD2, FIELD3) " & _
" VALUES (" & _
"'" & Column(1, introw) & "', " & _
"'" & Column(2, introw) & "', " & _
"'" & Column(3, introw) & "')"
adoCN.Execute sSQL
adoCN.Close
Set adoCN = Nothing
End Sub

Deleting Records in SQL server table prior to insert

I have a excel workbook that is a project plan template, that the PM fills in information and it gets loaded into a sql database. Currently the process if via a batch process that loads two tables(1 with 1 row of data and the other with multiple records). I am changing it to be a direct insert from excel into sql server via vba. I have the insert working but each table has a project id column which is the PK. The pm may update and save this file multiple times. The tables get updated with the most recent save information. I have solved this by adding a delete statement into my code and then inserting the updated record. This works great for the table with 1 record but I can't get the table with multiple records to work. It deletes the records and goes through the first loop of the insert but then goes back to the delete and removes the records.
I have attached the code for the multiple table delete and insert. Can someone tell me what I am doing wrong?
Public Sub exportprojdetaildata()
Dim stSQL As String
Dim conn As New ADODB.Connection
Dim rs As New ADODB.Recordset
Dim strConn As String
Dim iRowNo As Integer
Dim targetedFieldNames As Variant
Dim rowData As Variant
Dim lastrow As Long
Dim sql As String
Dim i As Integer
Dim cvt As Double
Dim aField As String
Dim compare As Variant
Dim value As Variant
Dim dvalue As Long
With Sheets("Data")
lastrow = .Range("A:A").Find(what:="*", SearchDirection:=xlPrevious, SearchOrder:=xlByRows).Row
'Open a connection to SQL Server
conn.Open _
"Provider=SQLOLEDB;Data Source=PWIRTPAUDD1HV8;Initial Catalog=STAR;User Id=STAR_USER;Password=dcistarrtp"
'Skip the header row
iRowNo = 2
targetedFieldNames = Join(WorksheetFunction.Transpose(wks_TargetFieldNames.Range("targetedFieldNames").value), "," & vbNewLine)
Do While iRowNo <= lastrow
rowData = wks_BackgroundData.Range("A" & iRowNo & ":AV" & iRowNo).value
compare = wks_BackgroundData.Range("AV2").value
'Generate and execute sql statement to import the excel rows to SQL Server table
With rs
.ActiveConnection = conn
.Open "Select proj_id from dbo.STAR_DC_INITIAL_ProjectDetails_ExcelDevCopy where proj_id = " & compare
wks_BackgroundData.Range("BA2").CopyFromRecordset rs
.Close
End With
value = wks_BackgroundData.Range("BA2").value
If compare = value Then
sql = "delete from dbo.STAR_DC_INITIAL_ProjectDetails_ExcelDevCopy where proj_id = " & value
conn.Execute sql
Else
sql = "insert into dbo.STAR_DC_INITIAL_ProjectDetails_ExcelDevCopy ("
sql = sql & targetedFieldNames
' Debug.Print sql
sql = sql & ") values (" & vbNewLine
' Debug.Print sql
'couldn't do transpose since rowData represents a row, not a column
For i = 1 To UBound(rowData, 2)
aField = Replace(rowData(1, i), "'", "''")
'escape single quotes
Select Case i
Case 1, 6, 16, 17, 23 To 47
' cvt = CDbl(aField)
If aField = vbNullString Then
sql = sql & "Null," & vbNewLine
Else
sql = sql & aField & "," & vbNewLine
End If
Case 2 To 5, 7 To 15, 18 To 22
sql = sql & "'" & aField & "', " & vbNewLine
Case 48
If aField = vbNullString Then
sql = sql & "Null"
Else
sql = sql & aField
End If
End Select
Next i
sql = sql & ");"
'sql = sql & "');"
' End If
conn.Execute sql
iRowNo = iRowNo + 1
Loop
End If
conn.Close
Set conn = Nothing
End With
End Sub
It's difficult to be sure without seeing the data that you're trying to save, but I suspect you have a logic error.
The value for rowData is built up dynamically in a loop. which is correct.
rowData = wks_BackgroundData.Range("A" & iRowNo & ":AV" & iRowNo).value
but the values for compare and value are always read from the same location inside the loop. So the delete statement will be executed over and over again.
compare = wks_BackgroundData.Range("AV2").value
value = wks_BackgroundData.Range("BA2").value
Should compare and value not also be read dynamically?
compare = wks_BackgroundData.Range("AV" & iRowNo).value
value = wks_BackgroundData.Range("BA" & iRowNo).value
Or
you should move the delete statement outside of the loop, to ensure that it's only executed once
Or
you should keep a flag that will indicate that the delete has already been executed, and not execute it again.
hasExecuted = false <- OUTSIDE THE LOOP
...
...
If compare = value and hasExecuted = false Then
sql = "delete from dbo.STAR_DC_INITIAL_ProjectDetails_ExcelDevCopy where proj_id = " & value
conn.Execute sql
hasExecuted = true
...
...
Also, I don't think you should have a IF x=y THEN delete ELSE INSERT. Should it not be IF x=y THEN delete, and always INSERT. With the else, it will only insert if the record didn't exist, but if it deleted the record, it will never insert the new one.
Hope that helps a bit
Avoid using VBA for new development work. If you need to constantly take this Excel document and insert it into a SQL Server database, then use SSIS and some C# to easily make it a scheduled task via the SQL Agent, or simply do as the screen shot below suggests, which is a no-code and easily configurable import of flat files / database tables into SQL Server. Lastly, from a usability standpoint, There are many better methods to track Excel sheets or forms data (SharePoint, Excel 2013, Access, cloud/on premise drives) or using an internal WordPress distribution with some plugins like WP-document revisions.
As noted above I used Spock addition of dynamic lookup of values for the compare and value variable. Once I did that I added the hasExecuted flag.
Public Sub exportprojinfodata()
Dim stSQL As String
Dim conn As New ADODB.Connection
Dim rs As New ADODB.Recordset
Dim strConn As String
Dim iRowNo As Integer
Dim targetFieldNames As Variant
Dim rowData As Variant
Dim lastrow As Long
Dim sql As String
Dim i As Integer
Dim aField As String
Dim compare As Variant
Dim value As Variant
Dim hasExecuted As String
hasExecuted = False
With Sheets("Data2")
lastrow = .Range("A:A").Find(what:="*", SearchDirection:=xlPrevious, SearchOrder:=xlByRows).Row
'Open a connection to SQL Server
conn.Open _
"Provider=SQLOLEDB;Data Source=PWIRTPAUDD1HV8;Initial Catalog=STAR;User Id=STAR_USER;Password=dcistarrtp"
'Skip the header row
iRowNo = 2
targetFieldNames = Join(WorksheetFunction.Transpose(wks_TargetFieldNames.Range("TargetFieldNames").value), "," & vbNewLine)
Do While iRowNo <= lastrow
rowData = wks_ProjDescription.Range("A" & iRowNo & ":AO" & iRowNo).value
compare = wks_ProjDescription.Range("B"& iRowNo).value
'Generate and execute sql statement to import the excel rows to SQL Server table
With rs
.ActiveConnection = conn
.Open "Select proj_id from dbo.STAR_DC_INITIAL_ProjectInfo_ExcelDevCopy where proj_id= " & compare
wks_ProjDescription.Range("AX2").CopyFromRecordset rs
.Close
End With
value = wks_ProjDescription.Range("AX"& iRowNo).value
If compare = value And hasExecuted = False Then
stSQL = "delete from dbo.STAR_DC_INITIAL_ProjectInfo_ExcelDevCopy where proj_id = " & value
conn.Execute stSQL
hasExecuted = True
End If
sql = "insert into dbo.STAR_DC_INITIAL_ProjectInfo_ExcelDevCopy ("
sql = sql & targetFieldNames
sql = sql & ") values (" & vbNewLine
'
'couldn't do transpose since rowData represents a row, not a column
For i = 1 To UBound(rowData, 2)
aField = Replace(rowData(1, i), "'", "''")
Select Case i
Case 1 To 40
sql = sql & "'" & aField & "', " & vbNewLine
Case 41
If aField Like "*,*" Then
sql = sql & "'" & """" & aField & """" & vbNewLine
Else
sql = sql & "'" & aField & "' " & vbNewLine
End If
End Select
Next i
sql = sql & ");"
' sql = sql & "');"
conn.Execute sql
iRowNo = iRowNo + 1
Loop
conn.Close
Set conn = Nothing
End With
End Sub

VB6 - Invalid Column name with Insert query

I'm testing a small program to write some data to a SQL Server 2008 database. This is the code:
Dim MyConn As ADODB.Connection
Dim MyRecSet As ADODB.Recordset
Dim st1 As Integer
Set MyConn = New ADODB.Connection
MyConn.ConnectionString = "Provider=sqloledb;" & _
"Data Source=xxx\SQLEXPRESS2;" & _
"Initial Catalog=db;" & _
"User Id=sa;" & _
"Password=xxx"
MyConn.Open
st1 = 5
MyConn.Execute("INSERT INTO steen (steen1) VALUES (st1)")
MyConn.Close
However, I'm getting the error: Invalid column name 'st1'.
I have no idea why I'm getting this erro.
When I change the query to this:
INSERT INTO steen (steen1) VALUES (5)
It works perfectly.
Does anyone have an idea why I'm getting the error?
Thanks
try:
MyConn.Execute("INSERT INTO steen (steen1) VALUES ("& st1 & ")")
Or:
st1 = 5
Dim StrQuery As String
StrQuery = "INSERT INTO steen (steen1) VALUES ("& st1 & ")"
MyConn.Execute(StrQuery)

Export data from Excel to Access - Error: Argument not Optional

I'm trying to export data from Excel 2010 to Access 2010 with a VBA code on my excel file when I press a button. I just want to export the data from "Water Quality" sheet to the "Water Quality" table on my database (In the excel file and access file are other sheets and tables).
My actual code is:
Sub Button14_Click()
' Exports data from the active worksheet to a table in an Access database
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim r As Long
Dim LastRow As Long
' Set cn = New ADODB.Connection
'cn.Open "Provider=Microsoft.ACE.OLEDB.12.0; " & _
"Data Source=C:\Documents and Settings\Administrador\Mis documentos\MonEAU\modelEAU Database V.2.accdb; " & _
"Persist Security Info=False;"
strCon = "Provider=Microsoft.ACE.OLEDB.12.0; " & _
"Data Source=C:\Documents and Settings\Administrador\Mis documentos\MonEAU\modelEAU Database V.2.accdb"
' Late binding, so no reference is needed
Set cn = CreateObject("ADODB.Connection")
cn.Open strCon
' Find LastRow in Col A into the Sheet1
LastRow = Sheet1.Range("A" & Rows.Count).End(xlUp).Row
' Insert unto a table called Water_Quality
scn = "[Excel 8.0;HDR=YES;DATABASE=" & ActiveWorkbook.FullName & "]"
strSQL = "INSERT INTO Water_Quality " _
& "SELECT * FROM " & scn & ".[Sheet1$A5:L" & LastRow & "]"
' Execute the statement
cn.Execute strSQL
rs.Close
cn.Close
Set rs = Nothing
Set cn = Nothing
End Sub
I can debug without any problem the code but when I run it, a run error appears: "The Microsoft Office Access database engine could not find the object 'Sheet1$A5:L10'. Make sure the object exists and that you spell its name and the path name correctly." It seems that there's a problem with the line cn.Execute strSQL.
I've checked the names and the path name as well, and I can't find where the problem is.
Any help to solve it would be greatly appreciated.
Here are a few examples for inserting all the data at once:
strCon = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=z:\docs\test.accdb"
''Late binding, so no reference is needed
Set cn = CreateObject("ADODB.Connection")
cn.Open strCon
''Create a table called ATable
scn = "[Excel 8.0;HDR=YES;DATABASE=" & ActiveWorkbook.FullName & "]"
strSQL = "SELECT * INTO ATable " _
& "FROM " & scn & ".[Sheet7$A1:C4]"
''Execute the statement
cn.Execute strSQL
''Insert into a table called ATable
scn = "[Excel 8.0;HDR=YES;DATABASE=" & ActiveWorkbook.FullName & "]"
strSQL = "INSERT INTO ATable " _
& "SELECT * FROM " & scn & ".[Sheet7$A1:C4]"
''Execute the statement
cn.Execute strSQL
''Insert into a table with no column header in Excel,
''the fields are [afield],[atext],[another]
scn = "[Excel 8.0;HDR=NO;DATABASE=" & ActiveWorkbook.FullName & "]"
strSQL = "INSERT INTO ATable ([afield],[atext],[another]) " _
& "SELECT F1 As afield, F2 As AText, F3 As another FROM " _
& scn & ".[Sheet7$A1:C4]"
''Execute the statement
cn.Execute strSQL

VBA: Robust Database creation

i find this code, when trying to create db, using adodb and adox.
Here you can check original, it is the same. Thanks for author
Private Sub Command1_Click()
Dim db_file As String
Dim conn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim num_records As Integer
' Get the database name.
db_file = App.Path
If Right$(db_file, 1) <> "\" Then db_file = db_file & _
"\"
db_file = db_file & "People.mdb"
' Open a connection.
Set conn = New ADODB.Connection
conn.ConnectionString = _
"Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & db_file & ";" & _
"Persist Security Info=False"
conn.Open
' Drop the Employees table if it already exists.
On Error Resume Next
conn.Execute "DROP TABLE Employees"
On Error GoTo 0
' Create the Employees table.
conn.Execute _
"CREATE TABLE Employees(" & _
"EmployeeId INTEGER NOT NULL," & _
"LastName VARCHAR(40) NOT NULL," & _
"FirstName VARCHAR(40) NOT NULL)"
' Populate the table.
conn.Execute "INSERT INTO Employees VALUES (1, " & _
"'Anderson', 'Amy')"
conn.Execute "INSERT INTO Employees VALUES (1, 'Baker', " & _
" 'Betty')"
conn.Execute "INSERT INTO Employees VALUES (1, 'Cover', " & _
" 'Chauncey')"
' Add more records ...
' See how many records the table contains.
Set rs = conn.Execute("SELECT COUNT (*) FROM Employees")
num_records = rs.Fields(0)
conn.Close
MsgBox "Created " & num_records & " records", _
vbInformation, "Done"
End Sub
But how to make it more robust, so, i don't want to delete db.
How to check, if db exists and if db.tables contains my table?
additional question: am i right, that this code create db for ms-access 2007?
Thanks for help!
Your question includes these two:
How to check, if db exists and if db.tables contains my table?
am i right, that this code create db for ms-access 2007?
For the first part of #1, use the Dir() function.
If Len(Dir("C:\SomeFolder\YourDb.mdb")) > 0 Then
Debug.Print "db exists"
Else
Debug.Print "db not found"
End If
For the second part of #1, try this function. pTable is the name of the table you're checking for. pDbPath is the full path, including the file name, for the db file you want to examine. The path can be one which begins with a drive letter, or it can be a UNC path ( \\Server\Share\YourDb.mdb ).
Public Function TableExists(ByVal pTable As String, _
Optional ByVal pDbPath As String) As Boolean
'return True if pTable exists as either a native or linked table '
'pass any error to caller '
Dim blnReturn As Boolean
Dim db As DAO.Database
Dim tdf As DAO.TableDef
If Len(Trim(pDbPath)) > 0 Then
Set db = OpenDatabase(pDbPath)
Else
Set db = CurrentDb
End If
For Each tdf In db.TableDefs
If tdf.Name = pTable Then
blnReturn = True
Exit For
End If
Next tdf
Set tdf = Nothing
If Len(Trim(pDbPath)) > 0 Then
db.Close
End If
Set db = Nothing
TableExists = blnReturn
End Function
Regarding your second question, no that code you showed us does not create a db file for any Access version. If db_file is not the path to an existing db file, that code will throw an error at conn.Open. It does not create the missing db file.
However I doubt that code will compile as VBA, despite the fact you included VBA in your title and tagged your question as vba. Really you should have at least tried it first before including it in a question on Stack Overflow.
For creating a MDB file from VB6/VBA code you could use ADOX. Here's a sample function to create an MDB file.
Public Function CreateMDB(strDBPath As String) As Boolean
'To make code compile add a reference to Microsoft ADO Ext 2.x for DDL and Security
'(msADOX.dll)
Dim catDB As ADOX.Catalog
Dim tblNew As ADOX.Table
Dim keyPrim As New ADOX.Key
Set catDB = New ADOX.Catalog
If Dir(strDBPath) = "" Then
CreateMDB = False
End If
With catDB
.Create "Provider=Microsoft.Jet.OLEDB.4.0;Locale Identifier=" & _
1033 & ";Data Source=" & strDBPath
.ActiveConnection = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & strDBPath
End With
Set tblNew = New ADOX.Table
With tblNew
.Name = "data"
With .Columns
.Append "Field_0", adVarWChar
.Append "Field_1", adVarWChar
.Append "Field_2", adVarWChar
.Append "Field_3", adVarWChar
End With
End With
catDB.Tables.Append tblNew
Set keyPrim = New ADOX.Key
With keyPrim
.Name = "Field_0"
.Type = adKeyPrimary
.RelatedTable = "data"
.Columns.Append "Field_0"
End With
catDB.Tables("data").Keys.Append keyPrim
Set catDB = Nothing
Set tblNew = Nothing
End Function

Resources