Подскажите как в items в dictionary занести несколько ячеек. Есть массив (таблица) который хочу запихнуть в dictionary. Ключами будет просто нумерованный список. А в значениях хотелось бы видеть ещё порядка 10 ячеек (то есть вся строка со значениями из 10 столбцов). Как я понял в словарях одному ключу может соответствовать только одно значение. Это значение может быть массивом? Вижу пока такое решение - в Item добавлять значения через какой-нибудь разделитель (например |) тогда получится такой словарь Ключ1 =1; Значение1 =(Ячейка1 + | + ячейка2 + | + и так далее) Затем при вставке значений на лист вытащить ячейки между разделителями. Но в таком случае уже наверно не получится оперировать с ячейками. Например некоторые надо будет объединить (сложить).
Подскажите как в items в dictionary занести несколько ячеек. Есть массив (таблица) который хочу запихнуть в dictionary. Ключами будет просто нумерованный список. А в значениях хотелось бы видеть ещё порядка 10 ячеек (то есть вся строка со значениями из 10 столбцов). Как я понял в словарях одному ключу может соответствовать только одно значение. Это значение может быть массивом? Вижу пока такое решение - в Item добавлять значения через какой-нибудь разделитель (например |) тогда получится такой словарь Ключ1 =1; Значение1 =(Ячейка1 + | + ячейка2 + | + и так далее) Затем при вставке значений на лист вытащить ячейки между разделителями. Но в таком случае уже наверно не получится оперировать с ячейками. Например некоторые надо будет объединить (сложить).fairylive
Пока нет примера непонятно что именно нужно поместить в словарь - ячейки (диапазон), значения как строку, массив значений, а может другой словарь с ключами из этих значений, раз уж там ещё что-то придётся суммировать. Потому и какой пример показывать - непонятно. Но вот например три, все варианты, может пригодятся: [vba]
Код
массив в словаре Option Explicit
Sub Otbor() Dim a(), oDict As Object, i As Long, temp As String, kk
With Application .DisplayAlerts = False .ScreenUpdating = False
a = [a1].CurrentRegion.Value
Set oDict = CreateObject("Scripting.Dictionary") oDict.CompareMode = vbTextCompare
For i = 1 To UBound(a)
temp = Application.Trim(a(i, 1)) If Not oDict.Exists(temp) Then ReDim b(1 To UBound(a) + 1, 1 To 1) b(1, 1) = a(i, 1): b(2, 1) = a(i, 2) b(UBound(b), 1) = 3 oDict.Add temp, b Else b = oDict.Item(temp) b(b(UBound(b), 1), 1) = a(i, 2): b(UBound(b), 1) = b(UBound(b), 1) + 1 oDict.Item(temp) = b End If Next
With Workbooks.Add.Sheets(1) i = 0 For Each kk In oDict.keys i = i + 1 b = oDict.Item(kk) Cells(1, i).Resize(b(UBound(b), 1)) = b Next .Cells.EntireColumn.AutoFit End With
.DisplayAlerts = True .ScreenUpdating = True End With End Sub
Sub PereborFailov() 'коллекция в словаре Dim a, i&, t$, Dic As Object Dim el, col
a = Range("C3", Cells(Rows.Count, "A").End(xlUp)).Value Set Dic = CreateObject("Scripting.Dictionary") With Dic .CompareMode = 1 For i = 1 To UBound(a) t = a(i, 1) If Not .exists(t) Then .Add t, New Collection .Item(t).Add a(i, 2) & "|" & a(i, 3) & "|" & i Next End With
For Each el In Dic.keys Debug.Print "Открываем файл " & el For Each col In Dic.Item(el) Debug.Print "Ищем данные " & col Next Debug.Print "Закрываем файл " & el Next
End Sub
Sub PereborFailov2() ' словарь в словаре Dim a, i&, t$, Dic As Object, Dic2 As Object Dim el, col
a = Range("C3", Cells(Rows.Count, "A").End(xlUp)).Value Set Dic = CreateObject("Scripting.Dictionary") With Dic .CompareMode = 1 For i = 1 To UBound(a) t = a(i, 1) If Not .exists(t) Then .Add t, CreateObject("Scripting.Dictionary") .Item(t).Item(a(i, 2) & "|" & a(i, 3) & "|" & i) = 0&
Next End With
For Each el In Dic.keys Debug.Print "Открываем файл " & el Set Dic2 = Dic.Item(el) For Each col In Dic2.keys Debug.Print "Ищем данные " & col '& "|" & Dic2.Item(col) Next Debug.Print "Закрываем файл " & el Next
End Sub
[/vba]
Пока нет примера непонятно что именно нужно поместить в словарь - ячейки (диапазон), значения как строку, массив значений, а может другой словарь с ключами из этих значений, раз уж там ещё что-то придётся суммировать. Потому и какой пример показывать - непонятно. Но вот например три, все варианты, может пригодятся: [vba]
Код
массив в словаре Option Explicit
Sub Otbor() Dim a(), oDict As Object, i As Long, temp As String, kk
With Application .DisplayAlerts = False .ScreenUpdating = False
a = [a1].CurrentRegion.Value
Set oDict = CreateObject("Scripting.Dictionary") oDict.CompareMode = vbTextCompare
For i = 1 To UBound(a)
temp = Application.Trim(a(i, 1)) If Not oDict.Exists(temp) Then ReDim b(1 To UBound(a) + 1, 1 To 1) b(1, 1) = a(i, 1): b(2, 1) = a(i, 2) b(UBound(b), 1) = 3 oDict.Add temp, b Else b = oDict.Item(temp) b(b(UBound(b), 1), 1) = a(i, 2): b(UBound(b), 1) = b(UBound(b), 1) + 1 oDict.Item(temp) = b End If Next
With Workbooks.Add.Sheets(1) i = 0 For Each kk In oDict.keys i = i + 1 b = oDict.Item(kk) Cells(1, i).Resize(b(UBound(b), 1)) = b Next .Cells.EntireColumn.AutoFit End With
.DisplayAlerts = True .ScreenUpdating = True End With End Sub
Sub PereborFailov() 'коллекция в словаре Dim a, i&, t$, Dic As Object Dim el, col
a = Range("C3", Cells(Rows.Count, "A").End(xlUp)).Value Set Dic = CreateObject("Scripting.Dictionary") With Dic .CompareMode = 1 For i = 1 To UBound(a) t = a(i, 1) If Not .exists(t) Then .Add t, New Collection .Item(t).Add a(i, 2) & "|" & a(i, 3) & "|" & i Next End With
For Each el In Dic.keys Debug.Print "Открываем файл " & el For Each col In Dic.Item(el) Debug.Print "Ищем данные " & col Next Debug.Print "Закрываем файл " & el Next
End Sub
Sub PereborFailov2() ' словарь в словаре Dim a, i&, t$, Dic As Object, Dic2 As Object Dim el, col
a = Range("C3", Cells(Rows.Count, "A").End(xlUp)).Value Set Dic = CreateObject("Scripting.Dictionary") With Dic .CompareMode = 1 For i = 1 To UBound(a) t = a(i, 1) If Not .exists(t) Then .Add t, CreateObject("Scripting.Dictionary") .Item(t).Item(a(i, 2) & "|" & a(i, 3) & "|" & i) = 0&
Next End With
For Each el In Dic.keys Debug.Print "Открываем файл " & el Set Dic2 = Dic.Item(el) For Each col In Dic2.keys Debug.Print "Ищем данные " & col '& "|" & Dic2.Item(col) Next Debug.Print "Закрываем файл " & el Next
Hugo, здесь на форуме создавал тему Так вот задача та же только кроме деталей и их количества есть ещё один столбец - длина деталей и суммировать количество деталей надо не только если одинаковое название детали но И если одинаковая длина. Кроме это в моей реальной задаче есть и другие столбцы - артикул, ед.изм, примечание (без них можно конечно и обойтись - добавить уже в итоговую таблицу в конце) которые тоже хотелось бы переносить в конце в итоговую таблицу. Сейчас там решение такое - имена деталей запихиваются в ключ словаря, а количество деталей в значения. С количествами идёт манипулирование - сложение и перемножение. И вот как выяснилось появляется ещё одна переменная - длина.
Hugo, здесь на форуме создавал тему Так вот задача та же только кроме деталей и их количества есть ещё один столбец - длина деталей и суммировать количество деталей надо не только если одинаковое название детали но И если одинаковая длина. Кроме это в моей реальной задаче есть и другие столбцы - артикул, ед.изм, примечание (без них можно конечно и обойтись - добавить уже в итоговую таблицу в конце) которые тоже хотелось бы переносить в конце в итоговую таблицу. Сейчас там решение такое - имена деталей запихиваются в ключ словаря, а количество деталей в значения. С количествами идёт манипулирование - сложение и перемножение. И вот как выяснилось появляется ещё одна переменная - длина.fairylive
Вот файл. Он очень близок к тому что я делаю. Вот здесь нашёл про то что спрашивал в первом сообщении. Массив в значениях. Видимо я до этого что-то не так делал - в упор не получалось.
Вот файл. Он очень близок к тому что я делаю. Вот здесь нашёл про то что спрашивал в первом сообщении. Массив в значениях. Видимо я до этого что-то не так делал - в упор не получалось.fairylive
Нет сейчас желания делать, но думаю чтоб особо не напрягаться - можно просто создать ещё один аналогичный словарь, где вместо количества собирать длину. Т.е. делаем всё так же, только из другого столбца берём данные, ну а в финале выгружаем рядом. P.S. Хотя нашёл в файле код, чуть дописал и чуть сократил: [vba]
Код
Sub ttt() Dim ws As Worksheet 'Создае объект - словарь Dim Zakaz As Object: Set Zakaz = CreateObject("Scripting.Dictionary") Dim Zakaz2 As Object: Set Zakaz2 = CreateObject("Scripting.Dictionary") Dim arr(), arr1(), I As Long, J As Long
'Вычисляем последнюю заполенную строку на листе и создаем 2-х мерный массив из диапазона с названием изделий и их количеством With Sheets("ЗАКАЗ") arr1 = .Range("B3:C" & .Cells(.Rows.Count, 2).End(xlUp).Row).Value End With 'Перебераем все листы в рабочей книге For Each ws In Worksheets With ws For J = 1 To UBound(arr1) 'Перебираем все названия изделий, взятые с листа ЗАКАЗ, проверяем на равенство названию листа If .Name = arr1(J, 1) Then 'Создаем 2-х мерный массив из названий деталей и их количества в изделии arr = .Range("A2:C" & .Cells(.Rows.Count, 2).End(xlUp).Row).Value 'Перебираем название деталей, если они уже есть, прибавляем количество деталей, умноженное на количество изделий For I = 1 To UBound(arr) If arr(I, 1) <> "" Then If Zakaz.exists(arr(I, 1)) Then Zakaz.Item(arr(I, 1)) = Zakaz.Item(arr(I, 1)) + (arr(I, 2) * arr1(J, 2)) Zakaz2.Item(arr(I, 1)) = Zakaz.Item(arr(I, 1)) + (arr(I, 3) * arr1(J, 2)) Else 'Если их нет, создаем новый элемент в словаре, равный количеству деталей в изделии, _ умноженному на количество изделий Zakaz.Add Key:=arr(I, 1), Item:=arr(I, 2) * arr1(J, 2) Zakaz2.Add Key:=arr(I, 1), Item:=arr(I, 3) * arr1(J, 2) End If End If Next End If Next End With Next 'Очищаем и заполняем соответствующй диапазон на листе Изготовление With Sheets("Изготовление") .Range("A3:C" & .Cells(.Rows.Count, 1).End(xlUp).Row).ClearContents .Cells(3, 1).Resize(Zakaz.Count, 3) = WorksheetFunction.Transpose(Array(Zakaz.keys, Zakaz.items, Zakaz2.items)) End With 'На всякий случай очищае переменные Erase arr: Erase arr1: Set Zakaz = Nothing End Sub
[/vba]
Нет сейчас желания делать, но думаю чтоб особо не напрягаться - можно просто создать ещё один аналогичный словарь, где вместо количества собирать длину. Т.е. делаем всё так же, только из другого столбца берём данные, ну а в финале выгружаем рядом. P.S. Хотя нашёл в файле код, чуть дописал и чуть сократил: [vba]
Код
Sub ttt() Dim ws As Worksheet 'Создае объект - словарь Dim Zakaz As Object: Set Zakaz = CreateObject("Scripting.Dictionary") Dim Zakaz2 As Object: Set Zakaz2 = CreateObject("Scripting.Dictionary") Dim arr(), arr1(), I As Long, J As Long
'Вычисляем последнюю заполенную строку на листе и создаем 2-х мерный массив из диапазона с названием изделий и их количеством With Sheets("ЗАКАЗ") arr1 = .Range("B3:C" & .Cells(.Rows.Count, 2).End(xlUp).Row).Value End With 'Перебераем все листы в рабочей книге For Each ws In Worksheets With ws For J = 1 To UBound(arr1) 'Перебираем все названия изделий, взятые с листа ЗАКАЗ, проверяем на равенство названию листа If .Name = arr1(J, 1) Then 'Создаем 2-х мерный массив из названий деталей и их количества в изделии arr = .Range("A2:C" & .Cells(.Rows.Count, 2).End(xlUp).Row).Value 'Перебираем название деталей, если они уже есть, прибавляем количество деталей, умноженное на количество изделий For I = 1 To UBound(arr) If arr(I, 1) <> "" Then If Zakaz.exists(arr(I, 1)) Then Zakaz.Item(arr(I, 1)) = Zakaz.Item(arr(I, 1)) + (arr(I, 2) * arr1(J, 2)) Zakaz2.Item(arr(I, 1)) = Zakaz.Item(arr(I, 1)) + (arr(I, 3) * arr1(J, 2)) Else 'Если их нет, создаем новый элемент в словаре, равный количеству деталей в изделии, _ умноженному на количество изделий Zakaz.Add Key:=arr(I, 1), Item:=arr(I, 2) * arr1(J, 2) Zakaz2.Add Key:=arr(I, 1), Item:=arr(I, 3) * arr1(J, 2) End If End If Next End If Next End With Next 'Очищаем и заполняем соответствующй диапазон на листе Изготовление With Sheets("Изготовление") .Range("A3:C" & .Cells(.Rows.Count, 1).End(xlUp).Row).ClearContents .Cells(3, 1).Resize(Zakaz.Count, 3) = WorksheetFunction.Transpose(Array(Zakaz.keys, Zakaz.items, Zakaz2.items)) End With 'На всякий случай очищае переменные Erase arr: Erase arr1: Set Zakaz = Nothing End Sub
Hugo, Спасибо! Там только длина не должна умножаться на кол-во. Немного поправил строчки
[vba]
Код
Zakaz2.Item(arr(I, 3)) = Zakaz.Item(arr(I, 3))
[/vba] [vba]
Код
Zakaz2.Add Key:=arr(I, 1), Item:=arr(I, 3)
[/vba]
Сам думал над этим - чтобы второй словарь сделать, но боялся что словари будут не совпадать. Сейчас проверил - всё работает. То что надо. И гораздо проще чем через разделители или целый массив в значениях (с которым у меня так ничего и не получилось).
PS Пока только учусь поэтому много чего не понимаю. Например конструкции вида вообще для меня не очевидны [vba]
Hugo, Спасибо! Там только длина не должна умножаться на кол-во. Немного поправил строчки
[vba]
Код
Zakaz2.Item(arr(I, 3)) = Zakaz.Item(arr(I, 3))
[/vba] [vba]
Код
Zakaz2.Add Key:=arr(I, 1), Item:=arr(I, 3)
[/vba]
Сам думал над этим - чтобы второй словарь сделать, но боялся что словари будут не совпадать. Сейчас проверил - всё работает. То что надо. И гораздо проще чем через разделители или целый массив в значениях (с которым у меня так ничего и не получилось).
PS Пока только учусь поэтому много чего не понимаю. Например конструкции вида вообще для меня не очевидны [vba]
- часть после & до последней скобки даёт номер последней занятой строки, т.е. первой занятой с низу. В итоге получаем например если это число 123: [vba]
Код
arr = .Range("A2:C123").Value
[/vba] что уже вполне ведь понятно? По словарям - вообще порядок ключей в словаре не регламентирован, поэтому надёжнее (но дольше и больше кода) делать так - сперва выгружаем ключи одного массива, затем идём по ним циклом и рядом выгружаем соответствующие этому конкретному ключу item'ы из обоих словарей. По одному. Но можно делать через массив - размеры ведь все известны, так будет не намного дольше.
- часть после & до последней скобки даёт номер последней занятой строки, т.е. первой занятой с низу. В итоге получаем например если это число 123: [vba]
Код
arr = .Range("A2:C123").Value
[/vba] что уже вполне ведь понятно? По словарям - вообще порядок ключей в словаре не регламентирован, поэтому надёжнее (но дольше и больше кода) делать так - сперва выгружаем ключи одного массива, затем идём по ним циклом и рядом выгружаем соответствующие этому конкретному ключу item'ы из обоих словарей. По одному. Но можно делать через массив - размеры ведь все известны, так будет не намного дольше.Hugo
Я саму конструкцию не очень понимаю. Как её прочитать по русски? Почему там именно цифра 2? Везде используются эти примеры, но я пока не буду понимать каждую точку перед каждым словом, скобочки все эти, вряд ли смогу построить нечто подобное сам. Придется слепо копировать. Так обучение не очень продвигается)
А на счёт надёжности. Я вот из этих соображений первоначально и хотел запихать массив (диапазон ячеек) в item. Тогда для одного ключа(детали) значением был бы массив и с количество и с длиной и с прочими ячейками. Тут правда с перемножением мне не очевидно становится уже. Но я так и не понял как прописать массив в Item.
Я саму конструкцию не очень понимаю. Как её прочитать по русски? Почему там именно цифра 2? Везде используются эти примеры, но я пока не буду понимать каждую точку перед каждым словом, скобочки все эти, вряд ли смогу построить нечто подобное сам. Придется слепо копировать. Так обучение не очень продвигается)
А на счёт надёжности. Я вот из этих соображений первоначально и хотел запихать массив (диапазон ячеек) в item. Тогда для одного ключа(детали) значением был бы массив и с количество и с длиной и с прочими ячейками. Тут правда с перемножением мне не очевидно становится уже. Но я так и не понял как прописать массив в Item.fairylive
С массивом в Item будет гемор когда понадобится его менять - нужно извлекать его во временный массив, менять, класть назад. Куча кода, отслеживать каждую букву... Я ведь там выше дал пример. На два значения проще сделать два словаря с одинаковыми ключами - код простой.
С массивом в Item будет гемор когда понадобится его менять - нужно извлекать его во временный массив, менять, класть назад. Куча кода, отслеживать каждую букву... Я ведь там выше дал пример. На два значения проще сделать два словаря с одинаковыми ключами - код простой.Hugo