Форум программистов, компьютерный форум, киберфорум
VBA
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.86/7: Рейтинг темы: голосов - 7, средняя оценка - 4.86
0 / 0 / 0
Регистрация: 10.05.2024
Сообщений: 6

Обновление данных в Dictionary

10.05.2024, 12:20. Показов 1889. Ответов 23
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем привет!
Есть dict
Dim dict As Object
Есть Set dict = CreateObject("Scripting.Dictionary")

Я в него пытаюс положить самую раннюю дату выдачи материала, и количество выданного материала.
Ключ - наименование материала.
Проблема с dict(material)(0) = CLng(dict(material)(0)) + quantity - не считает сумму, при отладке проходит
с датами таже беда, пишет первую дату из таблицы, дальше проходит условие If dateOut < CDate(dict(material)(1)) Then но данные в dict не изменяет

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
For Each cell In rngOut.Rows
        material = cell.Cells(1, 3).Value
        quantity = cell.Cells(1, 4).Value
        dateOut = CDate(cell.Cells(1, 1).Value)
 
        If Not dict.Exists(material) Then
            dict.Add material, Array(quantity, dateOut)
        Else
            If dateOut < CDate(dict(material)(1)) Then
                dict(material)(1) = CDate(dateOut)
            End If
            dict(material)(0) = CLng(dict(material)(0)) + quantity
        End If
    Next cell
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
10.05.2024, 12:20
Ответы с готовыми решениями:

Проинициализировать значениями dictionary вложенный в dictionary
Народ, помогите, как проинициализировать значениями такую конструкцию: Dictionary &lt;int,Dictionary&lt;string, int&gt;&gt;

Определить тип данных Dictionary
2. Придумайте определение для типа Dictionary (Header-файл dictionary.h) для сохранения пар из Strins и целых чисел. Используйте его, чтобы...

BackgroundWorker запись данных в Dictionary
Необходимо реализовать метод,который асинхронно будет парсить текст и создавать словарь из слов этого текста.На форме прогресс работы...

23
Эксперт MS Access
 Аватар для Eugene-LS
12030 / 5822 / 1491
Регистрация: 05.10.2016
Сообщений: 16,399
10.05.2024, 12:29
Цитата Сообщение от Igor_AIR Посмотреть сообщение
не считает сумму, при отладке проходит
Файлик к описанию траблы приложен будет? -Нет?!
0
0 / 0 / 0
Регистрация: 10.05.2024
Сообщений: 6
10.05.2024, 12:45  [ТС]
Вот
Вложения
Тип файла: xlsx Vot.xlsx (14.3 Кб, 8 просмотров)
0
3946 / 2339 / 790
Регистрация: 02.11.2012
Сообщений: 6,214
10.05.2024, 13:01
в xlsx макросы не живут.
0
0 / 0 / 0
Регистрация: 10.05.2024
Сообщений: 6
10.05.2024, 13:07  [ТС]
Вот 2
Вложения
Тип файла: zip Vot.zip (19.7 Кб, 14 просмотров)
0
Эксперт MS Access
 Аватар для Eugene-LS
12030 / 5822 / 1491
Регистрация: 05.10.2016
Сообщений: 16,399
10.05.2024, 13:33
Цитата Сообщение от Igor_AIR Посмотреть сообщение
Вот 2
А поздняк метаться уже ...
Держите:
Бед всякой дури - типа словарей:
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
Sub test01()
Dim cn As Object, rs As Object
Dim lVal&, strSql$
' -------------------------------------------------------------------------------------------------/
'Connect ...
    Set cn = CreateObject("ADODB.Connection")
    With cn
        .Provider = "Microsoft.ACE.OLEDB.12.0"
        .ConnectionString = "Data Source=" & ThisWorkbook.Path & "\" & ThisWorkbook.Name & ";" & _
        "Extended Properties=""Excel 12.0 Xml;HDR=No"";" ';HDR=Yes
        .Open
    End With
 
    lVal = ThisWorkbook.Sheets("Out").UsedRange.Rows.Count
    strSql = "SELECT F3, First(F4) AS FirstOfF4, First(F1) AS FirstOfF1 FROM [Out$A3:E" & lVal & "] WHERE (F4>0) GROUP BY F3;"
    Set rs = CreateObject("ADODB.Recordset")
    rs.Open strSql, cn, 1, 3 ', 2 'adOpenKeyset=1, adLockOptimistic=3, adCmdTable=2
 
