Хитрости »
Основные понятия (21)Здесь собраны статьи, в которых разъясняются базовые понятия работы в Excel и VBA, а так же проблемы, с которыми сталкивается большинство начинающих
Сводные таблицы и анализ данных (4) Раздел поможет изучить сводные таблицы и научиться их использовать "на полную"
Графики и диаграммы (4) Раздел поможет научиться создавать диаграммы и графики в Excel, в том числе нестандартные
Работа с VB проектом (9) С помощью статей раздела вы научитесь создавать процедуры программно и выполнять различные операции с объектами самого VBA
Условное форматирование (5) Этот раздел поможет поближе познакомиться с Условным форматированием на примерах различных ситуаций
Списки и диапазоны (5) Статьи, посвященные работе не только с выпадающими списками, но и с диапазонами и хитростями их применения в рабочих файлах
Макросы(VBA процедуры) (55) Статьи раздела направлены на изучение VBA с детальным разбором кодов. Множество статей с примерами кодов под всевозможные ситуации с комментариями и пояснениями
Разное (33) Собраны статьи, которые не подходят ни под одну из представленных выше категорий или входят сразу в несколько. Но эти статье не менее полезные!

Работа с модулями классов

Многие наверняка слышали про модули классов, но не все их используют. На самом деле довольно многие программирующие на VBA за все время программирования прекрасно обходятся без применения модулей классов. Т.к. VBA не является языком объектно-ориентированного программирования(ООП) в строгом смысле слова, то пользовательские классы здесь не обязательны и как следствие не так уж и часто используются при разработке. Это не значит, что VBA не содержит модулей классов: модули книги, листов, пользовательские формы - все это модули классов. Многие их, кстати, используют их даже не зная того, что используют именно модули классов. Т.к. модуль листа, книги и формы - это модуль класса, то почти каждый, кто работал с формой работал с модулем класса. В чем их большая польза - с их помощью можно отслеживать различные события объектов. Для форм это события самой формы или любого её элемента - например CommandButton_Click или TextBox_Change. Но мы сейчас рассмотрим лишь тот тип модулей, который в VBA обычно называют модулем класса - Class Module.

Модуль класса(Class Module) – это модуль, содержащий программные коды, которые реализуют работу пользовательских классов. В подавляющем большинстве случаев создается специально для отслеживания событий различных объектов. Создается так же, как и любой другой объект проекта: в окне проводника объектов щелкаем правой кнопкой мыши на нужном проекте-Insert-Class Module
Вставить модуль класса
Но прежде чем создать модуль, необходимо понять, что мы будем в нем хранить и для чего он нам. Возьмем для примера самую распространенную проблему: на форме создано несколько ТекстБоксов и необходимо отследить событие ввода данных в эти ТекстБоксы. Обычно делается все просто - для каждого ТекстБокса прописывается отслеживание события:

С одной стороны - все верно. А с другой: что если таких текстбоксов у нас не 3, а 43? Не очень удобно для каждого событие прописывать. Да и читабельность такой "портянки" кода тоже значительно падает.
Или другая ситуация - необходимо "на ходу" создать ТекстБоксы на форме и в дальнейшем отслеживать их события. Как тут быть? Ведь раз ТексБоксов еще нет - то и события в форме для них не создать.Создание для них кодов обработки событий заранее ничего не даст - они не будут связаны с самими объектами, поэтому и пытаться даже не стоит. Почему так - при создании элемента вручную VBE делает за нас всю грязную работу - он сам ассоциирует созданный объект с событиями, предназначенные для него заранее. Если же создать объект программно - то часть грязной работы придется делать самим. И создание модуля класса, с описанием в нем объекта ТекстБокс и его событий, как раз очень даже подойдет.
Рассмотрим сразу оба случая. Что нам для этого потребуется:

  1. для начала создать модуль класса с именем clsmTxtBxes(Insert-Class Module)
  2. создать стандартный модуль с именем mMain(Insert-Module)
  3. ну и сама форма тоже не лишняя(Insert-UserForm). У меня форма называется frmTest.
  4. очень желательно наличие у вас опыта написания хотя бы простейших процедур. Иначе может показаться все очень сложным и непонятным.

Для начала создадим на нашей форме frmTest 4 ТекстБокса, не меняя их имена(по умолчанию они будут TextBox1, TextBox2, TextBox3, TextBox4).
Далее в стандартный модуль mMain поместим следующий код:

aoTxtBxes - массив, который будет содержать 8 ТекстБоксов. Объявляется как Public(чтобы был доступен из любого модуля проекта. Подробнее в статье: Что такое переменная и как правильно её объявить?). Обращаю внимание, что данный массив объявлен как созданный нами модуль класса - clsmTxtBxes. Это обязательное условие. Если у вас модуль класса называется ClassModule1, то и объявлять aoTxtBxes следует соответственно:

но я не приветствую подобный подход, т.к. имя ClassModule1 ни о чем нам не говорит, в то время как clsmTxtBxes сразу дает понять, что там мы обрабатываем ТекстБоксы.
Теперь в модуль класса clsmTxtBxes запишем создание объекта и код, который хотим применить для всех наших ТекстБоксов:

Public WithEvents oTxtBx As MSForms.TextBox - создаем объект типа ТекстБокс с отслеживанием его событий. Идентификатором объекта с отслеживанием событий служит оператор WithEvents (может применяться только в модулях классов). Если необходимо отследить изменения не TextBox, а ComboBox, то соответственно объявляем объект нужного типа:

И напоследок создаем код в модуле формы frmTest:

Если коротко описать, что делает эта процедура. При запуске формы в массив aoTxtBxes запоминаются сначала те ТекстБоксы, которые мы предусмотрительно заранее создали на форме и затем создаются еще 4 новых ТекстБокса. Т.к. массив aoTxtBxes у нас является новым экземпляром класса, то обращаться к его содержимому мы можем только по законам работы с классами, т.е. только к тем объектам и методам, которые в классе прописаны. А у нас там только один объект прописан - oTxtBx(Public WithEvents oTxtBx As MSForms.TextBox). Его и используем. Ничего другого использовать VBE нам и не позволит.
А дальше уж все просто: т.к. класс мы создали, событие объекта прописали, объектам значения ТекстБоксов присвоили - остается только наслаждаться. Теперь любое изменение в любом из ТекстБоксов будет обработано и появится сообщение.
Если необходимо больше ТекстБоксов обработать - увеличиваем верхнюю границу массива aoTxtBxes. Если заранее неизвестно количество - либо задаем с запасом, либо объявляем aoTxtBxes как массив, а границы определяем в процессе. Но это уже совершенно другая тема.
Конечно, это пример показа сообщения при изменении ТекстБокса. Но ведь можно таким образом отследить практически любое доступное событие. И не просто сообщение показывать, а запретить ввод букв, делать проверку введенного значения на соответствие шаблону и пр. Все зависит от конкретной задачи.

Чтобы было проще вникнуть я по старой традиции прилагаю к статье пример с кодами.

Скачать пример »

  Tips_Macro_UseClassModules.xls (53,5 KiB, 1 367 скачиваний)

Также см.:
Что такое модуль? Какие бывают модули?
Что такое переменная и как правильно её объявить?
Variable not defined или что такое Option Explicit и зачем оно нужно?


Статья помогла? Сделай твит, поделись ссылкой с друзьями!

Поиск по меткам

Access Multex Outlook VBA работа в редакторе VBA управление кодами Бесплатные надстройки Дата и время Диаграммы и графики Записки Защита данных Интернет Картинки и объекты Листы и книги Макросы и VBA Настройка Поиск данных Почта Программы Работа с приложениями Работа с файлами Разработка приложений Сводные таблицы Списки Тренинги и вебинары Финансовые Форматирование Формулы и функции Функции Excel Функции VBA Ячейки и диапазоны вебинар ссылки тренинг
Обсуждение: оставлено 11 коммент.
  1. Fool:

    Большое спасибо. Долго пытался найти, как отследить действия над программно созданными объектами. Нашел пример кода. Написал аналог для своей проги, но вылетала ошибка Object does not source automation events. Так как найденный мной пример был без описания, я решил разобраться в принципах работы модуля классов и наткнулся на эту статью. Решение проблемы оказалось проще простого. Нужно было просто добавить MSForms. при описании.
    Еще раз огромное спасибо.

  2. A-Michael:

    Спасибо, очень красивый и понятный пример. Есть только один вопрос: как связаны кнопки с макросами? Я обычно использую простые CommandButton, но иногда хочется для разнообразия вставить что-то другое для запуска макроса.
    Поясните, пожалуйста или подскажите направление в котором покопать...

  3. Doc:

    Спасибо очень хорошая статья, именно то что искал.

  4. Александр:

    Подскажите,пожалуйста, тоже самое можно сделать, если textbox-сы находятся на листе?

    • Александр, можно. Только на листе разные типы текстбоксов. Элементы управления форм и ActiveX.
      Для ActiveX почти так же все выглядит. Только заносить в массив, скорее всего надо примерно таким циклом:

  5. Дмитрий. очень понятный пример и объяснения! большое спасибо за сатью! Мне необходимо создать контрлс не на самой форме а на MultiPage формы. Подскажите, пожауйста, как это сделать? заранее благодарен!

  6. Батор:

    Дмитрий, добрый день!
    не могу передать параметр внутрь Класса
    я объявил переменную внутри класса
    Public Property Let iIndexTXT(iNewIndex As Integer)
    iIndexTXT = iNewIndex
    End Property
    и попробовал передать данные
    With aoTxtBxes(i, 2).oTxtBx
    .iIndexTXT = i
    .Left = 160
    но выдает ошибку Объект не поддерживает метод или проперти

    • Видимо, потому что процедура iIndexTXT относится к самому классу, а не к отдельному объявленному там объекту? В данном случае эта процедура не нужна - достаточно использовать свойство Tag самого TextBox.

      • Батор:

        Спасибо, получилось!

        • Батор:

          У меня получилось передать данные в класс, созданный с формой.
          В самом модуле класса через процедуру setTextBox отразил привязку Set tBox = objTbx, и через эту же процедуру передал координаты и данные для расчетов.
          в итоге создание новой формы ТекстБокса модуле формы frmTest получилось одной строке:
          clsTxtBoxes(i).setTextBox Me.Controls.Add("Forms.TextBox.1", "TextBox" & i), 10, iTop, 18, 100, arrMain(i, 1), MyOptionTmp

Поделитесь своим мнением

Комментарии, не имеющие отношения к комментируемой статье, могут быть удалены без уведомления и объяснения причин. Если есть вопрос по личной проблеме - добро пожаловать на Форум


Для оформления сообщений Вы можете использовать следующие тэги:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">

Тренинги

Необходимо автоматизировать процессы в MS Office?
Доверьте это профессионалам и работа всегда будет сделана качественно и в срок!Заказать

Логин
Счетчики
Анализ сайта

Яндекс.Метрика
© 2016 Excel для всех  Войти