Loop through range and execute SQL statement when cell not empty - sql

I think I need help with this one:
I look for a way to send a number of line items within a transaction to a database with as little coding as possible
A transaction can consist of 1 or several lineitems for a defined set of products (CategoryIDs). Each combination of CategoryIDs and LineItems is stored in a seperate row. Rows with 0 lineItems are to be ignored.
The products are listed in Worksheet-Column B, and the number of products purchased (the lineitem number) is stored in Column C
In addition, I have a CustomerID and a TransactionID, but these two values are "outside" of the loop because they are the same for the complete transaction, so they are not part of my question.
What I would like to accomplish is:
let the code loop through each row
ignore all rows with 0 line items
at a row with >0 line items, run an SQL insert containing the categoryID and the lineitems of that row
go to next row
I am not sure if this is at all possible in the way I try to do this:
Private Sub AbsendenNeu_Click()
Dim Cell As Range
'Variables for the connection to the SQL server
Dim con As ADODB.Connection
Dim rs As ADODB.Recordset
Dim conStr As String
Dim strSQL As String
'variables "outside the loop" that I am not too concerned with in this question
Dim CustomerUniqueName As String
Dim TransactionID As String
CustomerUniqueName = Worksheets("Eingabe").CustomerSelect.Value
TransactionID = "1-" & CustomerUniqueName & Now()
'These are the two variables "in the loop"
Dim CatID As Range
Dim LineItems As Range
'Open the database connection
Set con = New ADODB.Connection
con.Open "Driver={ODBC Driver 17 for SQL Server};Server=tcp:my-servername,1433;Database=my-database;Uid=my-User;Pwd=My-Password;Encrypt=yes;TrustServerCertificate=no;Connection Timeout=30;"
'this is the loop I try to get to work
With Worksheets("EmissionenNeu") 'This is the worksheet that contains the CategoryIDs and LineItems
Set CatID = Range("B" & Cell.Row)
Set LineItems = Range("C" & Cell.Row)
For Each Cell In Range("C2:C39")
If Cell.Value > 0 Then
strSQL = "INSERT INTO tblTransactions(ShopID,TransactionID,CategoryID,CustomerUniqueName,LineItems) VALUES(1,'" & TransactionID & "','" & CatID & "', '" & CustomerUniqueName & "','" & LineItems & "');"
con.Execute strSQL
End If
Next Cell
con.Close
Set con = Nothing
' End With
End Sub
I read this example in a different context so I am not sure if I can adapt this to my case. I get an error at " Set CatID = Range("B" & Cell.Row) " that says "Object Variable or With-Block Variable not defined" (in German), which sounds pretty basic, and I have the feeling more problems might wait ahead. Is the route I am trying at all possible?
Thanks in advance.

Try something like this:
Private Sub AbsendenNeu_Click()
Dim Cell As Range, rw As Range
Dim con As ADODB.Connection
Dim strSQL As String
Dim CatID, LineItems
Dim CustomerUniqueName As String
Dim TransactionID As String
CustomerUniqueName = Worksheets("Eingabe").CustomerSelect.Value
TransactionID = "1-" & CustomerUniqueName & Now()
'Open the database connection
Set con = New ADODB.Connection
con.Open "Driver={ODBC Driver 17 for SQL Server};Server=tcp:my-servername,1433;" & _
"Database=my-database;Uid=my-User;Pwd=My-Password;Encrypt=yes;" & _
"TrustServerCertificate=no;Connection Timeout=30;"
'loop each row in the input range
For Each rw In Worksheets("EmissionenNeu").Range("B2:C39").Rows
CatID = rw.Cells(1).Value
LineItems = rw.Cells(2).Value
If Len(LineItems) > 0 Then
strSQL = "INSERT INTO tblTransactions(ShopID,TransactionID,CategoryID," & _
"CustomerUniqueName,LineItems) VALUES" & _
"(1,'" & TransactionID & "','" & CatID & "', '" & _
CustomerUniqueName & "','" & LineItems & "')"
con.Execute strSQL
End If
Next rw
con.Close
Set con = Nothing
End Sub

Related