'Проверка есть ли данные для вывода:
    If rs.BOF And rs.EOF Then
        MsgBox "Запрос не вернул записей, работа прекращёна!", vbExclamation, "Ошибка данных"
        GoTo test01_end
    End If
    
' Зачистка Листа (3):
     ActiveWorkbook.Sheets(3).UsedRange.Clear
 
'Вставка результата:
    ThisWorkbook.Worksheets(3).Range("A1").CopyFromRecordset rs
    ThisWorkbook.Worksheets(3).Activate
    
    MsgBox "Готово!", vbInformation
    
test01_end:
    On Error Resume Next
    rs.Close: Set rs = Nothing
    cn.Close: Set cn = Nothing
    Err.Clear
End Sub

- Проверяйте!
0
0 / 0 / 0
Регистрация: 10.05.2024
Сообщений: 6
10.05.2024, 13:51  [ТС]
Так же как и в моем случае, выдает список уникальных наименований, даты - выдает первые из сходной таблицы, количество выданного также не суммирует.
Тоесть имею исходную таблицу
21.04.2024 МФУ Canon i-Sensys MF446x 3514C006 Картридж 1,00 шт
17.04.2024 МФУ Canon i-Sensys MF446x 3514C006 Картридж 1,00 шт
12.04.2024 МФУ Canon i-Sensys MF446x 3514C006 Картридж 1,00 шт
06.04.2024 МФУ Canon i-Sensys MF446x 3514C006 Картридж3 1,00 шт
02.04.2024 МФУ Canon i-Sensys MF446x 3514C006 Картридж3 1,00 шт
10.03.2024 МФУ Canon i-Sensys MF446x 3514C006 Картридж 1,00 шт
24.02.2024 МФУ Canon i-Sensys MF446x 3514C006 Картридж 1,00 шт

в итоговой хочу получить -
Картридж 5 24.02.2024
Картридж3 2 02.04.2024
0
Эксперт MS Access
 Аватар для Eugene-LS
12030 / 5822 / 1491
Регистрация: 05.10.2016
Сообщений: 16,399
10.05.2024, 13:56
Цитата Сообщение от Igor_AIR Посмотреть сообщение
количество выданного также не суммирует.
А где про это написано?
Было в пост#1 "..., и количество выданного материала. "


Ну ничего страшного - измените запрос так:
Visual Basic
1
2
    strSql = "SELECT F3, Sum(F4) AS SumOfF4, Min(F1) AS MinOfF1 " & _
             "FROM [Out$A3:E" & lVal & "] WHERE (F4>0) GROUP BY F3;"
А про "самую раннюю дату выдачи материала" - это я пропустил, сорян.
... взял содержимое третьего листа примера за "желаемый результат" ...
1
 Аватар для Narimanych
