Представим себе такую задачу:
Есть две экселевские таблицы. Это могут быть и два разных листа одной книги и две отдельные книги. Их может быть и больше. И вам надо сопоставить ячейки одной таблицы с ячейками другой, чтоб получить значения из её строки. За пределами экселя это делается с помощью SQL. В самом экселе с каких-то пор появилась некая химера под названием PowerQuery, но ну её нафиг.
В составе офиса у нас уже есть DAO. Это ядро баз данных, используемое MS Access-ом - Jet. Его и будем использовать.
Всё то же самое делаем с другой таблицей. Главное, чтоб выходной файл имел другое название.
предварительно подключим библиотеку DAO 3.6
Dim dbs As DAO.Database, rst As DAO.Recordset, qdf As DAO.QueryDef
Set WShell = CreateObject("WScript.shell")
strMDB = WShell.ExpandEnvironmentStrings("%temp%") & "\mdb.mdb"
If FileExists(strMDB) Then Kill strMDB
If CreateDataBaseDAO(strMDB) Then
Set dbs = DAO.OpenDatabase(strMDB)
Set tdf = dbs.CreateTableDef("t1")
Set fld1 = tdf.CreateField("f1", dbText, 255)
Set fld1 = tdf.CreateField("f2", dbText, 255)
'создадим запрос на копирование строчек из файла в базу и выполним его
Set qdf = dbs.CreateQueryDef("q1", "insert into t1 SELECT * FROM [Лист1$] AS s_ IN '" & strFile1 & "'[EXCEL 8.0;HDR=no;];")
Так же создаём и заполняем столько таблиц, сколько нам надо связать в запросе.
И делаем простенький запрос на выборку со связыванием:
strSQL = "SELECT t1.F1, t1.F2, t2.F1 " & vbCrLf & _
"FROM t1 LEFT JOIN dst ON t1.F1 = t2.F1 " & vbCrLf & _
"WHERE t1.F1 Is Not Null AND t2.F1 Is Null;"
Set qdf = dbs.CreateQueryDef("qCompare", strSQL)
Set rst = dbs.OpenRecordset("qCompare")
'Debug.Print rst.Fields(0), rst.Fields(1)
Таким образом формируется запрос, в котором вывелись записи из первой таблицы, для которых не нашлось сопоставление во второй. Можем в цикле вывести эти записи в нашу книгу, например.
В коде встречаются две функции. Вот их код:
Function FileExists(strFile As String) As Boolean
If FileLen(strFile) <> 0 Then FileExists = True
If Err.Number = 53 Then FileExists = False
Function CreateDataBaseDAO(newDB As String, Optional sLocate As String = dbLangCyrillic, Optional iVersion As Integer = dbVersion40) As Boolean
Set dbNew = DBEngine.CreateDatabase(newDB, sLocate, iVersion)
MsgBox Err.Description, , Err.Number
CreateDataBaseDAO = False
Самая затратная по времени выполнения часть - это копирование записей из файлов в базу. Это приходится делать, т.к. Jet не считает экселевские файлы полноценным источником данных, не может работать с ними непосредственно через связь, и не может по ним строить индексы и вести нормальный поиск. Может только последовательный перебор от начала до конца файла, что нам совсем не удобно. А вот работа с объектами самого акцесса имеет вполне вменяемое быстродействие. В принципе самое быстрое на данный момент среди файловых баз данных.