2016-08-29 14 views
0

У меня есть приложение, для которого я в настоящее время использую объект словаря (в частности, это словарь словарей словарей, поэтому каждый поиск имеет три шага, если это имеет смысл!). Я делаю большое количество поисков на этих словарях и умножаю результаты вместе.excel словарь object error

Проблема в том, что в предыдущей версии приложения я использовал функцию VLookup для выполнения этой функции, и она будет ошибочной, когда я попытаюсь найти ключ, которого не было. Теперь он возвращает «Пустое», которое Excel с удовольствием размножается тем, что у меня уже было, и возвращает ноль. Это трудно отследить, и я бы очень хотел, чтобы он возвращал ошибку, как раньше.

Есть ли что-то, что я могу изменить, чтобы вернуть его, как это было бы с VLookup, или мне нужно создать новый модуль класса для этого? Модуль класса, скорее всего, потребует от меня перезаписать большой объем кода, который я бы хотел избежать (есть сотни запросов, которые мне нужно будет обновить в коде).

Спасибо.

Вот некоторые из моего кода:

Это модуль, который я использую для загрузки во всех таблицах в словаре:

Sub LoadFactorsAndBaseRates() 
    Dim t As Double 
    t = Timer 
    Dim n As Name 
    Dim TempArray() 
    Dim dict1 As Dictionary 
    Dim dict2 As Dictionary 
    Dim i As Integer 
    Dim j As Integer 
    For Each n In ThisWorkbook.Names 
     If InStr(1, n.RefersTo, "#") <> 0 Or InStr(1, n.RefersTo, "\") Then GoTo skipname 
     If Not FactorLookup.Exists(n.Name) And n.RefersToRange.Parent.Name <> "Rate Matrix" And InStr(1, n.Name, "Print") = 0 And InStr(1, n.Name, "FilterDatabase") = 0 And n.Name <> "Policies" Then 
      Set dict1 = New Dictionary 
      On Error GoTo err1 
      TempArray = n.RefersToRange.Value 
      For j = 1 To n.RefersToRange.Columns.Count 
       On Error Resume Next 
       Set dict2 = New Dictionary 
       For i = 1 To UBound(TempArray, 1) 
        dict2.Add TempArray(i, 1), TempArray(i, j) 
       Next i 
       dict1.Add j, dict2 
      Next j 
      Erase TempArray 
      FactorLookup.Add n.Name, dict1 
     End If 
skipname: 
    Next n 
    Exit Sub 
err1: 
    If Err.number = 1004 Then Resume skipname 
End Sub 

А вот пример кода поиска:

CoverageColumn = 2 
'Base Rate 
     Temp = FactorLookup("Base_Rates")(CoverageColumn)(State & "_" & Company & "_" & Terr) 

If Vehicle <> "Snowmobile" Then 
'Class 1 
    x = FactorLookup("Class1")(CoverageColumn)(State & "_" & Company & "_" & Class1) 
    Temp = xRound(Temp * x, 1) 
'Class 2 
    x = FactorLookup("Class2")(CoverageColumn)(State & "_" & Company & "_" & Class2) 
    Temp = xRound(Temp * x, 1) 
'Class 3 
    x = FactorLookup("Class3")(CoverageColumn)(State & "_" & Company & "_" & Class3) 
    Temp = xRound(Temp * x, 1) 
'Class 4 
    x = FactorLookup("Class4")(CoverageColumn)(State & "_" & Company & "_" & Class4) 
    Temp = xRound(Temp * x, 1) 

Код в основном представляет собой кучу страниц этого: посмотрите вверх, умножьте, округлите до ближайшей десятой, повторите. Иногда есть шаг, на котором мы добавляем вместо умножения.

Функция xRound добавляет 0,0000001, а затем использует функцию Round для округления до указанного числа десятичных знаков (для учета странности функции округления Excel VBA).

+0

Можете ли вы проверить данные, чтобы увидеть, пуст ли он до умножения? Например. 'If ​​IsEmpty (MyVariable) = False then ...' –

+0

Прежде чем мы получим дальнейшее, мне любопытно, почему у вас есть три уровня вложенного словаря. Я предполагаю, что вы используете их для построения связей между таблицами, а затем запрашиваете эти отношения. В этом случае я бы определенно предложил перейти к системе, созданной для этих видов запросов (либо для миграции в базу данных, либо просто для непосредственного запроса Excel непосредственно, как базы данных с использованием ADO). – Mikegrann

+0

Да, перед умножением данные пустые, но добавление операторов «if» вокруг каждого отдельного поиска было бы чрезвычайно трудоемким. Я могу это сделать, но это то, что я пытаюсь избежать, если это возможно. – whitesox130

ответ

0

Вам необходимо создать функцию «обернуть» словарь верхнего уровня, чтобы вы могли вызвать его с помощью трех «ключей» и вернуть значение ошибки, если эта комбинация не существует.

Function DoFactorLookup(k1, k2, k3) As Variant 
    Dim d, d2, rv 

    rv = CVErr(xlErrNA) ' #N/A error value 

    If FactorLookup.exists(k1) Then 
     Set d = FactorLookup(k1) 
     If d.exists(k2) Then 
      Set d2 = d(k2) 
      If d2.exists(k3) Then 
       rv = d2(k3) 
      End If 
     End If 
    End If 

    DoFactorLookup = rv 
End Function 
+0

Я закончил тем, что использовал этот подход. Спасибо за помощь. – whitesox130

Смежные вопросы