2751 / 1725 / 779
Регистрация: 23.03.2015
Сообщений: 5,449
10.05.2024, 14:05
Igor_AIR,
С дурью -типа словарей:
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Sub MMM()
    Set wsOut = ThisWorkbook.Sheets("Out")
    Set wsIn = ThisWorkbook.Sheets("Temp")
   rngOut = wsOut.Range("A4:E" & wsOut.Cells(wsOut.Rows.Count, "E").End(xlUp).Row).Value
   With CreateObject("Scripting.Dictionary")
         For i = 1 To UBound(rngOut)
                el = .Item(CStr(rngOut(i, 3)))
        Next
        ReDim arr(1 To .Count, 1 To 3)
        For i = 0 To .Count - 1
        dt = 9000000000#
            For j = 1 To UBound(rngOut)
                If .Keys()(i) = rngOut(j, 3) Then
                        arr(i + 1, 1) = rngOut(j, 3)
                       If rngOut(j, 1) < dt Then
                                dt = rngOut(j, 1)
                                arr(i + 1, 2) = arr(i + 1, 2) + rngOut(j, 4)
                                arr(i + 1, 3) = rngOut(j, 1)
                        End If
                End If
            Next
        Next
     wsIn.Cells(3, 3).Resize(UBound(arr), 3).Value = arr
   End With
End Sub
1
0 / 0 / 0
Регистрация: 10.05.2024
Сообщений: 6
10.05.2024, 14:16  [ТС]
Работает! Спасибо! SQL запросы в екселе еще не пихал до этого ))
0
Эксперт MS Access
 Аватар для Eugene-LS
12030 / 5822 / 1491
Регистрация: 05.10.2016
Сообщений: 16,399
10.05.2024, 14:33
Цитата Сообщение от Igor_AIR Посмотреть сообщение
SQL запросы в екселе еще не пихал до этого
А поэкспериментируйте ...
Настоятельно рекомендую, работает на порядок быстрее.

Цитата Сообщение от Narimanych Посмотреть сообщение
С дурью -типа словарей:
You've made my day.

Добавлено через 8 минут
Igor_AIR, Да! -чуть не забыл !
Если у вас в исходном материале могут быть нулевые количества , то условие отбора в запросе лучше изменить на например так:
Visual Basic
1
2
    strSql = "SELECT F3, Sum(F4) AS SumOfF4, Min(F1) AS MinOfF1 " & _
             "FROM [Out$A3:E" & lVal & "] WHERE (F3 Is Not Null) GROUP BY F3;"
Тут ... WHERE (F3 Is Not Null) ... = "Наименование заполнено (не пустое)"
0
 Аватар для Narimanych
2751 / 1725 / 779
Регистрация: 23.03.2015
Сообщений: 5,449
10.05.2024, 14:35
Eugene-LS,
Цитата Сообщение от Eugene-LS Посмотреть сообщение
Настоятельно рекомендую, работает на порядок быстрее.
Сообщение от Narimanych
С дурью -типа словарей:
You've made my day.
much appreciated
0
Эксперт MS Access
 Аватар для Eugene-LS
12030 / 5822 / 1491
Регистрация: 05.10.2016
Сообщений: 16,399
10.05.2024, 15:30
Цитата Сообщение от Eugene-LS Посмотреть сообщение
работает на порядок быстрее
Оговорюсь для вас, ув. Igor_AIR, тут такая штука:
На малых объёмах данных (500 -1000 записей) вариант от ув. Narimanych работает в несколько раз быстрее моего.
А вот уже на 5 000-ах записей результат машина выдала такой:
Visual Basic
1
2
3
Тест из 1 повторов - 5 000 записей:
01. Sub test01()........................................... Продолжительность: 00:00:00.171
02. Sub MMM().............................................. Продолжительность: 00:00:05.746
... а на 10 000-ах записей, я не смог дождаться результата от процедуры MMM()

Получаем: Мой способ годится только для больших объёмов.
Успехов!
1
6997 / 2895 / 555
Регистрация: 19.10.2012
Сообщений: 8,803
10.05.2024, 22:47
Да и первый код можно наладить, но так в массив не запишет - нужно массив извлечь из словаря, записать в этот массив, положить массив назад в словарь.

Добавлено через 10 минут
Ничего не оптимизировал, просто наладил что было показано
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
Sub tt()
 
Dim dict As Object, rngOut
Set rngOut = [a4].CurrentRegion
Set dict = CreateObject("Scripting.Dictionary")
 
