Есть база данных Access (одна таблица - 300 тыс. записей). Необходимо выгружать данные в Excel корректировать их и загружать обратно в базу (обновлять записи). Данные получаю с помощью ADO, но возникла проблема - утечка памяти. При каждом запросе Excel увеличивает количество используемой оперативной памяти. Получается так, что при запросе большого объема данных после нескольких итераций системные ресурсы заканчиваются. Помогает только перезапуск приложения. Как с этим бороться?
Скрытый текст
Public Sub Get_Data(ByRef vaData As Variant, ByVal strSQL As String, Optional blTranspose As Boolean = True) 'Запрос из базы записей указанной таблицы, возвращение их в виде массива
Вариант запустить новое приложение, выполнить запросы, а потом его "убить" у меня был, но я все же надеялся, что есть другое решение... Может зря надеялся?
Речь не про другой процесс, а просто другую книгу, можно в этом же процессе. При запросе через ADO к текущей книге утечка памяти практически на 100% обеспечена.
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
Владимир Захаров (ZVI) как-то давал ссылку на статью, в которой говорилось, что утечки памяти при работе с файлами Excel через ADO происходят именно при работе с открытыми файлами. но сейчас я эту ссылку никак не найду...
фрилансер Excel, VBA - контакты в профиле "Совершенствоваться не обязательно. Выживание — дело добровольное." Э.Деминг
1.Закрытие файла в том же процессе не помогает. 2.По поводу запроса к открытой книге Excel информацию находил, но у меня запрос к базе Access... Или это не имеет значения?
Никаких утечек памяти к открытой книге через ADO нет, я делал различные тесты, по 1000 различных запросов и SQL команд. Выше приведенные ссылки об утечки памяти относятся к старым версиям excelя 97 - 2000.
If Not Rst.EOF Then
vaData = Rst.GetRows
If blTranspose Then vaData = TransposeArray(vaData)
End If
Мне кажется, что вся проблема именно здесь: GetRows создаёт массив, а TransposeArray создаёт, по сути, ещё раз этот массив. Что не позволяет напрямую обрабатывать Recordset? Его, кстати, можно сохранить на диск и позже открыть его (отправить по почте).
Возможно дело не в ADO, а Вашем остальном коде, да и транспонировать 300 т записей это как? мне кажется транспозе ограничен 32 т, хотя возможно Вы и не транспонируете. В любом случае я бы отказался от перезаписи данных в массив и обрабатывал бы recordset.
Цитата
Получается так, что при запросе большого объема данных после нескольких итераций
Предлагаю вынести из процедуры Get_Data вот эти 2 строчки кода: Dim Con As New ADODB.Connection Dim Rst As New ADODB.Recordset и переместить их на уровень модуля. То есть, создавать эти объекты один раз, а не каждый раз при обращении к Get_Data
Добрый День! У меня этаже проблема, при работе со строками в 300 000 строк. (которую описывала немного раннее). Сейчас использую класс ADO от nerv для загрузки массива
Код
Dim ADO As New ADO
Dim Arr As Variant
Dim iColumn As Long
Dim iRow As Long
'ADO.DataSource = "G:\ÐÀÇÐÀÁÎÒÊÀ_2\äàííî" & "\" & "exim_ua_2015_1-8_ðûá.xls" '
ADO.DataSource = FileName
ADO.Query ("SELECT * FROM [exim_ua_2015_1_8_ðûá$]")
Arr = ADO.ToArray()
iColumn = ADO.iColumn
iRow = ADO.iRow
ExcelArray = Arr
и взяла ZVI вашу процедуру для поредения имени листа "Function OnlyOneSheetName"
Добрый день! Ответ запоздалый, но может кому то поможет. Сам недавно столкнулся с этой проблемой при импорте больших данных. Способа решения не нашел. Совершенно случайно заметил, что команда ThisWorkBook.Save занимаемую память в памяти уменьшила. Если раньше за 40-50 циклов (а необходимо 2000) память доходила до 1.2ГБ и Excel зависал, то после помещения команды в тело цикла память растет крайне медленно, что собственно полностью решило мою проблему.