Домашняя страница Undo Do New Save Карта сайта Обратная связь Поиск по форуму
МИР MS EXCEL - Гость.xls

Вход

Регистрация

Напомнить пароль

 

= Мир MS Excel/Выгрузка массива на несколько листов - Мир MS Excel

Старая форма входа
  • Страница 1 из 1
  • 1
Модератор форума: китин, _Boroda_  
Выгрузка массива на несколько листов
sboy Дата: Четверг, 25.04.2019, 15:56 | Сообщение № 1
Группа: Друзья
Ранг: Участник клуба
Сообщений: 2566
Репутация: 724 ±
Замечаний: 0% ±

Excel 2010
Добрый день друзья и коллеги.
есть макрос который собирает данные с листов в одномерный массив и выгружает на новый лист. Если значений в массиве <= число строк на листе, то отрабатывает без проблем.
А если больше, то не могу победить. Пробовал использовать копию массива (для обрезки и выгрузки частями) - вылетаю в Out of Memory (7).
Есть какой способ или придется делать цикл по количеству листов для вывода?


upd.
наврал про весь лист, при 70000 вылез еще мисматч тут
[vba]
Код
.Cells(1, 1).Resize(komb, 1).Value = Application.Transpose(arr_out)
[/vba]


Яндекс: 410016850021169

Сообщение отредактировал sboy - Четверг, 25.04.2019, 16:46
 
Ответить
СообщениеДобрый день друзья и коллеги.
есть макрос который собирает данные с листов в одномерный массив и выгружает на новый лист. Если значений в массиве <= число строк на листе, то отрабатывает без проблем.
А если больше, то не могу победить. Пробовал использовать копию массива (для обрезки и выгрузки частями) - вылетаю в Out of Memory (7).
Есть какой способ или придется делать цикл по количеству листов для вывода?


upd.
наврал про весь лист, при 70000 вылез еще мисматч тут
[vba]
Код
.Cells(1, 1).Resize(komb, 1).Value = Application.Transpose(arr_out)
[/vba]

Автор - sboy
Дата добавления - 25.04.2019 в 15:56
bmv98rus Дата: Четверг, 25.04.2019, 20:05 | Сообщение № 2
Группа: Друзья
Ранг: Участник клуба
Сообщений: 4115
Репутация: 769 ±
Замечаний: 0% ±

Excel 2013/2016
sboy, ну так дошли похоже до ограничения, хотя вроде как оспаривается это, но упоминается 65536.
Excel 32bit
[vba]
Код
Sub test()
a = Range("a1:a65536")
b = Application.Transpose(a)
Debug.Print UBound(b)
a = Range("a1:a65537")
b = Application.Transpose(a)
Debug.Print UBound(b)
End Sub
[/vba]
65536
1

На x64 не проверял, надо б переставить, но все лениво как то, а с большими данными не работаю, хватает того что есть.

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


Замечательный Временно просто медведь , процентов на 20.

Сообщение отредактировал bmv98rus - Четверг, 25.04.2019, 20:29
 
Ответить
Сообщениеsboy, ну так дошли похоже до ограничения, хотя вроде как оспаривается это, но упоминается 65536.
Excel 32bit
[vba]
Код
Sub test()
a = Range("a1:a65536")
b = Application.Transpose(a)
Debug.Print UBound(b)
a = Range("a1:a65537")
b = Application.Transpose(a)
Debug.Print UBound(b)
End Sub
[/vba]
65536
1

На x64 не проверял, надо б переставить, но все лениво как то, а с большими данными не работаю, хватает того что есть.

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

Автор - bmv98rus
Дата добавления - 25.04.2019 в 20:05
boa Дата: Пятница, 26.04.2019, 10:42 | Сообщение № 3
Группа: Друзья
Ранг: Ветеран
Сообщений: 559
Репутация: 167 ±
Замечаний: 0% ±

365
sboy,
можно добавить функции которые будут резать массив на нужное кол-во записей и транспонировать
[vba]
Код
Sub test()
Dim arr_out(), Arr_OT_DO(), i&, iStep&
    arr_out = Sheet1.Range("A1:A" & Sheet1.Cells(Rows.Count, 1).End(xlUp).Row)
    arr_out = TransposeArray_2to1(arr_out)
    iStep = 100000  ' здесь нужное число строк или activesheet.Rows.count
