Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Программирование, связанное с MS Office > Копирование массива в переменную Variant


Автор: НеуФазендник 25.5.2006, 16:40
Вопрос простой. Извиняюсь за тривиальность.
Dim a(10) As Integer
Dim c(10) As Integer
...
b = a() ' это присвоение работает (по крайней мере значение переменной b  в отладочном окне читаются как массив.
...
c() = b ' Это присваивание не работает. 

Прошу подсказать, как правильно упаковать массив в одну переменную, а затем снова распаковать в массив.

Необходимость в этом возникла из-за того, что есть несколько подпрограмм, которые запускаются событийно время от времени, и между ними необходимо передавать большой объем информации, причем не через параметры, а просто через глобальные переменные проекта. Сами глобальные переменные тоже имеют несколько наборов-контекстов, которые храняться в массиве типа Variant. В конкретный момент массив разворачивается в некий конкретный контекст по определенному индексу, и уже этот контекст передается одной из подпрограмм в виде конкретных переменных с конкретными значениями. Беда в том, что среди этих переменных есть и массивы. Чтобы все работало, желательно сделать рабочей схему хранения данных типа e(f,g)=h, где h - Variant, в том числе и массив с некоторой произвольной размерностью.
 

Автор: Akina 25.5.2006, 17:23
Цитата(НеуФазендник @  25.5.2006,  17:40 Найти цитируемый пост)
b = a() ' это присвоение работает (по крайней мере значение переменной b  в отладочном окне читаются как массив.

Правильно. Потому что а() - это не массив, а ссылка на массив. Переменная может хранить ссылку, переменной можно присвоить значение ссылки.

Цитата(НеуФазендник @  25.5.2006,  17:40 Найти цитируемый пост)
c() = b ' Это присваивание не работает.

Тоже правильно - ссылке нельзя присвоить значение переменной.

Цитата(НеуФазендник @  25.5.2006,  17:40 Найти цитируемый пост)
Необходимость в этом возникла из-за того, что [skipped]

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

Автор: cardinal 25.5.2006, 18:17
Если делается копия массива, то это значит, что делается копия всех его элементов! 

Автор: Staruha 25.5.2006, 21:00
Код

Dim b As Range 
Set b = Range(Cells(2, 1), Cells(9, 1))

 может так 

Автор: НеуФазендник 25.5.2006, 21:20
Цитата(Staruha @ 25.5.2006,  21:00)
Код

Dim b As Range 
Set b = Range(Cells(2, 1), Cells(9, 1))

 может так

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

Добавлено @ 21:25 
Akina, Спасибо.
Идея со ссылками при всей ее очевидности мне совсем не пришла в голову.
Это выход. Я еще помозгую. Если возникнут вопросы, буду задавать smile

Добавлено @ 21:33 
Akina, нет букваря по VBA, подскажи пожалуйста, как правильно связать массив со ссылкой вместо моего c() = b 

Автор: Akina 26.5.2006, 08:51
Цитата(НеуФазендник @  25.5.2006,  22:20 Найти цитируемый пост)
нет букваря по VBA

А кнопка F1 есть? букварь лежит прямо под ней...

Цитата(НеуФазендник @  25.5.2006,  22:20 Найти цитируемый пост)
как правильно связать массив со ссылкой вместо моего c() = b

Это что - попытка задать тот же вопрос другими словами?  

Автор: НеуФазендник 26.5.2006, 19:20
F1 in Einglesh.
What should I search?
I therefore ask, that I can not take advantage of the information. 

Автор: Aloha 26.5.2006, 20:27
НеуФазендник
Есть, по крайней мере, 2 варианта (хотя в действительности их больше).
1-й вариант
Цитата
Each element of an array must have its value assigned individually. 

Посему присваиваем каждому элементу массива его значение в отдельности.
Для начала инициализируем массив a().
Код
Dim a(10) As Integer
Sub ArrayIni()
  Dim i As Integer
  For i = 0 To 10
    a(i) = i
  Next i
End Sub

Потом работаем с массивами b() и c()
Код
Sub Test_1()
  Dim b() As Integer
  Dim c() As Integer
  
  Call ArrayIni
  
  ReDim b(UBound(a))
  For i = LBound(a) To UBound(a)
    b(i) = a(i)
  Next i

  ReDim c(UBound(b))
  For i = LBound(b) To UBound(b)
    c(i) = b(i)
  Next i

  Debug.Print " a"; Tab; " b"; Tab; " c"
  For i = LBound(a) To UBound(a)
    Debug.Print a(i); Tab; b(i); Tab; c(i)
  Next i
  
End Sub


2-й вариант
Цитата
You can place a whole array in a Variant, resulting in a single variant variable containing the whole array: 
Dim MyArr As Variant
MyVar = Arr2()
You then reference the elements of the array in the variant with the same subscript notation as for a normal array

