#arrays #excel #vba #dictionary
#массивы #excel #vba #словарь
Вопрос:
У меня есть словарь, и я хочу добавить новые строки к элементам. Моя идея состоит в том, чтобы создать список строк как item
для каждого key
.
Мой код пока:
Sub AccountEntitlements()
Dim sh1 As Worksheet
Dim acc As Worksheet
Dim arr() As Variant
Dim d As Variant
Dim i As Long
Dim count As Long
Set sh1 = Sheets("Sheet1")
Set acc = Sheets("accountsentitlements")
Set d = CreateObject("Scripting.Dictionary")
arr = sh1.Range("D:F")
For i = LBound(arr) To UBound(arr)
If d.Exists(arr(i, 3)) Then
ReDim Preserve arr(UBound(arr) 1) '<- Error line
d(arr(i, 3)) = Array(arr(i, 1))
Else
d.Add Key:=arr(i, 3), Item:=Array(arr(i, 1))
End If
Next i
For count = 1 To d.count - 1
acc.Cells(count 1, "D").Value = UCase(d.Keys()(count))
acc.Cells(count 1, "E").Value = d.Items()(count)
Next count
End Sub
Сообщение об ошибке является Run-time error '9': Subscript out of range
.
Важным блоком кода является
For i = LBound(arr) To UBound(arr)
If d.Exists(arr(i, 3)) Then
ReDim Preserve arr(UBound(arr) 1) '<- Error line
d(arr(i, 3)) = Array(arr(i, 1))
Else
d.Add Key:=arr(i, 3), Item:=Array(arr(i, 1))
End If
Ключом словаря является учетная запись пользователя, а элементами должны быть их группы членства.
Пример:
Ключ = ABCD , элемент= Правообладатель1, Правообладатель2 и т.д.
Как можно расширить массив элементов и включить в него предыдущие записи?
Комментарии:
1. Используйте словарь или коллекцию вместо массива для хранения групп членства. И зачем вообще создавать такой большой массив для перебора?
2. Ошибка заключается в том, что вы можете использовать только
Redim Preserve
последний элемент многомерного массива. Поскольку вы ужеarr= Range("D:F"), and your
повторно выполнили инструкцию Preserve arr(…`, должно завершиться ошибкой. Это НЕ действует на массив в словаре.3. @RonRosenfeld, что вы имеете в виду, говоря «такой большой массив»? Как бы вы разделили массив?
4.
arr = Range("D:F")
создает массив измерений(1 to 1048576, 1 to 4)
. У вас так много элементов в вашей базе данных? Подробное обсуждение смотрите в последней статье Чипа Пирсонса о массивах и диапазонах в VBA5. @RonRosenfeld, у меня 81.000 строк. Спасибо за ссылку. Я проверю это.
Ответ №1:
Среди других проблем:
Вы можете использовать только ReDim
последний элемент многомерного массива.
Ваша строка
arr = sh1.Range("D:F")
создаст 2D-массив на основе 1: arr(1 to 1048576, 1 to 4)
. Если у вас есть база данных с более чем 4*10^6
элементами, возможно, вы захотите рассмотреть другой инструмент.
Таким образом, допустимой командой может быть
Redim Preserve arr(1 to ubound(arr,1), 1 to ubound(arr,2) 1)
Но это не то, что ты делаешь. Чтобы выполнить то, что вы хотите сделать, попробуйте что-то вроде этого:
For i = LBound(arr) To UBound(arr)
If d.Exists(arr(i, 3)) Then
X = d(arr(i, 3))
ReDim Preserve X(UBound(X, 1) 1)
X(UBound(X, 1)) = arr(i, 1)
d(arr(i, 3)) = X
Else
d.Add Key:=arr(i, 3), Item:=Array(arr(i, 1))
End If
Next i
Но почему бы просто не использовать Dictionary
или Collection
для хранения вашего списка элементов. Тогда вам вообще не нужно беспокоиться об изменении размера вашего массива.
Ответ №2:
Большое спасибо за вашу помощь (@Ron Rosenfeld)!
Ниже приведена моя заключительная часть кода.
For i = LBound(arr) To UBound(arr)
If d.Exists(arr(i, 3)) Then
d(arr(i, 3)) = d.Item(arr(i, 3)) amp; "," amp; arr(i, 1)
Else
d.Add Key:=arr(i, 3), Item:=arr(i, 1)
End If
Next i
Я все еще проверял, следует ли мне объединять строки с amp; "," amp;
или с JOIN()
функцией, но в конечном итоге остановился на первом варианте.
Что касается моего размера массива, я добавил счетчик строк, чтобы соответствовать длине массива. lrow = sh1.Cells(Rows.count, "D").End(xlUp).Row
.