How to auto-increment primary key in SQL INSERT INTO statement

Private Sub btnAddInfo_Click()
On Error GoTo Error_Routine
'Declare variables
Dim intStudentID As Integer
Dim intTestID As Integer
Dim dblMark As Double
Dim intResultID As Integer
'Declare database
Dim db As DAO.Database
Dim rst As DAO.Recordset
'Set the database
Set db = CurrentDb
Set rst = db.OpenRecordset("Select ResultId FROM StudentResult ORDER BY RESULTID DESC", dbOpenDynaset)
'assign value to intResultID variable
intResultID = rst!ResultId
'Adds the additional 1 to the latest result id that was used
If Not rst.EOF Then
intResultID = intResultID + 1
End If
'Assigns value to variables
intStudentID = Forms!frmAdd!lstStudentID
strDescription = Forms!frmAdd!lstTest
dblMark = txtMark.Value
intTestID = Forms!frmAdd!lstTest
'Checks that Student ID has been selected
If Not IsNull(lstStudentID) Then
'Inserts new test record into StudentResult table
db.Execute "INSERT INTO StudentResult " _
& "(ResultId,StudentId,TestId, Mark) VALUES " _
& "('" & intResultID & "','" & intStudentID & "','" & intTestID & "','" & dblMark & "');"
End If
'Clears fields
txtMark.Value = ""
lstStudentID.Value = ""
lblExistingStudent.Caption = "Existing Student Name:"
'Closes database
Set db = Nothing
I'm trying to add new records. There is a list of 4 tests. ResultId is the primary key and it is an AutoNumber column.
The button adds tests scores just fine if the selected StudentID has not added a score for that TestId yet. But when I try to add a StudentId and TestId combination that has been entered before, it does not add a new record or even update the existing one.
Both StudentId and TestId allow duplicates. I've tried doing this counter variable but it has not worked. This is for a class and the professor says a student should be able to retake tests and it should just add a new record.
Thank you in advance for your help. Please let me know if you need any pictures of the form, tables, or more of my code.
Exclude the AutoNumber field, and don't wrap numbers in quotes:
If Not IsNull(lstStudentID) Then
' Verify values:
Debug.Print "StudentID:", intStudentID, "TestID:", intTestID, "Mark:", Str(dblMark)
'Inserts new test record into StudentResult table
db.Execute "INSERT INTO StudentResult " _
& "(StudentId, TestId, Mark) VALUES " _
& "(" & intStudentID & "," & intTestID & "," & Str(dblMark) & ");"
End If

Excel import to SQL via VBA (Run-Time Error)

I am trying to import via a VBA button a ton of Excel data (around 30k + daily) into an existing table in SQL server. My question is how can I do this as simple as possible, code speaking?
The headers both in my Excel file and SQL table are 1:1 the same so I just want to import everything into the SQL table
This is what I started to write but when I try to make the code work I get a "Run-time error '-2147217865 (80040e37): Invalid object name "dbo.Rawdata".
Private Sub cmdImport_Click()
Dim r As Range
Dim c As Range
Set r = Sheet1.Range("A6:DA269239")
Dim con As ADODB.Connection
Set con = New ADODB.Connection
con.ConnectionString = _
"Provider=MSOLEDBSQL;" & _
"Server =localhost\name" & _
"Database =name;" & _
"Trusted_Connection=yes;"
con.Open
Dim iRowNo As Integer
Dim strn_reference As String
Dim batchInsert As String
Dim batchSize As Integer
batchSize = 1000
iRowNo = 0
For Each cl In r
iRowNo = iRowNo + 1
batchInsert = batchInsert + (IIf(iRowNo > 1, ",", "")) + "('" & Replace(cl.Value2, "'", "''") & "')"
If (iRowNo = batchSize) Then
con.Execute "insert into dbo.Rawdata (trn_reference) Values " & batchInsert
iRowNo = 0
batchInsert = ""
End If
Next
If Len(batchInsert) > 0 Then con.Execute "insert into dbo.Rawdata (trn_reference) Values " & batchInsert
MsgBox "Reference Numbers imported"
con.Close
Set con = Nothing
End Sub
Thank you everyone for the help!
I guess you should refer to the table name from SQL server not dbo.Rawdata but directly:
Rawdata|"Insert into Rawdata(column_name) VALUES ('" & vba_variable & "')"
This should be the SQL statement from VBA.
This work for me very well.

