Overwrite value in DB with a NULL using VBA - sql-server

If cell.Value <> "" Then
uid = cell
lname = Left(Replace(Range(cell.Address).Offset(0, 1), "'", ""), 50)
fname = Replace(Range(cell.Address).Offset(0, 2), "'", "")
stat = Replace(Range(cell.Address).Offset(0, 3), "'", "")
role = Left(Replace(Range(cell.Address).Offset(0, 4), "'", ""), 50)
iqn = Replace(Range(cell.Address).Offset(0, 5), "'", "")
sdate = Format(Replace(Range(cell.Address).Offset(0, 6), "'", ""), "yyyy-mm-dd")
bdate = Format(Replace(Range(cell.Address).Offset(0, 7), "'", ""), "yyyy-mm-dd")
rodate = Format(Replace(Range(cell.Address).Offset(0, 8), "'", ""), "yyyy-mm-dd")
End If
hirereason = Replace(Range(cell.Address).Offset(0, 9), "'", "")
roreason = Replace(Range(cell.Address).Offset(0, 10), "'", "")
sql = "BEGIN TRAN IF EXISTS (SELECT * FROM " & TableName & " WITH (updlock, serializable)"
sql = sql & " WHERE UID = '" & uid & "')"
sql = sql & " BEGIN"
sql = sql & " UPDATE" & TableName
sql = sql & " SET LName='" & lname & "', FName='" & fname & "'"
sql = sql & ", Status='" & stat & "', Role='" & role & "'"
sql = sql & ", IQNRole='" & iqn & "', StartDate='" & sdate & "'"
sql = sql & ", BillableDate='" & bdate & "', RollOffDate='" & rodate & "'"
sql = sql & ", HireReason='" & hirereason & "', RollOffReason='" & roreason & "'"
sql = sql & " WHERE UID = '" & uid & "'"
sql = sql & " END"
sql = sql & " ELSE BEGIN"
sql = sql & " INSERT " & TableName & " (UID, LName, FName, Status, Role, IQNRole, StartDate"
sql = sql & ", BillableDate, RollOffDate, HireReason, RollOffReason)"
sql = sql & " VALUES('" & uid & "', '" & lname & "', '" & fname & "', '" & stat & "'"
sql = sql & ", '" & role & "', '" & iqn & "', '" & sdate & "', '" & bdate & "', '" & rodate & "'"
sql = sql & ", '" & hirereason & "', '" & roreason & "')"
sql = sql & " END COMMIT TRAN"
Cn.Execute (sql)
End If
I have some values and I'm formatting the date values which come is as string to date. If I run this as is it puts a default value for "" into the DB as 1900-1-1. I want the NULL values to actually stay in the DB and not be over-written. Furthermore I want them to update a cell with NULL if say it didn't use to be but now is.
I tried wrapping my value rodate in an IF statement and tried validating it against NULL, NOTHING, and EMPTY to say if it is one of these UPDATE DB with "NULL" but it doesn't do it. Date still comes out 1900-1-1. Any ideas?

Dim roDate
'...
'...
rodate = Trim(cell.Offset(0, 8).Value)
If len(rodate)=0 Then
rodate = null
else
rodate = "'" & Format(rodate, "yyyy-mm-dd") & "'"
end if
'....
'....
'note no single quote here around rodate
sql = sql & ", BillableDate='" & bdate & "', RollOffDate=" & rodate
'...
'...

I'm confused, not sure if I get this question right.
The only thing I understood from it is that you are struggling with saving a date as NULL in the database.
NULL and an empty string are not the same.
Try and see if this works:
dim vNull as variant
vNull = Null
if sDate = "" then
//Save vNull instead of Date
end if
I don't believe that you can capture NULL in a string datatype.
Edit
Perhaps stupid that I didn't think of this before, but instead of an empty string, can't you just put the string "NULL" in the query string?

Related

DateTime field not Updateable

Here's my code:
strSQL = "UPDATE tblTransactions SET Verifier = '" & strUserName & "' WHERE PatientAccountNumber = '" & Me.PatientAccountNumber & "'"
strSQL = "UPDATE tblTransactions SET VerifierAssgnDate = #" & Date & "# WHERE PatientAccountNumber = '" & Me.PatientAccountNumber & "'"
"Verifier" updates fine, but "VerifierAssignDate" throws a "field not updateable" error. It's a DateTime field.
Thanks!
You can and should combine these (and VerifierAssgnDate was probably misspelled):
strSQL = "UPDATE tblTransactions " & _
"SET Verifier = '" & strUserName & "', VerifierAssignDate = Date() " & _
"WHERE PatientAccountNumber = '" & Me.PatientAccountNumber & "'"

I get exception when I pass empty datetime value to sqlserver via VBA

