MyTetra Share
Делитесь знаниями!
Из Excel в Access - быстро!
Время создания: 16.03.2019 23:43
Текстовые метки: mod
Раздел: !Закладки - VBA - Access - Excel->Access
Запись: xintrea/mytetra_db_adgaver_new/master/base/15113545429t5pbjsu2m/text.html на raw.githubusercontent.com

На днях участник Djubocco сетовал в соседней теме http://www.excelworld.ru/forum/17-4539-182810-16-1460047613 , что его процедура перемещает 50 тыс. строк из Excel в Access за дикое количество времени, кажется, 167 минут?

Я не успел откликнуться, а тема уже оказалось закрытой... А товарищ Djubocco чего-то замолчал... Но мой альтруистический порыв оказался сильнее - надо ж выручить человека! - поэтому сам возобновлю разговор.

Использование библиотеки ADO в данном случае не очень удачный выбор. В Access существуют собственные, гораздо более эффективные средства экспорта/импорта.

Вот код, исполняемый в Access, которым я сегодня за 2 минуты "всосал" xlsx-файл размером 18 мегайт, содержащий 400 тыс.строк х 11 столбцов:

Sub fastImport()
    Access.Application.DoCmd.TransferSpreadsheet acImport, acSpreadsheetTypeExcel12, "Лист1", "C:\...\...\MyFile.xlsx", True
End Sub


"Access.Application" указываю, чтобы было понятно, к чему привязываться, если код будет запускаться извне (из Excel или еще откуда). Внутри Access достаточно начать этот оператор с "DoCmd".


У меня аналогичный пример 12 столбцов, 400000 строк, вес файла Excel 33 мегабайта плюс вставка данных в существующую таблицу занял порядка 97 секунд. Office 2016, 64bit.
Но. И с ADODB не всё так плохо, кодом из Excel вставилось тоже самое в существующую таблицу в Access за 301 секунду

Public Sub InsertToTable()
    Const lastRow = 400000, lastCol = 12
    Dim pCon As New ADODB.Connection, pRSet As New ADODB.Recordset, vData As Variant
    Dim k As Long, t As Single, i As Long
    t = Timer: k = 0
    pCon.CursorLocation = adUseClient
    pCon.Open "DBQ=c:\Projects\Database2 min.accdb;Driver={Microsoft Access Driver (*.mdb, *.accdb)};DriverId=25;FIL=MS Access;MaxBufferSize=2048;PageTimeout=5;ReadOnly=0;ExtendedAnsiSQL=1;"
    pRSet.CursorLocation = adUseClient: pRSet.CursorType = adOpenStatic
    pRSet.Open "Select * From forImport Where FLong1 Is Null", pCon, adOpenStatic, adLockOptimistic
    vData = Range("A2").Resize(lastRow, lastCol).Value
    pCon.BeginTrans
    For i = 1 To lastRow
        k = k + 1
        If (k Mod 10000) = 0 Then Debug.Print k: DoEvents
        pRSet.AddNew
        pRSet(0).Value = vData(i, 1)
        pRSet(1).Value = vData(i, 2)
        pRSet(2).Value = vData(i, 3)
        pRSet(3).Value = vData(i, 4)
        pRSet(4).Value = vData(i, 5)
        pRSet(5).Value = vData(i, 6)
        '
        pRSet(6).Value = vData(i, 7)
        pRSet(7).Value = vData(i, 8)
        pRSet(8).Value = vData(i, 9)
        pRSet(9).Value = vData(i, 10)
        pRSet(10).Value = vData(i, 11)
        pRSet(11).Value = vData(i, 12)
    Next
    pRSet.UpdateBatch: pCon.CommitTrans
    pRSet.Close: pCon.Close
    MsgBox Timer - t
End Sub


Так что у автора закрытого топика скорее всего были индексы в таблице Access, что и приводило к таким "тормозам".



если из экселя запустим, то как эксель узнает куда экспортировать, ну там имя базы, таблицы?


Ну, естественно, нужна предварительная подготовка. Типа CreateObject("Access.Application"), OpenDatabase и т.д. Просто открыть файл MDB или новый и писать в него (как в случае с ADO) - недостаточно, т.к. объект DoCmd доступен только в экземпляре Access.

P.S. Примерно такая минимальная болванка:

Sub runAccess()
    Set acApp = CreateObject("Access.Application")
    acApp.OpenCurrentDatabase strFileName
    
    Set acDoCmd = acApp.DoCmd
    acDoCmd.TransferSpreadsheet 0, 9, "Лист1", "C:\...\...\MyFile.xlsx", True
    
    acApp.Quit
End Sub

Так же в этом разделе:
 
MyTetra Share v.0.59
Яндекс индекс цитирования