Application.ScreenUpdating = False
    Dim Start!:           Start = Timer
    For i = LBound(arr_out) To UBound(arr_out) Step iStep
        Arr_OT_DO = splitArr(arr_out, i, i + iStep - 1)
        With Sheets.Add(after:=Sheets(Sheets.Count))
            .Cells(1, 1).Resize(UBound(Arr_OT_DO) + 1, 1).Value = TransposeArray_1to2(Arr_OT_DO)
            .Cells(UBound(Arr_OT_DO) + 1, 1).Select
        End With
    Next
    Sheet1.Activate
    Debug.Print "Затрачено: " & Format(Timer - Start, "#0.00") & " сек."
Application.ScreenUpdating = True
End Sub

Private Function splitArr(ByVal Massiv As Variant, ByVal OT_&, ByVal DO_&)
'режет одномерный массив
Dim i&, TmpArr() As Variant
If UBound(Massiv) < DO_ Then DO_ = UBound(Massiv)
ReDim TmpArr(0 To DO_ - OT_)
    For i = OT_ To DO_ Step 1
        TmpArr(i - OT_) = Massiv(i)
    Next i
    splitArr = TmpArr
End Function

Function TransposeArray_2to1(ByRef SourceArray() As Variant) As Variant
'Транспонирует из двумерного в одномерный
    Dim OT_&: OT_ = LBound(SourceArray, 1)
    Dim DO_&: DO_ = UBound(SourceArray, 1)
    Dim TempArray As Variant, i&
    ReDim TempArray(OT_ To DO_)
    For i = OT_ To DO_
        TempArray(i) = SourceArray(i, 1)
    Next i
    TransposeArray_2to1 = TempArray
End Function

Function TransposeArray_1to2(ByRef SourceArray() As Variant) As Variant
'Транспонирует из одномерного в двумерный
    Dim OT_&: OT_ = LBound(SourceArray)
    Dim DO_&: DO_ = UBound(SourceArray)
    Dim TempArray As Variant, i&
    ReDim TempArray(OT_ To DO_, 1 To 1)
    For i = OT_ To DO_
        TempArray(i, 1) = SourceArray(i)
    Next i
    TransposeArray_1to2 = TempArray
End Function
[/vba]
К сообщению приложен файл: splitArr2.xlsb (24.4 Kb)




Сообщение отредактировал boa - Пятница, 26.04.2019, 12:13
 
Ответить
Сообщениеsboy,
можно добавить функции которые будут резать массив на нужное кол-во записей и транспонировать
[vba]
Код
Sub test()
Dim arr_out(), Arr_OT_DO(), i&, iStep&
    arr_out = Sheet1.Range("A1:A" & Sheet1.Cells(Rows.Count, 1).End(xlUp).Row)
    arr_out = TransposeArray_2to1(arr_out)
    iStep = 100000  ' здесь нужное число строк или activesheet.Rows.count
Application.ScreenUpdating = False
    Dim Start!:           Start = Timer
    For i = LBound(arr_out) To UBound(arr_out) Step iStep
        Arr_OT_DO = splitArr(arr_out, i, i + iStep - 1)
        With Sheets.Add(after:=Sheets(Sheets.Count))
            .Cells(1, 1).Resize(UBound(Arr_OT_DO) + 1, 1).Value = TransposeArray_1to2(Arr_OT_DO)
            .Cells(UBound(Arr_OT_DO) + 1, 1).Select
        End With
    Next
    Sheet1.Activate
    Debug.Print "Затрачено: " & Format(Timer - Start, "#0.00") & " сек."
Application.ScreenUpdating = True
End Sub

Private Function splitArr(ByVal Massiv As Variant, ByVal OT_&, ByVal DO_&)
'режет одномерный массив
Dim i&, TmpArr() As Variant
If UBound(Massiv) < DO_ Then DO_ = UBound(Massiv)
ReDim TmpArr(0 To DO_ - OT_)
    For i = OT_ To DO_ Step 1
        TmpArr(i - OT_) = Massiv(i)
    Next i
    splitArr = TmpArr
