Использование VBA-Excel для запроса SQL по нескольким базам данных
Использование Excel 2010, SQL и DAO
Я пытаюсь выполнить запрос к таблицам, которые находятся за пределами текущей электронной таблицы. Это было бы тривиально, внутри Access, со связанными таблицами / базами данных, но использование VBA в Excel, я поставил в тупик.
Предполагая это:
ExcelFileOne; Tab; various headed field/columns
ExcelFileTwo; Tab; various headed field/columns
Я хочу выполнить запрос в третьем файле Excel, который выглядит примерно так [с использованием точечной нотации для объяснения, а не кодирования....] - простой пример:
SELECT FileOne.[Tab$].Fields, FileTwo.[Tab$].Fields, etc.
FROM FileOne, FileTwo, Thisworkbook
WHERE (FileOne.[Tab$].field2 <> FileTwo.[Tab$].Field2)
AND (ThisWorkbook.[Tab$].Field1 ....)
По сути, я хочу дублировать то, что Access будет делать изначально для этого связанного файла.
Указатели в правильных направлениях?
[[Я мог бы использовать указатель на то, почему использование "Excel 8.0..." в соединении работает или не удается в Excel2010 с макро-файлами, и как загрузить вариант 12 или 14 в сети / системе, закрытой для пользователей.... ]]
1 ответ
Вы действительно можете запрашивать другие книги, используя DAO и ADO непосредственно в операторе SQL, а также запрашивать таблицы доступа к базам данных, просто ссылаясь на их пути. И наоборот, в запросе Access вы можете запросить книги Excel! Это свидетельствует о том, что ядро Jet/ACE SQL (файлы Windows .dll) не ограничивается каким-либо одним продуктом MS Office или программой Windows, а является инструментом для всех.
В обоих приведенных ниже примерах макросы устанавливают прямое соединение с первой книгой, а в запросе SQL каждый косвенно связывается со второй книгой. Вы можете запускать код внутри или вне рабочих книг. Также оба работает по генрику INNER JOIN
на листах FileOne и FileTwo, но любой совместимый оператор Jet/ACE SQL должен работать. И оба выходных запроса приводят к существующей вкладке РЕЗУЛЬТАТЫ.
DAO
Dim dbE As Object, db As Object, rst As Object
Dim sqlString As String
Dim i As Integer
Const dbOpenDynaset = 2, dbReadOnly = 4
' OPEN DB CONNECTION
Set dbE = CreateObject("DAO.DBEngine.120") 'ALSO TRY: DAO.DBEngine.35 OR .36
Set db = dbE.OpenDatabase("C:\Path\To\FileOne.xlsm", False, True, "Excel 12.0 Xml;HDR=Yes")
' OPEN QUERY RECORDSET
sqlString = " SELECT * FROM [TAB$] t1" _
& " INNER JOIN (SELECT * FROM" _
& " [Excel 12.0 Xml;HDR=Yes;Database=C:\Path\To\FileTwo.xlsm].[TAB$]) t2" _
& " ON t1.ID = t2.ID"
Set rst = db.OpenRecordset(sqlString, dbOpenDynaset, dbReadOnly)
' COLUMNS
For i = 1 To rst.Fields.Count
Worksheets("RESULTS").Cells(1, i) = rst.Fields(i - 1).Name
Next i
' DATA ROWS
Worksheets("RESULTS").Range("A2").CopyFromRecordset rst
rst.Close
db.Close
Set rst = Nothing
Set db = Nothing
Set dbE = Nothing
АДО
Dim conn As Object, rst As Object, fld As Object
Dim strConnection As String, strSQL As String
Dim i As Integer
Set conn = CreateObject("ADODB.Connection")
Set rst = CreateObject("ADODB.Recordset")
' OPEN DB CONNECTION
strConnection = "Provider=Microsoft.ACE.OLEDB.12.0;" _
& "Data Source='C:\Path\To\FileOne.xlsm';" _
& "Extended Properties=""Excel 12.0 Xml;HDR=YES;"";"
conn.Open strConnection
' OPEN QUERY RECORDSET
strSQL = " SELECT * FROM [TAB$] t1" _
& " INNER JOIN (SELECT * FROM" _
& " [Excel 12.0 Xml;HDR=Yes;Database=C:\Path\To\FileTwo.xlsm].[TAB$]) t2" _
& " ON t1.ID = t2.ID"
rst.Open strSQL, conn
' COLUMNS
For i = 1 To rst.Fields.Count
Worksheets("RESULTS").Cells(1, i) = rst.Fields(i - 1).Name
Next i
' DATA ROWS
Worksheets("RESULTS").Range("A2").CopyFromRecordset rst
rst.Close
conn.Close
Set rst = Nothing
Set conn = Nothing