Гость
Форумы / Microsoft Office [игнор отключен] [закрыт для гостей] / Excel при загрузке данных ADODB недостаточно памяти / 11 сообщений из 11, страница 1 из 1
23.04.2012, 17:48
    #37766780
Excel при загрузке данных ADODB недостаточно памяти
Подскажите пожалуйста нужно выгрузить в 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
23.04.2012, 17:51
    #37766789
еушшш
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Excel при загрузке данных ADODB недостаточно памяти
фывапывапывап,

пользуйтесь тегами
Код: 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
23.04.2012, 18:02
    #37766819
скукотища
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Excel при загрузке данных ADODB недостаточно памяти
фывапывапывап,
транспонировать обязательно ?
...
Рейтинг: 0 / 0
23.04.2012, 18:05
    #37766824
R Dmitry
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Excel при загрузке данных ADODB недостаточно памяти
фывапывапывап,

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

Код: 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
23.04.2012, 18:07
    #37766830
AndreTM
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Excel при загрузке данных ADODB недостаточно памяти
Там не транспонирование, там просто a и c так созданы...

фывапывапывап, а что, и .CopyFromRecordset падал с ошибкой?
...
Рейтинг: 0 / 0
23.04.2012, 18:12
    #37766840
R Dmitry
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Excel при загрузке данных ADODB недостаточно памяти
или как вариант выгрузить все на лист и считать в массив, хотя при таких объемах copyfromrecordset, будет медленно выгружать
...
Рейтинг: 0 / 0
23.04.2012, 19:07
    #37766933
Игорь Горбонос
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Excel при загрузке данных ADODB недостаточно памяти
> Автор: фыкпыфвап
> Подскажите пожалуйста нужно выгрузить в 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
Период между сообщениями больше года.
15.05.2015, 09:44
    #38959450
Gabit
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Excel при загрузке данных ADODB недостаточно памяти
Делаю вывод данных порционно, но все равно возникает ошибка - Недостаточно памяти.
Что можно оптимизировать ?
Вот код:
Код: 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
15.05.2015, 11:19
    #38959576
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Excel при загрузке данных ADODB недостаточно памяти
Бесконечный цикл. Нет условия выхода.
...
Рейтинг: 0 / 0
16.05.2015, 02:38
    #38960423
Казанский
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Excel при загрузке данных ADODB недостаточно памяти
Несколько листов по миллиону строк в каждом? Неудивительно, что не хватает памяти.
Зачем это все в Excel тащить? Можно же делать запросы к БД, отбирая нужную часть данных.
Или Вы хотите спионерить базу, чтобы потом развернуть ее в другом месте?
Попробуйте после заполнения листа сохранять и закрывать книгу, и открывать новую. Таким образом, если хватает памяти на создание одного листа, то хватит на сколько угодно. А потом, после закрытия монструозного рекордсета, можно попробовать перенести листы из нескольких книг в одну. Или оставить набор книг по одному листу.
...
Рейтинг: 0 / 0
17.05.2015, 07:56
    #38960738
Gabit
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Excel при загрузке данных ADODB недостаточно памяти
Казанский , спасибо за подсказку !
Каждую порцию сохраняю в отдельном файле.

Сделал так:
Код: 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
Форумы / Microsoft Office [игнор отключен] [закрыт для гостей] / Excel при загрузке данных ADODB недостаточно памяти / 11 сообщений из 11, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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