Любой код VBA должен где-то храниться. Для хранения кодов в VBA используются модули, которые хранятся в книге. Книга может содержать сколько угодно модулей. Каждый модуль в свою очередь может содержать множество процедур(макросов).
Все имеющиеся в книге модули можно посмотреть через редактор VBA (Alt+F11). Если горячие клавиши не срабатывают, то в редактор Visual Basic можно перейти из вкладки Разработчик(Developer) -Visual Basic. Имеющиеся модули отображены в левой части редактора в проводнeике объектов(Project Explorer).
Объекты проектарис.1
Сам проводник объектов может быть не отображен по умолчанию и тогда его необходимо отобразить: нажать Ctrl+R либо в меню редактора VBA -View -Project Explorer
Проводник объектов

Модули делятся на пять основных типов:

Вообще, если точнее, то всего-то два типа модуля - обычный и модуль класса, т.к. Модуль листа, Модуль книги, Модуль пользовательской формы и Модуль класса по своей сути являются модулями классов. Но я специально разделил их на несколько типов, т.к. именно такие типы часто употребляются при пояснениях в различных учебниках и на всевозможных форумах и в самих книгах Excel они по виду и некоторому функционалу различны.

Для того, чтобы создать новый стандартный модуль(Module), модуль класса(ClassModule) или пользовательскую форму(UserForm) надо просто в окне Проводника объектов(Project Explorer) щелкнуть правой кнопкой мыши, выбрать пункт Insert и затем тип добавляемого объекта(ModuleClassModuleUserForm). Так же добавить модуль можно и через меню: Insert -тип модуля.
Удалить тоже просто: щелкнуть правой кнопкой мыши на нужном модуле в окне проекта и выбрать Remove.
Подробнее про удаление и перемещение модулей описано в конце этой статьи:

  • Удаление модулей
  • Перенос, импорт и экспорт модуля

  •  
    СТАНДАРТНЫЙ МОДУЛЬ
    на рис.1 Module1
    Самый распространенный тип модулей, который используется в большинстве случаев. Именно в них макрорекордер создает записываемые макросы. Все коды и процедуры в таких модулях пишутся вручную, либо копируются из других источников(другого модуля, с этого сайта и т.п.). В основном именно в стандартных модулях содержится большая часть кодов. Они предназначены для хранения основных процедур и Public переменных, которые могут быть доступны впоследствии из любого модуля. Как создать стандартный модуль: в окне проводника объектов щелкаем правой кнопкой мыши -Insert -Module. При записи макрорекордером модули создаются автоматически и им автоматически присваиваются имена.
    Многие коды, опубликованные в статьях на сайте необходимо размещать именно в стандартных модулях. Для этого достаточно создать новый стандартный модуль, скопировать текст кода с сайта и вставить.


     
    МОДУЛЬ ЛИСТА
    Лист1 или Sheet1 - на рис.1: Лист1(Лист1), Лист2(Лист2), Лист3(Лист3).
    Для каждого листа книги имеется свой отдельный модуль. Попасть в модуль листа проще, чем в остальные модули. Для этого надо просто щелкнуть правой кнопкой мыши по ярлычку листа и выбрать из контекстного меню пункт Исходный текст(View Code).
    в зависимости от версии Excel этот пункт на русском может называться так же: Просмотреть код или Исходный код:
    Перейти в модуль листа

    Можно и более трудным путем пойти - через редактор VBA: Alt+F11 и в окне Проводника объектов(Project Explorer) дважды щелкнуть по объекту с именем листа или правая кнопка мыши на модуле листа -View code.
    Размещая код в модуле листа следует помнить, что при копировании или переносе данного листа в другую книгу код так же будет скопирован, т.к. является частью листа. Это и плюс и минус одновременно. Плюс в том, что разместив код в модуле листа можно использовать этот лист в качестве шаблона для распространения со своими кнопками вызова этих кодов(в том числе создания книг кодом) и весь функционал будет доступен. Минус же заключается в некоторых нюансах обращения к ячейкам(подробнее можно ознакомиться в этой статье: Как обратиться к диапазону из VBA) и необходимости размещения ВСЕХ используемых процедур в этом листе, иначе при переносе в другие книги коды могут работать с ошибками.

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

    Названия событийных процедур носят достаточно информативные имена и большая их часть не нуждается в тщательной расшифровке. Но самые наиболее части применяемые в любом случае считаю нужным описать:

    • Activate - возникает при активации самого листа(но не возникает, если произошел переход из одной книги в другую и этот лист является там активным)
    • BeforeDoubleClick - возникает при двойном клике мыши на любой ячейке листа. Важно обращать внимание на передаваемые аргументы: Target и Cancel. Target - ссылка на ячейку, в которой было произведено действие; Cancel - отвечает за отмену режима редактирования
    • BeforeRightClick - возникает при клике правой кнопкой мыши на любой ячейке листа. Важно обращать внимание на передаваемые аргументы: Target и Cancel. Target - ссылка на ячейку, в которой было произведено действие; Cancel - отвечает за отмену показа всплывающего меню
    • Calculate - возникает при пересчете функций и формул на листе
    • Change - возникает при изменении значений ячеек на листе. Важно обращать внимание на передаваемый аргумент Target. Target - ссылка на ячейку, которая была изменена. Может отличаться от активной в момент обработки ячейки
    • Deactivate - возникает при переходе с этого листа на другой лист этой же книги
    • FollowHyperlink - возникает при переходе по гиперссылке, созданной в этом листе
    • SelectionChange - возникает при изменении адреса выделенной ячейки/области. Важно обращать внимание на передаваемый аргумент Target. Target - ссылка на диапазон ячеек, которые были выделены. Совпадает с выделенными на текущий момент ячейками

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

    Private Sub Worksheet_Change(ByVal Target As Range)
        MsgBox "Адрес измененной ячейки: " & Target.Address & _
               "; Адрес активной ячейки: " & Selection.Address, vbInformation, "www.excel-vba.ru"
    End Sub

    После этого запишите в ячейку A1 значение 5 и нажмите Enter. Событие Change сработает в момент завершения редактирования - т.е. в момент нажатия Enter. При этом будет произведен переход на ячейку A2(в большинстве случаев, если настройками не задано иное) и появится сообщение, которое покажет, что изменили ячейку A1, а выделена сейчас A2. Т.е. Target - это всегда ссылка именно на измененную ячейку независимо от того, что сейчас выделено. Данное событие(Worksheet_Change) не будет срабатывать при изменении значений ячеек с формулами. Только ручной ввод.

    Примечание: для всех кодов, приведенных на сайте, достаточно просто открыть необходимый модуль(книги или листа) и вставить предложенный код. Корректировка может понадобиться только в случаях, когда в модуле Листа или Книги вашего файла уже имеется код в необходимой событийной процедуре.

    ВАЖНО: могут быть обработаны только те событийные процедуры, которые можно выбрать из списка справа. Если простым языком - каждое событие из этого списка VBE регистрирует "внутри себя", что позволяет в дальнейшем его отслеживать. Если просто написать какое-либо событие "от себя" - то оно никогда не запустится, потому что VBE про него ничего не знает. Например, нам необходимо отследить смену имени листа. Мы создаем событие вроде Worksheet_ChangeName(). Но оно никогда не запустится, т.к. про такое событие VBE ничего не знает, нигде его не регистрирует и не отслеживает.


     
    МОДУЛЬ КНИГИ
    ЭтаКнига или ThisWorkbook:
    ЭтаКнига
    В модуль книги можно попасть только через проводник объектов(Project Explorer) редактора VBA - двойной щелчок по ЭтаКнига (ThisWorkbook) или правая кнопка мыши на модуле -View code. В модуле книги так же содержатся "встроенные" событийные процедуры. Так же как и для листа выбираем в списке объектов(вверху слева) Workbook. В правом окне выбора процедур, так же как и с модулем листа, будут все процедуры, доступные для объекта ЭтаКнига. Пример использования событийных процедур книги можно посмотреть в статье Как отследить событие(например выделение ячеек) в любой книге?
    Но там применяются все те же правила - главное не забывать про аргументы, доступные из этих процедур и передаваемые им самим Excel. Например, для события Workbook_BeforeClose доступен аргумент Cancel. Это можно использовать, если не хотите, чтобы книгу закрыл пользователь, не заполнив ячейку A1. Вот пример подобного кода:

    Private Sub Workbook_BeforeClose(Cancel As Boolean)
        If Me.Sheets("Отчет").Range("A1").Value = "" Then
            MsgBox "Необходимо заполнить ячейку A1 на листе 'Отчет'", vbCritical, "www.excel-vba.ru"
            Cancel = True 'отменяем закрытие книги
        End If
    End Sub

    Из кода видно, что на листе "Отчет" должна быть не пустой ячейка A1(лист "Отчет" тоже должен существовать в этой книге). Но есть и еще одна вещь - какое-то Me. Это краткое обращение к объекту модуля класса, в данном случае это равнозначно обращению ThisWorkbook.


    Наиболее часто используемое событие открытия книга - Workbook_Open. Как понятно из названия, событие срабатывает при открытии книги:

    Private Sub Workbook_Open()
        MsgBox "Открыли книгу с кодом", vbInformation, "www.excel-vba.ru"
    End Sub

    Важно помнить - код срабатывает только если открыта сама книга, в которой этот код записан. Если надо отслеживать открытие любой книги, то надо написать чуть больше кода. Подробнее в статье: Как отследить событие(например выделение ячеек) в любой книге?.


    А ниже пример кода для модуля ЭтаКнига, который запрещает сохранять исходную книгу, разрешая сохранить её только через пункт Сохранить как(SaveAs):

    Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
        If SaveAsUI = False Then 'используется простое сохранить
            MsgBox "Эта книга является шаблоном. Сохранять её можно только через Сохранить как", vbCritical, "www.excel-vba.ru"
            Cancel = True 'отменяем сохранение книги
        End If
    End Sub

    Такое может потребоваться, если книга является шаблоном с полями для заполнения и необходимо предотвратить случайное сохранение исходного документа. Хотя это можно так же сделать без макросов - книгу можно сохранить с правами только на чтение.


    И еще один пример - отслеживание активации листов. Может пригодиться, чтобы при активации конкретного листа сделать какое-либо конкретное действие. В коде ниже при активации листа "Лист4" будет показываться сообщение, но действие может быть любым(обновление данных, снятие защиты, установка защиты и т.п.):

    Private Sub Workbook_SheetActivate(ByVal Sh As Object)
        If Sh.Name = "Лист4" Then
            MsgBox "Вы перешли на Лист4", vbInformation, "www.excel-vba.ru"
        End If
    End Sub

    Обращаю внимание, что здесь, как и раньше, мы используем передаваемые процедуре аргументы. В данном случае это объект Sh - это именно тот лист, который мы активировали.


     
    МОДУЛИ ФОРМ
    UserForm - на рис.1 UserForm1.
    Содержатся внутри Пользовательской формы(UserForm) и её объектов. В Пользовательских формах в основном все завязано именно на событийных процедурах самой формы и на элементах этой формы(Кнопки, ТекстБоксы, КомбоБоксы(выпадающие списки) и т.д.). Очень удобно использовать Пользовательские формы в своих приложениях для общения с пользователем. Т.к. через формы очень удобно отслеживать действия пользователя и можно запретить доступ к листам с данными, путем их скрытия. Создается форма так же как и модуль: в окне проводника объектов щелкаем правой кнопкой мыши-Insert-UserForm. Примеры кодов с использованием форм можно посмотреть в статьях: Каждому пользователю свой лист/диапазон, Как оставить в ячейке только цифры или только текст?


     
    МОДУЛЬ КЛАССА
    ClassModule - на рис.1 Class1.
    В большинстве случаев создается специально для отслеживания событий различных объектов. Вряд ли понадобиться начинающим изучение VBA, хотя все зависит от поставленной задачи. Но обычно начинающим изучать это кажется слишком сложным. В любом случае, перед работой с модулями классов лучше научиться хоть чуть-чуть работать с обычными модулями и самостоятельно писать процедуры. Как добавить такой модуль: в окне проводника объектов щелкаем правой кнопкой мыши-Insert-Class Module. Подробнее про модули классов и работу с ними можно почитать в этой статье: Работа с модулями классов. Там описаны все основные принципы и приложен файл примера.


     
    УДАЛЕНИЕ МОДУЛЯ
    Действия по удалению любого из модулей одинаковы для всех типов. Для этого необходимо перейти в проект VBA нужной книги, выбрать нужный модуль, щелкнуть по нему правой кнопкой мыши и в появившемся меню выбрать Remove (Имя модуля)...(Remove Module1, Remove UserForm1, Remove Class1 и т.п.). После этого появится окно с запросом "Do you want to export (имя модуля) before removing it?". Это означает, что VBA спрашивает: хотите ли Вы сохранить копию кодов модуля перед удалением? Как правило выбирать следует Нет. Но если Вы хотите сохранить текст кодов из удаляемого модуля в отдельном файле, то соглашаетесь, нажав Да. Будет предложено выбрать папку для сохранения модуля и можно даже задать ему отдельное имя.


     
    ПЕРЕНОС, ИМПОРТ и ЭКСПОРТ МОДУЛЯ
    Иногда нужно модуль из одной книги переместить в другую. Сделать это можно несколькими способами. Самый простой - открыть обе книги, перейти в проводник проектов -найти нужный модуль -захватить его левой кнопкой мыши и не отпуская кнопку перетащить на проект другой книги:
    Копирование между книгами
    Следует помнить, что так можно перенести и скопировать только стандартный модуль, модуль класса и модуль UserForm. Коды модулей листов и книги придется переносить как обычный текст: переходим в модуль ЭтаКнига(откуда хотим копировать) -копируем весь код -переходим в модуль ЭтаКнига второй книги и вставляем скопированное:
    Копировать модуль листа/книги
    Экспорт модуля(сохранение в отдельный файл)
    Если же надо сохранить стандартный модуль, модуль класса или модуль формы и не переносить сразу же в другую книгу, то можно экспортировать модуль. Для чего это может быть нужно? Как правило, чтобы перенести коды из дома на работу, переслать кому-то на другой ПК(пересылка файла с макросами может быть запрещена политикой безопасности компании) и т.п. Делается это просто: щелкаем на модуле правой кнопки мыши -Export file.
    У экспортируемых модулей есть разные расширения, в зависимости от типа модуля. Для стандартных модулей это .bas(Module1.bas), для модулей класса - .cls(Class1.cls). А вот для модулей форм будет создано целых два файла: UserForm1.frm и UserForm1.frx. Их важно хранить вместе - один без другого не может быть импортирован в дальнейшем в файл. В файле .frx хранится информация об визуальном отображении формы и её элементах, если можно так сказать. В файле .frm хранятся непосредственно тексты кодов для формы и служебная информация(имя и размеры формы, некоторые глобальные директивы и ссылка на файл .frx). Поэтому не рекомендуется без соответствующих навыков переименовывать эти два файла в надежде, что потом все заработает.
    Импорт модуля(перенос экспортированного ранее в новую книгу)
    Для переноса экспортированного модуля в другую книгу надо просто в проводнике объектов выделить нужный проект правой кнопкой мыши -Import module -выбрать в диалоговом окне нужный модуль.
    Экспортировать можно любой модуль, а вот импортировать - нет. Модули листов и книг хоть и экспортируются в отдельные файлы(кстати, с расширением .cls), но импортировать их не получится в том виде, как это предполагается. Они будут импортированы как новые модули класса и только. Поэтому для переноса кодов из модулей листов и книг придется использовать все равно копирование и вставку непосредственно кодов.
    И в довершение - можно переносить модули автоматически, кодами VBA: Как добавить код процедуры программно, скопировать модуль

     

    Также см.:
    Копирование модулей и форм из одной книги в другую
    Что такое макрос и где его искать?
    Как удалить макросы в книге?

    Loading

    14 комментариев

    Добавить комментарий

    Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.