For Each cell In rngOut.Rows
        material = cell.Cells(1, 3).Value
        quantity = cell.Cells(1, 4).Value
        dateOut = CDate(cell.Cells(1, 1).Value)
 
        If Not dict.Exists(material) Then
            dict.Add material, Array(quantity, dateOut)
        Else
            If dateOut < CDate(dict(material)(1)) Then
            arr = dict(material)
                arr(1) = CDate(dateOut)
                dict(material) = arr
            End If
            arr = dict(material)
            arr(0) = CLng(arr(0)) + quantity
            dict(material) = arr
        End If
    Next cell
    
  For Each k In dict
  arr = dict(k) 'arr смотреть здесь
  Next
End Sub
Добавлено через 55 секунд
Вообще я бы в данном случае завёл 2 словаря - код короче, и писать меньше...
1
0 / 0 / 0
Регистрация: 10.05.2024
Сообщений: 6
11.05.2024, 10:01  [ТС]
Спасибо, паложить в два словаря тоже пробовал!
0
sleep
 Аватар для I can
4914 / 4551 / 837
Регистрация: 13.04.2015
Сообщений: 9,676
11.05.2024, 10:20
Цитата Сообщение от Igor_AIR Посмотреть сообщение
паложить в два словаря тоже пробовал!
Через удаление?

Вместо этого:
Цитата Сообщение от Igor_AIR Посмотреть сообщение
Visual Basic
1
dict(material)(0) = CLng(dict(material)(0)) + quantity
Так
Visual Basic
1
2
3
      quantity = Val(dict(material)(0)) + Val(quantity)
           dict.Remove material
           dict.Add material, Array(quantity, dateOut)
0
6997 / 2895 / 555
Регистрация: 19.10.2012
Сообщений: 8,803
11.05.2024, 19:30
Цитата Сообщение от Igor_AIR Посмотреть сообщение
паложить в два словаря тоже пробовал!
Так оно же намного проще:
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Sub tt2dict()
 
Dim dict1 As Object, dict2 As Object, rngOut
 
Set rngOut = [a4].CurrentRegion
Set dict1 = CreateObject("Scripting.Dictionary")
Set dict2 = CreateObject("Scripting.Dictionary")
 
For Each cell In rngOut.Rows
 
    material = cell.Cells(1, 3).Value
    quantity = cell.Cells(1, 4).Value
    dateOut = CDate(cell.Cells(1, 1).Value)
 
    dict1(material) = WorksheetFunction.Max(dict1(material), dateOut)
    dict2(material) = dict2(material) + quantity
 
Next cell
    
'и выгрузка для проверки, с форматом дат не заморачивался
 With Workbooks.Add(1).Sheets(1)
 .Cells(1, 1).Resize(dict1.Count, 1) = Application.Transpose(dict1.items)
 .Cells(1, 2).Resize(dict1.Count, 1) = Application.Transpose(dict1.keys)
 .Cells(1, 3).Resize(dict2.Count, 1) = Application.Transpose(dict2.items)
 End With
 
End Sub
Там правда с датами не так - Вы минимальную сохраняете, я не парюсь и сохраняю максимальную ))

Добавлено через 12 минут
При моём подходе чтоб сохранить минимальную дату нужно сперва записать первую, затем проверять на существование ключа и сверять текущую с предыдущей...

Добавлено через 4 часа 18 минут
Вот так отбирает минимальную дату:
Visual Basic
1
2
3
4
5
    If dict1.exists(material) Then
        dict1(material) = WorksheetFunction.Min(dict1(material), dateOut)
    Else
        dict1(material) = dateOut
    End If
0
 Аватар для Angry Old Man
