Динамический массив

  • Автор темы DEN888
  • Дата начала
D

DEN888

#1
Подскажите, пожалуйста.

Есть массив:
(LotusScript)
[codebox]
ReDim MyArr(2, 2)
MyArr(1, 1) = 1
MyArr(2, 1) = 2
MyArr(1, 2) = 3
MyArr(2, 2) = 4
'Добавляем элемент (столбец)
ReDim Precerve MyArr(2, 3)
MyArr(1, 3) = 5
MyArr(2, 3) = 6
[/codebox]

Как добавить строку?

На такой вариант выдает ошибку "Subscript out of range"
[codebox]
ReDim Precerve MyArr(3, 2)
MyArr(3, 1) = 5
MyArr(3, 2) = 6
[/codebox]
 
D

DEN888

#2
Разобрался.
[codebox]Redim MyArr(1, 0)
Redim Preserve MyArr(1, 1)
MyArr(0, 1) = 1
MyArr(1, 1) = 2
Redim Preserve MyArr(1, 2)
MyArr(0, 2) = 3
MyArr(1, 2) = 4
[/codebox]
 

Medevic

Что это ? :)
Lotus team
10.12.2004
3 346
1
#3
Я всегда четко границы указываю: Dim MyArr(1 To 2, 1 To 3).
На всякий случай(потому что есть такая штука как Option Base). -_-
 
D

DEN888

#4
Я всегда четко границы указываю: Dim MyArr(1 To 2, 1 To 3).
На всякий случай(потому что есть такая штука как Option Base). :)
Спасибо за подсказку.

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

Задача заключается в передаче данных в массив, (число столбцов постоянные,
а количество строк меняется, как динамически менять массив?)
а с массива в Excel.

Set Range = AppExl.("A1:B4")
Range.Value = MyArr

Данные, например:

Code Nm
444 test1
333 test2
777 test3
888 test4


Можно, не большой пример, как работать с массивом
 

Akupaka

А че я?.. О.о
04.10.2007
3 360
1
#5
открой хелп, ищи "dynamic arrays", там не много функций для работы с массивами, примеры есть, будут вопросы задавай более конкретно...

единственное скажу, что в нотесе динамические многомерные (многоуровневые) массивы - еще тот гемор, поэтому, чаще всего приходится выкручиваться, работая с массивами как с одномерными, а с их элементами, соотв., как с другими одномерными массивами, так и проще, и глюков меньше... это касается именно изменения размеров многомерного массива...

еще один совет, если заранее известны размеры массива, т.е. не во время компиляции, а именно во время выполнения, т.е. массив изначально динамический, то лучше выполнить операцию Redim единожды, задав эти размеры, а не в цикле увеличивать на 1 "размер", т.к. это корректнее в отношении использования памяти... но это не критично...

по поводу твоей задачи, не ясно откуда данные передаются, и нужен ли массив в этом случае вообще :) может можно просто циклом пройтись по ячейкам... еще не уверен, что "Range.Value = MyArr" сработает, не пробовал ранее...
 
D

DEN888

#6
открой хелп, ищи "dynamic arrays", там не много функций для работы с массивами, примеры есть, будут вопросы задавай более конкретно...

единственное скажу, что в нотесе динамические многомерные (многоуровневые) массивы - еще тот гемор, поэтому, чаще всего приходится выкручиваться, работая с массивами как с одномерными, а с их элементами, соотв., как с другими одномерными массивами, так и проще, и глюков меньше... это касается именно изменения размеров многомерного массива...

еще один совет, если заранее известны размеры массива, т.е. не во время компиляции, а именно во время выполнения, т.е. массив изначально динамический, то лучше выполнить операцию Redim единожды, задав эти размеры, а не в цикле увеличивать на 1 "размер", т.к. это корректнее в отношении использования памяти... но это не критично...

по поводу твоей задачи, не ясно откуда данные передаются, и нужен ли массив в этом случае вообще :) может можно просто циклом пройтись по ячейкам... еще не уверен, что "Range.Value = MyArr" сработает, не пробовал ранее...
Согласен, хелп там хороший, уже смотрел...

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

делаю на оборот

MyArr(3,1)
MyArr(3,2)

говорит Subscript out of range

[codebox]Sub Click(Source As Button)
Dim ExlApp, Range As Variant

