Reputation: 37
I am using an Excel sheet to grab information from an SQL Server then someone adds some information and it gets inserted back into a different SQL database and table. The problem I am having is that the string has the '
in it and so the INSERT INTO
fails
Private Sub SaveData_Click()
Dim conn As New ADODB.Connection
Dim iRowNo, answer, secondOne As Integer
Dim sJobNum, sWorkOrderNum, sItemDesc, sType, sCatName As String
answer = MsgBox("Are you sure you want to save the sheet?", vbYesNo + vbQuestion, "Save Categories")
If answer = vbYes Then
With Sheets("JobInformation")
'Open a connection to SQL Server
conn.Open "Provider=SQLOLEDB;Data Source=10.0.2.2;Initial Catalog=ReportingAddOn;User ID=SOMEID;Password=SOMEPASSWORD"
'Skip the header row
iRowNo = 2
'Loop until empty cell in CustomerId
Do Until .Cells(iRowNo, 1) = ""
If .Cells(iRowNo, 5) <> "" Then
sJobNum = .Cells(iRowNo, 1)
sWorkOrderNum = .Cells(iRowNo, 2)
sItemDesc = .Cells(iRowNo, 3)
sType = .Cells(iRowNo, 4)
sCatName = .Cells(iRowNo, 5)
'Generate and execute sql statement to import the excel rows to SQL Server table
conn.Execute "INSERT INTO dbo.TryOutCategoryComplete (JobNumber, WorkOrderNumber, ItemDescription, Type, CategoryName) VALUES ('" & sJobNum & "', '" & sWorkOrderNum & "', '" & sItemDesc & "', '" & sType & "', '" & sCatName & "')"
End If
iRowNo = iRowNo + 1
Loop
secondOne = MsgBox("Categories Saved!", vbOKOnly, "Successfully Saved!")
conn.Close
Set conn = Nothing
Sheets("CategoryName").Select
End With
End If
End Sub
The problem becomes when the sItemDesc
has something like this:
It is a value that hasn't happened
So the "hasn't" would error as the single quote mark in it causes an end of string in the INSERT INTO
So how would I go about still being able to use the INSERT
the way it is but have it watch out for the single quote block?
Upvotes: 0
Views: 1269
Reputation: 107767
Classic example to why one should use parameterization (an industry best practice) when inserting values into backend databases at the application layer as no quote enclosures are needed and therefore does not affect actual values.
Excel VBA can run parameterized queries with the ADO Command object where you bind parameters to a prepared statement divorcing SQL from VBA values. Below you will see the prepared SQL statement assigned once outside the loop:
Dim conn As New ADODB.Connection
Dim cmd As ADODB.Command
Dim strSQL As String
...
With Sheets("JobInformation")
'Open a connection to SQL Server
conn.Open "Provider=SQLOLEDB;Data Source=10.0.2.2;Initial Catalog=ReportingAddOn;User ID=SOMEID;Password=SOMEPASSWORD"
'Skip the header row
iRowNo = 2
' PREPARED STATEMENT WITH QMARK PLACEHOLDERS
strSQL = "INSERT INTO dbo.TryOutCategoryComplete (JobNumber, WorkOrderNumber, ItemDescription, Type, CategoryName) VALUES (?, ?, ?, ?, ?)"
'Loop until empty cell in CustomerId
Do Until .Cells(iRowNo, 1) = ""
If .Cells(iRowNo, 5) <> "" Then
sJobNum = .Cells(iRowNo, 1)
sWorkOrderNum = .Cells(iRowNo, 2)
sItemDesc = .Cells(iRowNo, 3)
sType = .Cells(iRowNo, 4)
sCatName = .Cells(iRowNo, 5)
' COMMAND OBJECT
Set cmd = New ADODB.Command
With cmd
.ActiveConnection = cn ' CONNECTION OBJECT
.CommandText = strSQL ' SQL STRING
.CommandType = adCmdText
' BINDING PARAMETERS
.Parameters.Append .CreateParameter("sJobNumParam", adVarChar, adParamInput, , sJobNum)
.Parameters.Append .CreateParameter("sWorkOrderNumParam", adVarChar, adParamInput, , sWorkOrderNum)
.Parameters.Append .CreateParameter("sItemDescParam", adVarChar, adParamInput, , sItemDesc)
.Parameters.Append .CreateParameter("sTypeParam", adVarChar, adParamInput, , sType)
.Parameters.Append .CreateParameter("sCatNameParam", adVarChar, adParamInput, , sCatName)
.Execute ' RUN ACTION
End With
Set cmd = Nothing
End If
iRowNo = iRowNo + 1
Loop
secondOne = MsgBox("Categories Saved!", vbOKOnly, "Successfully Saved!")
conn.Close
Set conn = Nothing
Sheets("CategoryName").Select
End With
Upvotes: 1