End Function

Function TransposeArray_2to1(ByRef SourceArray() As Variant) As Variant
'Транспонирует из двумерного в одномерный
    Dim OT_&: OT_ = LBound(SourceArray, 1)
    Dim DO_&: DO_ = UBound(SourceArray, 1)
    Dim TempArray As Variant, i&
    ReDim TempArray(OT_ To DO_)
    For i = OT_ To DO_
        TempArray(i) = SourceArray(i, 1)
    Next i
    TransposeArray_2to1 = TempArray
End Function

Function TransposeArray_1to2(ByRef SourceArray() As Variant) As Variant
'Транспонирует из одномерного в двумерный
    Dim OT_&: OT_ = LBound(SourceArray)
    Dim DO_&: DO_ = UBound(SourceArray)
    Dim TempArray As Variant, i&
    ReDim TempArray(OT_ To DO_, 1 To 1)
    For i = OT_ To DO_
        TempArray(i, 1) = SourceArray(i)
    Next i
    TransposeArray_1to2 = TempArray
End Function
[/vba]

Автор - boa
Дата добавления - 26.04.2019 в 10:42
sboy Дата: Пятница, 26.04.2019, 13:09 | Сообщение № 4
Группа: Друзья
Ранг: Участник клуба
Сообщений: 2566
Репутация: 724 ±
Замечаний: 0% ±

Excel 2010
bmv98rus, Спасибо! ограничение обошел, теперь выгружает до 1048576
boa, я похожее и сам пробовал в самом коде с копией массива (ошибка памяти). С помощью Вашей функции 1 лист выгружает, но потом тоже вываливается в ошибку памяти (при втором вызове функции)


Яндекс: 410016850021169
 
Ответить
Сообщениеbmv98rus, Спасибо! ограничение обошел, теперь выгружает до 1048576
boa, я похожее и сам пробовал в самом коде с копией массива (ошибка памяти). С помощью Вашей функции 1 лист выгружает, но потом тоже вываливается в ошибку памяти (при втором вызове функции)

Автор - sboy
Дата добавления - 26.04.2019 в 13:09
bmv98rus Дата: Пятница, 26.04.2019, 14:19 | Сообщение № 5
Группа: Друзья
Ранг: Участник клуба
Сообщений: 4115
Репутация: 769 ±
Замечаний: 0% ±

Excel 2013/2016
Вчера не удержался и все ж поставил 2016x64. Как и следовало ожидать ограничение 65536 - осталось. Думаю это сознательно сделано, для совместимости кодов.


Замечательный Временно просто медведь , процентов на 20.
 
Ответить
СообщениеВчера не удержался и все ж поставил 2016x64. Как и следовало ожидать ограничение 65536 - осталось. Думаю это сознательно сделано, для совместимости кодов.

Автор - bmv98rus
Дата добавления - 26.04.2019 в 14:19
SLAVICK Дата: Пятница, 26.04.2019, 15:15 | Сообщение № 6
Группа: Модераторы
Ранг: Старожил
Сообщений: 2290
Репутация: 766 ±
Замечаний: 0% ±

2019
Application.Transpose - зло и имеет кучу ограничений. Это же аналог старой функции листа.
не совсем понял что в первой части кода делается.
Но если нужно выгрузить большой одномерный массив на листы то вот:
[vba]
Код
Sub d()
Dim arr, arr2, i#, shN!, ii&, n#, n2&

n = 4546325

'Create arr:
ReDim arr(1 To n)
For i = 1 To n: arr(i) = i: Next
i = 1

'start loop
Do While i <= n
    n2 = IIf(n - i < Rows.Count - 2, n - i + 1, Rows.Count - 1)
    arr2 = GetPartArr(arr, i, i + n2 - 1)
    Sheets.Add after:=Sheets(Sheets.Count)
    [a2].Resize(UBound(arr2)) = arr2
    i = i + n2
Loop
End Sub
Function GetPartArr(arr, iStart, iFin)
ReDim arr2(1 To iFin - iStart + 1, 1 To 1)
    For i = 1 To UBound(arr2)
        arr2(i, 1) = arr(iStart + i - 1)
    Next
