How do you UPDATE SQL Table from Excel Table using VBA JOIN - sql

I've read through postStackoverflow 14814098 and would like to know (2) things.
Can you update MS SQL Tables from Excel by creating a string with an Update statement that refers to an Excel Table. Below is a rough idea in VBA of what I mean.
If you add the SQL Statement to the server, how do you call it from Excel using VBA?
Background: I'm attempting to pull a table from the MS SQL Server, Load results into Excel Sheet as an Excel Table where I can exit the sheet and Update all changes back to the server table.
I set up a class and worksheet module to update the server after individual cells are changed in the worksheet, but now I would like to update all the changes at once.
Is there a better way to go about getting the result?
Sub UpdateSqlWithExcelTableJoin()
Dim cmd As ADODB.Command
Dim strSQL As String
Set cnn = New ADODB.Connection
cnn.ConnectionString = "DRIVER=SQL Server;SERVER=MYSERVERNAME;DATABASE=MYDATABASENAME;Trusted_Connection=Yes"
Set cmd = New ADODB.Command
cnn.Open
cmd.ActiveConnection = cnn
cmd.CommandType = adCmdText
Call setString2
cmd.CommandText = strSQLUpdate
cmd.Execute
cnn.Close
Set cmd = Nothing
Set cnn = Nothing
End Sub
Sub setString2()
strSQLUpdate = _
"Update test.profile " & vbNewLine & _
"Set test.profile.Field = ExcelTable.Field " & vbNewLine & _
" test.profile.Profile_Name = ExcelTable.Profile_Name " & vbNewLine & _
"From test.profile " & vbNewLine & _
"INNER JOIN OPENROWSET('MICROSOFT.JET.OLEDB.4.0', 'Excel 8.0;Database=C:\Users\USERNAME\ONEDRIVE - FOLDER\SQL_VBA_b.xlsm;', 'Select ID, Profile_Name' " & vbNewLine & _
"From '[Sheet3$]') As ExcelTable " & vbNewLine & _
"ON test.profile.ID = ExcelTable.ID " & vbNewLine & _
"WHERE (test.profile.ID = ExcelTable.ID " & vbNewLine & _
" AND test.profile.Profile_Name = ExcelTable.Profile_Name)"
Debug.Print strSQLUpdate
End Sub

I always found this to be easier to run this through an MS-Access connection than to connect directly to SQL Server.
Set up an Acess data base with two ODBC connections. A. Define the Excel data as a table to Access. B. Define the SQL Server table as a table to Access.
In Excel VBA change your ADOdb connection to connect to the Access db.
Now you can run a single update statement in ODBC SQL that looks like this:
Update SQLServerTable
Set SQLServerColumn = ExcelColumn
From SQLServerTable S
Inner Join ExcelTable E
Where sqlServerkey = ExcelKey
This is more flexible than trying to do it directly because if the update relationship grows more complex you can always code the FROM clause as an Access saved query, and that is the only good way to do nested queries in ODBC (queries that use other queries in FROM).

You can't use select at that position it will always take the whole sheet.
Also you are missing a comma after Field
Update test.profile
Set test.profile.Field = ExcelTable.Field,
test.profile.Profile_Name = ExcelTable.Profile_Name
From test.profile
INNER JOIN OPENROWSET('MICROSOFT.JET.OLEDB.4.0', 'Excel 8.0;Database=C:\Users\USERNAME\ONEDRIVE - FOLDER\SQL_VBA_b.xlsm;', [Sheet3$]) As ExcelTable
ON test.profile.ID = ExcelTable.ID
WHERE (test.profile.ID = ExcelTable.ID
AND test.profile.Profile_Name = ExcelTable.Profile_Name)

ado to retrieve records from SQL
save excel file
add excel file and SQL Table in Access
create Update Query using linked tables (sql and excel)
Open workbook / update data / close workbook / run query.

Related

