0

I am trying to configure an SQL UPDATE query in a VBA program.

Basically, I update a table in the current workbook from a table in a closed workbook. This works great using the below query only if the source workbook is a .xls file :

Sub UPDATEQUERY(SourcePath As String, SourceSheet As String, TargetSheet As String, _
Columns As String, Filter As String)

    Dim Cn As ADODB.Connection
    Dim QUERY_SQL As String
    Dim CHAINE_HDR As String
    Dim STRCONNECTION As String

    CHAINE_HDR = "[Excel 8.0;Provider=Microsoft.ACE.OLEDB.12.0;Mode=1;Extended Properties='HDR=YES;'] "

    Set Cn = New ADODB.Connection

    QUERY_SQL = _
    "UPDATE [" & TargetSheet & "$] INNER JOIN (SELECT * FROM [" & SourceSheet & "$] " & _
    "IN '" & SourcePath & "' " & CHAINE_HDR & ") t2 " & _
    "ON [" & TargetSheet & "$].id = t2.id " & _
    "SET [" & TargetSheet & "$].ColA = t2.ColA "

    STRCONNECTION = _
    "Driver={Microsoft Excel Driver (*.xls)};" & _
    "DriverId=790;" & _
    "Dbq=" & ThisWorkbook.FullName & ";" & _
    "DefaultDir=" & ThisWorkbook.FullName & ";ReadOnly=False;"


    Cn.Open STRCONNECTION
    Cn.Execute (QUERY_SQL)

    '--- Fermeture connexion ---
    Cn.Close
    Set Cn = Nothing

End Sub

So as to use .xlsx file as the source file I want to connect to the source using the same provider/driver that I use to connect to the current wb, that is MSDASQL.1 instead of Microsoft.ACE.OLEDB.12.0. Indeed If I only set the 'CHAINE_HDR' to Excel 12.0 I get a "ISAM driver not found".

To achieve this I'm trying to use OPENROWSET like this :

Sub UPDATEQUERY(SourcePath As String, SourceSheet As String, TargetSheet As String, _
Columns As String, Filter As String)

    Dim Cn As ADODB.Connection
    Dim QUERY_SQL As String
    Dim STRCONNECTION As String
    Dim STRCONNECTION_SOURCE As String


    STRCONNECTION_SOURCE = _
    "'MSDASQL.1'," & _
    "'Driver={Microsoft Excel Driver (*.xls)};DriverId=790;Dbq=" & SourcePath & ";'," & _
    "'SELECT * FROM [Data$]'"

    Set Cn = New ADODB.Connection

    QUERY_SQL = _
    "UPDATE [" & TargetSheet & "$] INNER JOIN (SELECT * FROM OPENROWSET(" & STRCONNECTION_SOURCE & ")) t2 " & _
    "ON [" & TargetSheet & "$].id = t2.id " & _
    "SET [" & TargetSheet & "$].ColA = t2.ColA "

    STRCONNECTION = _
    "Driver={Microsoft Excel Driver (*.xls)};" & _
    "DriverId=790;" & _
    "Dbq=" & ThisWorkbook.FullName & ";" & _
    "DefaultDir=" & ThisWorkbook.FullName & ";ReadOnly=False;"


    Cn.Open STRCONNECTION
    Cn.Execute (QUERY_SQL)

    '--- Fermeture connexion ---
    Cn.Close
    Set Cn = Nothing

End Sub

However I get an "Synthax error in from clause".

How to properly set up my sql query ?

Thanks

Parfait
  • 104,375
  • 17
  • 94
  • 125
Lich4r
  • 1,305
  • 2
  • 13
  • 27

1 Answers1

1

First, OPENROWSET is a Microsoft SQL Server method (i.e., TSQL) which your link references. Such queries would only run inside an SQL Server query. It is not a Jet/ACE SQL Engine (which you are currently using) method. So you are getting your databases mixed up. As analogy, Oracle methods would not work in Postgres databases.

And yes, the ACE 12.0 provider can connect to both older .xls and current .xlsx files, just as it can with older MS Access (Office sibling to MS Excel) .mdb and current .accdb files. Simply change the versions: Excel 8.0; to Excel 12.0 Xml;.

In fact, you do not even need to specify the Provider in the inline SQL commands by using the following format:

...INNER JOIN [Excel 12.0 Xml;HDR=Yes;Database=C:\Path\To\Excel\File.xlsx].[SHEETNAME$]

With MS Access (highly advised for database needs, and available on all Windows machines, regardless of MSAccess.exe app install or not), you would not need to specify Excel parameters:

...INNER JOIN [C:\Path\To\Access\File.mdb].[TABLENAME]

...INNER JOIN [C:\Path\To\Access\File.accdb].[TABLENAME]
Parfait
  • 104,375
  • 17
  • 94
  • 125
  • The problem is if I use your inner join and still my connection string (STRCONNECTION) with MSDQSL I get a 'ISAM driver not found'. The real reason I'm using this provider instead of ACE is because ACE generate the following error : "you cannot edit this field because it resided in a linked Excel spreadsheet." From what I read I needed to replace ACE by the old one ie MSDASQL.1. My connection string is not compatible with the 'Excel 12.0' one for the source file. If I use `{Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)}` I also get the linked excel spreadsheet error. – Lich4r Oct 28 '17 at 17:48
  • Then simply keep original syntax as is and change the versions: `Excel 12.0 Xml;`. Sorry I never run update queries on workbooks and do not want to stray down that path as Excel is not a database. – Parfait Oct 28 '17 at 17:52
  • By the way, ACE is the engine used here to connect to workbooks, while OLEDB Providers and ODBC Drivers are the APIs to connect to it. They are complementary and not substitute softwares. And ACE.12.0 should connect to .xlsx files. The older Jet 4.0 was restricted to .xls files. – Parfait Oct 28 '17 at 17:52
  • I'm not using excel as a database. SQL query are just so much faster and enable to retrieve/send data without opening large wb. As I said I cannot only change the version to `Excel 12.0 Xml;` because it raises this error : "Could not find installable ISAM" – Lich4r Oct 28 '17 at 18:00
  • Same error. I could avoid the error by setting `{Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)}` but then I have "You cannot edit this field because it resides in a linked Excel spreadsheet. The ability to edit data in a linked Excel spreadsheet has been disabled in this Access release." while I'm not using Access or a linked Excel ws. – Lich4r Oct 29 '17 at 10:39
  • I add this [question](https://stackoverflow.com/questions/47001575/ado-error-message) on this specific point. – Lich4r Oct 29 '17 at 14:58