I'm trying to export some tables from EXCEL 2013 to my SQL Server 2017 Database via VBA ADO. All works fine, except when the datetime cell contains an empty value and then I get an exception. I tried to replace the values with NULL, 1900-01-01, '',((0)) but I always get SYSTEM ERROR &H80040E07
NUM_COURIER = rg.Cells(i, 3)
DATE_DEPART = rg.Cells(i, 4) 'DATETIME
DATE_RECEPTION = rg.Cells(i, 5) 'DATETIME
If DATE_DEPART = "" Then DATE_DEPART = "''" Else DATE_DEPART = "'" & DATE_DEPART & "'"
If DATE_RECEPTION = "" Then DATE_RECEPTION = "''" Else DATE_RECEPTION = "'" & DATE_RECEPTION & "'"
StrQuery = "INSERT INTO COURIER (NUM_COURIER_BANQUE,DATE_DEPART_BANQUE,DATE_RECEPTION_BANQUE) VALUES('" & NUM_COURIER & "'," & DATE_DEPART & "," & DATE_RECEPTION & ")"
Set rs = query(conn, StrQuery)

VBA inserting Update Statement with multiple columns to table in SQL

can anyone help me where am I doing wrong.. im building an update statement with multiple columns to update MSQL with VBA and values from Excel. heres my simple code, Im parsing variable in function to execute SQL command (I have a table name "People" and I have define all the column) below:
Function GetUpdateTextSQL(PIC As String,
Customer As String,
DOB As Date,
Rank As String,
Organization As String,
Status As String,
Gender As String,
Religion As String,
Hobby As String,
CreatedBy1 As String,
CreatedOn1 As Date,
ChangedBy1 As String,
ChangedOn1 As Date,
PeopleID As Integer) As String
SQLStr = _
"UPDATE People" & _
"SET PIC = " & _
"'" & PIC & "', Customer = '" & Customer & "'," & _
"DOB = '" & Format(DOB, "yyyy-mm-dd") & "', Rank = '" & Rank & "'," & _
"Organization = '" & Organization & "',Status = '" & Status & "', Gender = '" & Gender & "'," & _
"Religion = '" & Religion & "', Hobby = '" & Hobby & "'," & _
"CreatedBy = '" & CreatedBy1 & "', CreatedOn = '" & CreatedOn1 & "'," & _
"ChangedBy = '" & ChangedBy1 & "', ChangedOn = '" & ChangedOn1 & "'" & _
"WHERE PeopleID = & PeopleID &;"
GetUpdateTextSQL = SQLStr
//And here Im inserting and executing command below to get values from excel:
For Each r In Range("A45", Range("A45").End(xlDown))
CmdForSave.CommandText = _
GetUpdateTextSQL( _
r.Offset(0, 1).Value, r.Offset(0, 2).Value, _
r.Offset(0, 3).Value, _
r.Offset(0, 4).Value, r.Offset(0, 5).Value, _
r.Offset(0, 6).Value, r.Offset(0, 7).Value, _
r.Offset(0, 8).Value, r.Offset(0, 9).Value, _
r.Offset(0, 10).Value, r.Offset(0, 11).Value, _
r.Offset(0, 12).Value, r.Offset(0, 13).Value, _
r.Offset(0, 0).Value)
CmdForSave.Execute
Next r
The error I get is 'Incorrect Syntax near 'PIC'
What is wrong with my code? Iam using MS SQL Express (SQL 2012)
Thanks All,
I have figured it out why the problem is with space on the update SQL Statement.
The right statement using VBA (space before SET, space before WHERE):
SQLStr = _
"UPDATE People" & _
" SET PIC = '" & PIC & "', Customer = '" & Customer & "'" & _
" WHERE PeopleID = '" & PeopleID & "';"

Insert new records only into SQL Table Using VBA

