2015-09-02 7 views
4

Я хотел бы заполнить словарь несколькими свойствами элемента. Пример:Двумерный массив как элемент словаря

Sample data

Я имел в виду иметь предмета 1 и Пункт 2 как Dictionary ключи со array, который будет проводить свои свойства. Мне нужно было бы иметь возможность отдельного доступа к каждому свойству элемента, чтобы их конкатенировать, поскольку одна строка не является вариантом.

Я думаю о чем-то вроде ниже псевдокоде:

With Workbooks("testing macro").Sheets(test).Range("D7:G8") 

    For i = 1 To .Rows.count 

     items_dict.Add Key:=.Cells(i, 1).Value, _ 
Item:= array(i,1)= .cells(i,2).value array(i,2)=.cells(i,3).value array(i,3).cells(i,4) 
+0

Что такое вопрос? –

+0

Почему бы вам не использовать класс и коллекцию? – sous2817

+0

То, как я определил словарь, не работает. Я просто написал это, чтобы описать, что, как мне кажется, должно произойти. Я не использую коллекцию, потому что мне нужна ключевая функция словаря, чтобы выборочно извлекать данные. то есть иметь возможность получать информацию о конкретном элементе, который я имею в виду. – newdimension

ответ

1

Вот простой пример использования класса и коллекции (в основном модифицированные из примеров here:

Класс довольно просто (название категории - Employee):

Option Explicit 

Private pName As String 
Private pAddress As String 
Private pSalary As Double 

Public Property Get Name() As String 
    Name = pName 
End Property 
Public Property Let Name(Value As String) 
    pName = Value 
End Property 
Public Property Get Address() As String 
    Address = pAddress 
End Property 
Public Property Let Address(Value As String) 
    pAddress = Value 
End Property 
Public Property Get Salary() As Double 
    Salary = pSalary 
End Property 
Public Property Let Salary(Value As Double) 
    pSalary = Value 
End Property 

Вот код ошибки:

Option Explicit 

Sub test() 
    Dim counter As Integer 

    Dim Employees As Collection 
    Dim Emp As Employee 

    Dim currentEmployee As Employee 


    Set Employees = New Collection 

    For counter = 1 To 10 
     Set Emp = New Employee 

     Emp.Name = "Employee " & counter 
     Emp.Address = "Address " & counter 
     Emp.Salary = counter * 1000 

     Employees.Add Emp, Emp.Name 

    Next counter 

    Set currentEmployee = Employees.Item("Employee 1") 


    Debug.Print (currentEmployee.Address) 

End Sub 

Как вы можете видеть, я добавление элементов в мой класс указания ключа:

Employees.Add Emp, Emp.Name 

, которые вы можете использовать, чтобы непосредственно из без зацикливания.

1

Вы также можете сделать то, что вы изначально предложили, используя функцию Array для создания массива Variant. Если ваша структура данных становится такой сложной, обычно лучше иметь класс модели данных, как в ответе @ sous2817. Но этот метод полезен для adhoc, throwaway code.

Dim r As Range 

For Each r In ['[testing macro.xlsx]test'!D7:G8].Rows 
    ItemsDict.Add r.Cells(1).Value, Array(_ 
     r.Cells(2).Value, _ 
     r.Cells(3).Value, _ 
     r.Cells(4).Value) 
Next 
+0

Это хороший способ сделать это. Что происходит с массивом, когда мы перемещаемся по строкам? Мы в основном делаем 'Array (Value1, Value2, Value3)', это данные, которые просто перезаписываются? Что произойдет, когда мы перейдем во второй ряд? Кроме того, как VBA знает, чтобы установить 'Array [1] =" Value1 "' и не вызывать 'Array [1]'? – newdimension

+0

Array (1, 2, 3) создает новый массив с элементами 1,2,3. Каждый раз через цикл for вызывается Array(), поэтому для каждой строки создается новый массив. Вы должны индексировать dict как Debug.Print ItemsDict («Key») (0) (чтобы получить первый элемент). Не уверен, каков ваш последний вопрос. – Tmdean

+0

Получил, спасибо! – newdimension

1

Другой подход - словарь словарей:

Option Explicit 

Public Sub nestedList() 
    Dim ws As Worksheet, i As Long, j As Long, x As Variant, y As Variant, z As Variant 
    Dim itms As Dictionary, subItms As Dictionary 'ref to "Microsoft Scripting Runtime" 

    Set ws = Worksheets("Sheet1") 
    Set itms = New Dictionary 

    For i = 2 To ws.UsedRange.Rows.Count 

     Set subItms = New Dictionary   '<-- this should pick up a new dictionary 

     For j = 2 To ws.UsedRange.Columns.Count 

      '   Key: "Property 1",   Item: "A" 
      subItms.Add Key:=ws.Cells(1, j).Value2, Item:=ws.Cells(i, j).Value2 

     Next 

     '  Key: "Item 1",    Item: subItms 
     itms.Add Key:=ws.Cells(i, 1).Value2, Item:=subItms 

     Set subItms = Nothing    '<-- releasing previous object 

    Next 
    MsgBox itms("Item 3")("Property 3")  'itms(ws.Cells(3, 1))(ws.Cells(1, 3)) = "I" 
End Sub 

.

Он регулирует динамически общее число строк и столбцов, поэтому нет необходимости

Преимущества над коллекциями обслуживания является то, что вы можете проверить, если ключей существуют или нет

Самой медленной части добавления все элементы в словарях, но когда сделали доступ к детали очень быстро

Примечание: словари не могут иметь дубликаты ключей

.

Edit:

Если вы пошагово код, который вы сможете увидеть следующие объекты:

DictionaryOfDictionaries

.

Если заменить MsgBox строку со следующим:

For Each x In itms.Keys 
    For Each y In itms(x) 
     If InStr(y, 1) > 0 Then 
      Debug.Print vbNullString 
      Debug.Print x & " ---> Key: '" & y & "' -> Item: '" & itms(x)(y) & "'" 
     Else 
      Debug.Print vbTab & vbTab & " -> Key: '" & y & "' -> Item: '" & itms(x)(y) & "'" 
     End If 
    Next 
Next 

Вы получите:

Item 1 ---> Key: 'Property 1' -> Item: 'A' 
     -> Key: 'Property 2' -> Item: 'B' 
     -> Key: 'Property 3' -> Item: 'C' 

Item 2 ---> Key: 'Property 1' -> Item: 'D' 
     -> Key: 'Property 2' -> Item: 'E' 
     -> Key: 'Property 3' -> Item: 'F' 

Item 3 ---> Key: 'Property 1' -> Item: 'G' 
     -> Key: 'Property 2' -> Item: 'H' 
     -> Key: 'Property 3' -> Item: 'I' 

или типа

For Each x In itms.Keys: For Each y in itms(x): Debug.Print x & " -> " & y & " -> " & itms(x)(y): Next: Next 

в окне отладки

+0

'subItms.Add Key: = ws.Cells (1, j) .Value2, Item: = ws.Cells (i, j) .Value2' Первый цикл устанавливает' Свойство 1' => 'A',' Свойство 2 '=>' B', 'Свойство 3' =>' C'. Однако второй устанавливает 'Свойство 1' =>' D', 'Свойство 2' =>' E', 'Свойство 3' =>' F'. В какой строке говорится, что эти свойства принадлежат к пункту 2, а не к пункту 1? – newdimension

+0

2 вложенных цикла For делают различие между словарями: внешний цикл создает основной словарь, а внутренний цикл создает несколько суб-словарей. Строка, которая показывает, какие свойства принадлежат основному словарю, - это 'itms.Add Key: = ...' (объект с именем «itms» - словарь верхнего уровня). Я добавлю изображение структуры, чтобы сделать ее более четкой. –

+0

Мне кажется, что после того, как вы закончите цикл Item 1, вы вернетесь к настройке sdict («Свойство 1»), когда оно уже установлено. Я также получаю ключ, уже использующий ошибку для кода, который имитирует вашу логику. Изменить: Мне кажется, что вы не создаете более одного подъязыка. – newdimension

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