Set ExlApp = CreateObject("Excel.Application")
ExlApp.Visible = False
ExlApp.Workbooks.Add

'''''''''''''''''''''''''''''''''''''''''''''''''''''''
'Взято из хелпа
Redim MyArr(2, 2)
MyArr(1,1) = 1
MyArr(2,1) = 2
MyArr(1,2) = 3
MyArr(2,2) = 4

Redim Preserve MyArr(2,3)
MyArr(1,3) = 5
MyArr(2,3)=6
'''''''''''''''''''''''''''''''''''''''''''''''''''''''

Set Range = ExlApp.Range("A1:D10")
Range.Value = MyArr
ExlApp.Visible = True
End Sub[/codebox]
 

NickProstoNick

Статус как статус :)
Lotus team
22.08.2008
1 809
21
#7
я как-то пробовал извращиться с переменной Variant (Не МАССИВ!!!)
пользовал функции Split, Join и в конце FullTrim . Собирал строку с разделителем... а потом разбивал на массив
Это достаточно удобно для одномерных массивов... но думаю можно применить и к n-мерным... главное чтоб строка влезла и не спутать порядок элементов... отсутствие определенного элемента придется заменять пустой строкой или 0 в зависимости от типа :)

в твоем случае можно получить строку 444#test1#333#test2#777#test3#888#test4#
и работать с ней во вложеных циклах
 

Akupaka

А че я?.. О.о
04.10.2007
3 360
1
#8
делаю на оборот

MyArr(3,1)
MyArr(3,2)

говорит Subscript out of range
ну вот не слушаешь, что тебе говорят :)

сделай так:
Код:
dim a as variant
dim b as variant

redim a (0 to 1)
for i = lbound(a) to ubound(a)
redim b (0 to 1)
b(0) = "a" & cstr(i) & "b0"
b(1) = "a" & cstr(i) & "b1"
a(i) = b
next i
на выходе получишь массив
a0b0 a0b1
a1b0 a1b1
 

Medevic

Что это ? :)
Lotus team
10.12.2004
3 346
1
#9
Если не ошибаюсь, то эксель такую конструкцию не примет.

DEN888
Можешь код показать?
 

NickProstoNick

Статус как статус :)
Lotus team
22.08.2008
1 809
21
#10
Код:
Range.Value = MyArr
Я так понимаю ты хочешь передать значения всего массива в одну ячейку? Если не ошибаюсь Ехель понимает только простые типы данных
Потому String или Variant тебе в помощь... иначе строку не склеишь
 
D

DEN888

#11
Если не ошибаюсь, то эксель такую конструкцию не примет.

DEN888
Можешь код показать?
[codebox]Sub Click(Source As Button)
Dim ExlApp, Range As Variant

Set ExlApp = CreateObject("Excel.Application")
ExlApp.Visible = False
ExlApp.Workbooks.Add

Redim MyArr(2, 2)

MyArr(1,1) = 1
MyArr(2,1) = 2

MyArr(1,2) = 3
MyArr(2,2) = 4
'добавляет столбец, а мне нужно строку
'Redim Preserve MyArr(3,2) не работает
Redim Preserve MyArr(2,3)
MyArr(1,3) = 5
MyArr(2,3)=6

'ExlApp.Range("A1:D10") примерный диапазон для примера
'10 заменится на переменную, которая будет суммироваться в цикле
Set Range = ExlApp.Range("A1:D10")
Range.Value = MyArr
ExlApp.Visible = True
End Sub[/codebox]

Код:
Range.Value = MyArr
Я так понимаю ты хочешь передать значения всего массива в одну ячейку? Если не ошибаюсь Ехель понимает только простые типы данных
Потому String или Variant тебе в помощь... иначе строку не склеишь
нет, я хочу передать массив в диапазон ExlApp.Range("A1:D10"), да Variant, то что надо так, содержатся числовые, текстовые, дата данные
 

NickProstoNick

Статус как статус :)
Lotus team
22.08.2008
1 809
21
#12
Для просмотра контента необходимо: Войти или зарегистрироваться

Illegal REDIM
You used a ReDim statement in a context in which it is inappropriate:

* In referring, with the Preserve keyword, to a variable of type variant that doesn't already contain an array. For example:

Dim varV As Variant
varV = 5
ReDim Preserve varV(1 To 3) ' Illegal

Remove the keyword Preserve if you want varV to hold an array, or remove the Redim statement.
* You referred to a member variable of a class as though it were an array, though it isn't. For example:

Class AClass
Public X As Integer
End Class
Dim varV As Variant
Set varV = New AClass
ReDim varV.X(1 To 3) ' Illegal, because X isn't an array.

Declare X as a dynamic array or remove the ReDim statement.
* You referred to a member variable or property of a class as though it held or returned a dynamic array rather than a fixed array. For example:

Class AClass
Public X(1 To 2) As Integer
End Class
Dim varV As Variant
Set varV = New AClass
ReDim varV.X(1 To 3) ' Illegal, because X is a fixed array.

Define X as a dynamic array or remove the ReDim statement.
получается что нельзя акпкопределять массив если он уже был определен ранее... не важно как... в момент декларирования или первого переопределения.
Остается только выполнить Erase перед новым переопределение. Правда тогда потеряешь данные какие в ней были
 
K

K-Fire

#16
Разобраться как работают массивы в лотусе это полезная трата времени.
Но у меня впечатление что задача решается не совсем в нужном направлении.

можно просто циклом пройтись по ячейкам, но такой метод замедляет работу, если полей много
...данные передаются из представления, где отрабатывает условие и записываются в массив
в этом примере, массив меняется в столбце,
Насколько я понимаю использование массива вам нужно только для увеличения производительности? ИМХО никакой разницы не будет, все равно ячейки будут заполнены в цикле, только цикл будет либо в лотусе, либо внутри функции екселя.

Вопрос: ексель на экране отображается в момент заполнения данных или нет?
 

NickProstoNick

Статус как статус :)
Lotus team
22.08.2008
1 809
21
#17
думаю что не отображается... ну я бы по крайней мере так и делал.

А по производительности - считаю что ход верен... зачем весить Лотус если задачу можно перекинуть на другое вспомогательное приложение?

И вообще... нам-то собственно чего... автор темы вообще молчит :(
 

Medevic

Что это ? :)
Lotus team
10.12.2004
3 346
1
#18
K-Fire
Разница будет и весьма существенная. Наверное, эксель после каждого изменения ячеек делает перерасчет формул и т.п. Поэтому выгоднее изменить сразу несколько ячеек. Чем больше, тем лучше.
Я думаю, нужно сделать массив массивов(как написал Akupaka). В эксель выводить построчно.
 

Kee_Keekkenen

Well-known member
05.09.2006
639
4
#19
в случаях, когда типы данных позволяют, то я использую их строковые представления в таких конструкция
Код:
dim tmp variant
const DELIM ="~*~"

'как пример цикл чего-нибудь из чего берем единичное значение
forall s in somthing
tmp = tmp & DELIM & cstr(s)
endforall
tmp = strright(tmp,DELIM)
tmp = split(tmp,DELIM)
по-моему это достаточно эффективно
 
D

DEN888

#20
Разобраться как работают массивы в лотусе это полезная трата времени.
Но у меня впечатление что задача решается не совсем в нужном направлении.



Насколько я понимаю использование массива вам нужно только для увеличения производительности? ИМХО никакой разницы не будет, все равно ячейки будут заполнены в цикле, только цикл будет либо в лотусе, либо внутри функции екселя.

Вопрос: ексель на экране отображается в момент заполнения данных или нет?
Да, массив служит для увеличения производительности.

Excel соответственно скрываю (указал в коде примера :( ).
Разница будет.
Сравните сами.
Варианты:
1) Заполнять массив в цикле. Вывод массива в диапазон.
2) Или заполнять ячейки в цикле.

в данный момент у меня реализованно следующим образом, (в принципе работает быстро)

в цикле узнаю количество для массива, затем в втором цикле заполняю массив.

Результат (~5000 записей, 7 столбцов)
1 вариант 2 сек.
2 вариант ~ 1 минута
разница заметна ;)


думаю что не отображается... ну я бы по крайней мере так и делал.

А по производительности - считаю что ход верен... зачем весить Лотус если задачу можно перекинуть на другое вспомогательное приложение?

И вообще... нам-то собственно чего... автор темы вообще молчит :)
;) почему молчит?