I have an Excel workbook with the below code -
Sub Button1_Click()
Dim conn As New ADODB.Connection
Dim iRowNo As Integer
Dim sFirstName, sLastName As String
With Sheets("Sheet1")
'Open a connection to SQL Server
conn.Open "Provider=SQLOLEDB;" & _
"Data Source=server1;" & _
"Initial Catalog=table1;" & _
"User ID=user1; Password=pass1"
'Skip the header row
iRowNo = 2
'Loop until empty cell in CustomerId
Do Until .Cells(iRowNo, 1) = ""
sFirstName = .Cells(iRowNo, 1)
sLastName = .Cells(iRowNo, 2)
'Generate and execute sql statement
' to import the excel rows to SQL Server table
conn.Execute "Insert into dbo.Customers (FirstName, LastName) " & _
"values ('" & sFirstName & "', '" & sLastName & "')"
iRowNo = iRowNo + 1
Loop
MsgBox "Customers imported."
conn.Close
Set conn = Nothing
End With
End Sub
This opens up a connection to my database and inputs the values from the stated columns.
The primary key is an incremental key on the database. The problem is it will copy ALL values.
I'd like to add new rows of data into the Excel Sheet and only insert those rows that don't already exist.
I've tried different methods ('merge', 'if exist', if not exist', etc.) but I can't get it right.
The solution has to be through VBA. Setting up a link using SSMS is not an option.
I understand that it may be possible to use temporary tables and then trigger a procedure which performs the merge but I want to look into that as a last resort. Haven't read up on it yet (making my way through my MS SQL bible book) but I'm hoping it won't be necessary.
---Update from #Kannan's answer---
New portion of VBA -
conn.Execute "IF EXISTS (SELECT 1 FROM dbo.Customers WHERE FirstName = '" & sFirstName & "' and LastName = '" & sLastName & "') " & _
"THEN UPDATE dbo.customers SET WHERE Firstname = '" & sFirstName & "' and LastName = '" & sLastName & "' " & _
"ELSE INSERT INTO dbo.Customers (FirstName, LastName) " & _
"VALUES ('" & sFirstName & "', '" & sLastName & "')"
This returns error 'Incorrect syntax near the keyword 'THEN'.
Your SQL query isn't quite right - there is no THEN in a SQL IF.
Also, you don't need to do anything if it does exist, so just use if not exists.
"IF NOT EXISTS (SELECT 1 FROM dbo.Customers WHERE FirstName = '" & sFirstName & "' and LastName = '" & sLastName & "') " & _
"INSERT INTO dbo.Customers (FirstName, LastName) " & _
"VALUES ('" & sFirstName & "', '" & sLastName & "')"
This should do it for you.
Sub Button_Click()
'TRUSTED CONNECTION
On Error GoTo errH
Dim con As New ADODB.Connection
Dim rs As New ADODB.Recordset
Dim strPath As String
Dim intImportRow As Integer
Dim strFirstName, strLastName As String
Dim server, username, password, table, database As String
With Sheets("Sheet1")
server = .TextBox1.Text
table = .TextBox4.Text
database = .TextBox5.Text
If con.State <> 1 Then
con.Open "Provider=SQLOLEDB;Data Source=" & server & ";Initial Catalog=" & database & ";Integrated Security=SSPI;"
'con.Open
End If
'this is the TRUSTED connection string
Set rs.ActiveConnection = con
'delete all records first if checkbox checked
If .CheckBox1 Then
con.Execute "delete from tbl_demo"
End If
'set first row with records to import
'you could also just loop thru a range if you want.
intImportRow = 10
Do Until .Cells(intImportRow, 1) = ""
strFirstName = .Cells(intImportRow, 1)
strLastName = .Cells(intImportRow, 2)
'insert row into database
con.Execute "insert into tbl_demo (firstname, lastname) values ('" & strFirstName & "', '" & strLastName & "')"
intImportRow = intImportRow + 1
Loop
MsgBox "Done importing", vbInformation
con.Close
Set con = Nothing
End With
Exit Sub
errH:
MsgBox Err.Description
End Sub
Add a reference to:
Microsoft ActiveX Data Objects 2.8 Library
FYI, my sheet looks like this.
You can use sql query like this:
IF Exists ( Select 1 from dbo.customers where Firstname = '" & sFirstName & "' and LastName = '" & sLastName & "' THEN Update dbo.customers set --other columns where Firstname = '" & sFirstName & "' and LastName = '" & sLastName & "'
ELSE Insert into dbo.Customers (FirstName, LastName) " & _
"values ('" & sFirstName & "', '" & sLastName & "')"
Not sure about the syntax for excel and C#, you can correct that similar to this query

Excel DB connection: insert, update & delete? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I used the DATA-From Other Sources-From SQL Server controls to import a database table into my Excel workbook. It looks perfect, and refreshing data works like a charm.
However, whenever I make any changes to the table (editing, inserting or deleting rows), I cannot seem to find a way to push these changes to the database. This makes me wonder whether this is actually possible.
Can anybody tell me how to do this, or confirm that this is not supported?
When you make a 'live' table in Excel by linking to an external data source like you have described in this question, Excel manages this by using a QueryTable object behind the scenes.
QueryTable objects have the ability to be refreshed on demand, and to refresh on a periodic schedule defined by the user.
QuertyTable objects are NOT bi-directional. They can be used to import data into Excel, but not to write changes back to the data source.
QueryTable objects can be manipulated from VBA.
Custom VBA code can be written to automatically write to a data source any changes made by a user to a table. But this absolutely requires writing code... it is not a simple option that you can select from the Excel user interface for your table.
Can anybody tell me how to do this, or confirm that this is not supported?
Insert, update, and delete are not supported from the Excel user interface.
Since you didn't have an exact goal other than ,.. Can you, how to ? let me just dump my code that i KNOW works because i use it all the time. This is part of a custom ribbon that is on 20+ computer so they can update/merge their sales information into out database. This should help you out feel free to ask some questions. Basically how it works is creates SQL command, that creates a temp table then merge/updates against our database
Dim adoCN As ADODB.Connection
Dim sConnString As String
Dim sSQL, sSQLMerge As String
Dim Starting As Integer
''Find the starting point
For I = 1 To UBound(data, 2) - 1
If data(I, 0) <> "" Then
Starting = I
Exit For
End If
Next
'''This primes the temp table
'' into #tempTable " & vbCrLf
If LCase(CStr(data(Starting, 0))) = "null" Then
Else
sSQL = "select '" & replace(CStr(data(Starting, 0)), "'", "''") & "' as '" & _
replace(CStr(data(0, 0)), "'", "''") & "'"
End If
For I = 1 To UBound(data, 2) - 1
If LCase(replace(CStr(data(Starting, I)), "'", "''")) = "null" Then
sSQL = sSQL & ", '' as '" & _
replace(CStr(data(0, I)), "'", "''") & "'"
Else
sSQL = sSQL & ", '" & replace(CStr(data(Starting, I)), "'", "''") & "' as '" & _
replace(CStr(data(0, I)), "'", "''") & "'"
End If
Next
sSQL = sSQL & ", getdate() as 'UpdateDate', suser_sname() as 'UpdatedBy' into #tempTable " & vbCrLf
' this adds all the data to the temp table
For I = Starting + 1 To UBound(data, 1)
If replace(CStr(data(I, 0)), "'", "''") = "" Then 'Checks to see ifs it has prop id, if not skip
Else
If LCase(replace(CStr(data(I, 0)), "'", "''")) = "null" Then 'checks to see if null if so add blank
sSQL = sSQL & "union Select ''"
Else
sSQL = sSQL & "union Select '" & replace(CStr(data(I, 0)), "'", "''") & "'" 'if not null add value
End If
For II = 1 To UBound(data, 2) - 1
If LCase(replace(CStr(data(I, II)), "'", "''")) = "null" Then
sSQL = sSQL & ", ''"
Else
sSQL = sSQL & ", '" & replace(CStr(data(I, II)), "'", "''") & "'"
End If
Next
sSQL = sSQL & ", getdate(), suser_sname() " & vbCrLf
End If
Next
'GuidanceInputForm.SellerConditioning.Text = sSQL
''UserForm1.Label1.Caption = Len(sSQLMerge)
'GuidanceInputForm.Show
''Add Merge code
sSQLMerge = "Merge CommercialSandbox..MasterDataTape as t" & vbCrLf & _
" Using #temptable as S on (replace(t.[Property ID], '-','') = replace(s.[Property ID], '-','') and replace(t.[Event ID], '-','') = replace(s.[Event ID], '-','')) " & vbCrLf & _
" When NOT MATCHED BY TARGET THEN INSERT([" & data(0, 0) & "]"
For I = 1 To UBound(data, 2) - 1
sSQLMerge = sSQLMerge & ", [" & data(0, I) & "]"
Next
sSQLMerge = sSQLMerge & ", UpdateDate, UpdatedBy"
sSQLMerge = sSQLMerge & ") VALUES (s.[" & data(0, 0) & "]"
For I = 1 To UBound(data, 2) - 1
sSQLMerge = sSQLMerge & ", s.[" & data(0, I) & "]"
Next
sSQLMerge = sSQLMerge & ", s.UpdateDate, s.UpdatedBy"
sSQLMerge = sSQLMerge & ") " & vbCrLf & _
" When MATCHED THEN UPDATE SET t.[" & data(0, 0) & "] = s.[" & data(0, 0) & "]"
For I = 1 To UBound(data, 2) - 1
sSQLMerge = sSQLMerge & ", t.[" & data(0, I) & "] = s.[" & data(0, I) & "]"
Next
sSQLMerge = sSQLMerge & ", t.UpdateDate = s.UpdateDate, t.UpdatedBy = s.UpdatedBy"
sSQLMerge = sSQLMerge & ";"
'GuidanceInputForm.SellerConditioning.Text = sSQLMerge
''UserForm1.Label1.Caption = Len(sSQLMerge)
'GuidanceInputForm.Show
sConnString = "Provider=sqloledb;Server=ERPT01LAX01US.prod.auction.local\EDWALT;Database=Commercialsandbox;Integrated Security = SSPI"
Set adoCN = CreateObject("ADODB.Connection")
adoCN.CommandTimeout = 0
adoCN.Open sConnString
adoCN.Execute sSQL
adoCN.Execute sSQLMerge
adoCN.Close

Resources