VBA SQL "Insert Into" ERROR - sql

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

Related

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.

How to optimize a connection in vba

I am working with vba, and I am using an excel sheet to find prices using SQL code within vba. Below is an example of how it is done:
Sub connection()
Set cn = New ADODB.connection
Set cn = CreateObject("ADODB.Connection")
With cn
.Provider = "Microsoft.ACE.OLEDB.12.0"
.ConnectionString = "Data Source=" & ThisWorkbook.Path & "\" & ThisWorkbook.Name & ";" & _
"Extended Properties=""Excel 12.0 Xml;HDR=YES"";"
.Open
End With
End Sub
Function getAddres(ByVal sTableName As String) As String
With Range(sTableName & "[#All]")
getAddres = "[" & .Parent.Name & "$" & .Address(False, False) & "]"
End With
End Function
Function Get_Coeff_1_crit(couv As String, tabelle As String, edit As String, crit1 As String) As Variant
Dim NomFeuille As String, texte_SQL As String
Dim rst As ADODB.Recordset
Dim strRangeAddress As String
Call connection
strRangeAddress = getAddres(edit)
texte_SQL = "SELECT [Coeff] FROM " & strRangeAddress & " WHERE ([Tabelle]=" & Chr(34) & tabelle & Chr(34) & _
" ) AND (( [Booléen_1] = " & crit1 & " ) OR ( [Fixe_1] = " & crit1 & " ) OR (" & crit1 & " BETWEEN [Min_1] AND [Max_1] ))"
Set rst = New ADODB.Recordset
Set rst = cn.Execute(texte_SQL)
On Error Resume Next
Get_Coeff_1_crit = 0
Get_Coeff_1_crit = rst.Fields(0).Value 'ws.Range("N7").CopyFromRecordset Rst
End Function
So I have an input of variables and this function looks for the table and correct variable combination.
My issue is that with many functions each establishing a separate connection with the excel sheet, it takes an insane amount of time to process a lot of prices.
I was wondering if anyone knows of a better way, I am rather new at vba, so I was wondering if we can store dataframes within the process like in python or is there a different way to not establish connections each time.
Thanks.
if you're looping over Get_Coeff_1_crit repeatedly then I can see why it's bogging down while it's reestablishing that connection each pass.
You'd want to do something like this inside the function,
If Not cn is Nothing then 'verify the object is instantiated
If cn.State = adStateClosed then 'State property tells if it's open
Call Connection
End If
End If
'further details on that property - https://www.w3schools.com/asp/prop_comm_state.asp

Loop through range and execute SQL statement when cell not empty

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

Data-type mismatch Access 2010

We have been creating a HR Database using Access as the back-end and Excel as the front-end. When I run my macro in Excel to insert entries into the MasterTable it says; "Data Type Mismatch". The only field that I had changed was the "Job" Field which required a value between 0.0 - 1.0 (i.e. 0.2 means they are only working one day).
Previously when I inserted entries in the decimal place would not show until I changed the field type in Access to accept decimals. After this change, the macro no longer works.
Can anyone point out why this is?
I have only just started learning SQL/Access so it is very likely I made a very basic mistake.
I searched up on SO a few other answers which talked about using the DECIMAL field instead of changing the properties field but this didn't solve my issue. My code:
Sub ExportDataToAccess()
Dim cn As Object
Dim strQuery As String
Dim Id As String
Dim Positions As String
Dim BU As String
Dim Job As Double
Dim Variance As String
Dim myDB As String
'Initialize Variables
Id = Worksheets("test").Range("A2").Value
Positions = Worksheets("test").Range("B2").Value
BU = Worksheets("test").Range("C2").Value
Job = Worksheets("test").Range("D2").Value
myDB = "X:\Users\ADMIN\Documents\HR_Establishment_DB1.accdb"
Set cn = CreateObject("ADODB.Connection")
With cn
.Provider = "Microsoft.ACE.OLEDB.12.0" 'For *.ACCDB Databases
.ConnectionString = myDB 'Connects to my DB
.Open
End With
strQuery = "INSERT INTO MasterTable ([Id], [Positions], [BU], [Job]) " & _
"VALUES (""" & Id & """, """ & Positions & """, """ & BU & """, " & Job & "); "
cn.Execute strQuery
cn.Close
Set cn = Nothing
End Sub
Do you intend the value of ID to be obtained from the excel (Id = Worksheets("test").Range("A2").Value)?
I think it is causing the error. If a field on access is of AutoNumber data type, you don't have to include it on your INSERT query as access automatically assigns a value for this in incremental manner.
If you want access to automatically assign a value for ID, change this:
strQuery = "INSERT INTO MasterTable ([Id], [Positions], [BU], [Job]) " & _
"VALUES (""" & Id & """, """ & Positions & """, """ & BU & """, " & Job & "); "
to this:
strQuery = "INSERT INTO MasterTable ([Positions], [BU], [Job]) " & _
"VALUES (""" & Positions & """, """ & BU & """, " & Job & "); "

Updating Access Database from Excel Worksheet Data

I extract data from my Access database into an Excel worksheet using a macro. I first open a connection to the database, define my sql statement in a string var and then dump that data in a recordset:
Dim db As Database
Dim rs As RecordSet
Dim sql As String
Dim dbLocation As String
dbLocation = ThisWorkbook.Path & "\database\data.accdb"
Set db = OpenDatabase(dbLocation)
sql = "Select * FROM [Master Table]"
Set rs = db.OpenRecordSet(sql, dbOpenSnapshot)
If Not rs.EOF Then
Worksheets("Sheet1").Range("A1").CopyFromRecordset rs
End If
rs.Close
Set rs = Nothing
db.Close
Set db = Nothing
This works perfectly. I distribute this to some people and ask them to update fields. I then need to update the Access data with data that is passed back. The simple thing in terms of design is that the extracted excel data mirrors the access db in structure so the update query should be simple. Also there is a primary key, so I would just need to map on that field.
Any ideas how this can be done? Can I load the whole excel datasheet into a recordset and run some snazzy update query?
You need to loop over rows on sheet 1, and for each row make sql string that looks like:
"update [Master table] set
TableField1 = " & Range(Row, Col1).Value & ","
TableField2 = " & Range(Row, Col2).Value & ","
...
where IDTableField = " & Range(Row, IDColNum).Value
and then do
db.Execute thatString
PS: There are may be mistakes in my syntax. And you need to convert cell values to strings when making string.
An extension of shibormot's solution using DAO:
Set objConnection = CreateObject("DAO.DBEngine.36")
Set db = objConnection.OpenDatabase(strDBPath, blnExclusive, blnReadOnly, strPassword)
For Each row In Range("A1:C3").Cells
strSQL = "UPDATE table SET "
strSQL = strSQL & "Field1 = " & Chr(34) & row.Cells(1) & Chr(34) & ","
strSQL = strSQL & "Field2 = " & Chr(34) & row.Cells(2) & Chr(34) & ","
strSQL = strSQL & "Field3 = " & Chr(34) & row.Cells(3) & Chr(34)
Db.Execute
Next
Threw in the chr(34) for string data