Всем доброго времени суток! Не соображу никак: есть в модуле глобальный динамический массив, процедура получает ссылку на внеш. массив (тоже динамич.) через аргумент, как заставить глобальную ссылку указывать на этот внеш. массив?
[vba]
Код
Private gArr() as integer
Sub fillArray(ByRef xArr() as integer) gArr=xArr 'А потом, например, вызывается рекурсивная процедура, которая этот массив меняет ChangeArray(0) end sub
sub ChangeArray(n as integer) gArr(n, 1) = gArr(n, 2) ChangeArray(n+1) end sub
[/vba]
такой код просто создаёт глоб. копию массива, в исходном внешнем массиве xArr при этом ничего не меняется.
Извиняюсь, если это - заезженная тема. Поиск всяко-разного вываливает кучу, но конкретного решения не нашёл, а теоретические справки типа http://bbs.vbstreets.ru/viewtopic.php?t=26906 самому применить ума не хватает.
Всем доброго времени суток! Не соображу никак: есть в модуле глобальный динамический массив, процедура получает ссылку на внеш. массив (тоже динамич.) через аргумент, как заставить глобальную ссылку указывать на этот внеш. массив?
[vba]
Код
Private gArr() as integer
Sub fillArray(ByRef xArr() as integer) gArr=xArr 'А потом, например, вызывается рекурсивная процедура, которая этот массив меняет ChangeArray(0) end sub
sub ChangeArray(n as integer) gArr(n, 1) = gArr(n, 2) ChangeArray(n+1) end sub
[/vba]
такой код просто создаёт глоб. копию массива, в исходном внешнем массиве xArr при этом ничего не меняется.
Извиняюсь, если это - заезженная тема. Поиск всяко-разного вываливает кучу, но конкретного решения не нашёл, а теоретические справки типа http://bbs.vbstreets.ru/viewtopic.php?t=26906 самому применить ума не хватает.Формуляр
Excel 2003 EN, 2013 EN
Сообщение отредактировал Serge_007 - Четверг, 07.05.2015, 11:40
Option Explicit Public arr(1 To 10) Public Sub www() Dim i& For i = 1 To 10 arr(i) = i Next Stop End Sub Public Sub www1() Dim i& For i = 1 To 10 arr(i) = i * 2 Next Stop End Sub
Через add watch просматриваем массив arr.
Не очень-то понял. См. код.
Code
Option Explicit Public arr(1 To 10) Public Sub www() Dim i& For i = 1 To 10 arr(i) = i Next Stop End Sub Public Sub www1() Dim i& For i = 1 To 10 arr(i) = i * 2 Next Stop End Sub
Не, KuklP, это - не то. Глобальный указатель на массив gArr будут потом использовать другие процедуры модуля. Поэтому нужно просто присвоить ему адрес массива xArr, определённого где-то вовне.
PS: немного дописал исходный код - может понятнее станет. Да, забыл уточнить, массив - 2-мерный, если это может иметь значение.
Не, KuklP, это - не то. Глобальный указатель на массив gArr будут потом использовать другие процедуры модуля. Поэтому нужно просто присвоить ему адрес массива xArr, определённого где-то вовне.
PS: немного дописал исходный код - может понятнее станет. Да, забыл уточнить, массив - 2-мерный, если это может иметь значение.Формуляр
Excel 2003 EN, 2013 EN
Сообщение отредактировал Формуляр - Воскресенье, 11.09.2011, 23:28
Формуляр, чтобы переменную сделать глобальной необходима директива в заголовке модуля: Public gArr() as integer. gArr() после такого объявления будет доступен во всех модулях...
Формуляр, чтобы переменную сделать глобальной необходима директива в заголовке модуля: Public gArr() as integer. gArr() после такого объявления будет доступен во всех модулях...VovaK
Всем удачи. У нас все получится. С уважением, Владимир.
Глобальный указатель на массив gArr будут потом использовать другие процедуры модуля. Поэтому нужно просто присвоить ему адрес массива xArr, определённого где-то вовне.
А у меня что сделано? В одной процедуре присваиваем значения массиву, в другой меняем эти значения. В третьей можем делать с ним-же еще что-то и т.д. А массив один и тот же.
Quote (Формуляр)
Глобальный указатель на массив gArr будут потом использовать другие процедуры модуля. Поэтому нужно просто присвоить ему адрес массива xArr, определённого где-то вовне.
А у меня что сделано? В одной процедуре присваиваем значения массиву, в другой меняем эти значения. В третьей можем делать с ним-же еще что-то и т.д. А массив один и тот же.KuklP
Ну с НДС и мы чего-то стoим! kuklp60@gmail.com WM Z206653985942, R334086032478, U238399322728
Формуляр, чтобы переменную сделать глобальной необходима директива в заголовке модуля: Public gArr() as integer. gArr() после такого объявления будет доступен во всех модулях...
Верное замечание, но сути проблемы не меняет. С областью видимости проблем нет, массив xArr для процедуры fillArray - доступен. Вопрос - как присвоить одной переменной динамич. массива адрес другого, уже существующего.
Quote (KuklP)
А массив один и тот же.
Массив-то и должен быть тот же, только обращаться я к нему хочу не напрямую, а через промежуточный указатель. (Может, не совсем точно выражаюсь, уж не знаю как иначе сформулировать)
Quote (RAN)
А как этот адрес выглядит?
Не очень понял вопрос. В процедуру, где должно происходить присваивание он попадает как аргумент ByRef xArr() as integer В вышестоящей процедуре формируется так:
Code
Private Sub test() Dim bTree() As Integer ReDim bTree(5, 2) fillArray bTree End Sub
Quote (VovaK)
Формуляр, чтобы переменную сделать глобальной необходима директива в заголовке модуля: Public gArr() as integer. gArr() после такого объявления будет доступен во всех модулях...
Верное замечание, но сути проблемы не меняет. С областью видимости проблем нет, массив xArr для процедуры fillArray - доступен. Вопрос - как присвоить одной переменной динамич. массива адрес другого, уже существующего.
Quote (KuklP)
А массив один и тот же.
Массив-то и должен быть тот же, только обращаться я к нему хочу не напрямую, а через промежуточный указатель. (Может, не совсем точно выражаюсь, уж не знаю как иначе сформулировать)
Quote (RAN)
А как этот адрес выглядит?
Не очень понял вопрос. В процедуру, где должно происходить присваивание он попадает как аргумент ByRef xArr() as integer В вышестоящей процедуре формируется так:
Code
Private Sub test() Dim bTree() As Integer ReDim bTree(5, 2) fillArray bTree End Sub
Сергей! Ты работаешь с массивом. А Формуляр хочет с его адресом!?
Зачем? Я понимаю, если работа с массивом ведется через API (rtlmovememory и т.д.). А VBA сам определяет нужные ему параметры через простую ссылку. Как у тебя: Sub www(xArr)
Quote (RAN)
Сергей! Ты работаешь с массивом. А Формуляр хочет с его адресом!?
Зачем? Я понимаю, если работа с массивом ведется через API (rtlmovememory и т.д.). А VBA сам определяет нужные ему параметры через простую ссылку. Как у тебя: Sub www(xArr)KuklP
Ну с НДС и мы чего-то стoим! kuklp60@gmail.com WM Z206653985942, R334086032478, U238399322728
Коллеги! Поймите меня правильно: я не то, что не могу справиться с задачей вцелом - я не могу справиться с ней именно этим способом (который по ряду обстоятельств кажется наиболее подходящим). Форум ведь не только для спасения утопающих, но и для взаимного развития тоже (пусть поправит меня Сергей, если не так). А потребность передать адрес массива в др. переменную у меня возникает регулярно - и каждый раз приходится как-то изголяться...
Коллеги! Поймите меня правильно: я не то, что не могу справиться с задачей вцелом - я не могу справиться с ней именно этим способом (который по ряду обстоятельств кажется наиболее подходящим). Форум ведь не только для спасения утопающих, но и для взаимного развития тоже (пусть поправит меня Сергей, если не так). А потребность передать адрес массива в др. переменную у меня возникает регулярно - и каждый раз приходится как-то изголяться... Формуляр
А что с ним должно произойти? Вы его никак не меняли. Я опять ничего не понял. Вот пример, где меняется исходный.
Да. Мне нужно, чтоб менялся исходный. Но, при этом, eee() не должна ничего заранее знать про обрабатываемый массив. Ф-ция www() должна быть универсальной и вызываться из любого модуля, чтобы передать адрес обрабатываемого массива в eee().
Даже если вы меня убедите в том, что в данном случае такой подход неэффективен, я всё равно, споткнусь об эту же техническую проблему через месяц-другой. Мне нужно решить именно техническую проблему, а не найти оптимальное решение всей задачи. (Именно поэтому я привёл абстрактный короткий пример, а не реальный громоздкий код.) Тем более, что к решению я, похоже, уже близок.
Quote (KuklP)
А что с ним должно произойти? Вы его никак не меняли. Я опять ничего не понял. Вот пример, где меняется исходный.
Да. Мне нужно, чтоб менялся исходный. Но, при этом, eee() не должна ничего заранее знать про обрабатываемый массив. Ф-ция www() должна быть универсальной и вызываться из любого модуля, чтобы передать адрес обрабатываемого массива в eee().
Даже если вы меня убедите в том, что в данном случае такой подход неэффективен, я всё равно, споткнусь об эту же техническую проблему через месяц-другой. Мне нужно решить именно техническую проблему, а не найти оптимальное решение всей задачи. (Именно поэтому я привёл абстрактный короткий пример, а не реальный громоздкий код.) Тем более, что к решению я, похоже, уже близок. Формуляр
Sub qqq() xArr = [a1:b10].Value Call www(xArr) [c1:d10] = xArr End Sub
Code
'=== Module2 Declare Function VarPtrArray Lib "msvbvm60.dll" Alias "VarPtr" (Var() As Any) As Long Declare Sub GetMem4 Lib "msvbvm60.dll" (ByVal SrcPointer As Long, ByVal DstPointer As Long)
Private gArr() As Variant
Sub www(ByRef arr() As Variant) Dim adrLng As Long GetMem4 VarPtrArray(arr), VarPtrArray(gArr) Call eee adrLng = 0 GetMem4 VarPtr(adrLng), VarPtrArray(gArr) 'Думаю, важно обнулить указатель, чтобы избежать влияния gArr на внеш.массив End Sub
Sub eee() Dim i& For i = 1 To UBound(gArr) gArr(i, 1) = gArr(i, 1) * 2 Next End Sub
Пожалуй, тему можно на этом закрыть.
Спасибо RAN и KuklP за искреннее стремление убедить меня не заниматься глупостями. Искомое решение и в самом деле - далеко не самое простое и корректное. Но важно было его найти, хотя бы для того, чтобы иметь возможность от него отказаться.
Ну вот, разобрался, кажись.
Получилось как-то так
Code
'=== Module1 Public xArr() As Variant
Sub qqq() xArr = [a1:b10].Value Call www(xArr) [c1:d10] = xArr End Sub
Code
'=== Module2 Declare Function VarPtrArray Lib "msvbvm60.dll" Alias "VarPtr" (Var() As Any) As Long Declare Sub GetMem4 Lib "msvbvm60.dll" (ByVal SrcPointer As Long, ByVal DstPointer As Long)
Private gArr() As Variant
Sub www(ByRef arr() As Variant) Dim adrLng As Long GetMem4 VarPtrArray(arr), VarPtrArray(gArr) Call eee adrLng = 0 GetMem4 VarPtr(adrLng), VarPtrArray(gArr) 'Думаю, важно обнулить указатель, чтобы избежать влияния gArr на внеш.массив End Sub
Sub eee() Dim i& For i = 1 To UBound(gArr) gArr(i, 1) = gArr(i, 1) * 2 Next End Sub
Пожалуй, тему можно на этом закрыть.
Спасибо RAN и KuklP за искреннее стремление убедить меня не заниматься глупостями. Искомое решение и в самом деле - далеко не самое простое и корректное. Но важно было его найти, хотя бы для того, чтобы иметь возможность от него отказаться. Формуляр