Главная » Статьи » 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
Просмотров: 104604 | Комментарии: 65 | Рейтинг: 4.8/15
Всего комментариев: 651 2 »
65 homolud-mailru   (17.11.2022 21:16) [Материал]
Здравствуйте. Спасибо за статью. Но тема UDT осталась раскрыта не полностью.
Вы в своем примере для добавления данных пользовательского типа использовали класс с тремя переменными. Вы придумали класс с нужными переменными, и добавили его в словарь в качестве элемента. Потом вы прочитали его, и все типа сохранилось.
Далее обнаруживается вот что:
заполняем объектную переменную новыми данными.
добавляем ее в dictionary
начинаем читать первый и второй Item из Dictionary
и обнаруживаем, что и в первом и во втором итеме храняться только последние добавленные данные.
Тоесть.
При добавлении объектов в словарь, хранится только один, самый последний добавленный экземпляр объекта.
Хотя всякие там .Count будут показывать то, сколько раз вы вызвали .Add
Что я делаю не так?

Сорри. Нашел разгадку.
перед добавлением объекта в словарь, его нужно "породить".
Технология такая:

- объявляем заново объект
- заполняем в него данные
- добавляем в словарь

- объявляем
- заполняем
- добавляем в словарь
и так далее

Моя ошибка была вот в чем:
- объявляем объект
- заполняем данными 
- добавляем в словарь

- заполняем данными
- добавляем в словарь

Тоесть словарь хранит именно экземпляры объекта. Если вы все время складываете в словарь один и тот же экземпляр объекта, то словарь в каждом итеме будет хранить только этот экземпляр объекта. С последними актуальными значениями свойств

0
62 ilboxx   (16.09.2019 18:47) [Материал]
Скажите, пожалуйста, существует ли коллекция Dictionary? К примеру, объявляемых в одном макросе. И, соответственно, возможность обращения к ним, например, Dictionary(1), Dictionary(2)... Или возможно их в массив можно записать? Или можно создать MainDictionary, содержащий в качестве элементов Dictionary?

0
63 dsb75   (17.09.2019 21:21) [Материал]
Здравствуйте!
Да, можно создать многоуровневый словарь, где у корневого словаря элементами будут другие словари. Это вполне обычная вещь, но в данной статье она не описана. Напишите мне на мыло, я найду вам примеры кода.

64 ilboxx   (20.09.2019 19:08) [Материал]
Я Вам написал. Спасибо!

59 maxinter   (19.01.2018 21:01) [Материал]
Может быть в красивой табличке Раздела 3 имеет смысл упомянуть, что у методов Keys и Items есть 2 формы вызова:
без аргументов и с аргументом - номером интересующего элемента словаря.
Да, k = DicObj.Keys, как и k = DicObj.Keys() возвращают массив ключей словаря (индексация от 0).
Но допустим и такой вызов метода Keys:
k = DicObj.Keys(n), тогда мы сразу получаем ключ элемента словаря с индексом n.
По моему такая запись работает чуть быстрее, чем k = DicObj.Keys()(n), т.к. во втором варианте мы сначала получаем копию массива ключей (обращением к Keys без параметров), а только затем из полученной копии выбираем нужный ключ по его индексу.
То же самое относится и к Items.

0
60 dsb75   (14.08.2018 18:42) [Материал]
Дело в том, что этот метод не всегда работает. Например, если при создании объекта Dictionary используется позднее связывание, то конструкция Items(n) выдаст вам ошибку 451.

58 vascrilov2018   (22.12.2017 09:13) [Материал]
Я все-таки так и не понял, в словарь можно забивать многомерные массивы в качестве элементов? И как получить доступ к элементу массива как элемента словаря? Еще подскажите пожалуйста, имеет ли какие преимущества словарь по сравнению с ADO? В смысле экономии памяти и быстродействия? Есть ли какие ограничения по памяти словаря? Сколько гигов туда можно забить, чтобы обычный ноут не захлебывался?

0
61 dsb75   (14.08.2018 18:47) [Материал]
Если у вас элемент словаря - двумерный массив, то примерно так dicTemp.Item(i)(n,m)
Сравнивать с ADO тяжело, это инструменты для разных задач. Для ADO нужна некая внешняя база данных, а словарь всё хранит в памяти ПК. Но вообще VBA и MS Office не предназначены для манипулирования гигабайтами информации - слишком медленно. Но если всё-таки захотите попробовать, то используйте 64-разрядные версии ОС и офиса.

56 talkgroups   (04.05.2017 05:16) [Материал]
В разделе 6.3 небольшая неточность: константы vbTextCompare и vbBinaryCompare. Хотя, думаю, прочитавшим это будет и так понятно, но всё ж.

0
57 dsb75   (07.05.2017 08:24) [Материал]
Вы правы. Я, видимо, свои константы определил.

0
54 borro   (28.01.2017 13:27) [Материал]
Здравствуйте. Спасибо. В статье остался не освещен вопрос о том, как изменить элемент словаря, который представляет собой массив. Например надо изменить i-ый элемент массива, хранящегося в словаре под неким ключом

0
55 dsb75   (30.01.2017 10:53) [Материал]
Да, вы правы. Есть такой нюанс. Как мы оба, похоже, знаем - только через перезапись всего массива smile

52 ye   (04.09.2016 10:24) [Материал]
Доброго дня!
Спасибо большое за статью) как раз пытаюсь разобраться со словарями и массивами)
Появился вопрос: можно ли суммировать значения внутри взятых в словарь элементов ?

0
53 dsb75   (25.12.2016 22:22) [Материал]
Перебирайте и суммируйте

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

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