2995 / 738 / 310
Регистрация: 26.03.2022
Сообщений: 1,379
Записей в блоге: 1
11.05.2024, 19:32
Цитата Сообщение от Narimanych Посмотреть сообщение
С дурью -типа словарей:
и с типа массивом
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
Sub Igor_AIR()
    Const r1 As String = "A4"
    Const rDt As String = "A4"
    Const rMat As String = "C4"
    Const rM As String = "D4"
    Const rRez As String = "C2"
    
    Dim wsOut As Worksheet: Set wsOut = ThisWorkbook.Sheets("Out")
    Dim wsIn As Worksheet: Set wsIn = ThisWorkbook.Sheets("Temp")
    Dim rngOut As Range, rngIn As Range
    Dim All, key, dict As Object: Set dict = CreateObject("Scripting.Dictionary")
    Dim i, i1, iL, iDt, iMat, iM
    Dim ttt: ttt = Timer
    
    All = wsOut.Range(r1 + ":" + Split(wsOut.UsedRange.Address, ":")(1))
    iL = LBound(All, 1)
    
    i1 = Range(r1).Column
    iDt = Range(rDt).Column - i1 + iL
    iMat = Range(rMat).Column - i1 + iL
    iM = Range(rM).Column - i1 + iL
    
    For i = UBound(All, 1) To iL Step -1
        If dict.Exists(All(i, iMat)) Then
            If All(i, iDt) > dict(All(i, iMat))(0) Then
                dict(All(i, iMat)) = Array(All(i, iDt), dict(All(i, iMat))(1) + All(i, iM))
            Else
                dict(All(i, iMat)) = Array(dict(All(i, iMat))(0), dict(All(i, iMat))(1) + All(i, iM))
            End If
        Else
            dict.Add All(i, iMat), Array(All(i, iDt), All(i, iM))
        End If
    Next
    ReDim All(dict.Count - 1, 2)
    i = 0
    For Each key In dict.Keys
        All(i, 0) = key
        All(i, 1) = dict(key)(1)
        All(i, 2) = dict(key)(0)
        i = i + 1
    Next
    wsIn.UsedRange.ClearContents
    wsIn.Range(rRez).Resize(dict.Count, 3) = All
    
MsgBox "Готово!" & Timer - ttt, vbInformation
End Sub
Тестировал на 10000 строк, быстрее, чем с запросом. Eugene-LS, дайте образец Вашей таблицы на 10000 строк
0
6997 / 2895 / 555
Регистрация: 19.10.2012
Сообщений: 8,803
11.05.2024, 19:45
Интересно померить на 10к насколько быстрее будет на двух словарях и без массива в итем.
Или медленнее ((
0
Эксперт MS Access
 Аватар для Eugene-LS
12030 / 5822 / 1491
Регистрация: 05.10.2016
Сообщений: 16,399
11.05.2024, 21:59
Цитата Сообщение от Angry Old Man Посмотреть сообщение
дайте образец Вашей таблицы на 10000 строк
Вспомнили!
Удалено уж давно всё ...
Я просто размножил строки из примера, кол-во по возрастанию.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
11.05.2024, 21:59
Помогаю со студенческими работами здесь

Обновление базы и ошибка: Обновление невозможно. База данных или объект доступны только для чтения.
Помогите пожалуйста! asp не может обновить базу. Про ошибку говорит Microsoft OLE DB Provider for ODBC Drivers (0x80004005) ...

Поиск ключей и данных в коллекции Dictionary
Здравствуйте. Есть коллекция типа Dictionary с именем _Data типа &lt;string, string&gt;. Так же есть переменные типа string с именем _Char,...

class <T> и Dictionary со свободным типом данных
Всем доброго, есть проблема, не знаю как ее решить... Есть класс public class File &lt;T&gt; { public...

Dictionary как источник данных для dataGridView
Здравствуйте! Можно ли для dataGridView в качестве источника данных использовать Dictionary? Если можно, подскажите как? (нужно чтобы при...

Считывание базу данных из текстового файла и записывание в Dictionary<>
Всем привет! У меня задача создать базу данных в текстовом файле и работать с ней , но у меня есть проблема , я не понимаю как считать эту...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru