powered by simpleCommunicator - 2.0.39     © 2025 Programmizd 02
Форумы / Microsoft Office [игнор отключен] [закрыт для гостей] / Excel при загрузке данных ADODB недостаточно памяти
11 сообщений из 11, страница 1 из 1
Excel при загрузке данных ADODB недостаточно памяти
    #37766780
Подскажите пожалуйста нужно выгрузить в Excel данные из Oracle 90000 строк 40 столбцов (процедура Ref Cursor)
Что я не делал вылетает ошибка недостаточно памяти (вся память и в праду съедается). Код ниже
Ошибка появилась после добавления еще одного поля SubStr(ххх,1,255) пробовал и SubStr(ххх,1,25)
(в VBA я не специалист)

Public Function GetR(rs As Object, n As Long) As Variant
Dim a As Variant
Dim c() As Variant
Dim i, l, k As Long

l = rs.Fields.Count

a = rs.GetRows(n) ' выгрузив 80000 и съев всю память здесь падает

ReDim c(n - 1, l - 1)

For i = 0 To n - 1
For k = 0 To l - 1
c(i, k) = a(k, i)
Next k
Next i

Erase a
Set a = Nothing

GetR = c

Erase c
'Set c = Nothing

End Function


'функция выгрузки
Public Sub ADORun(ByVal FuncOrProcNameWithParams As String, _
ByVal FuncOrProcType As Byte, _
Optional FirstRow As Long = 0, _
Optional FirstCol As Long = 0, _
Optional LastCol As Long = 0)
Dim FuncOrProcCall As String
Dim CurLastRow As Long
Dim a As Variant
Dim n As Long
Dim j As Long

Select Case FuncOrProcType
Case adProc, adProcRetCur
FuncOrProcCall = "{call " + FuncOrProcNameWithParams + "}"
Case adFunc
FuncOrProcCall = "{? = call " + FuncOrProcNameWithParams + "}"
End Select

Command.CommandText = FuncOrProcCall
Command.Prepared = True

Select Case FuncOrProcType
Case adProc

Set ADOExec = Command.Execute()

Case adProcRetCur

Set RecordSet = Command.Execute() 'у меня такая команда

Call ClearRange(FirstRow, FirstCol, LastCol)

'изначально пробовал так
'With ThisWorkbook.ActiveSheet.QueryTables.Add( _
' Connection:=RecordSet, _
' Destination:=Cells(FirstRow, FirstCol))
' .Name = "Data List"
' .FieldNames = False
' .PreserveFormatting = True
' .RefreshStyle = xlOverwriteCells
' .AdjustColumnWidth = False
' .Refresh BackgroundQuery:=True
'End With

'Cells(FirstRow, FirstCol).CopyFromRecordset RecordSet ' потом так
' последний вариант грузить по 10000 строк
If Not RecordSet.EOF Then
'RecordSet.MoveLast
RecordSet.MoveFirst
End If

n = RecordSet.Fields("RowCnt")
If n <= 10000 Then

a = GetR(RecordSet, n) 'RecordSet.RecordCount)

Range(Cells(FirstRow, FirstCol), Cells(UBound(a, 1) + FirstRow, UBound(a, 2) + FirstCol)) = a
Else

For j = 1 To n \ 10000
a = GetR(RecordSet, 10000)
Range(Cells((j - 1) * 10000 + FirstRow, FirstCol), Cells((j - 1) * 10000 + UBound(a, 1) + FirstRow, UBound(a, 2) + FirstCol)) = a
Next j
a = GetR(RecordSet, n Mod 10000)
Range(Cells(n - (n Mod 10000) + FirstRow, FirstCol), Cells(n + FirstRow, UBound(a, 2) + FirstCol)) = a

End If
...
Рейтинг: 0 / 0
Excel при загрузке данных ADODB недостаточно памяти
    #37766789
еушшш
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
фывапывапывап,

пользуйтесь тегами
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
Public Function GetR(rs As Object, n As Long) As Variant
Dim a As Variant
Dim c() As Variant
Dim i, l, k As Long

l = rs.Fields.Count

a = rs.GetRows(n) ' выгрузив 80000 и съев всю память здесь падает

ReDim c(n - 1, l - 1)

For i = 0 To n - 1
For k = 0 To l - 1
c(i, k) = a(k, i)
Next k
Next i

Erase a
Set a = Nothing

GetR = c

Erase c
'Set c = Nothing

End Function


'функция выгрузки
Public Sub ADORun(ByVal FuncOrProcNameWithParams As String, _
ByVal FuncOrProcType As Byte, _
Optional FirstRow As Long = 0, _
Optional FirstCol As Long = 0, _
Optional LastCol As Long = 0)
Dim FuncOrProcCall As String
Dim CurLastRow As Long
Dim a As Variant
Dim n As Long
Dim j As Long

Select Case FuncOrProcType
Case adProc, adProcRetCur
FuncOrProcCall = "{call " + FuncOrProcNameWithParams + "}"
Case adFunc
FuncOrProcCall = "{? = call " + FuncOrProcNameWithParams + "}"
End Select

Command.CommandText = FuncOrProcCall
Command.Prepared = True

Select Case FuncOrProcType
Case adProc

Set ADOExec = Command.Execute()

Case adProcRetCur

Set RecordSet = Command.Execute() 'у меня такая команда

Call ClearRange(FirstRow, FirstCol, LastCol)

'изначально пробовал так
'With ThisWorkbook.ActiveSheet.QueryTables.Add( _
' Connection:=RecordSet, _
' Destination:=Cells(FirstRow, FirstCol))
' .Name = "Data List"
' .FieldNames = False
' .PreserveFormatting = True
' .RefreshStyle = xlOverwriteCells
' .AdjustColumnWidth = False
' .Refresh BackgroundQuery:=True
'End With

'Cells(FirstRow, FirstCol).CopyFromRecordset RecordSet ' потом так
' последний вариант грузить по 10000 строк
If Not RecordSet.EOF Then
'RecordSet.MoveLast
RecordSet.MoveFirst
End If

n = RecordSet.Fields("RowCnt")
If n <= 10000 Then

a = GetR(RecordSet, n) 'RecordSet.RecordCount)

Range(Cells(FirstRow, FirstCol), Cells(UBound(a, 1) + FirstRow, UBound(a, 2) + FirstCol)) = a
Else

For j = 1 To n \ 10000
a = GetR(RecordSet, 10000)
Range(Cells((j - 1) * 10000 + FirstRow, FirstCol), Cells((j - 1) * 10000 + UBound(a, 1) + FirstRow, UBound(a, 2) + FirstCol)) = a
Next j
a = GetR(RecordSet, n Mod 10000)
Range(Cells(n - (n Mod 10000) + FirstRow, FirstCol), Cells(n + FirstRow, UBound(a, 2) + FirstCol)) = a

End If 
...
Рейтинг: 0 / 0
Excel при загрузке данных ADODB недостаточно памяти
    #37766819
скукотища
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
фывапывапывап,
транспонировать обязательно ?
...
Рейтинг: 0 / 0
Excel при загрузке данных ADODB недостаточно памяти
    #37766824
R Dmitry
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
фывапывапывап,

а зачем Вам перегонять рекордсет в массив, затем транспонировать и затем дальше с ним работать.
Может проще просто перегонять в массив перебором из рекордсета

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
for i=0 to rs.count-1
x=x+1
if x=10000 then .....выгружаем куда нибудь массив     :x=0:Erase a
 for j=0 to rs.fields.count-1
    a(x,j)=rs.fields(j)
next
rs.movenext
next
...
Рейтинг: 0 / 0
Excel при загрузке данных ADODB недостаточно памяти
    #37766830
Фотография AndreTM
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Там не транспонирование, там просто a и c так созданы...

фывапывапывап, а что, и .CopyFromRecordset падал с ошибкой?
...
Рейтинг: 0 / 0
Excel при загрузке данных ADODB недостаточно памяти
    #37766840
R Dmitry
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
или как вариант выгрузить все на лист и считать в массив, хотя при таких объемах copyfromrecordset, будет медленно выгружать
...
Рейтинг: 0 / 0
Excel при загрузке данных ADODB недостаточно памяти
    #37766933
Фотография Игорь Горбонос
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
> Автор: фыкпыфвап
> Подскажите пожалуйста нужно выгрузить в Excel данные из Oracle 90000 строк 40 столбцов (процедура Ref Cursor)
> Что я не делал вылетает ошибка недостаточно памяти (вся память и в праду съедается). Код ниже

Добавь памяти, отличное обоснование для руководства для апгрейда компьютера.

P.S. Попробуй убрать массив a и присваивай Range напрямую результат GetR и поиграйся настройками Connection. Выставь
CursorLocation в adUseServer и Mode в adModeRead и CursorType в adOpenForwardOnly
P.S.S. В самой функции GetR убери массив с и работай напрямую с именем функции


Пока писал тему прикрыли.

Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
Excel при загрузке данных ADODB недостаточно памяти
    #38959450
Фотография Gabit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Делаю вывод данных порционно, но все равно возникает ошибка - Недостаточно памяти.
Что можно оптимизировать ?
Вот код:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
Sub ExportData()
    Dim CN As ADODB.Connection
    Dim rst As New ADODB.Recordset
    
    Set CN = CreateObject("ADODB.Connection")
    Application.StatusBar = "Подключение к БД..."
    
    
