2015-01-20 1 views
1

Я хотел бы объявить dict с ключевыми значениями и получить к нему доступ. Я использую Excel VBA, но я получаю ошибку (Excel 2010).Excel VBA dict как объявление, инициализация и доступ

Структура Я хотел бы объявить это (Python нотации):

ktable = {'a': [1.0, 2.0, 3.0], 
      'b': [2.0, 3.0, 4.0], 
      'c': [5.0, 0.0, 6.0], 
      'd': [8.0, 0.0, 9.0], 
      'e': [1.5, 0.5, 0.0], 
      'f': [0.0, 0.5, 1.0]} 

Мой код заключается в следующем:

Public ktable As New Collection 
Dim kt_a: kt_a = Array(1# , 2# , 3#) 
Dim kt_b: kt_b = Array(2# , 3# , 4#) 
Dim kt_c: kt_c = Array(5# , 0# , 6#) 
Dim kt_d: kt_d = Array(8# , 0# , 9#) 
Dim kt_e: kt_e = Array(1.5, 0.5, 0#) 
Dim kt_f: kt_f = Array(0# , 0.5, 1#) 
ktable.Add kt_a, "a" 
ktable.Add kt_b, "b" 
ktable.Add kt_c, "c" 
ktable.Add kt_d, "d" 
ktable.Add kt_e, "e" 
ktable.Add kt_f, "f" 

Sub test() 
    Debug.Print ktable.Item("a")(1) 
End Sub 

Что я делаю неправильно? Я получаю «Ошибка выполнения 424».

EDIT:

Хорошо, до сих пор был в состоянии работать на код ниже, используя информацию из обоих ответов - в частности замечания об использовании Tools -> Reference был очень полезным. Будет ли подождать некоторое время, а затем

Option Explicit 

Public ktable 

Sub INIT_CONSTANTS() 
    'ktable={'a' : [ 1.0 , 2.0 , 3.0 ], 
      'b' : [ 2.0 , 3.0 , 4.0 ], 
      'c' : [ 5.0, 0.0 , 6.0 ], 
      'd' : [ 8.0, 0.0 , 9.0 ], 
      'e' : [ 1.5, 0.5 , 0.0 ], 
      'f' : [ 0.0, 0.5 , 1.0 ]} 
    Set ktable = CreateObject("Scripting.Dictionary") 
    If Not ktable.Exists("a") Then 
     Dim kt_a: kt_a = Array(1# , 2# , 3#) 
     Dim kt_b: kt_b = Array(2# , 3# , 4#) 
     Dim kt_c: kt_c = Array(5# , 0# , 6#) 
     Dim kt_d: kt_d = Array(8# , 0# , 9#) 
     Dim kt_e: kt_e = Array(1.5, 0.5, 0#) 
     Dim kt_f: kt_f = Array(0# , 0.5, 1#) 
     ktable.Add "a", kt_a 
     ktable.Add "b", kt_b 
     ktable.Add "c", kt_c 
     ktable.Add "d", kt_d 
     ktable.Add "e", kt_e 
     ktable.Add "f", kt_f 
    End If 
End Sub 

Sub test() 
INIT_CONSTANTS 
    Debug.Print ktable.Item("a")(0) 
End Sub 

EDIT2:

Ok, самый короткий ответ ниже. Спасибо @Rory за указание, что мне не нужна промежуточная переменная.

Option Explicit 

Public ktable 

Sub INIT_CONSTANTS() 
    Set ktable = CreateObject("Scripting.Dictionary") 
    If Not ktable.Exists("a") Then 
     ktable.Add "a", Array(1# , 2# , 3#) 
     ktable.Add "b", Array(2# , 3# , 4#) 
     ktable.Add "c", Array(5# , 0# , 6#) 
     ktable.Add "d", Array(8# , 0# , 9#) 
     ktable.Add "e", Array(1.5, 0.5, 0#) 
     ktable.Add "f", Array(0# , 0.5, 1#) 
    End If 
End Sub 

Sub test() 
INIT_CONSTANTS 
    Debug.Print ktable.Item("a")(0) 
End Sub 
+1

Почему Вы используете 'Collection', а не' Dictionary'? –

+1

Это статический элемент, нет смысла изменять числа/ключи во время выполнения, мне просто нужно иметь возможность ссылаться на это легко и он должен быть доступен для всех функций модуля. Редактировать: грамматика – Elric

+1

Как правило, но не догматично, следует предпочесть словарь для коллекции в VBA. Для вашего прецедента (как вы его представили) словарь и коллекция достигают одинакового результата - и вы должны выбрать тот, который наиболее прост в кодировании и развертывании (ceteris paribus). В тех случаях, когда разработчику приходится беспокоиться о поиске/приобретении ссылок, чтобы заставить словарь работать (и не хочет связываться с последним); плохо разработанный, но доступный по существу VBA 'Collection', находит применение. Также подумайте о том, чтобы принять ответы на этот вопрос - и предыдущие вопросы, которые вы задали. –

ответ

1

Вы не можете инициализируется как этот снаружи от Sub. Это работает:

Public ktable As New Collection 

Sub test() 
    Dim kt_a: kt_a = Array(1#, 2#, 3#) 
    Dim kt_b: kt_b = Array(2#, 3#, 4#) 
    Dim kt_c: kt_c = Array(5#, 0#, 6#) 
    Dim kt_d: kt_d = Array(8#, 0#, 9#) 
    Dim kt_e: kt_e = Array(1.5, 0.5, 0#) 
    Dim kt_f: kt_f = Array(0#, 0.5, 1#) 
    ktable.Add kt_a, "a" 
    ktable.Add kt_b, "b" 
    ktable.Add kt_c, "c" 
    ktable.Add kt_d, "d" 
    ktable.Add kt_e, "e" 
    ktable.Add kt_f, "f" 
     Debug.Print ktable.Item("a")(1) 
End Sub 

Или более типично, использует некоторую форму "инициализацию" к югу, как это:

Public ktable As New Collection 

Sub INIT_thing(ByRef C As Collection) 
    Dim kt_a: kt_a = Array(1, 2, 3) 
    Dim kt_b: kt_b = Array(2, 3, 4) 
    Dim kt_c: kt_c = Array(5#, 0#, 6#) 
    Dim kt_d: kt_d = Array(8#, 0#, 9#) 
    Dim kt_e: kt_e = Array(1.5, 0.5, 0#) 
    Dim kt_f: kt_f = Array(0#, 0.5, 1#) 
    C.Add kt_a, "a" 
    C.Add kt_b, "b" 
    C.Add kt_c, "c" 
    C.Add kt_d, "d" 
    C.Add kt_e, "e" 
    C.Add kt_f, "f" 

End Sub 

Sub test() 
    Call INIT_thing(ktable) 
    Debug.Print ktable.Item("a")(1) 
End Sub 
1

Вы вводите путаницу.

Python list == VBA collection 
Python dictionary == Microsoft Scripting dictionary 

Словари в VBA используются следующим образом:

ПРЕДПОСЫЛКИ: ссылку на MS Scripting Runtime в ваши инструменты/ссылки.

Затем создать словарь MS Scripting:

Set MSdict = CreateObject("Scripting.Dictionary") 

Таким образом добавить свои значения:

If Not MSdict.Exists(key) Then 
    MSdict.Add key, value 
End If 
+1

Словарь VBA - это просто 'Microsoft.Scripting.Dictionary' VBA не владеет этим, так что словарь VBA немного выключен :) Кстати. Если вы добавляете ссылки на «Microsoft.Scripting.Runtime», рекомендуется использовать раннее связывание «Dim d as Dictionary», за которым следует «Установить d = новый словарь» - преимущество - скорость и интеллект. –

+0

Настоящий сэр, сейчас отредактирует, спасибо за замечание! –

+0

Есть ли менее скучный способ инициализации? Я воспринимаю 3 * 3 * 6 + 1 строки кода по сравнению с 6 строками в Python ... – Elric

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