Inserting values into SQL Server table via VBA

Suppose I have a table in Excel with two columns (Name, Rate) (say, this table's name tExcel). Table starts at cell (2,1), and Date is static (in cell (1,1))
I want to insert those values into SQL Server 2008 tRate table with following logic
insert tRate(ID, Rate, Date)
select
s.ObjectID, e.Rate, Date -- date comes from cell(1,1). DateType is smalldatetime
from
tExcel e, tSecurity s
where
e.Name = s.Number
I've created a connection
Sub disp_cust()
Dim adoCN As ADODB.Connection
Dim sConnString As String
Dim sSQL As String
Dim lRow As Long, lCol As Long
Set cn = New ADODB.Connection
sConnString = "Provider=sqloledb;Server=xxx;Database=xxx;User Id=xxx;Password=xxx"
Set adoCN = CreateObject("ADODB.Connection")
adoCN.Open sConnString
adoCN.Close
Set adoCN = Nothing
End Sub
Thanks for help.
EDIT to #jaimetotal answer
sql= "insert tRate(ID, Rate, Date) SELECT s.ObjectId ," & Replace(Row.Cells(2).Value, ",", ".") & ",'" & defaultDate & "' FROM tSecurity s where s.number = '" & row.Cells(1).Value & "'; "
For this sample, I assume that tExcel.Number is the first column and tExcel.Rate is the second. The idea here is to do a for each row in the table (or range) and create an insert/select statement.
Dim rng as Range
Dim defaultDate As string
Dim sql as string, bulkSql as string
Set rng = Range("A1:XX") -- Range of the table.
defaultDate = Format(Range("A2").Value, "yyyy/mm/dd")
bulkSql = ""
'generated sample: insert tRate(ID, Rate, Date) SELECT s.ObjectId, '0.15', '2015/08/24' FROM tSecurity s where s.Number = '007'
For Each row In rng.Rows
sql= "insert tRate(ID, Rate, Date) SELECT s.ObjectId " & "','" & row.Cells(2).Value & "','" & defaultDate & "' FROM tSecurity s where s.number = '" & row.Cells(1).Value & "'; "
bulkSql = bulkSql & sql
Next row
adoCn.Execute bulkSql, , adCmdText
Edit:
If you really mean a table, than you can use this sample based from here.
Dim lo As Excel.ListObject
Dim ws As Excel.Worksheet
Dim lr As Excel.ListRow
Set ws = ThisWorkbook.Worksheets(1)
Set lo = ws.ListObjects("tExcel")
'The other code from the previous sample. Use the following ForEach instead
For Each lr In lo.ListRows
Dim Rate as String
Dim Number as String
Rate = Intersect(lr.Range, lo.ListColumns("Rate").Range).Value
Number = Intersect(lr.Range, lo.ListColumns("Number").Range).Value
'Generate the query from these values instead
Next lr

VBA SQL "Insert Into" ERROR

I got some annoying problem, and i already struggle for an hour fixing this thing..
so basically I try to Insert the Values of some Excel table into Access Database, But when i run my code, it keeps telling me that there is some missing operator, while i'm sure that my query is correct already.
I am not familiar with VBA or even SQL.
Here is My Code :
'Put Into Database
Dim ent As String
ent = ThisWorkbook.Sheets("Tracking").Cells(row, 1)
Dim cn As ADODB.Connection
Set cn = New ADODB.Connection
cn.Mode = adModeReadWrite
cn.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=C:\Users\reza.ariefianto\Documents\Routing.mdb;"
Dim qq As ADODB.Command
Set qq = New ADODB.Command
qq.ActiveConnection = cn
Dim bid As String
bid = ThisWorkbook.Sheets("RFA Fill Form").Cells(11, 5)
Dim ttl As String
Dim cont As String
Dim typ As String
ttl = ThisWorkbook.Sheets("RFA Fill Form").Cells(12, 5)
cont = ThisWorkbook.Sheets("RFA Fill Form").Cells(19, 5)
typ = ThisWorkbook.Sheets("RFA Fill Form").Cells(15, 5)
Dim com As String
com = "insert into Entry([RFA],[Bid Number],[Title],[Contractor],[Type]) values (" & ent & "," & bid & "," & ttl & "," & cont & "," & typ & ");"
cn.Execute com
cn.Close
You need to ensure that the values that are strings are wrapped in single quotes.
So let assume the first 2 values are strings and the rest are numbers, you need to speicyf it as
com = "insert into Entry([RFA],[Bid Number],[Title],[Contractor],[Type]) values ('" & ent & "','" & bid & "'," & ttl & "," & cont & "," & typ & ");"
Also, I would rather look at using the Command.Execute method, which would allow you to make use of Parameters instead, as to avoid SQL Injection

Sql query taking values from the column in the excelsheet using VBA(macro)

I need to use sql query using VBA. My input values for the query is from the Column in the excel sheet.I need to take all the values present in the column and it should be passed as input to the query to sqlserver. But i could'nt get the answer. I am getting type mismatch as error. could any one help me out. Thanks in advance
for example in J column contains J1=25, j2=26, ....so on
stSQL = "SELECT * FROM prod..status where state in"
stSQL = stSQL & wsSheet.Range("J:J").Value
My full code is below
Sub Add_Results_Of_ADO_Recordset()
'This was set up using Microsoft ActiveX Data Components version 2.8
Dim cnt As ADODB.Connection
Dim rst As ADODB.Recordset
Dim stSQL As Variant
Dim wbBook As Workbook
Dim wsSheet As Worksheet
Dim rnStart As Range
Const stADO As String = "Provider=SQLOLEDB.1;Integrated Security=SSPI;" & _
"Persist Security Info=False;" & _
"Initial Catalog=prod;" & _
"Data Source=777777777V009D\YTR_MAIN4_T"
'where BI is SQL Database & AURDWDEV01 is SQL Server
Set wbBook = ActiveWorkbook
Set wsSheet = wbBook.Worksheets("sheet1")
With wsSheet
Set rnStart = .Range("A2")
End With
' My SQL Query
stSQL = "SELECT * FROM prod..status where state in"
stSQL = stSQL + wsSheet.Range("J:J").Value
Set cnt = New ADODB.Connection
With cnt
.CursorLocation = adUseClient
.Open stADO
.CommandTimeout = 0
Set rst = .Execute(stSQL)
End With
'Here we add the Recordset to the sheet from A1
rnStart.CopyFromRecordset rst
'Cleaning up.
rst.Close
cnt.Close
Set rst = Nothing
Set cnt = Nothing
End Sub
change to
stSQL = stSQL + " ('" + Replace(wsSheet.range("J:J").Value, "'", "") + ")"
but sql IN statement is usually used like this
state IN (25,26,28)
But if you are only using one integer value you might want to go this way.
stSQL = "SELECT * FROM prod..status where state = "
stSQL = Val(wsSheet.range("J:J").Value)
There is though one thing that is dangerous in using a in statement.
If your In part of the statement is very long, it will become slow and then with even larger in statements crash altogeather.
The solution for that kind of situation is creating a temp table with the in values and do where in (temp table) or a inner join based on the temp table
There is no space after your "in" in your stSQL variable. So if your cell contains the value "TEST", stSQL will be
SELECT * FROM prod..status where state inTEST
I used for loop and mid command to convert the values in the column to a single variable. Below is the code i used to perform the function which i required
' Getting the last row
With wsSheet
lastrow1 = .Range("J" & .Rows.Count).End(xlUp).Row
End With
' Appending the values to a single variable
For i = 1 To lastrow
s1 = s1 & "'" & Val(wsSheet.Cells(i, 10)) & "'" & ","
Next
' Variable which could be used in IN command
If lastrow > 0 Then
s1 = Mid(s1, 1, Len(s1) - 1)
s1 = "(" & s1 & ")"
Else
Exit Sub
End If