VBA - Поиск по словарю - несоответствие типов - PullRequest
0 голосов
/ 27 июня 2018

Итак, я учусь использовать словари, но столкнулся с проблемой типа. В приведенном ниже коде я получаю сообщение об ошибке.

Несоответствие типов

Каждый раз, когда я пытаюсь позвонить If Not target.SearchItem(sKey) Is Nothing Then. Я хочу, чтобы он возвращал объект, тогда, если это не Nothing, я могу преобразовать его обратно в long.

For Each target In dList.getArray
    For Each key In aList.getArray(1).getKeys
        sKey = CStr(key)
            'Error occurs here - as Type mismatch
            If Not target.SearchItem(sKey) Is Nothing Then
                cData.setData(sKey) = CLng(target.SearchItem(sKey))
                target.removeData = sKey
             Else
                 'if value doesn't exists it will just be 0
                  cData.setData(sKey) = 0
              End If
    Next key
Next target

data - мой словарь, который находится в отдельном классе:

Property Get SearchItem(name As String) As Variant
    If data.exists(name) Then
        'becomes a Variant/Integer - data(name) is a Variant/long
        Set SearchItem = CVar(data(name))
    Else
        'Should return Nothing if item doesnt exist
        Set SearchItem = Nothing
    End If
End Property

Обновление: чтобы объяснить проблему, я немного подробнее. Даже если я верну его как вариант, он все равно будет частично целочисленным, и поэтому, если не target.SearchItem(sKey) Is Nothing Then вернет несоответствие, поскольку ему нужен объект, а VBA не читает, это вариант или что-то в этом роде. Есть ли что-нибудь вроде Nothing, null или равно, что работает долго? Это решило бы проблему.

Этот код ниже возвращает значение, пока я этого хочу, но я не могу использовать -99, так как это повредит анализ данных. Это должно быть что-то, что не является значением

Property Get SearchItem(name As String)
    If data.exists(name) Then
        SearchItem = data(name)
    Else
        'SearchItem = Nothing
         SearchItem = -99
    End If
End Property

Ответы [ 3 ]

0 голосов
/ 27 июня 2018
  1. If Not target.SearchItem(sKey) Is Nothing Then
    • Это означает, что сохраненный объект является объектом
  2. cData.setData(sKey) = CLng(target.SearchItem(sKey))
    • Единственный способ, которым эта строка будет работать с Объектом, - это то, что Объект имеет значение по умолчанию, которое можно преобразовать в long. Если значение объекта по умолчанию возвращает значение, которое можно преобразовать в long.

Работает ли Clng(Object) с реальным Объектом, который хранится в Словаре?

Если вы храните смешанный тип данных, тогда SearchItem проверьте, являются ли возвращаемые данные объектом.

Property Get SearchItem(name As String) As Variant
    If isObject(data(name)) Then
        Set SearchItem = data(name)
    Else
        SearchItem = data(name)
    End If
End Property

Я бы не конвертировал тип данных в этом методе. Вместо этого я бы создал один или несколько отдельных методов или преобразовал бы тип данных в точке использования.

Function getTypedItem(Key as Variant, DataType as VbVarType) as Variant

IsNumeric (Obj)

Поскольку вы используете фактические ключи словаря, мы знаем, что он что-то вернет, и в этом контексте .Exists не требуется. Что вам нужно сделать, это проверить, возвращает ли он объект, прежде чем проверять, является ли Object Is Nothing.

If IsObject(Target.SearchItem(sKey)) Then
    If IsNumeric(Target.SearchItem(sKey)) Then
        cData.setData(sKey) = CLng(Target.SearchItem(sKey))
    End If
ElseIf IsNumeric(Target.SearchItem(sKey)) Then
    cData.setData(sKey) = CLng(Target.SearchItem(sKey))
End If
0 голосов
/ 27 июня 2018

К сожалению, в VBA нет обнуляемых примитивных типов, таких как обнуляемый Long. Обычный обходной путь - использовать вариант, которому можно присвоить значение Empty и который также может содержать нативно Long.

Я бы переписал вашу собственность следующим образом:

Property Get SearchItem(name As String) As Variant
    If Data.exists(name) Then
        SearchItem = Data(name)
    Else
        SearchItem = Empty
    End If
End Property

И тест на пустоту будет:

If Not IsEmpty(target.SearchItem(sKey)) Then ...
0 голосов
/ 27 июня 2018

Я не думаю, что вы можете использовать Set для назначения целого числа, поэтому свойство не будет работать, если элемент словаря равен Integer. Возможно использование:

Property Get SearchItem(name As String) As Variant
    If data.exists(name) Then
        'becomes a Variant/Integer - data(name) is a Variant/long
        SearchItem = data(name)
        ...
...