OraConnect:
        UName = "User1"
        PWord = "Pass1"
        SDbName = "Dbname"
        
        s_str = "Provider=OraOLEDB.Oracle;Data Source=" & SDbName & ";User ID=" & UName & ";Password=" & PWord & ";PLSQLRSet=1;"
        CN.ConnectionString = s_str
        CN.Open
    
    CN.Execute "alter session set optimizer_features_enable='11.2.0.3'"
        
    Set MainSh = ActiveWorkbook.Worksheets(1)
    s_str = ActiveSheet.Range("s_query")   ' Получаем запрос
    
    MainSh.Range("A33").Value = Time
    Application.StatusBar = "Выборка ..."
    rst.CursorLocation = 3
    n_max = 1048575
    n_part = 10000
    
    rst.Open s_str, CN
    
    n_sh = 1
    Set NewB = Workbooks.Add()
    n_sh_cnt = NewB.Worksheets.Count
    Set NewSh = NewB.Worksheets(n_sh)
    
    b_exec = True
    n_rec = 0
    n_sh_old = 1
    n_rows = 0
    Do While Not rst.EOF
        If n_sh_old <> n_sh Then
            If n_sh > n_sh_cnt Then
               NewB.Worksheets.Add
               NewB.ActiveSheet.Move After:=NewSh
            End If
            Set NewSh = NewB.Worksheets(n_sh)
            ' Выгружаю шапку
            For i = 1 To rst.Fields.Count
                NewSh.Cells(1, i).Value = rst.Fields(i - 1).Name
            Next i
        End If
        n_sh_old = n_sh
        n_rows = n_rows + n_part
        If n_rows > n_max Then
           n_rec = n_part - (n_max - n_rows)
           n_rows = 0
           n_sh = n_sh + 1
        Else
           n_rec = n_part
        End If
        ' Выгружаю данные
        NewSh.Range("A2").CopyFromRecordset rst, n_rec
    Loop
    
    rst.Close
    CN.Close
    
    Set CN = Nothing
    Set rst = Nothing
    
    Application.StatusBar = "Завершен"
    MainSh.Range("A34").Value = Time
    MsgBox ("Данные выгружены")
End Sub
...
Рейтинг: 0 / 0
Excel при загрузке данных ADODB недостаточно памяти
    #38959576
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Бесконечный цикл. Нет условия выхода.
...
Рейтинг: 0 / 0
Excel при загрузке данных ADODB недостаточно памяти
    #38960423
Казанский
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Несколько листов по миллиону строк в каждом? Неудивительно, что не хватает памяти.
Зачем это все в Excel тащить? Можно же делать запросы к БД, отбирая нужную часть данных.
Или Вы хотите спионерить базу, чтобы потом развернуть ее в другом месте?
Попробуйте после заполнения листа сохранять и закрывать книгу, и открывать новую. Таким образом, если хватает памяти на создание одного листа, то хватит на сколько угодно. А потом, после закрытия монструозного рекордсета, можно попробовать перенести листы из нескольких книг в одну. Или оставить набор книг по одному листу.
...
Рейтинг: 0 / 0
Excel при загрузке данных ADODB недостаточно памяти
    #38960738
Фотография Gabit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Казанский , спасибо за подсказку !
Каждую порцию сохраняю в отдельном файле.

Сделал так:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
    n_max = 1048575
    rst.Open s_str, CN

    n_file = 0    
    Do While Not rst.EOF
        n_file = n_file + 1
        Set NewB = Workbooks.Add()
        Set NewSh = NewB.Worksheets(1)
        
        ' Выгружаю шапку
        For i = 1 To rst.Fields.Count
            NewSh.Cells(1, i).Value = rst.Fields(i - 1).Name
        Next i
        
        ' Выгружаю данные
        NewSh.Range("A2").CopyFromRecordset rst, n_max
        
        fn_xls = trim(n_file) & ".xlsb"
        
        If Len(Dir(fn_xls)) <> 0 Then ' файл существует
           res1 = MsgBox("Файл существует, перезаписать ? " & fn_xls, (vbYesNo + vbQuestion + vbSystemModal), "Сохранение файла")
           If res1 = vbYes Then 'нажата кнопка "Да" (Yes)
                Application.DisplayAlerts = False
                NewB.SaveAs Filename:=fn_xls, FileFormat:=xlExcel12, CreateBackup:=False
                Application.DisplayAlerts = True
                NewB.Close
           Else
              Exit Sub
           End If
        Else
            NewB.SaveAs Filename:=fn_xls, FileFormat:=xlExcel12, CreateBackup:=False
            NewB.Close
        End If
    Loop
    
    rst.Close
    CN.Close
    
    Set CN = Nothing
    Set rst = Nothing
    
    Application.StatusBar = "Завершен"
    MsgBox ("Данные выгружены, создано файлов - " & Trim(n_file))
...
Рейтинг: 0 / 0
11 сообщений из 11, страница 1 из 1
Форумы / Microsoft Office [игнор отключен] [закрыт для гостей] / Excel при загрузке данных ADODB недостаточно памяти
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]