GetPartArr = arr2
End Function
[/vba]
Этот пример выгрузит от 1 до n = 4546325 записей на листы
только заметил - похоже на то что boa предложил :)
К сообщению приложен файл: splitArr_D.xlsb (17.7 Kb)


Иногда все проще чем кажется с первого взгляда.

Сообщение отредактировал SLAVICK - Пятница, 26.04.2019, 15:24
 
Ответить
СообщениеApplication.Transpose - зло и имеет кучу ограничений. Это же аналог старой функции листа.
не совсем понял что в первой части кода делается.
Но если нужно выгрузить большой одномерный массив на листы то вот:
[vba]
Код
Sub d()
Dim arr, arr2, i#, shN!, ii&, n#, n2&

n = 4546325

'Create arr:
ReDim arr(1 To n)
For i = 1 To n: arr(i) = i: Next
i = 1

'start loop
Do While i <= n
    n2 = IIf(n - i < Rows.Count - 2, n - i + 1, Rows.Count - 1)
    arr2 = GetPartArr(arr, i, i + n2 - 1)
    Sheets.Add after:=Sheets(Sheets.Count)
    [a2].Resize(UBound(arr2)) = arr2
    i = i + n2
Loop
End Sub
Function GetPartArr(arr, iStart, iFin)
ReDim arr2(1 To iFin - iStart + 1, 1 To 1)
    For i = 1 To UBound(arr2)
        arr2(i, 1) = arr(iStart + i - 1)
    Next
GetPartArr = arr2
End Function
[/vba]
Этот пример выгрузит от 1 до n = 4546325 записей на листы
только заметил - похоже на то что boa предложил :)

Автор - SLAVICK
Дата добавления - 26.04.2019 в 15:15
boa Дата: Пятница, 26.04.2019, 15:41 | Сообщение № 7
Группа: Друзья
Ранг: Ветеран
Сообщений: 559
Репутация: 167 ±
Замечаний: 0% ±

365
но потом тоже вываливается в ошибку памяти (при втором вызове функции)
увидеть бы сам файл.

свой файлик протестил на массиве 1048576х5 загнал данные в одномерный массив, потом выгрузил на 5-ть листов
[vba]
Код
Массив создан за 10,76 сек.
Данные выгружены за 22,19 сек.
[/vba] Ошибок нет
во вложении видоизмененный файл
Протяните формулы до конца листа, т.к. удалил строки для уменьшения размера файла
К сообщению приложен файл: 7141021.xlsb (26.2 Kb)


 
Ответить
Сообщение
но потом тоже вываливается в ошибку памяти (при втором вызове функции)
увидеть бы сам файл.

свой файлик протестил на массиве 1048576х5 загнал данные в одномерный массив, потом выгрузил на 5-ть листов
[vba]
Код
Массив создан за 10,76 сек.
Данные выгружены за 22,19 сек.
[/vba] Ошибок нет
во вложении видоизмененный файл
Протяните формулы до конца листа, т.к. удалил строки для уменьшения размера файла

Автор - boa
Дата добавления - 26.04.2019 в 15:41
sboy Дата: Пятница, 26.04.2019, 16:13 | Сообщение № 8
Группа: Друзья
Ранг: Участник клуба
Сообщений: 2566
Репутация: 724 ±
Замечаний: 0% ±

Excel 2010
Application.Transpose - зло и имеет кучу ограничений

