Главная » Статьи » Excel » Макросы и программы VBA

Исчерпывающее описание объекта Dictionary

Содержание:

1. Что такое Dictionary?

2. Создание Dictionary

3. Свойства и методы объекта Dictionary

4. Наполнение словаря

    4.1. Типы данных ключа и элемента
    4.2. Через метод Add
    4.3. Через свойство Item
    4.4. Неявное добавление ключа в Dictionary

5. Удаление элементов

    5.1. Удаление конкретного элемента
    5.2. Очистка всего словаря

6. Ключи

    6.1. Последовательность хранения
    6.2. Добавление элементов с ключами разных типов
    6.3. Уникальность строковых ключей
    6.4. Генерация уникальных ключей

7. Элементы

    7.1. Типы элементов
    7.2. UDT

8. Доступ к элементам словаря

    8.1. Извлечение элемента по ключу
    8.2. Извлечение элемента по номеру его индекса
    8.3. Извлечение ключа по номеру его индекса

9. Перебор словаря

    9.1. For each по массивам Keys и Items
    9.2. For по массивам Keys и Items
    9.3. Фильтрация элементов
    9.4. Выгрузка словаря в диапазон ячеек
    9.5. Операции с ключами/элементами при помощи формул рабочего листа

10. Файл примера

11. Заключение

12. Использованный источник

1. Что такое Dictionary?

Если вы программируете на VBA/VBS, то рано или поздно вынуждены будете познакомиться с объектом Dictionary. Если в двух словах, то Dictionary - это продвинутый массив. Как вы знаете, массив - это упорядоченный набор неких (обычно однородных) элементов. Вот типичный массив:

Элементы пронумерованы и доступны по номеру индекса. Индекс всегда числовой.


А вот, что из себя представляет Dictionary (словарь):

Как видите, каждому элементу поставлен в соответствие не просто числовой индекс, а уникальный ключ, который в данном случае представляет из себя текстовую строку (имена). Двух одинаковых ключей в словаре быть не может, но могут быть одинаковые элементы (хоть все одинаковые). Таким образом словарь - это обычно некий список, снабжённый ключом, при помощи которого вы хотите извлекать полезную информацию (элементы). В указанном примере мы имеем, допустим, имена детей в качестве ключа, а в качестве элементов, поставленных в соответствие ключу, скажем, количество карманных денег у ребёнка.

С другой стороны нечто подобное можно же сделать, используя массив. Давайте объявим двумерный массив:

Должно быть у словаря есть какие-то преимущества перед таким использованием массивов? И это действительно так!

Давайте пока просто перечислим важнейшие преимущества:

  1. Словарь контролирует уникальность ключей. Два одинаковых ключа не могут быть добавлены в словарь. Это важное свойство, так как программисту очень часто требуется обеспечить или проконтролировать уникальность каких-либо наборов значений, и в этом может с успехом быть использован Dictionary;

  2. Словарь очень эффективно (при помощи встроенного алгоритма бинарного поиска) осуществляет извлечение элементов по известному ключу. В десятки раз быстрее, чем обычный перебор;

  3. У словаря есть встроенный метод (Exists), при помощи которого можно понять, добавлен ли некий ключ в коллекцию;

  4. Словарь позволяет добавлять новые элементы и удалять любые элементы, что, работая с массивами, сделать гораздо сложнее;

  5. Словарь может вернуть все ключи и все элементы в виде отдельных одномерных массивов.

▲ вверх

2. Создание Dictionary

Существует несколько способов создать объект типа Dictionary. Ознакомимся с ними:

Считается, что методы, использующие позднее связывание надёжнее в плане обеспечения работоспособности программы на разных компьютерах, так как не зависят от настроек Tools - References... редактора VBA.

Однако, учитывая, что библиотека Microsoft Scripting Runtime присутствует везде, начиная с Windows 2000, я думаю, что вы без какого-либо ущерба можете использовать методы раннего связывания. Раннее связывание хорошо тем, что оно несколько быстрее работает, а также во время разработки вы можете пользоваться функцией завершения кода (когда среда программирования вам подсказывает имеющиеся у объекта свойства и методы). Выбор за вами.

▲ вверх

3. Свойства и методы объекта Dictionary

Тип Идентификатор Описание
Свойство Count dicObject.Count
Возвращает количество элементов в словаре. Только для чтения.
Свойство Item dicObject.Item(key)[ = newitem]
Устанавливает или возвращает элемент с указанным ключом. Чтение/запись.
Свойство Key dicObject.Key(key) = newkey
Заменяет ключ элемента на новое значение.
Свойство CompareMode dicObject.CompareMode[ = compare]
Устанавливает и возвращает режим сравнения текстовых ключей в словаре. Чтение/запись.
Метод Add dicObject.Add (key, item)
Добавляет пару ключ-элемент в словарь.
Метод Exists dicObject.Exists(key)
Возвращает true, если указанный ключ существует в словаре, либо false - в противном случае.
Метод Items dicObject.Items( )
Возвращает массив, состоящий из всех элементов, имеющихся в коллекции.
Метод Keys dicObject.Keys( )
Возвращает массив, состоящий из всех ключей, имеющихся в коллекции.
Метод Remove dicObject.Remove(key)
Удаляет из словаря элемент с указанным ключом.
Метод RemoveAll dicObject.RemoveAll( )
Полностью очищает словарь от элементов. Сам объект словаря при этом не уничтожается.

▲ вверх

4. Наполнение словаря


4.1. Типы данных ключа и элемента

Dictionary наполняется по одному элементу. Не существует способов наполнить словарь массово. Чтобы добавить в словарь новый элемент вы должны иметь уникальный ключ и сам элемент, который под этим ключом будет храниться в словаре.

В качестве типа данных для элемента может быть использовано практически всё что угодно: числа, логический тип, строки (в том числе пустые), дата-время, массивы, любые объекты (листы, диапазоны, коллекции, другие словари, пустой указатель Nothing).

В качестве типа данных для ключа могут быть использованы: числа, строки, дата-время, объекты, но не массивы.

UDT (User Defined Type) не может напрямую использоваться в качестве ключа и/или элемента, но данное ограничение можно обойти, объявив аналог UDT, создав класс и определив в нём свойства аналогичные имеющимся в UDT. А поскольку класс - это объектный тип, то его уже можно использовать для ключей и элементов.

▲ вверх

4.2. Через метод Add

На листе Example, прилагаемого к статье файла, есть таблица с TOP30 стран по площади их территории. Для области данных этой таблицы объявлен именованный диапазон SquareByCountry. Пример ниже добавляет все строки указанногот ИД в Dictionary по принципу страна (key) - площадь (item):

Как видите, для добавления элемента (item) мы в 12-й строке кода использовали метод Add объекта dicCountry. Если в нашей таблице будет задвоена страна, то при попытке добавить в словарь элемента с ключом, который в словаре уже есть, будет сгенерировано исключение:

▲ вверх

4.3. Через свойство Item

Используя свойство Item, также можно добавлять пары ключ-элемент, однако, при попытке добавить дублирующий ключ исключения сгенерировано НЕ БУДЕТ, а элемент будет заменён на новый (с потерей старого). Это очень полезно - иметь возможность выбирать способы наполнения словаря, отличающиеся реакцией на задвоение ключей.

▲ вверх

4.4. Неявное добавление ключа в Dictionary

И ещё один неожиданный и я бы сказал экзотический способ пополнения словаря. Если упомянуть свойство Item по ПРАВУЮ сторону оператора присваивания, то он оказывается добавит в словарь key с пустым item, если данного key не существует в коллекции. Если же такой key уже существует, то никаких действий предпринято не будет.

Ещё раз хочу обратить ваше внимание, что элемент (item) при таком пополнении коллекции будет пустым (Empty). Это можно использовать, если вам нет необходимости что-то хранить в элементах в качестве полезной нагрузки (например, когда вы просто строите список уникальных значений, встречающихся в столбце таблицы).

Если вы читаете словарь через Item (а это, собственно, самый логичный и распространенный метод), и при этом хотите избежать добавления пустых ключей в словарь, используйте предварительно метод Exists, что контроля наличия такого ключа в коллекции.

▲ вверх

5. Удаление элементов

Есть 2 варианта удаления элементов из словаря:

5.1. Удаление конкретного элемента

▲ вверх

5.2. Очистка всего словаря

Полагаю, комментировать тут нечего.

▲ вверх

6. Ключи

6.1. Последовательность хранения

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

▲ вверх

6.2. Добавление элементов с ключами разных типов

Продемонстрируем, добавление элементов с ключами разных типов в словарь:

Вот, что мы получим, выполнив представленный код:

▲ вверх

6.3. Уникальность строковых ключей

При помощи свойства CompareMode можно управлять тем, как Dictionary будет реагировать на одинаковые текстовые ключи, набранные в разном регистре. При значении CompareMode равным константе TextCompare (1) разный регистр игнорируется и ключи считаются идентичными, а при константе BinaryCompare (0) такие ключи считаются разными. Менять CompareMode можно только, когда словарь пуст (либо только создан, либо только что очищен).

▲ вверх

6.4. Генерация уникальных ключей

Иногда требуется сохранить в Dictionary все элементы, а какие при этом будут ключи нам всё равно - лишь бы они были уникальные, так как в противном случае мы можем потерять некоторые элементы (items). В таких случаях очень удобно использовать свойство Count в качестве генератора уникального значения ключа, так как Count гарантированно увеличивается на единицу всякий раз, когда добавляется элемент.

▲ вверх

7. Элементы

7.1. Типы элементов

Продемонстрируем добавление в словарь элементов разных типов:

▲ вверх

7.2. UDT

Как я уже упоминал, напрямую переменные типа UDT нельзя сохранять в качестве элементов Dictionary. Чтобы это обойти нужно вместо UDT создать модуль класса, полностью соответствующий структуре необходимого вам UDT. Например, я создал модуль класса с названием MyRGB и определил его так:

далее становится возможным следующее:

▲ вверх

8. Доступ к элементам словаря

8.1. Извлечение элемента по ключу

Этот способ мы уже обсуждали, но для полноты картины повторимся.

Мы используем свойство Item с указанием ключа. Если ключа не существует, то будет возвращено значение Empty, а в словарь добавлен данный ключ со значением Empty в качестве элемента. Никаких исключений не генерируется. Если хотите избежать добавления ключа в коллекцию, используйте предварительно метод Exists для проверки его наличия.

▲ вверх

8.2. Извлечение элемента по номеру его индекса

Для извлечения конкретного элемента по его индексу необходимо использовать конструкцию Items()(i), где i - индекс элемента, начинающийся с нуля. Это довольно неожиданный синтаксис, я не припомню, чтобы он применялся где-то ещё кроме Dictionary. Согласно таблице, приведенной выше, Items - свойство, содержащее одномерный массив всех элементов словаря. Также есть соответствующий массив Keys для всех ключей словаря.

▲ вверх

8.3. Извлечение ключа по номеру его индекса

Безусловно то же самое справедливо и для извлечения ключей.

▲ вверх

9. Перебор словаря

9.1. For each по массивам Keys и Items

▲ вверх

9.2. For по массивам Keys и Items

▲ вверх

9.3. Фильтрация элементов

Для фильтрации словаря по ключам или элементам крайне удобно использовать VBA функцию Filter. Вот как это может выглядеть:

▲ вверх

9.4. Выгрузка словаря в диапазон ячеек

Результат:

▲ вверх

9.5. Операции с ключами/элементами при помощи формул рабочего листа

Если ключи/элементы у вас в виде числовых значений, то к ним легко можно применять стандартные функции рабочего листа. Например, ниже я определяю страну с наибольшей территорией и вывожу её название. Числовую территорию в данном случае желательно иметь в виде ключа, так как зная ключ, вывести элемент легко, а вот, зная элемент, найти по нему ключ, гораздо сложнее (потребуется перебор всего словаря).

К вашим услугам и другие функции, такие как: Min(), Large(), Small() и т.д.

▲ вверх

10. Файл примера

Скачать примеры кода VBA

▲ вверх

11. Заключение

Я надеюсь, что данная статья помогла вам хорошенько разобрать с объектом Dictionary. В моих ближайших планах рассказать, как при помощи словаря строить произвольные иерархические структуры. Так же стоит упомянуть, что в VBA есть такой встроенный объект Collection. Однако, по своим функциональным возможностям он достаточно уныл и вчистую проигрывает Dictionary, поэтому я не хочу тратить на него силы и время. Единственное его преимущество это то, что он часть MS Office, а словарь - часть MS Windows, поэтому первый работает в MS Excel for Mac, а второй - нет. Но пока (да и вообще) в нашей стране это обстоятельство можно с лёгкостью игнорировать.

▲ вверх

12. Использованный источник

Массу конкретного материала по объекту Dictionary я подчерпнул из этой замечательной (огромной!) статьи некоего, по всей видимости испанского, автора, имени которого на сайте нет. Очень рекомендую. На сайте также даётся огромное количество примеров работы с объектной моделью Outlook!


Читайте также:

Категория: Макросы и программы VBA | Добавил: dsb75 (20.07.2015) | Автор: Батьянов Денис E W
Просмотров: 10921 | Комментарии: 52 | Рейтинг: 5.0/5
Всего комментариев: 52
52 ye   (04.09.2016 10:24)
Доброго дня!
Спасибо большое за статью) как раз пытаюсь разобраться со словарями и массивами)
Появился вопрос: можно ли суммировать значения внутри взятых в словарь элементов ?

48 amuhanin   (27.03.2016 17:55)
Денис, спасибо за статью. 
Я только познакомился с Dictionary, но сразу столкнулся с ограничением, о котором упоминал Kokonoko... 

При выводе словаря, содержащего более 65000 строк (вычислил я точную цифру, но не суть), возникают проблемы... 

Это ограничение можно обойти как-то красиво?

0
49 dsb75   (18.07.2016 16:35)
Посоветую использовать 64-разрядную версию MS Office

46 Aleksey   (19.11.2015 14:22)
Для сортировки элементов по текстовым ключам функция есть?

0
47 dsb75   (19.11.2015 15:24)
Словарь не отсортируешь, можно взять массив Keys и отсортировать через функции сортировки массивов. А если надо иметь сортированный словарь, то только через пересоздание.

0
11 Kokonoko   (05.09.2015 21:23)
Еще возник технический вопрос реализации работы словарей:
Самая часто встречающаяся рабочая задача собрать неким образом обработанные данные из разных источников в двумерную таблицу – матрицу NxM. Где N количество
строк мы никогда не знает, а M- количество столбцов, почти всегда известно. И далее эту матрицу просто вставить в определённое место.
А так как поячеичная вставка данных занимает много ресурсовсистемы и выполняется крайне медленно. Пришлось исхитрятся в оптимизации). В конце концов я вывел для себя способ:
- сами данные собираю(1 x M) собираю в одномерный массив (1 x M), а массивы собираю в коллекцию.

Когда приходит время выгружать на лист иду циклом по коллекцииа массивы сразу гружу в Range строки, и получается нечто похожее:
Код
[b]For i = 1 To collRows.Count
[b]ws.Range(ws.Cells(i, 1), ws.Cells(i, UBound(collRows(i)))) = collRows(i)
[b]Next i


Когда прочитал Вашу статью решил взять на вооружение новыйметод:
Т.е. основные данные также собирать в массивы (1 x M), а массивы собирать всловарь.
И на выходе при помощи .Items  -> мы получимквадратную матрицу которую можно будет одномоментно (без цикла) грузить на лист
в Range. Но не тут то
было…
Матрица получается какая-то не понятная экселю и на лист невыгружается ничего: т.е.
Код
[b]Range(“”)=[b]dct.[b]items()

будет пустым. Для того чтобы данные выгрузились, нужно использоватьдвойное транспонирование:
Код
Range(“”)=Application.Transpose(Application.Transpose(dct.Items))

– и это работает! Но только до тех пор, пока не натыкаетсяна ограничение «Transpose»,
65 тыщ. строк в транспонируемом массиве – дальше Дамп.

0
13 dsb75   (05.09.2015 23:21)
Я обычно использую такой метод:
если Arr - двумерный массив, который я хочу видеть на листе, то вставляется он так:
ActiveCell.Resize(UBound(Arr, 1), UBound(Arr, 2)) = Arr

Надо заметить, что это красивый код, он мне очень нравится.

0
15 Kokonoko   (07.09.2015 13:30)
Да, довольно лаконично)
Но вопрос в другом, Вы никогда не работали со словарём (состоящим из одномерных массивов) как с матрицей, может знаете, почему данные в таком случае не грузятся на лист напрямую?

0
17 dsb75   (07.09.2015 15:46)
Покажите мне полный код. Я что-нибудь посоветую.

0
19 Kokonoko   (07.09.2015 16:54)
Пока не надо)
После перезагрузки экселя ошибка ушла...

0
18 dsb75   (07.09.2015 16:03)
Не совсем понял, раз вы говорите про 1xM, то значит данные вы разбиваете по строкам, а столбцы видимо будут идти непрерывно в целевом диапазоне. Почему бы тогда не подготовить в памяти массив NxM и не вставить его сразу целиком? Ведь, когда вы формируете свою коллекцию, то на тот момент N наверняка ведь уже известна?

0
20 Kokonoko   (07.09.2015 17:05)
Потому что он динамический, с неизвестным количеством строк.
N - мы узнаём в самом конце консолидации данных.
https://fotki.yandex.ru/next/users/kokonoko/album/496947/view/1326452

0
21 dsb75   (07.09.2015 18:34)
Короче, ясно. Словарь с с массивами 1xM можно оставить. После заполнения словаря его содержимое перепишите в массив NxM (N вы уже знаете на этот момент dicObj.Count). И никакое транспонирование вам не потребуется.

Альтернативный вариант можно базировать на том, чтобы работать с динамическими массивами M x N, а не (N x M). Поскольку внешнюю размерность массива можно расширять через ReDim, то словарь вам не потребуется. А подпрограмму для транспонирования массива вы можете взять у Чарльза Пирсона

22 Kokonoko   (10.09.2015 11:27)
Вариант с промежуточным массивом тоже не прошёл тестирование: т.к. словарь занимает большое количество памяти, и при количестве строк от 80-100 тыс. excel периодически падает в дамп "Out of Memory", еще при попытке средимить промежуточный массив по параметрам словаря.
А вариант через с Redim обратного массива,  для меня не очень красивый из-за перевернутости массива и не даст суммарного прироста производительности, т.к. redim preserve ест много ресурсов (а редимить скачками усложняет процесс реализации).

Просто хотел взять в работу более совершенный и простой инструмент smile

В сухом остатке: остаюсь на текущей технологии ч/з коллекцию/словарь с наборами одномерных массивов и построчной выгрузкой на лист, как на методе (на мой взгляд) находящимся на пересечении простоты и краткости реализации, быстроты работы и надёжности ))

Спасибо за советы!

0
23 dsb75   (10.09.2015 13:12)
Сомневаюсь, что построчная выгрузка на лист не является узким местом в плане производительности. Сколько это занимает по времени для 50 000 строк?

0
24 dsb75   (10.09.2015 13:13)
Кстати в плане идей посмотрите ещё эту статью

0
26 Kokonoko   (14.09.2015 13:35)
Дома позанимался НИОКР ом (правда там машина несколько быстрее чем на работе).
Дано: 41 файл откуда будет извлекаться 73606 обработанных строк с данными.

Время чистой консолидации (мин:сек)
                                           в словарь  1-43
                                           в коллекцию 1-41
Время полной работы программы (консолидация+выгрузка в файл) в строке вида:
 ws.Range(ws.Range("A" & lngR), ws.Cells(lngR, UBound(dctRows.items()(0)))) = dctRows(lngR - 1) ' Т.е. с извлечением размера массива на лету из Item'а
                                            словарь 1-46
                                            коллекция 3-23

Время полной работы программы (консолидация+выгрузка в файл) в строке вида:
ws.Range(ws.Range("A" & lngR), ws.Cells(lngR, 8)) = dctRows(lngR - 1)
' Т.е. без извлечения размера массива из Item'а:
                                            словарь 1-46
                                            коллекция 2-36

Из чего можно сделать вывод, что на мощной машине (I7-4770s +16GB RAM+SSD) построчная выгрузка данных словаря почти не влияет на время работы общей процедуры, причём не зависимо от отдельной распаковки элемента для получения ширине массива.
Коллекция выгружает данные медленнее, а если ещё и отдельно распаковывать элементы, то производительность снижается ещё сильнее.

0
28 dsb75   (14.09.2015 14:04)
А вы не могли бы кинуть всю процедуру, а то о многих вещах приходится догадываться, а предыдущая переписка довольно сумбурна.

0
29 dsb75   (14.09.2015 20:06)
Душевная конфигурация компа smile

Я тут смотрел на ваши скрины и не могу взять в толк, накой чОрт вы всё-таки это делаете построчно?
1. Открыли файл, нашли диапазон N  x M,
2. прочитали его в динамический массив
3. динамический массив поместили в словарь
4. Следующий файл

5. Консолидация в обратном порядке

Код рациональней и эффективность будет выше.

0
30 Kokonoko   (14.09.2015 22:22)
И правда душевная, а главное всё в 3-х литровом корпусе и почти бесшумно , можно и бесшумно сделать (но лениво единственный вентилятор менять на Noctua Noctua NF-S12A ULN) biggrin

Это усложение процесса обработки)) На самом деле нет проблемы обработать какие-то файлы. Я просто в поисках идеально сбалансированного (для себя) метода обработки: самый простой и короткий с точки реализации и отдладки, и при этом быстрый. Такой вот поиск совершенства biggrin За советы Спасибо!!!

Теперь главное с глюками словарей (или моими) разобраться и буду их использовать намного чаще)

0
32 dsb75   (14.09.2015 23:53)
Где же усложнение? Давайте посоревнуемся smile

0
37 Kokonoko   (15.09.2015 22:47)
Можно))

0
39 dsb75   (15.09.2015 22:49)
С вас формальное описание задачи smile

0
40 Kokonoko   (15.09.2015 22:55)
Хорошо только я на нём повишу некоторое время.
Если брать файлы заказчика - то их придётся сначала переработать, ибо политика безопасности...

0
42 dsb75   (15.09.2015 22:57)
Нагенерите всякий мусор - без разницы

43 Kokonoko   (21.09.2015 13:16)
Добрый день.
Обещанное ТЗ)
Нужно сгенерировать csv файл состоящий из 8-ми полей из n-го количества файлов.
Правила заполнения на листе "Запуск" в книге "Формирование CSV на основе ОИБ.." CSV - результат (Master Data от 21.09.2015) и мой файл делающий обработку (Формирование CSV на основе ОИБ v3.2 Раб) я приложил.
https://yadi.sk/i/vMLnSRvGjDYg8
https://yadi.sk/d/56t9QFaejDYgE
https://yadi.sk/i/jzQiWXEhjDYgG

0
44 dsb75   (21.09.2015 23:27)
Здравствуйте!
Ознакомился с вашими данными и алгоритмом. У вас тут есть ПРИЧИНА, по которой вы считываете данные построчно - данные то идут не подряд, а перемежаются скрытыми строками (вы, кажется, об этом не упоминали).

Стиль, конечно, есть куда совершенствовать, но в главном тут навряд ли что-то можно улучшить - всё проистекает из структуры данных...

0
45 Kokonoko   (22.09.2015 15:07)
Добрый день.
Это типичная задача, в которой нельзя сразу определить количество строк целевого массива.

Но словари всё равно крутая штука, отдельное СПАСИБО что разъяснили про поведение словаря при добавлении его в watches (проблемы с ненужным добавлением исчезли), теперь в разы больше пользуюсь словарями (вместо коллекций).

А стиль... всегда есть куда совершенствоваться smile

0
8 Kokonoko   (05.09.2015 20:54)
На основе Вашей статьи вывел перебор элементов (Items) в цикле аналогичном циклу по коллекции, если использовать в виде ключа "dicTemp.Count + 1".

Код
Sub Loop_3()

Dim dicTemp As Object
Dim varCountry As Variant
Dim strShow As String, i As Integer

Set dicTemp = CreateObject("Scripting.Dictionary") 'Мне так привычнее

For Each varCountry In Array("Russia", "Canada", "China", "USA", "Brazil")
dicTemp(dicTemp.Count + 1) = varCountry
Next varCountry

For i = 1 To dicTemp.Count
strShow = strShow & dicTemp(i) & vbLf
Next i

MsgBox strShow

strShow = vbNullString
End Sub


Единственная проблема: словарь может самопроизвольно добавлять (пустые) элементы в конце (даже если с него не ничего считывать, перед этим), при обращении к которым может возникнуть дамп.

9 dsb75   (05.09.2015 21:16)
C нуля начинается нумерация Items, а не с 1 и заканчивается на Count-1.

И вот это не имеет смысла "strShow = vbNullString"

0
10 Kokonoko   (05.09.2015 21:21)
Со вторым согласен, просто оставил.
А с первым - нет. Мы когда добавляем 5 элементов в словарь, - у нас dicTemp.count будет 5. Я извлекаю по ключу подогнанному под count.

0
12 dsb75   (05.09.2015 23:16)
Да, я не совсем прав. Items, конечно, начинается с нулевого элемента, только он тут не при чём. Тут речь про ключи, а они могут быть вообще любыми. Тогда, что за проблемы самопроизвольного добавления...?

0
14 Kokonoko   (07.09.2015 13:25)
Бывает что у меня (и других сотрудников) словари подглючивают.
Обычно это выражается так: в одной процедуре идёт формирование и заполнения словаря. После выхода из неё, и при входе в другую процедуру (где значения должны выгружаться) в словаре появляются 1 или несколько пустых элементов в конце. Обычно это решается перезапуском экселя или перезагрузкой компьютера. Возможно в словарь попадает какой то мусор из кэша.

0
16 dsb75   (07.09.2015 15:41)
Маловероятно. Надо смотреть код внимательно. Вы же читали, как просто добавить новый ключ с пустым элементом...

0
25 Kokonoko   (14.09.2015 13:22)
Добрый день.
Наловил 2 глюка словарей. Код процедуры неизменен.
1 Глюк: при инициализации словаря в нём уже есть пустой элемент:
https://yadi.sk/i/vP0erLjZj5Hxp
2 Глюк: при обработке exists вместо проверки создаётся пустой элемент с данным ключом.
https://yadi.sk/i/cwCcXkMCj5JEd

