Страницы: 1
RSS
Подсчёт значений нарастающим итогом, VBA, scripting.dictionary
 
Привет всем участникам зелёного форума.
Учу словарик на VBA, поставил себе задачу посчитать суммы по статьям нарастающим итогом, но что то у меня идёт не так. Иду по списку, проверяю exists- ом, если да - то плюсую к 0 итем по ключу.

Не стал делать слишком много статей в файле, что бы не усложнять. Хочу понять, как сделать так что бы можно было идти циклом по массиву со статьями, и при срабатывании свойства exists, считалась сумма в нарастании по каждой статье, далее выгружалась в ("b4") (эта часть не проблема)
Код
Sub lknb()

'просуммировать значения в нарастании по ключам
Dim d1 As Object, i As Integer, j As Integer
Dim a, b, c

'пилим словарь
Set d1 = CreateObject("scripting.dictionary")

'массив с нарастающим итогом
a = Range("a4").CurrentRegion
'массив сттатей, которые попадут в нарастающий итог
b = Range("d4").CurrentRegion

For i = 1 To UBound(a, 1)
    d1.Add a(i, 1), 0
Next

'прохожусь по статьям в массиве b. Если есть ключ сущестует, тогда
'к итему с 0 суммой прибавляется сумма привязанная к этому ключу
For i = 1 To UBound(b, 1)
    If d1.Exists((a(1, 1))) Then d1(a(1, 1)) = d1(a(1, 1)) + b(i, 2)
Next

'массив для вставки сложенных в нарастании итемов (сумм) по ключам
'ReDim c(1 To UBound(a, 1), 1 To 1)

c = d1(a(1, 1))

Stop
End Sub
Изменено: Yum - 03.11.2022 07:26:11
 
Код
Sub lknb()

'просуммировать значения в нарастании по ключам
Dim d1 As Object, i As Integer, j As Integer
Dim a, b, c

'пилим словарь
Set d1 = CreateObject("scripting.dictionary")

'массив с нарастающим итогом
a = Range("a4").CurrentRegion
'массив сттатей, которые попадут в нарастающий итог
b = Range("d4").CurrentRegion

'For i = 1 To UBound(a, 1)
'    d1.Add a(i, 1), 0
'Next

'прохожусь по статьям в массиве b. Если есть ключ сущестует, тогда
'к итему с 0 суммой прибавляется сумма привязанная к этому ключу
For i = 1 To UBound(b, 1)
'    If d1.Exists((a(1, 1))) Then d1(a(1, 1)) = d1(a(1, 1)) + b(i, 2)
    d1.Item(b(i, 1)) = d1.Item(b(i, 1)) + b(i, 2)
Next

'массив для вставки сложенных в нарастании итемов (сумм) по ключам
'ReDim c(1 To UBound(a, 1), 1 To 1)

'c = d1(a(1, 1))
c = d1.Items

Stop
End Sub
 
RAN,

Спасибо! я был очень близок к решению

даже если в цикл добавить
Код
"If d1.exists (b(i,1)) then"
то всё равно работает
Изменено: Yum - 03.11.2022 08:50:55
 
Yum, здравствуйте
Подробно
Исчерпывающее описание объекта Dictionary
Изменено: Jack Famous - 03.11.2022 10:04:14
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
Jack Famous,
Приветствую. Спасибо очень интересно!
 
Всем ещё раз привет. Всё же возникла проблема с выгрузкой одномерного массива на лист.
Поэтому придумал такой вот велосипед в строках 32-34. Выложу сюда, вдруг кому пригодится:

К исходному файлу в 1 посте можно добавить еще несколько статей с суммами, что бы было понаглядней
Код
Sub lknb()

'просуммировать значения в нарастании по ключам
Dim d1 As Object, i As Integer, j As Integer
Dim a, b, c

Range("b1").EntireColumn.Clear

'пилим словарь
Set d1 = CreateObject("scripting.dictionary")

'массив с нарастающим итогом. КЛЮЧИ
a = Range("a4").CurrentRegion
'массив статей, которые попадут в нарастающий итог. ИТЕМЫ в 1 столбце массива
b = Range("d4").CurrentRegion

'циклом назначаем пару ключ/итем. Итемы будут = 0, потому что
'надо собрать сумму в нарастании из другого места
For i = 1 To UBound(a, 1)
    d1.Add a(i, 1), 0
Next

'прохожусь по статьям в массиве b. Если есть ключ существует, тогда
'к итему с 0 суммой прибавляется сумма привязанная к этому ключу
For i = 1 To UBound(b, 1)
   If d1.Exists(b(i, 1)) Then d1(b(i, 1)) = d1(b(i, 1)) + b(i, 2)
   Debug.Print d1(b(i, 1))
Next

c = d1.Items

For i = 1 To UBound(a, 1)
    Cells(i + 3, 2).Value = d1.Items()(i - 1)
Next

End Sub
Изменено: Yum - 17.11.2022 03:30:40
 
Если у вас массив менее 16900 позиций, можно так
Код
    c = d1.Items
    Range("B4").Resize(UBound(c) + 1, 1).Value = WorksheetFunction.Transpose(c)

P.S. Желательно никогда не объявлять целочисленные переменные как As Integer. Лучше всегда объявляйте As Long. Мы сейчас с вами не в 1998 году (Это намёк на то, что у вас в компьютере сейчас гигабайты оперативной памяти, а не мегабайты). А ошибку как-нибудь обязательно получите, когда массив будет > 32767 элементов
Изменено: New - 17.11.2022 04:09:30
 
New,

Хорошо, спасибо за совет и решение)
Страницы: 1
Наверх