Общий способ проверить, находится ли ключ в коллекции в Excel VBA
у меня разные коллекции в моем коде. Некоторые из них содержат объекты (различных видов), другие имеют типы (например, длинные) внутри них.
есть ли способ проверить, содержится ли ключ в коллекции, которая работает как для типов, так и для объектов?
до сих пор у меня есть две функции.
функции:
Private Function ContainsObject(objCollection As Object, strName As String) As Boolean
Dim o As Object
On Error Resume Next
Set o = objCollection(strName)
ContainsObject = (Err.Number = 0)
Err.Clear
End Function
вторая функция:
Private Function ContainsLong(AllItems As Collection, TheKey As String) As Boolean
Dim TheValue As Long
On Error Resume Next
TheValue = AllItems.Item(TheKey)
ContainsLong = (Err.Number = 0)
Err.Clear
End Function
причина двух функций заключается в том, что ContainsObject, похоже, не работает, если я передаю Коллекция, имеющая пары Longs (функция всегда возвращает False.)
С. П.: первая функция является копией третьего ответа от проверить или проверить, существует ли лист
2 ответов
вы должны использовать Variant
в первой функции. Вы можете назначить Object
до Variant
, например, это не ошибка:
Sub Test()
Dim var As Variant
Dim obj As Object
Set obj = Application
var = Application
Debug.Print var
End Sub
но это даст Type Mismatch
ошибка компиляции, т. е. пытается назначить Long
до Object
:
Sub Test()
Dim obj As Object
Dim lng As Long
lng = 3
Set obj = lng
End Sub
Итак, для общей функции (вдоль строк вашего кода), чтобы проверить, если Collection
ключ действителен, вы можете использовать:
Function HasKey(coll As Collection, strKey As String) As Boolean
Dim var As Variant
On Error Resume Next
var = coll(strKey)
HasKey = (Err.Number = 0)
Err.Clear
End Function
тестовый код:
Sub Test()
Dim coll1 As New Collection
coll1.Add Item:=Sheet1.Range("A1"), Key:="1"
coll1.Add Item:=Sheet1.Range("A2"), Key:="2"
Debug.Print HasKey(coll1, "1")
Dim coll2 As New Collection
coll2.Add Item:=1, Key:="1"
coll2.Add Item:=2, Key:="2"
Debug.Print HasKey(coll2, "1")
End Sub
есть полезная статья на MSDN относительно этого. Контекст-VB6, но относится к VBA.
несколько опечаток в комментариях уже были исправлены во время редактирования вашего поста.
В ответ на ваш вопрос я хотел бы осветить соответствующие аспекты.
при использовании ключей в коллекциях имеет в основном три преимущества
- Если заказ изменится, ваш код по-прежнему будет иметь доступ к правильному элементу
- Вы можете напрямую получить доступ к элементу без чтения через весь
коллекция
- Это может сделать код более читабельным.
*но в то же время есть are главным образом три проблемы с использованием ключей в сборники
вы не можете проверить, если ключ существует
вы не можете изменить ключ
вы не можете получить ключ
в соответствии со статьей Pearsons ключи коллекции доступны только для записи - нет способа получить список существующих ключей коллекции. Далее идет через quoted параграф: -
здесь Coll-это объект коллекции, в котором мы будем хранить несколько Объекты то cfile. Коллекция CollKeys используется для хранения ключей объекты CFile, хранящиеся в коллекции Coll. Нам нужна эта секунда. Коллекция, потому что ключи коллекции только для записи - есть невозможно получить список существующих ключей коллекции. Один из улучшения предоставляемых CFiles является возможность получения списка Ключи для Коллекция.
Пользовательские Классы Коллекций
один из способов-перебирать членов коллекции и посмотреть, есть ли совпадение для того, что вы ищете, а другой способ-поймать Item not in collection
ошибка, а затем установите флаг, чтобы сказать, что элемент не существует. Мнения различаются по этим подходам, в то время как некоторые люди считают, что это не хороший метод, чтобы поймать ошибку, в то время как другой раздел чувствует, что это будет значительно быстрее, чем итерация для любое средство к большому собранию.
Поэтому, если мы идем на метод, чтобы поймать ошибку, то номер ошибки мы получаем зависит от того, что именно вызвало ошибку. Нам нужен код, чтобы проверить ошибку. В самом простом смысле.
'c1 is the collection
For i = 1 To c1.Count
Debug.Print Err.Number, Err.Description
If Err.Number <> 0 Then Err.Clear
Next i
процедуры обнаружения ошибок, предлагаемые различными специалистами, отличаются номером ошибки, который они считают важным и включают в свою рутину.Различные часто встречающиеся номера ошибок, связанные с объектом collection:-
-
Error 5
недопустимый вызов процедуры или аргумент.Эта ошибка также может произойти если предпринята попытка вызвать процедуру, которая недопустима на текущая платформа. Например, некоторые процедуры могут быть действительны только для В Microsoft Windows или для Macintosh, и так далее. -
error 438
"объект не поддерживает это свойство или метод объект является экземпляром класса. Экземпляр класса поддерживает некоторые свойства определено в этом определении типа класса и не поддерживает вот этот. -
Error 457
этот ключ уже связан с элементом этого коллекция.Вы указали ключ для члена коллекции, который уже идентифицирует другого члена коллекции. Выберите другой ключ для этого члена. -
Error 91
объектная переменная или переменная блока With не задана.Есть два шаги по созданию переменной объекта. Сначала вы должны объявить объектная переменная. Затем необходимо назначить допустимую ссылку на объект переменная, использующая набор заявление. Вы пытались использовать объект переменной, которая еще не ссылается на допустимый объект. -
Error 450
неверное число аргументов или недопустимое свойство назначение.Количество аргументов в вызове процедуры не совпадает количество обязательных аргументов процедура.Если вы попытались присвоить значение свойству только для чтения,
среди вышеуказанных ошибок номер ошибки 438 считается важным, а другой-5. Я включение рутины функции в мою программу тестирования образца, которая была опубликована Mark Nold 7 лет назад в 2008 году vide SO question определение того, является ли объект членом коллекции в VBA с должным уважением к нему.
некоторые ошибки, такие как ошибка 457, не будут разрешены во время тестового запуска программы. Я попытался заполнить данные дубликатов ключей, он дал ошибку во время тестирования программы, как показано в снимок.
после удаления он показывает правильный результат, как показано на снимок.
возможно, невозможно получить список ключей коллекции с коллекцией vanilla без сохранения значений ключей в независимом массиве. Самая простая альтернатива сделать это-добавить ссылку на Microsoft Scripting Runtime и вместо этого использовать более способный словарь.
Я включил это подход, чтобы получить список ключей в моей программе.
При заполнении коллекции необходимо убедиться, что ключ является вторым параметром и должен быть уникальной строкой.
полный код моей программы.
Sub Generic_key_check()
Dim arr As Variant
Dim c1 As New Collection
Dim dic As Object
With Application
.ScreenUpdating = False
End With
Set dic = CreateObject("Scripting.Dictionary")
dic.CompareMode = vbTextCompare
'Populate the collection
c1.Add "sheet1", "sheet1"
c1.Add "sheet2", "sheet2"
c1.Add "sheet3", "sheet3"
c1.Add "sheet4", "sheet4"
c1.Add "sheet5", "sheet5"
c1.Add 2014001, "Long1"
c1.Add 2015001, "Long2"
c1.Add 2016001, "Long3"
c1.Add 2015002, "Long4"
c1.Add 2016002, "Long5"
'Populate the dictionary
dic.Add "sheet1", "sheet1"
dic.Add "sheet2", "sheet2"
dic.Add "sheet3", "sheet3"
dic.Add "sheet4", "sheet4"
dic.Add "sheet5", "sheet5"
dic.Add "Long1", 2014001
dic.Add "Long2", 2015001
dic.Add "Long3", 2016001
dic.Add "Long4", 2015002
dic.Add "Long5", 2016002
' Get a list of key items by Dictionary Method
Dim N As Variant
For Each N In dic.Keys
Debug.Print "Key: " & N, "Value: " & dic.item(N)
Next
'Test for two types of data whether key exists or not.
If InCollection(c1, "Long1") Then
'If Exists("Long1", c1) Then
Debug.Print "Good"
Else
' If there is error then print out the error number and its description.
Debug.Print Err.Number, Err.Description
Debug.Print "Not Good"
End If
If InCollection(c1, "sheet2") Then
Debug.Print "Good"
Else
Debug.Print Err.Number, Err.Description
Debug.Print "Not Good"
End If
'Checking whether desired key has populated correctly
Debug.Print c1("Sheet1")
Debug.Print c1("Long3")
'Listing out collection items to check theyexist in the collection.
For i = 1 To c1.Count
Debug.Print c1.item(i)
Next i
With Application
.ScreenUpdating = True
End With
Set c1 = Nothing
End Sub
Public Function InCollection(col As Collection, key As String) As Boolean
Dim var As Variant
Dim errNumber As Long
InCollection = False
Set var = Nothing
Err.Clear
On Error Resume Next
var = col.item(key)
errNumber = CLng(Err.Number)
On Error GoTo 0
'5 is not in, 0 and 438 represent incollection
If errNumber = 5 Then ' it is 5 if not in collection
InCollection = False
Else
InCollection = True
End If
End Function
окончательный вывод в соответствии с программой, как показано в окне Immediate, был показан в моментальном снимке.