В переменной типа Variant можно хранить (ссылку на) массив. (На это собственно указал Akina).
При этом остается возможность использовать обычную (для массивов) нотацию при обращении к отдельным элементам.
Код
Sub Test_2()
  Dim b As Variant 'если явно не объявлять тип переменных b и с
  Dim c As Variant 'все равно по умолчанию они будут иметь тип Variant

  Call ArrayIni
  
  b = a()
  c = b

  Debug.Print " a"; Tab; " b"; Tab; " c"
  For i = LBound(a) To UBound(a)
    Debug.Print a(i); Tab; b(i); Tab; c(i)
  Next i
  
End Sub

    

Автор: cardinal 26.5.2006, 21:00
Цитата(Aloha @  26.5.2006,  19:27 Найти цитируемый пост)
При этом остается возможность использовать обычную (для массивов) нотацию при обращении к отдельным элементам.

Только к отдельным элементам копии! (а не ссылки или указателя), что показывает след. пример
Код

Option Explicit

Private Sub Command1_Click()
Test_2
End Sub

Sub Test_2()
  Dim a(1 To 3) As Integer
  Dim b As Variant 'если явно не объявлять тип переменных b и с
  Dim c As Variant 'все равно по умолчанию они будут иметь тип Variant
  Dim i As Integer

  a(1) = 4
  a(2) = 3
  a(3) = 2
     
  b = a()
  c = b

  c(1) = 11
  
  Debug.Print " a"; Tab; " b"; Tab; " c"
  For i = 1 To UBound(a)
    Debug.Print a(i); Tab; b(i); Tab; c(i)
  Next i
    
End Sub
 

Автор: НеуФазендник 27.5.2006, 08:16
Aloha, спасибо. Второй вариант то - что искал. Первый не пройдет, т.к. не решена исходная задача - сохранить некий контекст переменных, в том числе и массивы в некотором массиве f(g,h) as variant, где g-номер контекста а h-условный номер некоторой переменной. К примеру 
f(1,0)= имя рабочего листа, которому принадлежит контекст номер 1
а
f(5,16)= к примеру array(10) of integer 'как раз наш массив a() для контекста номер 5

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

Теперь же, думаю, все реализуется по задумке! Спасибо! 

Автор: НеуФазендник 27.5.2006, 08:33
cardinal, спасибо за дополнение. Все понятно. 

Автор: cardinal 27.5.2006, 14:31
Цитата(НеуФазендник @  27.5.2006,  07:33 Найти цитируемый пост)
cardinal, спасибо за дополнение.

Пожалуйста. smile  

Автор: Aloha 27.5.2006, 15:12
НеуФазендник
Если все так сложно в твоем приложении, может быть имеет смысл создать некую объектную модель приложения. И использовать, например, при обращении к свойствам нотацию:
Код
myMainObject.ItsChildObject. … .ItsChildObject.Property_01=

вместо
Код
f(5,16)=
 

Автор: НеуФазендник 28.5.2006, 09:00
Aloha, я ,в общем, уверен, что так было бы правильнее сделать. Просто мешает этому мой консерватизм. Так уж вышло, что Excel как оболочку я узнал в тот момент, когда уже немного умел работать в Delphi и делал в дельфях не сложные базы данных.
Так вот почувствовав силу Excel я забыл про Delphi. Причина элементарна - она в простоте Excel. Здесь достаточно сложные вещи создаются и модифицируются с минимумом затрат времени. Сейчас не будем говорить об обратной стороне медали - она тоже есть. Тем не менее Excel очень подходящая среда для реализации новых идей именно на той стадии, пока концепция и логика только формируются, и все на ходу переделывается и меняется. Как только всё устаканиться - можно формулировать техзадание программисту и писать нормальное ЕХЕ приложение в любой другой среде.
Так вот по этой же причине я не леплю в Excele никаких форм. Рабочий лист Excel настолько напичкан всевозможными встроенными полезностями от формул с функциями до условного форматирования, что большинство не тривиальных задач решается вообще самим листом. Ну уж если не решается - берусь дописывать код. Но опять таки - никаких объектов не на листе ни в коде! В том числе и управляющих кнопок. Изменения любой ячейки листа прекрасно анализируются в Worksheet_Change. А смещение фокуса ввода через Worksheet_SelectionChange. А дальше могучий оператор IF решает все вопросы.
В моем коде все как у первоклассника в прописях. Никакого излишнего ООП. Чем проще код, тем он надежнее работает. Хотя, как видишь, коль тема поднята, иногда появляются нетривиальные структуры, где можно было бы и отступить от принципов. Но, поверь - тяжело smile
 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)