это я уже понял, в копилку положил
Странно, но файл SLAVICK, отрабатывает нормально. Вставил код в свой, вываливает в Out of Memory.
Буду копать, чем я оперативку забиваю :(


Яндекс: 410016850021169
 
Ответить
Сообщение
Application.Transpose - зло и имеет кучу ограничений

это я уже понял, в копилку положил
Странно, но файл SLAVICK, отрабатывает нормально. Вставил код в свой, вываливает в Out of Memory.
Буду копать, чем я оперативку забиваю :(

Автор - sboy
Дата добавления - 26.04.2019 в 16:13
SLAVICK Дата: Пятница, 26.04.2019, 16:17 | Сообщение № 9
Группа: Модераторы
Ранг: Старожил
Сообщений: 2290
Репутация: 766 ±
Замечаний: 0% ±

2019
А на какой строке ошибка?
не тут случайно?:
[vba]
Код
ReDim arr_out(1 To komb)
[/vba]
есть такое предположение - что komb - слишком большой получается


Иногда все проще чем кажется с первого взгляда.
 
Ответить
СообщениеА на какой строке ошибка?
не тут случайно?:
[vba]
Код
ReDim arr_out(1 To komb)
[/vba]
есть такое предположение - что komb - слишком большой получается

Автор - SLAVICK
Дата добавления - 26.04.2019 в 16:17
sboy Дата: Пятница, 26.04.2019, 16:26 | Сообщение № 10
Группа: Друзья
Ранг: Участник клуба
Сообщений: 2566
Репутация: 724 ±
Замечаний: 0% ±

Excel 2010
О! Помогло забытое Erase
очистил оперативку от использованного исходного массива и который частично выгружает на лист и заработало
[vba]
Код
        Erase arr_v '÷èñòèì îïåðàòèâêó
        Erase arr_v 'чистим оперативку
        Erase arr_sh
'SLAVIK'
        i = 1
        n = UBound(arr_out)
                Do While i <= n
                    n2 = IIf(n - i < Rows.Count - 2, n - i + 1, Rows.Count - 1)
                    arr2 = GetPartArr(arr_out, i, i + n2 - 1)
                    Sheets.Add after:=Sheets(Sheets.Count)
                    [a2].Resize(UBound(arr2)) = arr2
                    Erase arr2 'еще раз чистим
                    i = i + n2
                Loop

[/vba]


Яндекс: 410016850021169
 
Ответить
СообщениеО! Помогло забытое Erase
очистил оперативку от использованного исходного массива и который частично выгружает на лист и заработало
[vba]
Код
        Erase arr_v '÷èñòèì îïåðàòèâêó
        Erase arr_v 'чистим оперативку
        Erase arr_sh
'SLAVIK'
        i = 1
        n = UBound(arr_out)
                Do While i <= n
                    n2 = IIf(n - i < Rows.Count - 2, n - i + 1, Rows.Count - 1)
                    arr2 = GetPartArr(arr_out, i, i + n2 - 1)
                    Sheets.Add after:=Sheets(Sheets.Count)
                    [a2].Resize(UBound(arr2)) = arr2
                    Erase arr2 'еще раз чистим
                    i = i + n2
                Loop

[/vba]

Автор - sboy
Дата добавления - 26.04.2019 в 16:26
sboy Дата: Пятница, 26.04.2019, 16:29 | Сообщение № 11
Группа: Друзья
Ранг: Участник клуба
Сообщений: 2566
Репутация: 724 ±
Замечаний: 0% ±

Excel 2010
не тут случайно?

нет, ругался в функции
[vba]
Код
GetPartArr = arr2
[/vba]


Яндекс: 410016850021169
 
Ответить
Сообщение
не тут случайно?

нет, ругался в функции
[vba]
Код
GetPartArr = arr2
[/vba]

Автор - sboy
Дата добавления - 26.04.2019 в 16:29
boa Дата: Суббота, 27.04.2019, 22:45 | Сообщение № 12
Группа: Друзья
Ранг: Ветеран
Сообщений: 559
Репутация: 167 ±
Замечаний: 0% ±

365
ругался в функции

При пошаговом проходе проверьте создается ли массив arr2,
может к функцие GetPartArr приходит не одномерный массив.
очистил оперативку
А сколько ее у вас?




Сообщение отредактировал boa - Суббота, 27.04.2019, 22:47
 
Ответить
Сообщение
ругался в функции

При пошаговом проходе проверьте создается ли массив arr2,
может к функцие GetPartArr приходит не одномерный массив.
очистил оперативку
А сколько ее у вас?

Автор - boa
Дата добавления - 27.04.2019 в 22:45
  • Страница 1 из 1
  • 1
Поиск:

Яндекс.Метрика Яндекс цитирования
© 2010-2024 · Дизайн: MichaelCH · Хостинг от uCoz · При использовании материалов сайта, ссылка на www.excelworld.ru обязательна!