Вот код, которым задаем массив со всеми ячейками с данными.
Код
Option Base 1
'определяем последнюю ячейку с данными
With ActiveSheet.UsedRange: End With
lLastRow = ActiveSheet.UsedRange.Row + ActiveSheet.UsedRange.Rows.Count - 1
lLastCol = ActiveSheet.UsedRange.Column + ActiveSheet.UsedRange.Columns.Count - 1
'задаем массив исходных данных
arr = Range(Cells(1, 1), Cells(lLastRow, lLastCol)).Value
Подскажите, плз, есть ли способ, чтобы превратить массив arr в трехмерный вида arr(номер_листа, строка, столбец)? Я не могу сообразить синтаксис. Как добавить номер листа?
Код
For Each sh In Sheets
sh.Activate
arr = Range(Cells(1, 1), Cells(lLastRow, lLastCol)).Value 'как добавить номер листа в эту строку?
Next
Понятно, что можно запустить двойной вложенный цикл (for i=1 to lLastRow, for j=1 to lLastCol) по всем ячейкам каждого листа, а есть ли способ проще, используя Range или еще как то?
С таким подходом и один лист в массив часто запихнуть не получается (если там реально работа идёт), куда там ещё всю книгу... Просто банально не хватит памяти.
У меня за редким исключением в каждой ячейке есть данные. Мне они нужны для обработки. Через Range проще всего засунуть их в массив, несколько пустых ячеек мне не мешают.
Так было до тех пор, пока не попался файл с несколькими вложенными листами. Понятно, что можно цикл запустить, но я полагал, что как-то можно попроще, используя ActiveSheet.Index и Range
Можно использовать массив массивов. Т. е. массив листов, содержащий массивы диапазонов ячеек. Работать с такой структурой будет удобнее, но, замечание от Hugo из поста № 3 все равно актуально!
SAS888 написал: Можно использовать массив массивов
Я читал про них. Сделал вывод, что для меня массив массивов не подойдет, т.к. дальше работа ведется с каждым элементом массива через
Код
For Each el In arr
... 'тут много букв
Next
Поэтому сейчас реализовал через цикл. Будет тормозить на очень больших объемах данных — буду оптимизировать код, благо точно есть куда (далее на основе массива создается Словарь, а можно это сделать сразу)
Цитата
SAS888 написал: замечание от Hugo из поста № 3 все равно актуально!
lLastRowMax и lLastColMax определяю заранее на каждом листе (циклом)
Код
For Each sh In Sheets
sh.Activate
'определяем последнюю ячейку с данными
With ActiveSheet.UsedRange: End With
lLastRow = ActiveSheet.UsedRange.Row + ActiveSheet.UsedRange.Rows.Count - 1
lLastCol = ActiveSheet.UsedRange.Column + ActiveSheet.UsedRange.Columns.Count - 1
If lLastRowMax < lLastRow Then lLastRowMax = lLastRow
If lLastColMax < lLastCol Then lLastColMax = lLastCol
Next
Глобально, скрипт нужен лично мне, у меня 16 Гиг оперативки, так что я как то не парюсь по этому поводу. Пока памяти хватает с избытком=) Ну или я не понимаю тогда, что конкретно имеется в виду SAS888 и Hugo в 3м посте. Поясните, плз.
Как-то тестил - у меня в массив помещалось только 30 столбцов, правда не помню сколько было строк. И это не зависит от размера памяти, но говорят на х64 её доступно больше. В общем если данных бывает много, да и вообще - лучше в массивы брать не всё, а только то что конкретно нужно.
Вообще, я согласен, что лучше сразу забивать только нужными данными.
У меня в большинстве случаев так и будет, т.к. чаще всего я на "вход" скрипту задаю txt файл, в котором одна колонка, в каждой строке которой всего 1-2 слова. Когда на вход стал подавать xlsx из нескольких листов, встала вышеописанная задача. Я даже бросился код менять, чтобы Словарь сразу забивать (без массива, как сейчас), но понял, что для этого придется половину проекта переписать, изменив саму логику (алгоритм). Решил, что пока тормозов не будет или ошибки не свалятся от больших объемов — этого делать не буду.
В общем, сделал пока так:
Код
'создаем массив с данными для поиска
ReDim arr(Worksheets.Count, lLastRowMax, lLastColMax)
'Забиваем массив данными
If Worksheets.Count = 1 Then 'если один лист, используем Range
ReDim arr(lLastRowMax, lLastColMax)
arr = Range(Cells(ActiveSheet.UsedRange.Row, ActiveSheet.UsedRange.Column), Cells(lLastRow, lLastCol)).Value
Else 'если несколько листов, используем цикл
For Each sh In Sheets
sh.Activate
For i = ActiveSheet.UsedRange.Row To lLastRow
For j = ActiveSheet.UsedRange.Column To lLastCol
arr(ActiveSheet.Index, i, j) = Cells(i, j).Value
Next
Next
Next
End If