Бывает ещё 3 глюк, когда пустые элемены добавляются в словарь после окончания работы с ним. Пруфа пока нет))

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

0
27 dsb75   (14.09.2015 13:53)
Полагаю, дело в том, что ваши действия по контролю состояния объекта Dictionary во время отдадки и создают эти элементы. По крайней мере, в глюке № 2. Вы ведь добавили соответствующий watch.

0
31 Kokonoko   (14.09.2015 22:24)
Очень инетересно замечание, я всегда мониторю переменные через watch (поэтому и with очень редко использую). А почему watch может давать такой эффект и как с эти бороться?

0
33 dsb75   (15.09.2015 00:01)
Ну,  в статье же написано, что Dictionary при чтении свойства Item создаёт соответствующий Key. Вот вы, видимо, добавили в watch
dct(strBudg), когда strBudg ещё не было инициализировано и - вуаля -
создался пустой элемент с пустым ключом.
Чтобы ничего не создавалось, надо не трепыхать свойство Item (делать отладочную печать
через Items?), либо писать программы так, чтобы пустые узлы ни на что не
могли повлиять - фильтровать их...

0
34 Kokonoko   (15.09.2015 22:31)
Похоже у меня пробел в знаниях) Думал что в watch только приходят параметры (работает исключительно как монитор) и из него ничего не уходит в программу... Тогда всё становится яснее.

0
35 dsb75   (15.09.2015 22:43)
О, я тоже этого не знал, пока вы не сообщили о своём глюке. Это гипотеза, которая хорошо укладывается в известные факты smile

0
36 Kokonoko   (15.09.2015 22:45)
Да, очень похоже, причём очень сильно.
А я на что только не грешил, думал нужно ключ создавать чисто текстовый или что словарь может подсосать какой-нибудь мусор из оперативки если программу прервать))

0
38 dsb75   (15.09.2015 22:48)
Создатели объекта Dictionary большие оригиналы - менять структуры по факту чтения, это очень необычно.... Спорное архитектурное решение, чего уж там.

0
41 Kokonoko   (15.09.2015 22:57)
Это точно...

0
6 Dman   (05.09.2015 11:58)
Проверил. Действительно можно.

Ещё раз спасибо.

0
7 dsb75   (05.09.2015 12:01)
Гишпанец, поди говорил про Keys и Items, а вы так расширительно интерпретировали. Бывает smile

0
4 Dman   (05.09.2015 11:30)
Случайно наткнулся на Ваш сайт.
Понравился. Понравилось оформление, понравилось наполнение, понравился стиль изложения.
Хочу сделать дополнение к статье - стоит указать в явном виде, что нельзя редактировать отдельные элементы массивов, сохранённых в Dictionary, - только полной заменой всего массива как единого целого. Это я, кстати, почерпнул в указанном Вами источнике.

А в целом - очень хорошая статья по Dictionary. Спасибо.

0
5 dsb75   (05.09.2015 11:44)
Спасибо, но я с вами не согласен по поводу массивов. С чего бы это нельзя?

0
2 Kokonoko   (03.09.2015 16:20)
Это самая Лучшая статья по VBA которую я читал!!!
Пользуюсь словарями уже 2 с лишним года и не знал половины возможностей!!!
Специально зарегистрировался, чтобы сказать Вам СПАСИБО !!!

0
3 dsb75   (03.09.2015 20:29)
Приятно, чёрт побери smile

0
1 dsb75   (01.08.2015 17:29)
Статья то хорошая? нет? smile

50 bezurog   (06.08.2016 11:55)
Статья хорошая, но не исчерпывающая. Например, нет информации как получить список значений по ключу

0
51 dsb75   (06.08.2016 18:32)
Касатик, а что такое "список значений по ключу" ?

Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Яндекс.Метрика