Страница 1 из 2

Переопределение границ массива с сохранением его элементов

Добавлено: 21 сен 2009, 02:45
AlexZZZ
Доброго времени суток всем!
Подскажите, пожалуйста, что-то я застопорился: на простом, вроде, коде выдаёт ошибку:

Код: Выделить всё

Dim nArray As Variant
'.....
ReDim Preserve nArray(1 To 2, 1 To 2) 'Переопределение массива с сохранением элементов
P/S: Так тоже выдаёт ошибку

Код: Выделить всё

ReDim Preserve nArray(2, 2)
Так, что я делаю не так?

Re: Переопределение границ массива с сохранением его элементов

Добавлено: 21 сен 2009, 03:00
EducatedFool
Попробуйте так:

Код: Выделить всё

[color=darkblue]Sub[/color] test1()
    [color=darkblue]Dim[/color] nArray[B][color="Red"]()[/color][/B] [color=darkblue]As[/color] [color=darkblue]Variant[/color]
    [color=green]'.....[/color]
    [color=darkblue]ReDim[/color] [color=darkblue]Preserve[/color] nArray(1 [color=darkblue]To[/color] 2, 1 To 2)    'Переопределение массива с сохранением элементов
[color=darkblue]End[/color] [color=darkblue]Sub[/color]

Re: Переопределение границ массива с сохранением его элементов

Добавлено: 21 сен 2009, 06:03
SAS888
Необходимо заметить, что во-первых, при определении (переопределении) массива, безусловно, переменную нужно объявлять как массив (см, замечания от Educated Fool). Во-вторых, переопределение границ массива с сохранением данных, возможно только для последней размерности многомерного массива. Например:

Код: Выделить всё

Sub qq()
    Dim nArray() As Variant
    ReDim nArray(1 To 2, 1 To 2)
    '.....
    ReDim Preserve nArray(1 To 2, 1 To 3) 'Этот код сработает нормально
    ReDim Preserve nArray(1 To 3, 1 To 2) 'Этот код выдаст ошибку
End Sub

Re: Переопределение границ массива с сохранением его элементов

Добавлено: 21 сен 2009, 16:25
AlexZZZ
Спасибо за советы!
переопределение границ массива с сохранением данных, возможно только для последней размерности многомерного массива
Но как же тогда быть? Ведь, добавлять приходится именно первую размерность (это строки, число которых в начале цикла неизвестно, чтобы потом вставить это в листбокс). Тогда подскажите, как "транспонировать" массив?

Re: Переопределение границ массива с сохранением его элементов

Добавлено: 21 сен 2009, 19:31
EducatedFool
Но как же тогда быть? Ведь, добавлять приходится именно первую размерность (это строки, число которых в начале цикла неизвестно, чтобы потом вставить это в листбокс)
А почему не объявить массив с большим запасом строк?
Например, nArray(1 To 100000, 1 To 2)
Не так уж много памяти отъест этот массив, а код намного упростится.

Или, может, имеет смысл использовать коллекции?
Я в абсолютном большинстве случаев использую коллекции вместо массивов (за редким исключением, разве что когда массивы огромны, и очень важна скорость работы; либо если этот массив потом приходится переносить на лист)

Re: Переопределение границ массива с сохранением его элементов

Добавлено: 21 сен 2009, 22:44
AlexZZZ
Попробовал, в общем, проще всего в моём случае оказалось сделать 2 цикла: один определяет число строк в массиве, затем переопределяется массив и второй цикл по тем же условиям заполняет массив значениями. Всё работает, но решение какое-то не изящное, и вероятно, не самое производительное.
По совету EducatedFool попробую ещё разобраться, как организовывать двумерные коллекции, если такие существуют.

Re: Переопределение границ массива с сохранением его элементов

Добавлено: 22 сен 2009, 04:58
SAS888
AlexZZZ,
1. А какая конкретно у Вас задача? Почему нужно организовывать цикл для определения числа строк? Без него никак?
2. Если Вы работаете с массивом, перебирая его элементы в цикле, то я бы не советовал использовать ReDim Preserve. Ибо каждый раз, выполняя эту функцию, происходит перезапись всех элементов последней размерности массива, что есть долго и не рационально. Может быть лучше объявить другой (пустой) массив требуемой размерности, а в цикле просто присваивать значения его элементам? Уверяю Вас, что будет существенно быстрее.

Re: Переопределение границ массива с сохранением его элементов

Добавлено: 22 сен 2009, 11:32
AlexZZZ
Задача следующая. Есть строка данных вида:
Аспирин - 100 уп.
Анальгин - 280 уп.
Димедрол - 80 уп.

Её нужно пропарсить и вставить в двухколоночный листбокс. Для этого циклом определяю количество строк (считаю символы переноса строки) и по выходу из цикла указываю размерность массива (теперь уже только один раз и без сохранения элементов), а затем следующим циклом последовательно разбиваю эту строку на исходные составляющие и заполняю массив.
Повторюсь, что сейчас всё работает нормально, просто до этого пытался сделать всё в одном цикле, переопределяя в нём каждый раз границы массива.

Re: Переопределение границ массива с сохранением его элементов

Добавлено: 22 сен 2009, 12:14
Aent
Зачем же циклом считать количество vbCR ?

Код: Выделить всё

n = len(s) - len(replace(s,vbCr,vbNullString))
'или
n = UBound(split(s,vbCr))+1
Да и с массивом полученным по Split можно сразу работать.

Re: Переопределение границ массива с сохранением его элементов

Добавлено: 22 сен 2009, 23:10
AlexZZZ
Aent, как всегда приятно удивляете!

Вот это и есть изящное решение, которое я имел в виду! Правда, константы vba, почему-то в моём случае не работают, а работает так (n - число строк в массиве):

Код: Выделить всё

n = Len(s) - Len(Replace(s, Chr(10), "")) + 1
А Split я вообще раньше не использовал, а зря! Правда , как из него сделать двумерный массив я не разобрался, зато с одномерными работает отлично:

Код: Выделить всё

ListBox1.List = Split(s, Chr(10))