По мотивам ЭТОЙ темы. Здравствуйте Уважаемые! Давно хотел уточнить у Вас, дорогие друзья, такой вопрос. Есть Словарь элементами которого являются Массивы Как (и можно ли в принципе), напрямую, без передачи Массива в переменную, изменить какое нибудь его значение? Прочитать единичное значение напрямую получается, а вот изменить никак. Макрос складывает отдельные значения по ключу. Может где-то в синтаксисе туплю...
Код
Private Sub CommandButton1_Click()
Dim x(), iArr(), newArr(), I&, J&
x = Range("A1:F4").Value
On Error Resume Next
With CreateObject("Scripting.Dictionary")
For I = 1 To UBound(x)
.Add x(I, 1), Application.Index(x, I, 0)
If Err <> 0 Then
'так работает
iArr = .Item(x(I, 1))
For J = 2 To UBound(iArr)
iArr(J) = iArr(J) + x(I, J)
Next
.Item(x(I, 1)) = iArr
' 'необходимо увеличить каждый элемент массива на определенное значение
' 'прямое изменение элемента массива не работает
' For J = 2 To UBound(.Item(x(I, 1)))
' .Item(x(I, 1))(J) = .Item(x(I, 1))(J) + x(I, J)
' Next
Err.Clear
End If
Next
ReDim newArr(1 To .Count, 0 To UBound(x, 2)): I = Empty
For Each iKey In .Keys
I = I + 1: newArr(I, 0) = I
'простое обращение к элементу массива работает
For J = 1 To UBound(.Item(iKey))
newArr(I, J) = .Item(iKey)(J)
Next
Next
End With
Range("A16").Resize(UBound(newArr), UBound(newArr, 2) + 1) = newArr
End Sub
Всех причастных с праздником! Мирного неба над головой.
Sanja, надо всё-таки было в Курилке "развивать" тему
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
БМВ написал: чтоб так, "по наглому", можно было обратится для записи.
С Михаилом неинтересно - слишком быстро думает.
В #8 выражение da("Key1") возвращает переменную типа variant, являющуюся массивом. Мы изменяем эту переменную, но объекту da про это ничего не известно.
Sanja написал: Прочитать единичное значение напрямую получается, а вот изменить никак.
видимо, есть на то весомые причины при попытке изменить зачение элемента массива, никто об ошибке не пишет, но и не делает ничего! массив из словаря передать переменной, изметить значение, затолкать массив обратно в словарь
Код
Sub Test()
Dim ar, dc, i&
Set dc = CreateObject("Scripting.Dictionary")
ar = Array("A", "B", "Start")
dc.Add "test", ar: Debug.Print "1. " & dc("test")(2)
dc("test")(2) = "In dc var": Debug.Print "2. " & dc("test")(2)
ar = dc("test")
ar(2) = "in external var"
dc("test") = ar: Debug.Print "3. " & dc("test")(2)
End Sub
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
? См. #12 В строке 18 из #1 (не закомментированной) свойство .Item(x(I, 1)) возвращает нам массив Variant/Variant(). Мы в этом возвращенном массиве (временная переменная?) меняем один из элементов. На массив, хранящийся в словаре, это действие не влияет.
sokol92, Владимир, приветствую. да это я видел. Про Exists написал только по причине того что нечего ошибку теребонькать и это не относится к основному вопросу.
Ігор Гончаренко написал: массив из словаря передать переменной, изметить значение, затолкать массив обратно в словарь
Игорь, я собственно так и делаю (строки кода с 10 по 14 в стартовом сообщении). Просто хотелось убедиться что прямого доступа для изменения элементов массива, который сам является элементом словаря, НЕТ. Все, всем большое спасибо! Скоро пограничные сутки заканчиваются можно и коньячку 'потеребонькать' ! Ну, за ПВ!
Sanja, как мог, порылся. Результаты выкладываю (не впечатляющие). 1. В первом тесте записал по выдаваемом словарем адресу - инфу (2), т.к. инфа не дошла до внутренностей библы, делаю вывод - данные отдаются по ByVal, залезть в библу не смогу. 2. Во втором тесте попробовал запихнуть весь массив, опять же не вышло (хотя в этом же тесте, обмен инфой между двумя массивами по указателю проходит нормально), из чего вывод - da("Key1") это не ссылка/указатель, а ByVal, которую нам выкладывает библа. В свои внутренности не пускает. 3. В третьем тесте можно хранить указатель/ссылку в библиотеке и работать с ним, как с обычным массивом... Ах да... это VBA, а не С++
В итоге: прямого доступа к элементам коллекции - не нашел. Работа только через методы самой библиотеки, с передачей информации по значению - ByVal.
Код
Private Declare PtrSafe Function VarPtrArray Lib "VBE7" Alias "VarPtr" (ByRef Var() As Any) As LongPtr
Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Sub test1()
Dim da As Object, y As Long
Set da = CreateObject("Scripting.Dictionary")
da("Key1") = Array(0&, 1&, 2&)
y = 2& 'хотим 2
CopyMemory ByVal VarPtr(da("Key1")(1)), ByVal VarPtr(y), 4&
'похоже мы переписали память, которая ByVal
Debug.Print da("Key1")(1)
End Sub
Sub test2()
Dim da As Object, y
Dim Arr1() As Long
Dim Arr2() As Long
ReDim Arr1(0 To 5)
ReDim Arr2(0 To 5)
Set da = CreateObject("Scripting.Dictionary")
da("Key1") = Arr1
'так можем, смотрим данные из второго массива
Arr2(5) = 2
CopyMemory ByVal VarPtrArray(Arr1), ByVal VarPtrArray(Arr2), 4 * 6
Debug.Print Arr1(5)
'не можем записать массив по адресу, который выдает словарь
CopyMemory ByVal VarPtrArray(da("Key1")), ByVal VarPtrArray(Arr2), 4 * 6& 'здесь возникает ошибка
Debug.Print da("Key1")(1)
End Sub
Sub test3()
Dim da As Object, y, x
Dim Arr1()
Dim Arr2()
ReDim Arr1(0 To 5)
ReDim Arr2(0 To 5)
Set da = CreateObject("Scripting.Dictionary")
da("Key1") = VarPtrArray(Arr1)
' все! дальше извлечь данные по ссылке/указателю в VBA - не представляется работоспособным
Debug.Print da("Key1")
End Sub
Парни, все что мог, за время, которое удалось выкроить. Всех с Праздником!
Off Сейчас пришло в голову, что эту задачу я решал, когда писал программу Life (по ссылке выкладывал все исходники на репозитории, кому интересно). Там так же в контейнере std::unordered_map (хранит пары ключ-значение с уникальными ключами) хранил байтовый массив, точнее указатели, и доступ был к элементам байтового массива через указатель, и даже больше - работал с отдельными битами в каждом байте. Все это через прямую адресацию к памяти. Полный доступ к памяти, конечно, сильный инструмент. Sanja, переходите на С++ Свои dll для Excel, скорость и защита. P.S. будет с кем живительные выстрелы в ногу пообсуждать