Run-Time Error 3146 - VBA Access Execute Stored Procedure - Cursor state(#0)

I am getting an error code (3146: ODBC-call failed - Invalid cursor state (#0) on my local machine using Microsoft Access 365, but it works in our remote desktop environment using 2016 Access Professional Plus.
After reading this post, I set my ODBC timeout to 2000 in the query's property sheet, but still, get the same error and it only takes about 10 seconds to throw.
I also read that there were issues with the cursor state in an earlier version of Access 2016 and not sure if that is a problem with Office 365?
This subroutine has worked for years without any issues. It looks like it is tied to Office 365.
Any ideas?
The code errors on this line
DoCmd.OpenQuery "qryImportGMSData" 'Creates tempTable with Weekly Import from GMS
Below is my subroutine
Sub GMSImport(StartDate As Date, EndDate As Date)
Dim SqlStr As String
Dim db As DAO.Database
Set db = CurrentDb()
'Builds query string for stored procedure maintained by SWDev from GMS to show Weekly Deals for report.
SqlStr = "EXEC dbo.upRpt_WeeklyDealsReport #BeginDate = '" & Format(StartDate, "yyyy-mm-dd") & "' ," & _
" #EndDate = '" & Format(EndDate, "yyyy-mm-dd") & "' ," & _
" #RegionType_Short_List = 'CA~GC~MC~MW~SW~WE~NE' ," & _
" #IncludeBulletDeals = 0 ," & _
" #FormatType = 'spgexporttype'"
db.QueryDefs("ptqry_DataExport").sql = SqlStr 'sets the parameters for the stored procedure
DoCmd.SetWarnings False
DoCmd.OpenQuery "qryImportGMSData" 'Creates tempTable with Weekly Import from GMS
DoCmd.RunSQL "ALTER TABLE temp_GMSImport ADD COLUMN Selected BIT" 'Add Selected Column to temp table
DoCmd.RunSQL "ALTER TABLE temp_GMSImport ADD COLUMN dvsValuationDef_ID INT" 'Adds Valuation Def Column to temp table
DoCmd.RunSQL "UPDATE temp_GMSImport SET temp_GMSImport.Selected = -1;" 'Sets all Selected field to TRUE
DoCmd.SetWarnings True
End Sub
It errors out on this line:
DoCmd.OpenQuery "qryImportGMSData" 'Creates tempTable with Weekly Import from GMS
I am able to execute the stored procedure in SMSS with no issues:
"EXEC dbo.upRpt_WeeklyDealsReport #BeginDate = '" & Format(StartDate, "yyyy-mm-dd") & "' ," & _
" #EndDate = '" & Format(EndDate, "yyyy-mm-dd") & "' ," & _
" #RegionType_Short_List = 'CA~GC~MC~MW~SW~WE~NE' ," & _
" #IncludeBulletDeals = 0 ," & _
" #FormatType = 'spgexporttype'"
When I test by 64 bit ODBC connection, it test successfully.
Update -more testing inside Access:
I was able to execute the T-SQL code inside Access without using VBA.
There are 3 queries involved in the sequence and the one that is not working is qryImportGMSData. It is a problem without using VBA, so that narrows it down a bit.
qryImportGMSData
Query: Make Table Query (Replicated)
This one is causing the error
SELECT * INTO temp_GMSImport
FROM qryImportTransform;
qryImportTransform
Query: Select Query (Replicated) Works
SELECT *
FROM ptqry_DataExport;
Ptqry_DataExport
SQL Pass-Through Query (Replicated) Works
EXEC dbo.upRpt_WeeklyDealsReport #BeginDate = '2021-02-22' , #EndDate = '2021-02-28' , #RegionType_Short_List = 'CA~GC~MC~MW~SW~WE~NE' , #IncludeBulletDeals = 0 , #FormatType = 'spgexporttype'
Ok, so we narrowed down that the PT query can work from Access.
We are likely dealing with two different connections - so there is a "wee bit" of asynchronous (threading) occurring here.
If not already, use the SAME connection object to run all 3 query.
So, use this:
db.Execute "qryImportGMSData",dbFailOnError
db.Execute "ALTER TABLE temp_GMSImport ADD COLUMN Selected BIT", dbFailOnError
db.Execute "ALTER TABLE temp_GMSImport ADD COLUMN dvsValuationDef_ID INT"
db.Execute "UPDATE temp_GMSImport SET temp_GMSImport.Selected = -1;",dbFailOnError
The other BIG advantage is above is faster, does NOT mess with the Access "UI" settings, and you don't have to change setwarnings.
And the above does NOT force access to try and use "transactions".
So, the problem is we using two different connections, you using "db", and then using the docmd which is a "separate" connection - and you can't control this much.
With two connection objects, it "almost" similar to two people running the two different parts of the code.
Give the above a try - stick to "one" connection object, so they can "behave" as a similar group of commands. And as noted, dumping docmd has several downsides, and is more attached to the Access "UI" options then it is to pure code.

Access Error 3141

I am trying to set recordset for a report using the following query:
Dim RS As Recordset
Set RS = CurrentDb.OpenRecordset("Select DISTINCT SalesOrders.SalesOrderNumber, Vendors.Name, SalesOrders.OrderDate, SalesOrders.Grade, SalesOrders.QuantityUOM, SalesOrders.PortOfDischarge, SalesOrders.Quantity, IIf([SalesOrders.DTHCIncludedYN],'DTHC INCLUDED','DTHC NOT INCLUDED') AS DTHCIncludedYN," & _
" SalesOrders.DeliveryTerms, SalesOrders.SalesOrderID, SalesOrders.GenesisDocumenationAssistant, Products.ProductLoadPorts, Customers.CustomerType, SalesOrders.UnitPriceUOM, SalesOrders.UnitPrice, Customers.CustomerName, Products.ProductName, SalesOrders.PaymentTerms, SalesOrders.PlaceOfDelivery, SalesOrders.SalesCommission, SalesOrders.LatestShipDate, [SalesOrders.Quantity]*[UnitPrice] AS Amount," & _
" IIf([AdvisingBank]='GEB','GREAT EASTERN BANK',IIf([AdvisingBank]='BOC','BANK OF CHINA',IIf([AdvisingBank]='CB','CATHAY BANK',IIf([AdvisingBank]='HSBC','HSBC Bank USA',IIf([AdvisingBank]='COM','COMMERCE BANK'))))) AS [Bank Name]," & _
" IIf([CCICType]= '1','ONE ORIGINAL INSPECTION CERTIFICATE ISSUED BY CCIC NORTH AMERICA INC','ONE ORIGINAL PRESHIPMENT INSPECTION CERTIFICATE ISSUED BY ANY CCIC EUROPEAN OFFICE') AS [CCIC-Clause]," & _
" IIf([OnCarriageIncluded],'ON CARRIAGE INCLUDED','ON CARRIAGE NOT INCLUDED') AS OCIText, IIf(IsNull([PlaceOfDelivery]),[PortOfDischarge],[PlaceOfDelivery]) AS PODText, Vendors.AB1AddressLine1, Vendors.SupplierLocation AS [Swift Code], " & _
" IIf(IsNull(AdvisingBank),' ','TEL ' & [Vendors.AB1Phone] & ', ' & 'FAX ' & [Vendors.AB1Fax]) AS [Contact Details], IIf(IsNull(AdvisingBank),'',Vendors.AB1AddressLine1 & ', ' & [Vendors.AB1City] & ', ' & [Vendors.AB1State] & ' ' & [Vendors.AB1Zip] & ' ' & [Vendors.AB1Country]) AS AddressLine," & _
" FROM (Products INNER JOIN (Customers INNER JOIN SalesOrders ON Customers.CustomerID = SalesOrders.CustomerID) ON Products.Grade = SalesOrders.Grade) LEFT JOIN Vendors ON SalesOrders.AdvisingBank = Vendors.VendorID " & _
" WHERE (SalesOrders.SalesOrderNumber= Forms!frmPrintContracts!txtGreenSales AND ((Customers.CustomerType)='GREEN' Or (Customers.CustomerType)='GREEN-JC' Or (Customers.CustomerType)='GREEN-DL' Or (Customers.CustomerType)='SIHU' Or (Customers.CustomerType)='PAPYRUS'))ORDER BY SalesOrders.SalesOrderNumber DESC ")
I am getting error saying that I have used reserved keyword or there is a punctuation mistake. Can anyone help me figure out what the error is.
Any help is appreciated. Thank you
Consider saving your SQL statement as an Access stored query and not VBA string for the following reasons:
All syntax errors are checked before you save. You cannot save via the MS Access query design GUI a non-compilable query.
Stored Access queries are more efficient than VBA string queries as the database engine saves the best execution plan for stored queries and cannot when called on the fly in VBA.
You can set a saved query to most Access objects (comboboxes or listboxes row sources, form or report recordsources) with less code.
Me.cboText.RowSource = "myStoredQuery"
Me.cboText.RowSourceType = "Table/Query"
Me.cboText.Requery
Me.Form.RecordSource = "myStoredQuery"
Me.Form.Requery
Your application code is more readable and maintainable as you avoid the VBA string concatenation. Plus, you abstract away the special-purpose nature of SQL from your application layer code.
Dim RS As Recordset
Set RS = CurrentDb.OpenRecordset("myStoredQuery")
The industry standard of parameterization is easier to achieve with stored queries which can serve as a prepared statement. If you ever need to pass VBA variable values for dynamic querying, you can parameterize stored queries with PARAMETERS clause and querydefs all while still using stored queries. See example below:
Stored Query
PARAMETERS [myParam] Date;
SELECT DISTINCT SalesOrders.SalesOrderNumber
FROM SalesOrders
WHERE SalesOrders.OrderDate = [myParam]
VBA
Dim qdef As QueryDef
Dim RS As Recordset
Set qdef = Currentdb.QueryDefs("myStoredQuery")
qdef!myParam = Date()
Set RS = qdef.OpenRecordset()

Getting user ID from a Spreadsheet and Access database

Why is this code not working? Sorry for the generic question....
I am tasked with generating reports with reference information that needs to be drawn from an access database and an excel spreadsheet.
Basically in my role I'm responsible for providing service to people who live in a community; the record of all the people I provide service for is contained in an access database. There's reference information; address, name, situation, and other information needed for regular reports to funders or the board of directors.
I also provide service to local businesses; this information is contained within a spreadsheet, and not a database. The information could be put into a relational database, with the two related together; but there is resistance at the organization for significant changes to the system, nor is there really the knowledge of how to do this.
So I'm trying to move forward with a spreadsheet - if I provide service to person A or organization B, that this spreadsheet will check both the access database, and the excel spreadsheet to see whether that person or organization is entered; if it is, it should populate a table with that information, and assign it a unique code.
The unique code is determined on the basis of the database; whether or not the person or organization has been entered into the database before.
The spreadsheet I am working at the base with is this:
The bottom table I am looking to be a 'lookup' table. Its name is Lookup. The code I want to run with it looks like this (but obv not is this):
Sub getUserID()
Dim myTable As ListObject
Set myTable = Sheets("Client Codes").ListObjects("Lookup")
If myTable.ListRows.Count >= 1 Then
myTable.DataBodyRange.Delete
End If
With Sheets("Client Codes").ListObjects("Lookup").Add(SourceType:=0, Source:=Array(Array("ODBC;DSN=MS Access Database;DBQ=C:\database\here\test.accdb;DefaultDir=F:\Housing;DriverId=25;FIL=MS Access;MaxBufferSize=2048;PageTimeo"), Array("ut=5;")), Destination:=myTable.Range(Cells(1, 1)))
.CommandText = Array("SELECT Clients.ID, Clients.LastName, Clients.FirstName " & Chr(13) & "" & Chr(10) & "FROM `C:\database\here\test.accdb`.Clients Clients" & Chr(13) & "" & Chr(10) & "WHERE (Clients.LastName='" & Range("b1").End(xlDown) & "') AND (Clients.FirstName='" & Range("c1").End(xlDown) & "')")
End With
With Sheets("Client Codes").ListObjects("Lookup").Add(SourceType:=0, Source:=Array(Array("ODBC;DSN=Excel Files;DBQ=C:\spreadsheet\here\text.xlsx;DefaultDir=c:\spreadsheet;DriverId=1046;MaxBufferSize=2"), Array("048;PageTimeout=5;")), Destination:=myTable.Range(Cells(1, 1)))
.CommandText = Array("SELECT `Businesses$`.Operation" & Chr(13) & "" & Chr(10) & "FROM `C:\spreadsheet\here\test.xlsx`.`Businesses$` `Businesses$`" & Chr(13) & "" & Chr(10) & "WHERE (`Businesses$`.Operation='" & Range("b1").End(xlDown) & "')")
End With
End Sub
The hope is to be able to query the database on the basis of either a persons first and last name, or to query the spreadsheet on the basis of organization name; and if there is a value that is found, to add some information to the table 'Lookup'. If nothing is found, then I will know its a new entry, and enter in the information as such.
For reference, the database has 3 fields (ID, LastName, FirstName); and the spreadsheet has 1 column (Operation).
Really the confusion is focused here:
How to 'add' the information based on a query to the listobject to a pre-existing table
How to do this both with an access database and an Excel spreadsheet
Any suggestions on other ways how this can be done would be appreciated; pull information from multiple data sources into one table so that it can be validated in that table.
EDIT: If I did this through Access or another database program, I would do an INNERJOIN on two tables; one of people, the other of businesses. I'm looking to keep excel though - I find it to be more user friendly.
EDIT: Code based on Ian's response....generates the following error message:
'run time error -2147467259, could not find installable ISAM'
Research on the internet seems to indicate the following:
1) People have gotten this error before
2) There might not be a proper DLL installed - not certain this is the case, because I'm trying to access access from excel, and it doesn't seem like there is a DLL for access here: https://support.microsoft.com/en-us/kb/209805
3) There might be issue of how the connection string is framed. The data source might need to be in quotes, the JET OLEDB needs to be used not ACE, the connection string needs to be extended to include 'extended properties' here: Error: "Could Not Find Installable ISAM"
The last one is obviously the biggest target (and has the most error about it).
Option Explicit
Sub getUserID()
Dim cmd As New ADODB.Command
Dim conn As New ADODB.Connection
Dim rs As New ADODB.Recordset
Dim strConn As String
Dim strSQL As String
Dim firstName As String
Dim lastName As String
firstName = "John"
lastName = "Smith"
strConn = "Provider = Microsoft.ACE.OLEDB.12.0;'DataSource=F:\Housing\bpTest.accdb'"
conn.Open strConn
strSQL = "SELECT * FROM Table Where FirstName = '" & firstName & "' AND LastName = '" & lastName & "';"
'& ... ' or You could put your InnerJoin SQL here
rs.Open strSQL, conn, adOpenDynamic, adLockOptimistic
If rs.EOF Then 'If the returned RecordSet is empty
MsgBox ("No record found")
Else
MsgBox (rs.Index)
End If
end sub
You will most like want to use ActiveX Data Objects to accomplish this. This will let you to pull data from the access database and also update the records in the access database from Excel.
Here is the Microsoft reference material: https://msdn.microsoft.com/en-us/library/ms677497(v=vs.85).aspx
And some sample code:
Dim cmd As New adodb.Command
Dim conn As New adodb.Connection
Dim rs As New adodb.Recordset
Dim strConn As String
strConn = "Provider = Microsoft.ACE.OLEDB.12.0;" _
& "Data Source=C:\AccessDatabse.accdb"
conn.Open strConn
strSQL = "SELECT * FROM Table Where FristName =" & strName & ... ' or You could put your InnerJoin SQL here
rs.Open strSQL, conn, adOpenDynamic, adLockOptimistic
If rs.EOF then 'If the returned RecordSet is empty
'...there is no match in database
Else
'the rs object will hold the ID you are looking for
End If
you can add a new records to the Access Database with:
myFieldList = Array("ID", "FirstName", "LastName")
myValues = Array(IDValue, FirstNameValue, LastNameValue)
rs.AddNew myFieldList, myValues

How to run parameterized query from VBA. Parameters sourced from recordset

I have a form where a user selects a vendor's name from a combobox, whose catalog file is to be imported. The combobox selection then drives a query to create a one-record recordset (rsProfile) containing several profile variables queried from a table of all vendor profiles. These variables are then used in a series of different queries to reformat, translate and normalize the vendor's uniquely structured files to a standardized format that can be imported into our system.
I am frustrated that I can't figure out how to build my stored queries that will use one or more parameters that are automatically populated from the profile recordset.
Here is my rsProfile harvesting code. It works. Note that intVdrProfileID is a global variable set and used in other places.
Private Sub btn_Process_Click()
Dim ws As Workspace
Dim db, dbBkp As DAO.Database
Dim qdf As DAO.QueryDef
Dim rsProfile, rsSubscrip As Recordset
Dim strSQL As String
Dim strBkpDBName As String
Dim strBkpDBFullName As String
strBkpDBName = Left(strVdrImportFileName, InStr(strVdrImportFileName, ".") - 1) & "BkpDB.mdb"
strBkpDBFullName = strBkpFilePath & "\" & strBkpDBName
Set db = CurrentDb
Set ws = DBEngine.Workspaces(0)
MsgBox ("Vendor Profile ID = " & intVdrProfileID & vbCrLf & vbCrLf & "Backup file path: " & strBkpFilePath)
' Harvest Vendor Profile fields used in this sub
strSQL = "SELECT VendorID, Div, VPNPrefix, ImportTemplate, " & _
"VenSrcID, VenClaID, ProTyp, ProSeq, ProOrdPkg, ProOrdPkgTyp, JdeSRP4Code, " & _
"PriceMeth, " & _
"ProCost1Frml, ProCost2Frml, " & _
"ProAmt1Frml, ProAmt2Frml, ProAmt3Frml, ProAmt4Frml, ProAmt5Frml " & _
"FROM tZ100_VendorProfiles " & _
"WHERE VendorID = " & intVdrProfileID & ";"
Set qdf = db.QueryDefs("qZ140_GetProfileProcessParms")
qdf.SQL = strSQL
Set rsProfile = qdf.OpenRecordset(dbOpenSnapshot)
DoCmd.OpenQuery "qZ140_GetProfileProcessParms"
' MsgBox (qdf.SQL)
I have used QueryDefs to rewrite stored queries at runtime, and although it works, it is quite cumbersome and does not work for everything.
I was hoping for something like the sample below as a stored query using DLookups. I can get this to work in VBA, but I can't get anything to work with stored queries. I am open to other suggestions.
Stored Query "qP0060c_DirectImportTape":
SELECT
DLookUp("[VPNPrefix]","rsProfile","[VendorID]=" & intVdrProfileID) & [PartNo] AS VenPrtId,
Description AS Des,
DLookup("[Jobber]","rsProfile",[VendorID=" & intVdrProfileID) AS Amt1,
INTO tP006_DirectImportTape
FROM tJ000_VendorFileIn;
ADDENDUM:
Let me adjust the problem to make it a bit more complex. I have a collection of about 40 queries each of which use a different collection of parameters (or none). I also have a table containing the particular set of queries that each vendor 'subscribes' to. The goal is to have a database where a non-coding user can add new vendor profiles and create/modify the particular set of queries which would be run against that vendor file. I have almost 100 vendors so far, so coding every vendor seperately is not practical. Each vendor file will be subjected to an average of 14 different update queries.
Simplified Example:
Vendor1 file needs to be processed with queries 1, 2 and 5. Vendor2 file might need only update queries 2 and 4. The parameters for these queries might be as follows:
query1 (parm1)
query2 (parm1, parm4, parm8, parm11)
query4 (parm5, parm6, parm7, parm8, parm9, parm10, parm11)
query5 () -no parms required
This is the core query processing that loops through only the queries relevant to the current vendor file. rsSubscrip is the recordset (queried from a master table) containing this filtered list of queries.
' Run all subscribed queries
MsgBox "Ready to process query subscription list."
With rsSubscrip
Do While Not .EOF
db.Execute !QueryName, dbFailOnError
.MoveNext
Loop
.Close
End With
You can set the parameters of a predefined query using the syntax;
Set qdf = CurrentDB.QueryDefs(QueryName)
qdf.Parameters(ParameterName) = MyValue
To add parameters to the query, add the following before the SELECT statement in the sql
PARAMETERS [ParameterOne] DataType, [ParameterTwo] DataType;
SELECT * FROM tblTest;

INSERT data from Excel into SQL DB

I have created an Excel Sheet that does some lookups to format data that needs to be inserted into another table. This Excel Workbook needs to be given to some users that are free to add some new rows, and then need to be able to hit an "Insert Into Database" button and have the records transformed and inserted as new records into a SQL Table. I am using Excel 2010 and SQL Server 2008. I have a connection to the DB as I am using it to pull some data back in order to verify the new rows being added, but I'm not sure how to then insert the data back.
You can do a lot with ADO:
Dim cn As New ADODB.Connection
''You should probably change Activeworkbook.Fullname to the
''name of your workbook
strCon = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" _
& ActiveWorkbook.FullName _
& ";Extended Properties=""Excel 8.0;HDR=Yes;IMEX=1"";"
cn.Open strCon
s = "INSERT INTO [ODBC;Description=TEST;DRIVER=SQL Server;" _
& "SERVER=Server;Trusted_Connection=Yes;" _
& "DATABASE=test].SomeTable ( Col1, Col2, Col3, Col4 ) " _
& "SELECT a.Col1, a.Col2, a.Col3, a.Col4 " _
& "FROM [Sheet2$] a " _
& "LEFT JOIN [ODBC;Description=TEST;DRIVER=SQL Server;" _
& "SERVER=Server;Trusted_Connection=Yes;" _
& "DATABASE=test].SomeTable b ON a.Col1 = b.Col1 " _
& "WHERE b.Col1 Is Null"
cn.Execute s
You can also use the ACE connection: http://www.connectionstrings.com/ or OPENROWSET and an SQL Server connection. In all cases, you may have problems with mixed data types in columns, depending on your registry settings (http://forum.lessthandot.com/viewtopic.php?f=17&t=12043&p=59669&hilit=excel#p59669)
I have found out that within a macro, you can create an ADO connection by adding a reference to the "Microsoft ActiveX Data Objects 6.0 Library". Once you have opened a connection within the Macro, you can create your insert statement and execute it via using the connection.Execute(statement) method:
Dim item as String = "Insert Into MyTable(ColA,ColB) VALUES('Foo', 'Bar')"
Dim thisCon As New ADODB.Connection
thiscon.Open("ConnectionString")
thisCon.Execute (item)
After modifying the data in excel, need to generate Update statements, which will be executed by pressing the button "update". As a result, will be executed Update and Insert statements. Then have to send a query to refresh the data in Excel.(imho)