Основы офисного программирования и язык VBA

       

Встроенный динамический класс Collection


Коллекция в VBA - упорядоченная совокупность элементов, вообще говоря, разного типа. Этим коллекция отличается от массива, где объединяются только однотипные элементы. Все элементы индексированы, но некоторые могут иметь и ключ, связанный с элементом. Размер коллекции заранее не фиксируется и может динамически изменяться. Любой существующий элемент коллекции может быть удален, при этом не возникает "дыр" - элементы перенумеровываются, и непрерывность последовательности индексов не нарушается. Неприятным следствием этого факта, приводящего иногда к ошибке, является то, что индекс в отличие от ключа не является постоянной характеристикой элемента и может изменяться в процессе работы с коллекцией. Новый элемент может быть добавлен в произвольное место коллекции, - как перед некоторым элементом, так и после любого из элементов.

У класса Collection одно свойство - Count и 3 метода: Add, Item, Remove. Рассмотрим их подробнее:

  1. Свойство Count возвращает число элементов коллекции. Доступно только для чтения, имеет тип возвращаемого значения Long.
  2. Метод Add (item, key, before, after) добавляет элементы в коллекцию. Первый параметр Item является обязательным и задает добавляемый элемент. Параметр key - необязателен, он задается, когда элементу ставится в соответствие ключ. Два последних необязательных параметра уточняют позицию вставки, - задают индекс или ключ элемента, перед или после которого добавляется новый элемент. Только один из этих параметров может быть задан. Если не задан ни один, элемент добавляется в конец коллекции.
  3. Метод Remove(key) удаляет элементы коллекции. Удаляется элемент с заданным ключом: заметьте, это может быть индекс элемента. После удаления происходит перенумерация элементов и уменьшается счетчик Count.
  4. Метод Item(key) возвращает значение элемента списка с заданным ключом. И здесь в роли ключа может выступать обычный индекс элемента.

Обратите внимание на мощность методов класса. Они позволяют реализовать различные классические динамические структуры.
Конечно же, совсем просто реализуется обычный односвязный список с возможностью добавления элементов в начало или конец списка. Но можно реализовать и значительно более мощную структуру, называемую словарем. Словарь представляет собой связанную совокупность пар элементов. Первый элемент пары называется ключом, второй - информационным полем. Особенностью словарей является то, что, зная ключ элемента, можно получить доступ к информационному полю. При этом, обратите внимание, в классе Collection на ключ не накладывается никаких ограничений, - это обычная строка. Немаловажно, что есть и альтернативный способ прямого доступа к элементам коллекции по индексу, когда в качестве ключа выступает порядковый номер элемента в коллекции. Таким образом, коллекция соединяет в себе достоинства списков и массивов.

Приведем теперь пример процедуры, подробнее демонстрирующий работу с коллекцией. Наша коллекция будет включать данные двух типов: целочисленные и строковые. Часть элементов будет иметь ключ, остальные - только индекс. Элементы будут добавляться в заданную позицию и удаляться. Отладочная печать позволит проследить за этим процессом:

Пример 5.8.

(html, txt)

Приведем теперь результаты отладочной печати:

Число элементов пустой коллекции = 0 Число элементов после 6-и вызовов метода Add = 6 Элементы коллекции: один 2 три 4 пять 6 Число элементов после двух вызовов метода Remove = 4 Элементы коллекции: один 2 три 6

Подчеркнем еще раз основные свойства класса Collection:

  1. Класс позволяет объединять в коллекцию элементы разных типов, хотя чаще применяются однотипные коллекции.
  2. Класс объединяет в себе свойства линейного списка, динамического массива и структуры, называемой словарем , или отображением (map).
  3. Это список, поскольку определена операция Add, позволяющая динамически добавлять элементы в конец списка.
  4. Это динамический массив, поскольку все элементы индексированы и к ним возможен прямой доступ по индексу. С другой стороны, размер массива не фиксируется и динамически изменяется при добавлении и удалении элементов.
  5. Это словарь, поскольку добавляемые элементы могут иметь ключ.


    Прямой доступ к элементам возможен как по индексу, так и по ключу. Под "прямым" здесь понимается доступ, основанный на применении функций расстановки (хэширования). Конкретный вид этих функций, определяющий эффективность поиска, - "секрет фирмы".
  6. В классе определены методы Add, Item, Remove и свойство Count.


Элементами коллекции могут быть данные любых типов, встроенных в VBA. Не менее важно, что допускается строить коллекцию из объектов, классы которых определены программистом. В предыдущих примерах этой лекции мы использовали для построения групп массивы только по той причине, что еще не ввели понятие коллекции. Более разумно было бы использование коллекций при работе с личностями, владельцами машин и самими машинами. Построим пример, в котором действует коллекция личностей:

Пример 5.9.

(html, txt)

В процессе работы этой процедуры в диалоговом окне появится сообщение о Шекспире, а в отладочном окне Immediate появятся следующие результаты:

Пушкин - это Гений! Булгаков - это Мастер! Адам Первый Человек родился 01.01.100 Ной Праведник родился 01.01.100 Гомер Великий Слепой родился 01.01.100 Вильям Шекспир родился 23.04.1564 Александр Пушкин родился 06.06.1799 Михаил Булгаков родился 23.01.1891

При создании коллекции мы использовали все три возможности добавления элементов: с заданным ключом, с заданным индексом и в конец списка. Доступ к элементам осуществлялся либо по индексу, либо по ключу. Так что наш пример демонстрирует все достоинства работы с классом Collection. Но, говоря о достоинствах, не следует забывать и о недостатках. Заметьте: при работе с коллекцией потребовалось для каждой личности создать собственную переменную, так что, по существу, мы имеем копии всех элементов коллекции в виде переменных. Это связано с тем, что при добавлении элемента в коллекцию не создается копия элемента, а используется ссылка на существующий элемент, так что коллекция не имеет собственной памяти для хранения элементов. Позже мы покажем, как можно преодолеть этот недостаток коллекции, а пока же подчеркнем, что по этой причине и по многим другим следует уметь создавать собственные динамические структуры данных.К их рассмотрению мы и переходим.



Более разумно было бы использование коллекций при работе с личностями, владельцами машин и самими машинами. Построим пример, в котором действует коллекция личностей:

Public Sub Collection() 'Создание и работа с коллекцией личностей Dim Личности As New Collection 'Работа с коллекцией, как со списком Dim Адам As New Личность Адам.InitPerson "Адам", "Первый Человек", #1/1/100# Личности.Add Адам Dim Ной As New Личность Ной.InitPerson "Ной", "Праведник", #1/1/100# Личности.Add Ной 'Работа с коллекцией, как с динамическим массивом Dim Шекспир As New Личность Шекспир.InitPerson "Вильям", "Шекспир", #4/23/1564# Личности.Add Item:=Шекспир, After:=2 Dim Гомер As New Личность Гомер.InitPerson "Гомер", "Великий Слепой", #1/1/100# Личности.Add Item:=Гомер, Before:=3 Личности(4).SayWhoIs 'Работа с коллекцией, как со словарем Dim Пушкин As New Личность Пушкин.InitPerson "Александр", "Пушкин", #6/6/1799# Личности.Add Item:=Пушкин, Key:="Гений" Dim Булгаков As New Личность Булгаков.InitPerson "Михаил", "Булгаков", #1/23/1891# Личности.Add Item:=Булгаков, Key:="Мастер" Debug.Print Личности("Гений").ВашаФамилия, " - это Гений!" Debug.Print Личности("Мастер").ВашаФамилия, " - это Мастер!" 'Печать всего списка Dim I As Byte For I = 1 To Личности.Count Личности(I).PrintPerson Next I End Sub

Пример 5.9.

В процессе работы этой процедуры в диалоговом окне появится сообщение о Шекспире, а в отладочном окне Immediate появятся следующие результаты:

Пушкин - это Гений! Булгаков - это Мастер! Адам Первый Человек родился 01.01.100 Ной Праведник родился 01.01.100 Гомер Великий Слепой родился 01.01.100 Вильям Шекспир родился 23.04.1564 Александр Пушкин родился 06.06.1799 Михаил Булгаков родился 23.01.1891

При создании коллекции мы использовали все три возможности добавления элементов: с заданным ключом, с заданным индексом и в конец списка.Доступ к элементам осуществлялся либо по индексу, либо по ключу. Так что наш пример демонстрирует все достоинства работы с классом Collection. Но, говоря о достоинствах, не следует забывать и о недостатках. Заметьте: при работе с коллекцией потребовалось для каждой личности создать собственную переменную, так что, по существу, мы имеем копии всех элементов коллекции в виде переменных. Это связано с тем, что при добавлении элемента в коллекцию не создается копия элемента, а используется ссылка на существующий элемент, так что коллекция не имеет собственной памяти для хранения элементов. Позже мы покажем, как можно преодолеть этот недостаток коллекции, а пока же подчеркнем, что по этой причине и по многим другим следует уметь создавать собственные динамические структуры данных. К их рассмотрению мы и переходим.


Содержание раздела