Серега_ Пользователь Сообщений: 257 |
#1 07.11.2015 10:55:31 Здравствуйте. Есть событие закрытия книги.
Какое событие отмены закрытия книги, после того как кликнешь по отмене в информационном сообщении при закрытии книги? |
||
Юрий М Модератор Сообщений: 60567 Контакты см. в профиле |
Не слышал про такое событие. |
Серега_ Пользователь Сообщений: 257 |
Юрий я тем более… Так как у меня интерфейс книги скрыт, то при закрытия книги интерфейс восстанавливается, но если кликнуть отмену то интерфейс зависает на раскрытие, что дает без труда раскрыть его полностью в ручную. Изменено: Серега_ — 08.11.2015 12:03:34 |
Тоже о таком событии не слышал. С уважением, |
|
Серега_ Пользователь Сообщений: 257 |
#5 07.11.2015 11:21:19 И как это прописать в модуле книги с учетом данных событий?
Или как при закрытие книги на кнопку отмена повесить макрос? Изменено: Серега_ — 08.11.2015 12:05:37 |
||
Catboyun Пользователь Сообщений: 1631 |
#6 08.11.2015 08:01:32
|
||
Серега_ Пользователь Сообщений: 257 |
#7 08.11.2015 12:00:19 Здравствуйте. Catboyun я так понял Вы предлагаете дополнительным сообщение решить данное условие но тогда, основному оператору, закрыть книгу ДА — восстановить интерфейс.
Необходимо добавить второй оператор сохранить книгу ОТМЕНА – скрыть интерфейс.
Если нажать кнопку ДА “Закрыть книгу?” то выходит системное сообщение и если в нем нажать отмену сохранения то интерфейс зависает на раскрытии по причине того что запускается Оператор1 (в принципе та же проблема что и была). . Как в Вашем коде правильно расставить операторы, возможно я что то не понял и неверно делаю? Изменено: Серега_ — 08.11.2015 15:29:50 |
||||
Андрей VG Пользователь Сообщений: 11878 Excel 2016, 365 |
#8 08.11.2015 12:41:37 Доброе время суток
Успехов. |
||
Серега_ Пользователь Сообщений: 257 |
Андрей VG
Смотрите последовательность Вашего кода. |
Андрей VG Пользователь Сообщений: 11878 Excel 2016, 365 |
#10 08.11.2015 13:09:51
Вот мой файл — докажите, что выходит системное сообщение? Мне неизвестно, что делает ваш метод ВосстановитьИнтерфейс. Переместите Me.Saved = True после него тогда. Прикрепленные файлы
Изменено: Андрей VG — 08.11.2015 13:14:31 |
||
Серега_ Пользователь Сообщений: 257 |
#11 08.11.2015 13:41:37 У Вас да, нет системного сообщения, но без него как?. Если более лаконично, то должно быть так.
ВосстановитьИнтерфейс – должен выполняться при закрытии и сохранения книги
Данное действие выполняется. УбратьВсе – должен выполняться при отмене закрытия книги кликом по кнопке ОТМЕНА в системном сообщении “Сохранение изменений». Изменено: Серега_ — 08.11.2015 13:50:09 |
||||
The_Prist Пользователь Сообщений: 14181 Профессиональная разработка приложений для MS Office |
#12 08.11.2015 13:48:08
Никак. Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы… |
||
Серега_ Пользователь Сообщений: 257 |
Лаконичный ответ. |
The_Prist Пользователь Сообщений: 14181 Профессиональная разработка приложений для MS Office |
Вот странный вопрос…Вы едите на машине. Впереди ремонт догори. Вы хотите поехать прямо, но можно только в объезд. О чем Вам и говорят — никак нельзя прямо, только по объезду, т.к. мост не построен еще. На что спрашиваете: а что, никак нельзя отсутствие моста не брать в расчет? Поймите — когда выплыло диалоговое окно — то VBA уже дальше в событии Close не участвует. По идее, можно было бы еще и событие beforeSave привязать и по нему скрывать/отображать панель, но человек ведь может и отказаться сохранять и тогда события не произойдет. Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы… |
Андрей VG Пользователь Сообщений: 11878 Excel 2016, 365 |
В принципе, можно построить свой «ходульный» мостик — лишь бы проскочить То есть создаёте форму, внешне не отличимую от диалога Excel закрыть файл, и сами обрабатываете и выполняете все необходимые действия, связанные с каждой из её кнопок. |
Серега_ Пользователь Сообщений: 257 |
The_Prist
Если не утрировать ситуацию, то для некоторых “персон”, используя ресурсы и время в пустую, создаются условия по принципу “системы игрек” (цитата из фильма “Печки лавочки”). Поэтому Ваше сравнение не является таким безнадежным, но так как я не из тех персон будем считать что данная система здесь не рулит. Андрей VG Если “система игрек” рулит, тогда как? Изменено: Серега_ — 08.11.2015 14:47:28 |
Андрей VG Пользователь Сообщений: 11878 Excel 2016, 365 |
#17 08.11.2015 14:51:45
Для начала подумать — как система рулит? Как это связано с объектной моделью Excel? Как на основании полученных сведений реализовать аналогичное поведение собственной формы подмены. А для этого изучите: Workbook.Saved, Workbook.Close, событие Workbook.BeforeClose. Подумать, почему в предложенном мною коде система не рулит |
||
Серега_ Пользователь Сообщений: 257 |
Андрей VG
Примерно вижу это так, при закрытии книги необходимо заменить системное сообщение на программное с тремя кнопками (сохранить, нет, отмена) и вешать на кнопки нужные коды. Но так как я вижу это примерно и размыто в понимании, оставлю как оно есть. |
RAN Пользователь Сообщений: 7091 |
#19 08.11.2015 15:33:47 Чё-то вижу, чё-то слышу…
|
||
Андрей VG Пользователь Сообщений: 11878 Excel 2016, 365 |
#20 08.11.2015 15:40:16
Собственно, в рамках предложенного кода. Стандартный диалог появляется если свойство книги Saved = False 1. Если Saved = True — то ничего не делаем. Вам надо будет понять, что меняет в книге ваш метод ВосстановитьИнтерфейс, чтобы учесть его влияние на этот алгоритм. Успехов |
||
Серега_ Пользователь Сообщений: 257 |
При закрытии книги появляется сообщения после выбор да или нет появляется системное сообщение кроме выбора отмена. |
Андрей VG Пользователь Сообщений: 11878 Excel 2016, 365 |
#22 08.11.2015 16:55:37
А какие ваши доказательства? Опять голословные утверждения? Прикрепленные файлы
|
||
Серега_ Пользователь Сообщений: 257 |
#23 08.11.2015 17:14:34 Андрей VG
Доказательства просты, там идет связь событий в модуле книги с кодами в стандартном модуле, где и перескакивает False на True (что не учитывалось в предлагаемых кодах и примерах). Думаю что данный код (скрытия и раскрытия интерфейса) многим известен… Решил проще Изменил
На
При закрытия книги и появления системного сообщения, сохранения книги, интерфейс скрыт, потому как событие выполняет код скрытия интерфейса. Предполагал, что при сохранении или не сохранения данной книги (варианта «Скрыть интерфейс») и открытие другой, интерфейс будет скрыт, что не желательно было бы, поэтому и создал эту тему, на самом деле в другой книге интерфейс восстанавливается. Изменено: Серега_ — 08.11.2015 17:52:35 |
||||
На чтение 31 мин. Просмотров 19.3k.
Когда вы создаете или записываете макрос в Excel, вам нужно запустить макрос, чтобы выполнить шаги в коде.
Несколько способов запуска макроса включают использование диалогового окна макроса, назначение макроса кнопке, использование ярлыка и т.д.
Помимо этих запускаемых пользователем макросов, вы также можете использовать события VBA для запуска макроса.
Содержание
- События Excel VBA — Введение
- Различные типы событий Excel VBA
- Где поставить код, связанный с событием
- Понимание последовательности событий
- Понимание роли аргументов в событиях VBA
- События на уровне рабочей книги (поясняются примерами)
- События уровня рабочего листа (объясненные с примерами)
- Событие Excel VBA OnTime
- Событие Excel VBA OnKey
- Отключение событий в VBA
- Влияние событий Undo Stack
Позвольте мне сначала объяснить, что такое событие в VBA.
Событие — это действие, которое может инициировать выполнение указанного макроса.
Например, когда вы открываете новую книгу, это событие. Когда вы вставляете новый лист, это событие. Если дважды щелкнуть ячейку, это событие.
В VBA есть много таких событий, и вы можете создавать коды для этих событий. Это означает, что как только происходит событие, и если вы указали код для этого события, этот код будет немедленно выполнен.
Excel автоматически сделает это, как только заметит, что событие произошло. Таким образом, вам нужно только написать код и поместить его в правильную подпрограмму события (это будет описано далее в этой статье).
Например, если вы вставляете новый лист и хотите, чтобы он имел префикс года, вы можете написать для него код.
Теперь, когда кто-нибудь вставляет новый лист, этот код будет автоматически выполняться и добавлять префикс года к имени листа.
Другой пример: вы хотите изменить цвет ячейки, когда кто-то дважды щелкает по ней. Вы можете использовать событие двойного щелчка для этого.
Точно так же вы можете создавать коды VBA для многих таких событий (рассмотрим позже в этой статье).
Ниже приведена краткая картинка, показывающая событие двойного щелчка в действии. Как только я дважды щелкну по ячейке A1. Excel мгновенно открывает окно сообщения, в котором отображается адрес ячейки.
Двойной щелчок — это событие, а отображение окна сообщения — это то, что я указал в коде, когда происходит событие двойного щелчка.
Хотя приведенный выше пример является бесполезным событием, я надеюсь, что он поможет вам понять, как это происходит.
Различные типы событий Excel VBA
В Excel есть разные объекты — например, сам Excel (к которому мы часто обращаемся как приложение), рабочие книги, рабочие таблицы, диаграммы и т.д.
Каждый из этих объектов может иметь различные события, связанные с ним. Например:
- Если вы создаете новую книгу, это событие уровня приложения.
- Если вы добавляете новый лист, это событие уровня книги.
- Если вы измените значение в ячейке на листе, это событие уровня рабочего листа.
Ниже приведены различные типы событий, которые существуют в Excel:
- События уровня рабочего листа. Это типы событий, которые запускаются на основе действий, выполненных в рабочем листе. Примеры этих событий включают изменение ячейки на рабочем листе, изменение выделения, двойной щелчок по ячейке, щелчок правой кнопкой мыши по ячейке и т.д.
- События на уровне рабочей книги. Эти события будут инициироваться на основе действий на уровне рабочей книги. Примеры таких событий включают добавление новой рабочей таблицы, сохранение рабочей книги, открытие рабочей книги, печать части или всей рабочей книги и т.д.
- События уровня приложения: это события, которые происходят в приложении Excel. Примером этого может быть закрытие любой из открытых рабочих книг или открытие новой рабочей книги.
- События уровня пользовательской формы: эти события будут инициироваться на основе действий в пользовательской форме. Примеры этого включают инициализацию пользовательской формы или нажатие кнопки в пользовательской форме.
- События диаграммы: это события, относящиеся к листу диаграммы. Лист диаграммы отличается от рабочего листа. Примеры таких событий могут включать изменение серии диаграммы или изменение размера диаграммы.
- События OnTime и OnKey. Это два события, которые не соответствуют ни одной из перечисленных выше категорий. Поэтому я перечислил их отдельно. Событие «OnTime» позволяет вам выполнить код в определенное время или по истечении определенного времени. Событие «OnKey» позволяет выполнить код, когда используется определенное нажатие клавиши (или комбинация нажатий клавиш).
Где поставить код, связанный с событием
В приведенном выше разделе я рассмотрел различные типы событий.
В зависимости от типа события вам необходимо поместить код в соответствующий объект.
Например, если это событие, связанное с рабочим листом, оно должно идти в окне кода объекта рабочего листа. Если она связана с книгой, она должна идти в окне кода для объекта книги.
В VBA разные объекты — такие как Worksheets, Workbooks, Chart Sheets, UserForms и т.д. Имеют собственные окна кода. Вам необходимо поместить код события в окно кода соответствующего объекта. Например, если это событие уровня рабочей книги, вам нужно иметь код события в окне кода рабочей книги.
Следующие разделы охватывают места, где вы можете поместить код события:
В окне кода Worksheet
Когда вы откроете VB Editor (используя сочетание клавиш ALT + F11), вы заметите объект рабочих таблиц в Project Explorer. Для каждого листа в книге вы увидите один объект.
Если дважды щелкнуть объект листа, в который вы хотите поместить код, откроется окно кода для этого листа.
Хотя вы можете начать писать код с нуля, гораздо лучше выбрать событие из списка параметров и позволить VBA автоматически вставить соответствующий код для выбранного события.
Для этого вам нужно сначала выбрать рабочий лист из выпадающего списка в левом верхнем углу окна кода.
После выбора рабочего листа из выпадающего списка вы получите список всех событий, связанных с рабочим листом. Вы можете выбрать тот, который вы хотите использовать, из выпадающего списка в правом верхнем углу окна кода.
Как только вы выберете событие, оно автоматически введет первую и последнюю строку кода для выбранного события. Теперь вы можете добавить свой код между двумя строками.
Примечание. Как только вы выберете «Worksheet» в раскрывающемся списке, вы увидите две строки кода в окне кода. После того, как вы выбрали событие, для которого вы хотите код, вы можете удалить строки, которые появились по умолчанию.
Обратите внимание, что каждый лист имеет собственное окно кода. Когда вы вводите код для Лист1, он будет работать только в том случае, если событие происходит в Лист1.
В окне кода ThisWorkBook
Точно так же как рабочие листы, если у вас есть код события уровня книги, вы можете поместить его в окно кода ThisWorkbook.
Когда вы дважды щелкните на ThisWorkbook, он откроет окно кода для него.
Вам нужно выбрать Workbook из выпадающего списка в верхнем левом углу окна кода.
После выбора Workbook из выпадающего списка вы получите список всех событий, связанных с Workbook. Вы можете выбрать тот, который вы хотите использовать, из выпадающего списка в правом верхнем углу окна кода.
Как только вы выберете событие, оно автоматически введет первую и последнюю строку кода для выбранного события. Теперь вы можете добавить свой код между двумя строками.
Примечание. Как только вы выберете Workbook из выпадающего списка, вы увидите две строки кода в окне кода. После того, как вы выбрали событие, для которого вы хотите код, вы можете удалить строки, которые появились по умолчанию.
В окне кода Userform
Когда вы создаете пользовательские формы в Excel, вы также можете использовать события пользовательской формы для выполнения кодов на основе определенных действий. Например, вы можете указать код, который будет выполняться при нажатии кнопки.
Хотя объекты Sheet и ThisWorkbook уже доступны при открытии редактора VB, пользовательская форма — это то, что вам нужно создать в первую очередь.
Чтобы создать пользовательскую форму, щелкните правой кнопкой мыши любой из объектов, перейдите на вкладку «Вставка» и выберите «UserForm».
Это вставит объект UserForm в книгу.
Если дважды щелкнуть пользовательскую форму (или любой объект, который вы добавляете в пользовательскую форму), откроется окно кода для пользовательской формы.
Теперь, так же как рабочие листы или ThisWorkbook, вы можете выбрать событие, и оно вставит первую и последнюю строку для этого события. И тогда вы можете добавить код в середине этого.
В окне кода Chart
В Excel вы также можете вставлять листы диаграмм (которые отличаются от листов). Лист диаграмм должен содержать только диаграммы.
Вставив лист диаграммы, вы сможете увидеть объект листа диаграммы в редакторе VB.
Вы можете добавить код события в окно кода листа диаграммы, как мы это делали на листе.
Дважды щелкните объект листа Chart в Project Explorer. Это откроет окно кода для листа диаграммы.
Теперь вам нужно выбрать Chart из выпадающего списка в верхнем левом углу окна кода.
После выбора Chart из выпадающего списка вы получите список всех событий, связанных с листом Chart. Вы можете выбрать тот, который вы хотите использовать, из выпадающего списка в правом верхнем углу окна кода.
Примечание. Как только вы выберете Chart из выпадающего списка, вы заметите две строки кода в окне кода. После того, как вы выбрали событие, для которого вы хотите код, вы можете удалить строки, которые появились по умолчанию.
В Class Module
Class Module должны быть вставлены так же, как пользовательские формы.
Модуль класса может содержать код, связанный с приложением, которым может быть сам Excel и встроенные диаграммы.
Я расскажу о модуле класса в качестве отдельного учебного пособия в ближайшие недели.
Обратите внимание, что кроме событий OnTime и OnKey, ни одно из перечисленных выше событий не может быть сохранено в обычном модуле VBA.
Понимание последовательности событий
Когда вы запускаете событие, оно не происходит изолированно. Это также может привести к последовательности нескольких триггеров.
Например, когда вы вставляете новый лист, происходит следующее:
- Добавлен новый рабочий лист
- Предыдущая рабочая таблица деактивируется
- Новый лист активируется
Хотя в большинстве случаев вам не нужно беспокоиться о последовательности, если вы создаете сложные коды, основанные на событиях, лучше знать последовательность, чтобы избежать неожиданных результатов.
Понимание роли аргументов в событиях VBA
Прежде чем мы перейдем к примерам событий и удивительным вещам, которые вы можете с ним сделать, я должен рассмотреть одну важную концепцию.
В событиях VBA было бы два типа кодов:
- Без каких-либо аргументов
- С аргументами
И в этом разделе я хочу быстро осветить роль аргументов.
Ниже приведен код без аргументов (круглые скобки пусты):
Private Sub Workbook_Open() MsgBox "Не забудьте заполнить расписание" End Sub
С помощью приведенного выше кода, когда вы открываете рабочую книгу, она просто показывает окно сообщения с сообщением — «Не забудьте заполнить расписание».
Теперь давайте посмотрим на код, который имеет аргумент.
Private Sub Workbook_NewSheet(ByVal Sh As Object) Sh.Range("A1") = Sh.Name End Sub
Приведенный выше код использует аргумент Sh, который определен как тип объекта. Аргумент Sh может быть рабочим листом или листом диаграммы, так как указанное выше событие вызывается при добавлении нового листа.
Присвоив новый лист, который добавляется к книге, объектной переменной Sh, VBA позволил нам использовать его в коде. Поэтому, чтобы обратиться к новому названию листа, я могу использовать Sh.Name.
Концепция аргументов будет полезна при ознакомлении с примерами событий VBA в следующих разделах.
События на уровне рабочей книги (поясняются примерами)
Ниже приведены наиболее часто используемые события в книге.
Событие | Что запускает событие |
Activate | Когда книга активирована |
AfterSave | Когда книга установлена как надстройка |
BeforeSave | Когда рабочая книга сохранена |
BeforeClose | Когда рабочая книга закрыта |
BeforePrint | Когда печатается книга |
Deactivate | Когда книга деактивирована |
NewSheet | Когда добавляется новый лист |
Open | Когда рабочая книга открыта |
SheetActivate | Когда любой лист в книге активирован |
SheetBeforeDelete | При удалении любого листа |
SheetBeforeDoubleClick | При двойном щелчке по любому листу |
SheetBeforeRightClick | При щелчке правой кнопкой мыши по любому листу |
SheetCalculate | Когда любой лист рассчитывается или пересчитывается |
SheetDeactivate | Когда рабочая книга деактивирован |
SheetPivotTableUpdate | При обновлении книги |
SheetSelectionChange | При изменении рабочей книги |
WindowActivate | Когда книга активирована |
WindowDeactivate | Когда книга деактивирована |
Обратите внимание, что это не полный список.
Помните, что код для события Workbook хранится в окне кода объектов ThisWorkbook.
Теперь давайте посмотрим на некоторые полезные события из рабочей книги и посмотрим, как они могут быть использованы в вашей повседневной работе.
Событие Workbook Open
Допустим, вы хотите показать пользователю дружеское напоминание, чтобы заполнять его расписания при каждом открытии определенной рабочей книги.
Вы можете использовать приведенный ниже код, чтобы сделать это:
Private Sub Workbook_Open() MsgBox "Не забудьте заполнить расписание" End Sub
Теперь, как только вы откроете рабочую книгу с этим кодом, она покажет вам окно сообщения с указанным сообщением.
При работе с этим кодом (или с кодами событий рабочей книги в целом) необходимо знать несколько вещей:
- Если в книге есть макрос, и вы хотите сохранить его, вам нужно сохранить его в формате .XLSM. В противном случае код макроса будет потерян.
- В приведенном выше примере код события будет выполняться только при включенных макросах. Может появиться желтая полоса, запрашивающая разрешение на включение макросов. Пока это не включено, код события не выполняется.
- Код события Workbook помещается в окно кода объекта ThisWorkbook.
Вы можете дополнительно уточнить этот код и показать сообщение только пятницы.
Код ниже сделает это:
Private Sub Workbook_Open() wkday = Weekday(Date) If wkday = 6 Then MsgBox "Не забудьте заполнить расписание" End Sub
Обратите внимание, что в функции «Weekday» воскресенье присваивается значение 1, понедельник — 2 и т. Д.
Поэтому на пятницу я использовал 6.
Событие Open Workbook может быть полезно во многих ситуациях, таких как:
- Когда вы хотите показать приветственное сообщение человеку, когда книга открыта.
- Когда вы хотите отобразить напоминание, когда рабочая книга открыта.
- Если вы хотите всегда активировать один конкретный лист в книге, когда она открыта.
- Когда вы хотите открыть связанные файлы вместе с книгой.
- Если вы хотите фиксировать дату и время каждый раз, когда открывается рабочая книга.
Событие Workbook NewSheet
Событие NewSheet запускается при вставке нового листа в рабочую книгу.
Допустим, вы хотите ввести значение даты и времени в ячейку A1 вновь вставленного листа. Вы можете использовать приведенный ниже код, чтобы сделать это:
Private Sub Workbook_NewSheet(ByVal Sh As Object) On Error Resume Next Sh.Range("A1") = Format(Now, "dd-mmm-yyyy hh:mm:ss") End Sub
Приведенный выше код использует «On Error Resume Next» для обработки случаев, когда кто-то вставляет лист диаграммы, а не лист. Поскольку на листе диаграммы нет ячейки A1, будет отображаться ошибка, если «On Error Resume Next» не используется.
Другой пример может быть, когда вы хотите применить некоторые базовые настройки или форматирование к новому листу, как только он будет добавлен. Например, если вы хотите добавить новый лист и хотите, чтобы он автоматически получал серийный номер (до 100), то вы можете использовать код ниже.
Private Sub Workbook_NewSheet(ByVal Sh As Object) On Error Resume Next With Sh.Range("A1") .Value = "S. No." .Interior.Color = vbBlue .Font.Color = vbWhite End With For i = 1 To 100 Sh.Range("A1").Offset(i, 0).Value = i Next i Sh.Range("A1", Range("A1").End(xlDown)).Borders.LineStyle = xlContinuous End Sub
Приведенный выше код также немного форматирует. Это дает ячейке заголовка синий цвет и делает шрифт белым. Это также применяет границу ко всем заполненным ячейкам.
Приведенный выше код является примером того, как короткий код VBA может помочь вам украсть несколько секунд каждый раз, когда вы вставляете новый лист (на случай, если вам придется каждый раз это делать).
Событие Workbook BeforeSave
Событие «BeforeSave» запускается при сохранении книги. Обратите внимание, что событие инициируется сначала, а затем рабочая книга сохраняется.
При сохранении книги Excel возможны два сценария:
- Вы сохраняете его в первый раз, и он покажет диалоговое окно Сохранить как.
- Вы уже сохранили его ранее, и он просто сохранит и перезапишет изменения в уже сохраненной версии.
Теперь давайте рассмотрим несколько примеров, где вы можете использовать событие BeforeSave.
Предположим, у вас есть новая книга, которую вы сохраняете впервые, и вы хотите напомнить пользователю о необходимости сохранить ее на диске K, затем вы можете использовать следующий код:
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean) If SaveAsUI Then MsgBox "Сохраните этот файл на диске K" End Sub
В приведенном выше коде, если файл никогда не был сохранен, SaveAsUI имеет значение True и вызывает диалоговое окно Save As. Приведенный выше код будет отображать сообщение до появления диалогового окна «Save As».
Другим примером может быть обновление даты и времени, когда файл сохраняется в определенной ячейке.
Приведенный ниже код вставляет отметку даты и времени в ячейку A1 листа She1 при каждом сохранении файла.
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean) Worksheets("Лист1").Range("A1") = Format(Now, "dd-mmm-yyyy hh:mm:ss") End Sub
Обратите внимание, что этот код выполняется, как только пользователь сохраняет рабочую книгу. Если книга сохраняется в первый раз, в ней отобразится диалоговое окно «Save As». Но код уже выполняется к тому времени, когда вы видите диалоговое окно Save As. На этом этапе, если вы решите отменить и не сохранить книгу, дата и время уже будут введены в ячейку.
Событие Workbook BeforeClose
Событие «BeforeClose» происходит непосредственно перед закрытием книги.
Приведенный ниже код защищает все рабочие листы до их закрытия.
Private Sub Workbook_BeforeClose(Cancel As Boolean) Dim sh As Worksheet For Each sh In ThisWorkbook.Worksheets sh.Protect Next sh End Sub
Помните, что код события срабатывает, как только вы закрываете книгу.
Об этом событии важно знать, что не имеет значения, закрыта ли рабочая книга или нет.
В случае, если рабочая книга не была сохранена, и вы увидите приглашение с вопросом о том, сохранять рабочую книгу или нет, и вы нажмете Отмена, она не сохранит вашу рабочую книгу. Однако код события уже был бы выполнен к тому времени.
Событие Workbook BeforePrint
Когда вы даете команду печати (или команду предварительного просмотра), запускается событие «BeforePrint».
Приведенный ниже код будет пересчитывать все рабочие листы до их печати.
Private Sub Workbook_BeforePrint(Cancel As Boolean) For Each ws in Worksheets ws.Calculate Next ws End Sub
Когда пользователь печатает книгу, событие вызывается независимо от того, печатает ли он всю книгу или только ее часть.
Другой пример, приведенный ниже, — это код, который добавляет дату и время в нижний колонтитул при печати рабочей книги.
Private Sub Workbook_BeforePrint(Cancel As Boolean) Dim ws As Worksheet For Each ws In ThisWorkbook.Worksheets ws.PageSetup.LeftFooter = "Напечатано - " & Format(Now, "dd-mmm-yyyy hh:mm") Next ws End Sub
События уровня рабочего листа (объясненные с примерами)
События рабочего листа происходят на основе триггеров в рабочем листе.
Ниже приведены наиболее часто используемые события на листе.
Событие | Что запускает событие |
Activate | Когда лист активирован |
BeforeDelete | Перед удалением листа |
BeforeDoubleClick | Перед двойным щелчком на листе |
BeforeRightClick | Перед щелчком правой кнопкой мыши по рабочему листу |
Calculate | До того, как рабочий лист будет рассчитан или пересчитан |
Change | При изменении ячеек на листе |
Deactivate | Когда лист деактивирован |
PivotTableUpdate | При обновлении сводной таблицы на листе |
SelectionChange | Когда выбор на рабочем листе изменяется |
Обратите внимание, что это не полный список. Вы можете найти полный список здесь.
Помните, что код события Worksheet хранится в окне кода объекта рабочего листа (в том, в котором вы хотите, чтобы событие было запущено). В одной книге может быть несколько рабочих листов, и ваш код будет запущен только тогда, когда событие происходит в рабочей таблице, в которой оно размещено.
Теперь давайте посмотрим на некоторые полезные события на листе и посмотрим, как их можно использовать в вашей повседневной работе.
Событие Worksheet Activate
Это событие вызывается при активации рабочего листа.
Приведенный ниже код снимает защиту листа, как только он активирован.
Private Sub Worksheet_Activate() ActiveSheet.Unprotect End Sub
Вы также можете использовать это событие, чтобы убедиться, что конкретная ячейка или диапазон ячеек (или именованный диапазон) выбран, как только вы активируете рабочую таблицу. Приведенный ниже код выберет ячейку D1, как только вы активируете лист.
Private Sub Worksheet_Activate() ActiveSheet.Range("D1").Select End Sub
Событие Worksheet Change
Событие изменения запускается всякий раз, когда вы вносите изменения в лист.
Ну .. не всегда.
Есть некоторые изменения, которые вызывают событие, а некоторые нет. Вот список некоторых изменений, которые не вызовут событие:
- При изменении форматирования ячейки (размер шрифта, цвет, рамка и т.д.).
- Когда вы объединяете клетки. Это удивительно, так как иногда объединение ячеек также удаляет содержимое из всех ячеек, кроме верхнего левого.
- Когда вы добавляете, удаляете или редактируете комментарий к ячейке.
- Когда вы сортируете диапазон ячеек.
- Когда вы используете поиск цели.
Следующие изменения могут вызвать событие (даже если вы думаете, что не должно):
- Копирование и вставка форматирования вызовут событие.
- Очистка форматирования вызовет событие.
- Запуск проверки орфографии вызовет событие.
Ниже код будет отображать окно сообщения с адресом ячейки, которая была изменена.
Private Sub Worksheet_Change(ByVal Target As Range) MsgBox "Вы только что изменились " & Target.Address End Sub
Хотя это бесполезный макрос, он показывает, как использовать аргумент Target, чтобы узнать, какие ячейки были изменены.
Теперь давайте посмотрим пару более полезных примеров.
Предположим, у вас есть диапазон ячеек (скажем, A1: D10), и вы хотите показать подсказку и спросить пользователя, действительно ли он хочет изменить ячейку в этом диапазоне, вы можете использовать приведенный ниже код.
Отображается подсказка с двумя кнопками — «Да» и «Нет». Если пользователь выбирает «Да», изменение выполняется, в противном случае оно отменяется.
Private Sub Worksheet_Change(ByVal Target As Range) If Target.Row <= 10 And Target.Column <= 4 Then Ans = MsgBox("Вы вносите изменения в ячейки в A1: D10. Вы уверены, что хотите это?", vbYesNo) End If If Ans = vbNo Then Application.EnableEvents = False Application.Undo Application.EnableEvents = True End If End Sub
В приведенном выше коде мы проверяем, находится ли целевая ячейка в первых 4 столбцах и первых 10 строках. Если это так, появится окно сообщения. Кроме того, если пользователь выбрал «Нет» в окне сообщения, изменение отменяется (с помощью команды Application.Undo).
Обратите внимание, что я использовал Application.EnableEvents = False перед строкой Application.Undo. И затем я изменил его, используя Application.EnableEvent = True в следующей строке.
Это необходимо, поскольку, когда происходит отмена, это также вызывает событие изменения. Если я не установлю для параметра EnableEvent значение False, он продолжит вызывать событие изменения.
Вы также можете отслеживать изменения в именованном диапазоне, используя событие изменения. Например, если у вас есть именованный диапазон с именем «DataRange», и вы хотите показать подсказку на случай, если пользователь внесет изменение в этот именованный диапазон, вы можете использовать код ниже:
Private Sub Worksheet_Change(ByVal Target As Range) Dim DRange As Range Set DRange = Range("DataRange") If Not Intersect(Target, DRange) Is Nothing Then MsgBox "Вы только что внесли изменения в диапазон данных" End If End Sub
Приведенный выше код проверяет, имеет ли ячейка / диапазон, в котором вы внесли изменения, какие-либо ячейки, общие для диапазона данных. Если это так, он показывает окно сообщения.
Событие SelectionChange Workbook
Событие изменения выбора запускается всякий раз, когда в рабочем листе есть изменение выбора.
Приведенный ниже код будет пересчитывать лист, как только вы измените выбор.
Private Sub Worksheet_SelectionChange(ByVal Target As Range) Application.Calculate End Sub
Другой пример этого события — когда вы хотите выделить активную строку и столбец выбранной ячейки.
Что-то, как показано ниже:
Следующий код может сделать это:
Private Sub Worksheet_SelectionChange(ByVal Target As Range) Cells.Interior.ColorIndex = xlNone With ActiveCell .EntireRow.Interior.Color = RGB(248, 203, 173) .EntireColumn.Interior.Color = RGB(180, 198, 231) End With End Sub
Код сначала удаляет цвет фона из всех ячеек, а затем применяет цвет, упомянутый в коде, к активной строке и столбцу.
И это проблема с этим кодом. Что он удаляет цвет со всех клеток.
Если вы хотите выделить активную строку / столбец, не изменяя цвета в других ячейках, используйте технику, показанную в этом руководстве.
Событие Workbook DoubleClick
Это одно из моих любимых событий на листе, и вы увидите много учебных пособий, в которых я использовал это.
Это событие срабатывает при двойном щелчке по ячейке.
Позвольте мне показать вам, как это круто.
С помощью приведенного ниже кода вы можете дважды щелкнуть ячейку, и она применит цвет фона, изменит цвет шрифта и сделает текст в ячейке жирным;
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean) Cancel = True With Target .Interior.Color = vbBlue .Font.Color = vbWhite .Font.Bold = True End With End Sub
Это может быть полезно, когда вы просматриваете список ячеек и хотите выделить несколько выбранных. Хотя вы можете использовать клавишу F4, чтобы повторить последний шаг, он сможет применить только один вид форматирования. С этим событием двойного щелчка вы можете применить все три с помощью двойного щелчка.
Обратите внимание, что в приведенном выше коде я сделал значение Cancel = True.
Это сделано для того, чтобы действие двойного щелчка по умолчанию было отключено — то есть войти в режим редактирования. Если Cancel = True, Excel не переведет вас в режим редактирования, если дважды щелкнуть ячейку.
Вот еще один пример.
Если у вас есть список дел в Excel, вы можете использовать событие двойного щелчка, чтобы применить формат перечеркивания, чтобы пометить задачу как выполненную.
Как показано ниже:
Вот код, который сделает это:
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean) Cancel = True CurrFormat = Target.Font.Strikethrough If CurrFormat Then Target.Font.Strikethrough = False Else Target.Font.Strikethrough = True End If End Sub
Обратите внимание, что в этом коде я сделал двойной щелчок в качестве события переключения. Если дважды щелкнуть ячейку, она проверяет, был ли уже применен формат зачеркивания. Если это так, двойной щелчок удаляет зачеркнутый формат, а если этого не было, то применяется зачеркнутый формат.
Событие Excel VBA OnTime
События, которые мы видели до сих пор в этой статье, были связаны с одним из объектов Excel, будь то рабочая книга, рабочий лист, лист диаграммы или пользовательские формы и т.д.
Событие OnTime отличается от других событий, поскольку оно может быть сохранено в обычном модуле VBA (тогда как другие должны были быть помещены в окно кода объектов, таких как ThisWorkbook или Worksheets или UserForms).
В обычном модуле VBA он используется как метод объекта приложения.
Причина, по которой это считается событием, заключается в том, что оно может быть запущено в зависимости от указанного вами времени. Например, если я хочу, чтобы лист пересчитывался каждые 5 минут, я могу использовать для него событие OnTime.
Или, если я хочу показать сообщение / напоминание в определенное время дня, я могу использовать событие OnTime.
Ниже приведен код, который будет показывать сообщение в 2 часа дня каждый день.
Sub MessageTime() Application.OnTime TimeValue("14:00:00"), "ShowMessage" End Sub Sub ShowMessage() MsgBox "Время обеда" End Sub
Помните, что вам нужно поместить этот код в обычный модуль VBA,
Кроме того, хотя событие OnTime будет запускаться в указанное время, макрос необходимо запускать вручную в любое время. После запуска макроса он будет ждать до 14:00, а затем вызовет макрос «ShowMessage».
Макрос ShowMessage будет отображать сообщение.
Событие OnTime принимает четыре аргумента:
Application.OnTime (Самое раннее время, Процедура, Последнее время, Расписание)
- EarliestTime: время, когда вы хотите запустить процедуру.
- Procedure: имя процедуры, которая должна быть запущена.
- LatestTime (Необязательно): Если другой код выполняется и указанный код не может быть запущен в указанное время, вы можете указать LatestTime, которого он должен ждать. Например, это может быть EarliestTime + 45 (что означает, что он будет ждать 45 секунд, пока другая процедура завершится). Если даже через 45 секунд процедура не может быть запущена, она прекращается. Если вы не укажете это, Excel подождет, пока код может быть запущен, а затем запустит его.
- Schedule (необязательно): если установлено значение «ИСТИНА», оно планирует новую процедуру времени. Если ЛОЖЬ, то это отменяет ранее установленную процедуру. По умолчанию это ИСТИНА
В приведенном выше примере мы использовали только первые два аргумента.
Давайте посмотрим на другой пример.
Приведенный ниже код будет обновлять лист каждые 5 минут.
Dim NextRefresh as Date Sub RefreshSheet() ThisWorkbook.Worksheets("Лист1").Calculate NextRefresh = Now + TimeValue("00:05:00") Application.OnTime NextRefresh, "RefreshSheet" End Sub Sub StopRefresh() On Error Resume Next Application.OnTime NextRefresh, "RefreshSheet", , False End Sub
Приведенный выше код обновляет лист каждые 5 минут.
Он использует функцию «Now», чтобы определить текущее время, а затем добавляет 5 минут к текущему времени.
Событие OnTime будет продолжаться до тех пор, пока вы его не остановите. Если вы закроете книгу, а приложение Excel все еще будет запущено (другие книги открыты), книга, в которой запущено событие OnTime, снова откроется.
Это лучше сделать, если специально остановить событие OnTime.
В приведенном выше коде у меня есть код StopRefresh, но вам нужно выполнить его, чтобы остановить событие OnTime. Вы можете сделать это вручную, назначить ее кнопке и сделать это, нажав кнопку или вызвав ее из события закрытия рабочей книги.
Private Sub Workbook_BeforeClose(Cancel As Boolean) Call StopRefresh End Sub
Вышеупомянутый код события «BeforeClose» находится в окне кода ThisWorkbook.
Событие Excel VBA OnKey
Когда вы работаете с Excel, он продолжает отслеживать нажатия клавиш, которые вы используете. Это позволяет нам использовать нажатия клавиш в качестве триггера для события.
С помощью события OnKey вы можете указать нажатие клавиши (или комбинацию нажатий клавиш) и код, который должен выполняться при использовании этого нажатия клавиши. При нажатии этих клавиш выполняется код для него.
Точно так же, как событие OnTime, у вас должен быть способ отменить событие OnKey. Кроме того, когда вы устанавливаете событие OnKey для определенного нажатия клавиши, оно становится доступным во всех открытых книгах.
Прежде чем я покажу вам пример использования события OnKey, позвольте мне сначала поделиться кодами клавиш, которые вам доступны в VBA.
Ключ | Код |
Backspace | {BACKSPACE} or {BS} |
Break | {BREAK} |
Caps Lock | {CAPSLOCK} |
Delete | {DELETE} or {DEL} |
Down Arrow | {DOWN} |
End | {END} |
Enter | ~ |
Enter (on the nueric keypad) | {ENTER} |
Escape | {ESCAPE} or {ESC} |
Home | {HOME} |
Ins | {INSERT} |
Left Arrow | {LEFT} |
NumLock | {NUMLOCK} |
PageDown | {PGDN} |
PageUp | {PGUP} |
RightArrow | {RIGHT} |
Scroll Lock | {SCROLLOCK} |
Tab | {TAB} |
Up Arrow | {UP} |
F1 through F15 | {F1} through {F15} |
Когда вам нужно использовать любое событие onkey, вам нужно использовать код для него.
В приведенной выше таблице приведены коды для однократных нажатий.
Вы также можете комбинировать их со следующими кодами:
Shift: + (знак плюс)
Контроль: ^ (Карет)
Alt:% (в процентах)
Например, для Alt F4 вам нужно использовать код: «% {F4}» — где% для клавиши ALT, а {F4} для клавиши F4.
Теперь давайте посмотрим на примере (помните, код для событий OnKey находится в обычном модуле VBA).
Когда вы нажимаете клавишу PageUp или PageDown, она переходит на 29 строк выше / ниже активной ячейки (по крайней мере, это то, что она делает на моем ноутбуке).
Если вы хотите, чтобы он перескакивал только на 5 строк одновременно, вы можете использовать следующий код:
Sub PageUpDOwnKeys() Application.OnKey "{PgUp}", "PageUpMod" Application.OnKey "{PgDn}", "PageDownMod" End Sub Sub PageUpMod() On Error Resume Next ActiveCell.Offset(-5, 0).Activate End Sub Sub PageDownMod() On Error Resume Next ActiveCell.Offset(5, 0).Activate End Sub
Когда вы запускаете первую часть кода, он запускает события OnKey. Как только это будет выполнено, использование PageUp и клавиши PageDown заставит курсор перескакивать только на 5 строк за раз.
Обратите внимание, что мы использовали «On Error Resume Next», чтобы убедиться, что ошибки игнорируются. Эти ошибки могут возникать, когда вы нажимаете клавишу PageUp, даже если вы находитесь в верхней части листа. Поскольку больше нет строк для перехода, код покажет ошибку. Но так как мы использовали «On Error Resume Next», он будет проигнорирован.
Чтобы убедиться, что эти события OnKey доступны, вам нужно запустить первую часть кода. Если вы хотите, чтобы это было доступно, как только вы откроете рабочую книгу, вы можете поместить ее в окно кода ThisWorkbook.
Private Sub Workbook_Open() Application.OnKey "{PgUp}", "PageUpMod" Application.OnKey "{PgDn}", "PageDownMod" End Sub
Приведенный ниже код вернет ключи к их нормальной работе.
Sub Cancel_PageUpDownKeysMod() Application.OnKey "{PgUp}" Application.OnKey "{PgDn}" End Sub
Если вы не укажете второй аргумент в методе OnKey, он вернет нажатие клавиши к своей обычной функциональности.
В случае, если вы хотите отменить функциональность нажатия клавиши, чтобы Excel ничего не делал при использовании этого нажатия клавиши, вам нужно использовать пустую строку в качестве второго аргумента.
В приведенном ниже коде Excel ничего не будет делать, когда мы используем ключи PageUp или PageDown.
Sub Ignore_PageUpDownKeys() Application.OnKey "{PgUp}", "" Application.OnKey "{PgDn}", "" End Sub
Отключение событий в VBA
Иногда вам может потребоваться отключить события, чтобы ваш код работал правильно.
Например, предположим, что у меня есть диапазон (A1: D10), и я хочу показать сообщение всякий раз, когда ячейка изменяется в этом диапазоне. Поэтому я показываю окно сообщения и спрашиваю пользователя, уверены ли они, что хотят внести изменения. Если ответ «Да», изменение внесено, и если ответ «Нет», VBA отменит его.
Вы можете использовать следующий код:
Private Sub Worksheet_Change(ByVal Target As Range) If Target.Row <= 10 And Target.Column <= 4 Then Ans = MsgBox("Вы вносите изменения в ячейки в A1: D10. Вы уверены, что хотите это?", vbYesNo) End If If Ans = vbNo Then Application.Undo End If End Sub
Проблема с этим кодом заключается в том, что когда пользователь выбирает «Нет» в окне сообщения, действие отменяется (как я использовал Application.Undo).
Когда происходит отмена, и значение возвращается к исходному, событие изменения VBA снова инициируется, и пользователю снова отображается то же самое окно сообщения.
Это означает, что вы можете продолжать нажимать НЕТ в окне сообщения, и оно будет отображаться. Это происходит, когда вы застряли в бесконечном цикле в этом случае.
Чтобы избежать таких случаев, вам нужно отключить события, чтобы событие изменения (или любое другое событие) не срабатывало.
Следующий код будет хорошо работать в этом случае:
Private Sub Worksheet_Change(ByVal Target As Range) If Target.Row <= 10 And Target.Column <= 4 Then Ans = MsgBox("Вы вносите изменения в ячейки в A1: D10. Вы уверены, что хотите это?", vbYesNo) End If If Ans = vbNo Then Application.EnableEvents = False Application.Undo Application.EnableEvents = True End If End Sub
В приведенном выше коде, прямо над строкой Application.Undo, мы использовали — Application.EnableEvents = False.
Если для параметра EnableEvents установлено значение False, это не приведет к возникновению какого-либо события (в текущей или любой открытой рабочей книге).
После того, как мы завершили операцию отмены, мы можем переключить свойство EnableEvents на True.
Имейте в виду, что отключение событий влияет на все книги, которые в данный момент открыты (или открыты, когда для параметра EnableEvents установлено значение False). Например, как часть кода, если вы откроете новую книгу, событие Workbook Open не будет работать.
Влияние событий Undo Stack
Позвольте мне сначала рассказать вам, что такое Undo Stack.
Когда вы работаете в Excel, он продолжает следить за вашими действиями. Когда вы делаете ошибку, вы всегда можете использовать Control + Z, чтобы вернуться к предыдущему шагу (то есть отменить ваше текущее действие).
Если вы дважды нажмете Control + Z, это вернет вас назад на два шага. Эти шаги, которые вы выполнили, сохраняются как часть Undo Stack.
Любое событие, которое изменяет рабочий лист, уничтожает этот стек отмены. Это означает, что если я выполнил 5 действий до запуска события, я не смогу использовать Control + Z, чтобы вернуться к этим предыдущим шагам. Запуск события уничтожил этот стек для меня.
В приведенном ниже коде я использую VBA для ввода метки времени в ячейку A1 при каждом изменении в листе.
Private Sub Worksheet_Change(ByVal Target As Range) Application.EnableEvents = False Range("A1").Value = Format(Now, "dd-mmm-yyyy hh:mm:ss") Application.EnableEvents = True End Sub
Поскольку я делаю изменения в листе, это уничтожит Undo Stack.
Также обратите внимание, что это не ограничивается только событиями.
Если у вас есть код, который хранится в обычном модуле VBA, и вы вносите изменения в рабочую таблицу, это также уничтожит Undo Stack в Excel.
Например, приведенный ниже код просто вводит текст «Hello» в ячейку A1, но даже выполнение этого приведет к разрушению
Undo Stack.
Sub TypeHello() Range("A1").Value = "Привет" End Sub
-
07-25-2014, 07:57 AM
#1
Registered User
Cancel As Boolean Help
Hello everyone, I’m looking for a bit of help on this issue I’ve been getting when I tried to combine 2 snippets of code together. I’m really a excel newbie and have been messing around with for quite some time, I can usually find the answer online but I’m stumped on this one.
Code:
I get a run-time error ‘1004’, application defined or object defined error when I try printing. What I’m using this code for is to make sure some users input something in those specified cells AND hide a few different other cells when printing (by turning the text white I guess). The 2 separate codes work just fine when I use either one separately, but when I combined (or tried to anyways) them i get an error. I know nothing about programming so I’m really stumped, I’m sure there’s a IF-ELSE-THEN statement I’m not making or something like that. Any help would be greatly appreciated. Thanks again!
Edit: [Solved]
Last edited by Kiotofl; 07-25-2014 at 11:45 AM.
-
07-25-2014, 08:53 AM
#2
Registered User
Re: Cancel As Boolean Help
Hi Kiotofl,
Can you upload your (example) document as well?
It’s hard to figure out which cells are checked etc.
-
07-25-2014, 08:57 AM
#3
Re: Cancel As Boolean Help
hi Kiotofl, welcome to Excelforum, as a quess:
-
07-25-2014, 09:03 AM
#4
Registered User
Re: Cancel As Boolean Help
I don’t get the need of hiding text when printing, what is the purpose of that? What are you trying to achieve here?
Prevent a user to print something, before some cells are filled?
-
07-25-2014, 09:19 AM
#5
Registered User
Re: Cancel As Boolean Help
It would be probably best not to upload the form just because it has internal company information, and the reason I ‘m trying to hide some cells is because the customers receiving the printed version (PDF or otherwise) should not have some of this «internal information» shown to them such as internal cost, warranty and contact information. This is useful for the person creating this estimate, but it should not be seen by the customer receiving the printed version of the form. Does this make sense?
-
07-25-2014, 09:36 AM
#6
Registered User
Re: Cancel As Boolean Help
I’m so dumb. My code works just fine but I locked the cells and protected the sheet (to keep the users from making changes to these fields) and that was the problem the whole time. So now that I unlocked those cells and unprotected the sheet, the code works for both functions, to hide some cells and to prevent the user from printing without filling the required cells. So that solved that problem, but a new problem arises, is there a way this could work WITH the locked cells and protected sheet? Also, is there a way that I could hide the condition as well? I noticed that if I have a condition for one of the cells I’m trying to hide (for instance, turn the text color red if a warranty is expired) if the condition is met, the text will not hide.
Last edited by Kiotofl; 07-25-2014 at 09:39 AM.
-
07-25-2014, 09:40 AM
#7
Registered User
Re: Cancel As Boolean Help
Hahah, well… that happens with all of at some end I think
Yes you can, you can Unprotect your sheet before printing and Protect it again after print. But thats another topic!
-
07-25-2014, 10:32 AM
#8
Registered User
Re: Cancel As Boolean Help
Well I found a solution again for this. I ended up having to run a Sheets(«SheetName»).Unprotect & Sheets(«SheetName»).Protect before and after the initiation of the VBA code. I guess VBA doesn’t like locked/merged cells win conjunction with having a protected sheet. This fixed all of the issues I was having and here’s how the code looks now:
-
07-25-2014, 11:26 AM
#9
Registered User
Re: Cancel As Boolean Help
Yes, that should be alright I think
When you create or record a macro in Excel, you need to run the macro to execute the steps in the code.
A few ways of running a macro includes using the macro dialog box, assigning the macro to a button, using a shortcut, etc.
Apart from these user-initiated macro executions, you can also use VBA events to run the macro.
Excel VBA Events – Introduction
Let me first explain what is an event in VBA.
An event is an action that can trigger the execution of the specified macro.
For example, when you open a new workbook, it’s an event. When you insert a new worksheet, it’s an event. When you double-click on a cell, it’s an event.
There are many such events in VBA, and you can create codes for these events. This means that as soon as an event occurs, and if you have specified a code for that event, that code would instantly be executed.
Excel automatically does this as soon as it notices that an event has taken place. So you only need to write the code and place it in the correct event subroutine (this is covered later in this article).
For example, if you insert a new worksheet and you want it to have a year prefix, you can write the code for it.
Now, whenever anyone inserts a new worksheet, this code would automatically be executed and add the year prefix to the worksheet’s name.
Another example could be that you want to change the color of the cell when someone double-clicks on it. You can use the double-click event for this.
Similarly, you can create VBA codes for many such events (as we will see later in this article).
Below is a short visual that shows the double-click event in action. As soon as I double click on cell A1. Excel instantly opens a message box that shows the address of the cell.
Double-click is an event, and showing the message box is what I have specified in the code whenever the double-click event takes place.
While the above example is a useless event, I hope it helps you understand what events really are.
Different Types of Excel VBA Events
There are different objects in Excel – such as Excel itself (to which we often refer to as the application), workbooks, worksheets, charts, etc.
Each of these objects can have various events associated with it. For example:
- If you create a new workbook, it’s an application level event.
- If you add a new worksheet, it’s a workbook level event.
- If you change the value in a cell in a sheet, it’s a worksheet level event.
Below are the different types of Events that exist in Excel:
- Worksheet Level Events: These are the types of events that would trigger based on the actions taken in the worksheet. Examples of these events include changing a cell in the worksheet, changing the selection, double-clicking on a cell, right-clicking on a cell, etc.
- Workbook Level Events: These events would be triggered based on the actions at the workbook level. Examples of these events include adding a new worksheet, saving the workbook, opening the workbook, printing a part or the entire workbook, etc.
- Application Level Events: These are the events that occur in the Excel application. Example of these would include closing any of the open workbooks or opening a new workbook.
- UserForm Level Events: These events would be triggered based on the actions in the ‘UserForm’. Examples of these include initializing a UserForm or clicking a button in the UserForm.
- Chart Events: These are events related to the chart sheet. A chart sheet is different than a worksheet (which is where most of us are used to work in Excel). A chart sheets purpose is to hold a chart. Examples of such events would include changing the series of the chart or resizing the chart.
- OnTime and OnKey Events: These are two events that don’t fit in any of the above categories. So I have listed these separately. ‘OnTime’ event allows you to execute a code at a specific time or after a specific time has elapsed. ‘OnKey’ event allows you to execute a code when a specific keystroke (or a combination of keystrokes) is used.
Where to Put the Event-Related Code
In the above section, I covered the different types of events.
Based on the type of event, you need to put the code in the relevant object.
For example, if it’s a worksheet related event, it should go in the code window of the worksheet object. If it’s workbook related, it should go in the code window for a workbook object.
In VBA, different objects – such as Worksheets, Workbooks, Chart Sheets, UserForms, etc., have their own code windows. You need to put the event code in the relevant object’s code window. For example – if it’s a workbook level event, then you need to have the event code in the Workbook code window.
The following sections cover the places where you can put the event code:
In Worksheet Code Window
When you open the VB Editor (using keyboard shortcut ALT + F11), you would notice the worksheets object in the Project Explorer. For each worksheet in the workbook, you will see one object.
When you double-click on the worksheet object in which you want to place the code, it would open the code window for that worksheet.
While you can start writing the code from scratch, it’s much better to select the event from a list of options and let VBA automatically insert the relevant code for the selected event.
To do this, you need to first select worksheet from the drop down at the top-left of the code window.
After selecting worksheet from the drop down, you get a list of all the events related to the worksheet. You can select the one you want to use from the drop-down at the top right of the code window.
As soon as you select the event, it would automatically enter the first and last line of the code for the selected event. Now you can add your code in between the two lines.
Note: As soon as you select Worksheet from the drop-down, you would notice two lines of code appear in the code window. Once you have selected the event for which you want the code, you can delete the lines that appeared by default.
Note that each worksheet has a code window of its own. When you put the code for Sheet1, it will only work if the event happens in Sheet1.
In ThisWorkbook Code Window
Just like worksheets, if you have a workbook level event code, you can place it in ThisWorkbook code window.
When you double-click on ThisWorkbook, it will open the code window for it.
You need to select Workbook from the drop-down at the top-left of the code window.
After selecting Workbook from the drop down, you get a list of all the events related to the Workbook. You can select the one you want to use from the drop-down at the top right of the code window.
As soon as you select the event, it would automatically enter the first and last line of the code for the selected event. Now you can add your code in between the two lines.
Note: As soon as you select Workbook from the drop-down, you would notice two lines of code appear in the code window. Once you have selected the event for which you want the code, you can delete the lines that appeared by default.
In Userform Code Window
When you’re creating UserForms in Excel, you can also use UserForm events to executes codes based on specific actions. For example, you can specify a code that is executed when the button is clicked.
While the Sheet objects and ThisWorkbook objects are already available when you open the VB Editor, UserForm is something you need to create first.
To create a UserForm, right-click on any of the objects, go to Insert and click on UserForm.
This would insert a UserForm object in the workbook.
When you double-click on the UserForm (or any of the object that you add to the UserForm), it would open the code window for the UserForm.
Now just like worksheets or ThisWorkbook, you can select the event and it will insert the first and the last line for that event. And then you can add the code in the middle of it.
In Chart Code Window
In Excel, you can also insert Chart sheets (which are different then worksheets). A chart sheet is meant to contain charts only.
When you have inserted a chart sheet, you will be able to see the Chart sheet object in the VB Editor.
You can add the event code to the chart sheet code window just like we did in the worksheet.
Double click on the Chart sheet object in the Project Explorer. This will open the code window for the chart sheet.
Now, you need to select Chart from the drop-down at the top-left of the code window.
After selecting Chart from the drop-down, you get a list of all the events related to the Chart sheet. You can select the one you want to use from the drop-down at the top right of the code window.
Note: As soon as you select Chart from the drop-down, you would notice two lines of code appear in the code window. Once you have selected the event for which you want the code, you can delete the lines that appeared by default.
In Class Module
Class Modules need to be inserted just like UserForms.
A class module can hold code related to the application – which would be Excel itself, and the embedded charts.
I will cover the class module as a separate tutorial in the coming weeks.
Note that apart from OnTime and OnKey events, none of the above events can be stored in the regular VBA module.
Understanding the Event Sequence
When you trigger an event, it doesn’t happen in isolation. It may also lead to a sequence of multiple triggers.
For example, when you insert a new worksheet, the following things happen:
- A new worksheet is added
- The previous worksheet gets deactivated
- The new worksheet gets activated
While in most cases, you may not need to worry about the sequence, if you’re creating complex codes that rely on events, it’s better to know the sequence to avoid unexpected results.
Understanding the Role of Arguments in VBA Events
Before we jump to Event examples and the awesome things you can do with it, there is one important concept I need to cover.
In VBA events, there would be two types of codes:
- Without any arguments
- With arguments
And in this section, I want to quickly cover the role of arguments.
Below is a code that has no argument in it (the parenthesis are empty):
Private Sub Workbook_Open() MsgBox "Remember to Fill the Timesheet" End Sub
With the above code, when you open a workbook, it simply shows a message box with the message – “Remember to fill the Timesheet”.
Now let’s have a look at a code that has an argument.
Private Sub Workbook_NewSheet(ByVal Sh As Object) Sh.Range("A1") = Sh.Name End Sub
The above code uses the Sh argument which is defined as an object type. The Sh argument could be a worksheet or a chart sheet, as the above event is triggered when a new sheet is added.
By assigning the new sheet that is added to the workbook to the object variable Sh, VBA has enabled us to use it in the code. So to refer to the new sheet name, I can use Sh.Name.
The concept of arguments will be useful when you go through the VBA events examples in the next sections.
Workbook Level Events (Explained with Examples)
Following are the most commonly used events in a workbook.
EVENT NAME | WHAT TRIGGERS THE EVENT |
Activate | When a workbook is activated |
AfterSave | When a workbook is installed as an add-in |
BeforeSave | When a workbook is saved |
BeforeClose | When a workbook is closed |
BeforePrint | When a workbook is printed |
Deactivate | When a workbook is deactivated |
NewSheet | When a new sheet is added |
Open | When a workbook is opened |
SheetActivate | When any sheet in the workbook is activated |
SheetBeforeDelete | When any sheet is deleted |
SheetBeforeDoubleClick | When any sheet is double-clicked |
SheetBeforeRightClick | When any sheet is right-clicked |
SheetCalculate | When any sheet is calculated or recalculated |
SheetDeactivate | When a workbook is deactivated |
SheetPivotTableUpdate | When a workbook is updated |
SheetSelectionChange | When a workbook is changed |
WindowActivate | When a workbook is activated |
WindowDeactivate | When a workbook is deactivated |
Note that this is not a complete list. You can find the complete list here.
Remember that the code for Workbook event is stored in the ThisWorkbook objects code window.
Now let’s have a look at some useful workbook events and see how these can be used in your day-to-day work.
Workbook Open Event
Let’s say that you want to show the user a friendly reminder to fill their timesheets whenever they open a specific workbook.
You can use the below code to do this:
Private Sub Workbook_Open() MsgBox "Remember to Fill the Timesheet" End Sub
Now as soon as you open the workbook that has this code, it will show you a message box with the specified message.
There are a few things to know when working with this code (or Workbook Event codes in general):
- If a workbook has a macro and you want to save it, you need to save it in the .XLSM format. Else the macro code would be lost.
- In the above example, the event code would be executed only when the macros are enabled. You may see a yellow bar asking for permission to enable macros. Until that is enabled, the event code is not executed.
- The Workbook event code is placed in the code window of ThisWorkbook object.
You can further refine this code and show the message only of Friday.
The below code would do this:
Private Sub Workbook_Open() wkday = Weekday(Date) If wkday = 6 Then MsgBox "Remember to Fill the Timesheet" End Sub
Note that in the Weekday function, Sunday is assigned the value 1, Monday is 2 and so on.
Hence for Friday, I have used 6.
Workbook Open event can be useful in many situations, such as:
- When you want to show a welcome message to the person when a workbook is opened.
- When you want to display a reminder when the workbook is opened.
- When you want to always activate one specific worksheet in the workbook when it’s opened.
- When you want to open related files along with the workbook.
- When you want to capture the date and time stamp every time the workbook is opened.
Workbook NewSheet Event
NewSheet event is triggered when you insert a new sheet in the workbook.
Let’s say that you want to enter the date and time value in cell A1 of the newly inserted sheet. You can use the below code to do this:
Private Sub Workbook_NewSheet(ByVal Sh As Object) On Error Resume Next Sh.Range("A1") = Format(Now, "dd-mmm-yyyy hh:mm:ss") End Sub
The above code uses ‘On Error Resume Next’ to handle cases where someone inserts a chart sheet and not a worksheet. Since chart sheet doesn’t have cell A1, it would show an error if ‘On Error Resume Next’ is not used.
Another example could be when you want to apply some basic setting or formatting to a new sheet as soon as it is added. For example, if you want to add a new sheet and want it to automatically get a serial number (up to 100), then you can use the code below.
Private Sub Workbook_NewSheet(ByVal Sh As Object) On Error Resume Next With Sh.Range("A1") .Value = "S. No." .Interior.Color = vbBlue .Font.Color = vbWhite End With For i = 1 To 100 Sh.Range("A1").Offset(i, 0).Value = i Next i Sh.Range("A1", Range("A1").End(xlDown)).Borders.LineStyle = xlContinuous End Sub
The above code also does a bit of formatting. It gives the header cell a blue color and makes the font white. It also applies a border to all the filled cells.
The above code is an example of how a short VBA code can help you steal a few seconds every time you insert a new worksheet (in case this is something that you have to do every time).
Workbook BeforeSave Event
Before Save event is triggered when you save a workbook. Note that the event is triggered first and then the workbook is saved.
When saving an Excel workbook, there could be two possible scenarios:
- You’re saving it for the first time and it will show the Save As dialog box.
- You’ve already saved it earlier and it will simply save and overwrite the changes in the already saved version.
Now let’s have a look at a few examples where you can use the BeforeSave event.
Suppose you have a new workbook that you’re saving for the first time, and you want to remind the user to save it in the K drive, then you can use the below code:
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean) If SaveAsUI Then MsgBox "Save this File in the K Drive" End Sub
In the above code, if the file has never been saved, SaveAsUI is True and brings up the Save As dialog box. The above code would display the message before the Save As dialog box appear.
Another example could be to update the date and time when the file is saved in a specific cell.
The below code would insert the date & time stamp in cell A1 of Sheet1 whenever the file is saved.
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean) Worksheets("Sheet1").Range("A1") = Format(Now, "dd-mmm-yyyy hh:mm:ss") End Sub
Note that this code is executed as soon as the user saves the workbook. If the workbook is being saved for the first time, it will show a Save As dialog box. But the code is already executed by the time you see the Save As dialog box. At this point, if you decide to cancel and not save the workbook, the date and time would already be entered in the cell.
Workbook BeforeClose Event
Before Close event happens right before the workbook is closed.
The below code protects all the worksheets before the workbook is closed.
Private Sub Workbook_BeforeClose(Cancel As Boolean) Dim sh As Worksheet For Each sh In ThisWorkbook.Worksheets sh.Protect Next sh End Sub
Remember that the event code is triggered as soon as you close the workbook.
One important thing to know about this event is that it doesn’t care whether the workbook is actually closed or not.
In case the workbook has not been saved and you’re shown the prompt asking whether to save the workbook or not, and you click Cancel, it will not save your workbook. However, the event code would have already been executed by then.
Workbook BeforePrint Event
When you give the print command (or Print Preview command), the Before Print event is triggered.
The below code would recalculate all the worksheets before your workbook is printed.
Private Sub Workbook_BeforePrint(Cancel As Boolean) For Each ws in Worksheets ws.Calculate Next ws End Sub
When the user is printing the workbook, the event would be fired whether he/she is printing the entire workbook or only a part of it.
Another example below is of the code that would add the date and time to the footer when the workbook is printed.
Private Sub Workbook_BeforePrint(Cancel As Boolean) Dim ws As Worksheet For Each ws In ThisWorkbook.Worksheets ws.PageSetup.LeftFooter = "Printed On - " & Format(Now, "dd-mmm-yyyy hh:mm") Next ws End Sub
Worksheet Level Events (Explained with Examples)
Worksheet events take place based on the triggers in the worksheet.
Following are the most commonly used events in a worksheet.
Event Name | What triggers the event |
Activate | When the worksheet is activated |
BeforeDelete | Before the worksheet is deleted |
BeforeDoubleClick | Before the worksheet is double-clicked |
BeforeRightClick | Before the worksheet is right-clicked |
Calculate | Before the worksheet is calculated or recalculated |
Change | When the cells in the worksheet are changed |
Deactivate | When the worksheet is deactivated |
PivotTableUpdate | When the Pivot Table in the worksheet is updated |
SelectionChange | When the selection on the worksheet is changed |
Note that this is not a complete list. You can find the complete list here.
Remember that the code for Worksheet event is stored in the worksheet object code window (in the one in which you want the event to be triggered). There can be multiple worksheets in a workbook, and your code would be fired only when the event takes place in the worksheet in which it is placed.
Now let’s have a look at some useful worksheet events and see how these can be used in your day-to-day work.
Worksheet Activate Event
This event is fired when you activate a worksheet.
The below code unprotects a sheet as soon as it is activated.
Private Sub Worksheet_Activate() ActiveSheet.Unprotect End Sub
You can also use this event to make sure a specific cell or a range of cells (or a named range) is selected as soon as you activate the worksheet. The below code would select cell D1 as soon as you activate the sheet.
Private Sub Worksheet_Activate() ActiveSheet.Range("D1").Select End Sub
Worksheet Change Event
A change event is fired whenever you make a change in the worksheet.
Well.. not always.
There are some changes that trigger the event, and some that don’t. Here is a list of some changes that won’t trigger the event:
- When you change the formatting of the cell (font size, color, border, etc.).
- When you merge cells. This is surprising as sometimes, merging cells also removes content from all the cells except the top-left one.
- When you add, delete, or edit a cell comment.
- When you sort a range of cells.
- When you use Goal Seek.
The following changes would trigger the event (even though you may think it shouldn’t):
- Copy and pasting formatting would trigger the event.
- Clearing formatting would trigger the event.
- Running a spell check would trigger the event.
Below is a code would show a message box with the address of the cell that has been changed.
Private Sub Worksheet_Change(ByVal Target As Range) MsgBox "You just changed " & Target.Address End Sub
While this is a useless macro, it does show you how to use the Target argument to find out what cells have been changed.
Now let’s see a couple of more useful examples.
Suppose you have a range of cells (let’s say A1:D10) and you want to show a prompt and ask the user if they really wanted to change a cell in this range or not, you can use the below code.
It shows a prompt with two buttons – Yes and No. If the user selects ‘Yes’, the change is done, else it is reversed.
Private Sub Worksheet_Change(ByVal Target As Range) If Target.Row <= 10 And Target.Column <= 4 Then Ans = MsgBox("You are making a change in cells in A1:D10. Are you sure you want it?", vbYesNo) End If If Ans = vbNo Then Application.EnableEvents = False Application.Undo Application.EnableEvents = True End If End Sub
In the above code, we check whether the Target cell is in first 4 columns and the first 10 rows. If that’s the case, the message box is shown. Also, if the user selected No in the message box, the change is reversed (by the Application.Undo command).
Note that I have used Application.EnableEvents = False before the Application.Undo line. And then I reversed it by using Application.EnableEvent = True in the next line.
This is needed as when the undo happens, it also triggers the change event. If I don’t set the EnableEvent to False, it will keep on triggering the change event.
You can also monitor the changes to a named range using the change event. For example, if you have a named range called “DataRange” and you want to show a prompt in case user makes a change in this named range, you can use the code below:
Private Sub Worksheet_Change(ByVal Target As Range) Dim DRange As Range Set DRange = Range("DataRange") If Not Intersect(Target, DRange) Is Nothing Then MsgBox "You just made a change to the Data Range" End If End Sub
The above code checks whether the cell/range where you have made the changes has any cells common to the Data Range. If it does, it shows the message box.
Workbook SelectionChange Event
The selection change event is triggered whenever there is a selection change in the worksheet.
The below code would recalculate the sheet as soon as you change the selection.
Private Sub Worksheet_SelectionChange(ByVal Target As Range) Application.Calculate End Sub
Another example of this event is when you want to highlight the active row and column of the selected cell.
Something as shown below:
The following code can do this:
Private Sub Worksheet_SelectionChange(ByVal Target As Range) Cells.Interior.ColorIndex = xlNone With ActiveCell .EntireRow.Interior.Color = RGB(248, 203, 173) .EntireColumn.Interior.Color = RGB(180, 198, 231) End With End Sub
The code first removes the background color from all the cells and then apply the one mentioned in the code to the active row and column.
And that’s the problem with this code. That it removes color from all cells.
If you want to highlight the active row/column while keeping the color in other cells intact, use the technique shown in this tutorial.
Workbook DoubleClick Event
This is one of my favorite worksheet events and you’ll see a lot of tutorials where I have used this (such as this one or this one).
This event is triggered when you double-click on a cell.
Let me show you how awesome this is.
With the below code, you can double-click on a cell and it will apply a background color, change the font color, and make the text in the cell bold;
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean) Cancel = True With Target .Interior.Color = vbBlue .Font.Color = vbWhite .Font.Bold = True End With End Sub
This can be useful when you’re going through a list of cells and want to highlight a few selected ones. While you can use the F4 key to repeat the last step, it would only be able to apply one kind of formatting. With this double-click event, you can apply all three with just a double-click.
Note that in the above code, I have made the value of Cancel = True.
This is done so that the default action of double-click is disabled – which is to get into the edit mode. With Cancel = True, Excel would not get you into Edit mode when you double-click on the cell.
Here is another example.
If you have a to-do list in Excel, you can use double-click event to apply the strikethrough format to mark the task as completed.
Something as shown below:
Here is the code that will do this:
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean) Cancel = True CurrFormat = Target.Font.Strikethrough If CurrFormat Then Target.Font.Strikethrough = False Else Target.Font.Strikethrough = True End If End Sub
Note that in this code, I have made double-click as a toggle event. When you double-click on a cell, it checks if the strikethrough format has already been applied. If it has been, double-click removes the strikethrough format, and if it hasn’t been, then the strikethrough format is applied.
Excel VBA OnTime Event
The events that we have seen so far in this article were associated with one of the Excel objects, be it the workbook, worksheet, chart sheet, or UserForms, etc.
OnTime event is different than other events as it can be stored in the regular VBA module (while the others were to be placed in the code window of objects such as ThisWorkbook or Worksheets or UserForms).
Within the regular VBA module, it is used as a method of the application object.
The reason this is considered an event is that it can be triggered based on the time you specify. For example, if I want the sheet to recalculate every 5 minutes, I can use the OnTime event for it.
Or, if I want to show a message/reminder at a specific time of the day, I can use the OnTime event.
Below is a code that will show a message at 2 pm every day.
Sub MessageTime() Application.OnTime TimeValue("14:00:00"), "ShowMessage" End Sub Sub ShowMessage() MsgBox "It's Lunch Time" End Sub
Remember you need to place this code in the regular VBA module,
Also, while the OnTime event would be triggered at the specified time, you need to run the macro manually at any time.
Once you run the macro, it will wait till it’s 2 PM and then call the ‘ShowMessage’ macro.
The ShowMessage macro would then display the message.
The OnTime event takes four arguments:
Application.OnTime(EarliestTime, Procedure, LatestTime, Schedule)
- EarliestTime: The time when you want to run the procedure.
- Procedure: The name of the procedure that should be run.
- LatestTime (Optional): In case another code is running and your specified code can’t be run at the specified time, you can specify the LatestTime for which it should wait. For example, it could be EarliestTime + 45 (which means it will wait for 45 seconds for the other procedure to get completed). If even after 45 seconds the procedure is not able to run, it gets abandoned. If you don’t specify this, Excel would wait until the code can be run, and then run it.
- Schedule (Optional): If set to True, it schedules new time procedure. If False, then it cancels the previously set procedure. By default, this is True.
In the above example, we only used the first two arguments.
Let’s look at another example.
The below code would refresh the worksheet every 5 min.
Dim NextRefresh as Date Sub RefreshSheet() ThisWorkbook.Worksheets("Sheet1").Calculate NextRefresh = Now + TimeValue("00:05:00") Application.OnTime NextRefresh, "RefreshSheet" End Sub Sub StopRefresh() On Error Resume Next Application.OnTime NextRefresh, "RefreshSheet", , False End Sub
The above code would refresh the worksheet every 5 minutes.
It uses the Now function to determine the current time and then adds 5 minutes to the current time.
The OnTime event would continue to run until you stop it. If you close the workbook and Excel application is still running (other workbooks are open), the workbook that has the OnTime event running in it would reopen itself.
This is better handled by specifically stopping the OnTime event.
In the above code, I have the StopRefresh code, but you need to execute it to stop the OnTime event. You can do this manually, assign it to a button and do this by pressing the button or call it from the Workbook Close event.
Private Sub Workbook_BeforeClose(Cancel As Boolean) Call StopRefresh End Sub
The above ‘BeforeClose’ event code goes in ThisWorkbook code window.
Also read: Make VBA Code Pause or Delay
Excel VBA OnKey Event
When you’re working with Excel, it keeps monitoring the keystrokes you use. This allows us to use keystrokes as the trigger for an event.
With OnKey event, you can specify a keystroke (or a combination of keystrokes) and the code that should be executed when that keystroke is used. When these keystrokes are pressed, it will execute the code for it.
Just like OnTime event, you need to have a way to cancel the OnKey event. Also, when you set the OnKey event for a specific keystroke, it becomes available in all the open workbooks.
Before I show you an example of using the OnKey event, let me first share the key codes that are available to you in VBA.
KEY | CODE |
Backspace | {BACKSPACE} or {BS} |
Break | {BREAK} |
Caps Lock | {CAPSLOCK} |
Delete | {DELETE} or {DEL} |
Down Arrow | {DOWN} |
End | {END} |
Enter | ~ |
Enter (on the nueric keypad) | {ENTER} |
Escape | {ESCAPE} or {ESC} |
Home | {HOME} |
Ins | {INSERT} |
Left Arrow | {LEFT} |
NumLock | {NUMLOCK} |
PageDown | {PGDN} |
PageUp | {PGUP} |
RightArrow | {RIGHT} |
Scroll Lock | {SCROLLOCK} |
Tab | {TAB} |
Up Arrow | {UP} |
F1 through F15 | {F1} through {F15} |
When you need to use any onkey event, you need to use the code for it.
The above table has the codes for single keystrokes.
You can also combine these with the following codes:
- Shift: + (Plus Sign)
- Control: ^ (Caret)
- Alt: % (Percentage)
For Example, for Alt F4, you need to use the code: “%{F4}” – where % is for the ALT key and {F4} is for the F4 key.
Now let’s have a look at an example (remember the code for OnKey events are placed in the regular VBA module).
When you hit the PageUp or PageDown key, it jumps 29 rows above/below the active cell (at least that’s what it’s doing on my laptop).
If you want it to jump only 5 rows at a time, you can use the below code:
Sub PageUpDOwnKeys() Application.OnKey "{PgUp}", "PageUpMod" Application.OnKey "{PgDn}", "PageDownMod" End Sub Sub PageUpMod() On Error Resume Next ActiveCell.Offset(-5, 0).Activate End Sub Sub PageDownMod() On Error Resume Next ActiveCell.Offset(5, 0).Activate End Sub
When you run the first part of the code, it will run the OnKey events. Once this is executed, using the PageUp and the PageDown key would only make the cursor jump 5 rows at a time.
Note that we have used ‘On Error Resume Next’ to make sure errors are ignored. These errors can occur when you press the PageUp key even when you’re at the top of the worksheet. Since there are no more rows to jump, the code would show an error. But since we have used ‘On Error Resume Next’, it will be ignored.
To make sure these OnKey events are available, you need to run the first part of the code. In case you want this to be available as soon as you open the workbook, you can place this in the ThisWorkbook code window.
Private Sub Workbook_Open() Application.OnKey "{PgUp}", "PageUpMod" Application.OnKey "{PgDn}", "PageDownMod" End Sub
The below code will return the keys to their normal functionality.
Sub Cancel_PageUpDownKeysMod() Application.OnKey "{PgUp}" Application.OnKey "{PgDn}" End Sub
When you don’t specify the second argument in the OnKey method, it will return the keystroke to its regular functionality.
In case you want to cancel the functionality of a keystroke, so that Excel does nothing when that keystroke is used, you need to use a blank string as the second argument.
In the below code, Excel would do nothing when we use the PageUp or PageDown keys.
Sub Ignore_PageUpDownKeys() Application.OnKey "{PgUp}", "" Application.OnKey "{PgDn}", "" End Sub
Disabling Events in VBA
Sometimes you may need to disable events to make your code work properly.
For example, suppose I have a range (A1:D10) and I want to show a message whenever a cell is changed in this range. So I show a message box and asks the user whether they are sure that they want to make the change. If the answer is Yes, the change is made, and if the answer is No, then VBA would undo it.
You can use the below code:
Private Sub Worksheet_Change(ByVal Target As Range) If Target.Row <= 10 And Target.Column <= 4 Then Ans = MsgBox("You are making a change in cells in A1:D10. Are you sure you want it?", vbYesNo) End If If Ans = vbNo Then Application.Undo End If End Sub
The problem with this code is that when the user selects No in the message box, the action is reversed (as I have used Application.Undo).
When the undo happens and the value is changed back to the original one, the VBA change event is again triggered, and the user is again shown the same message box.
This means that you can continue to click NO on the message box and it will keep showing up. This happens as you have got stuck in the infinite loop in this case.
To avoid such cases, you need to disable events so that the change event (or any other event) is not triggered.
The following code would work well in this case:
Private Sub Worksheet_Change(ByVal Target As Range) If Target.Row <= 10 And Target.Column <= 4 Then Ans = MsgBox("You are making a change in cells in A1:D10. Are you sure you want it?", vbYesNo) End If If Ans = vbNo Then Application.EnableEvents = False Application.Undo Application.EnableEvents = True End If End Sub
In the above code, right above the Application.Undo line, we have used – Application.EnableEvents = False.
Setting EnableEvents to False would not trigger any event (in the current or any open workbooks).
Once we have completed the undo operation, we can switch back the EnableEvents property to True.
Keep in mind that disabling events impacts all the workbooks that are currently opened (or opened while EnableEvents is set to False). For example, as a part of the code, if you open a new workbook, then the Workbook Open event would not work.
Impact of Events Undo Stack
Let me first tell you what an Undo Stack is.
When you work in Excel, it keeps monitoring your actions. When you make a mistake, you can always use Control + Z to go back to the previous step (i.e., undo your current action).
If you press Control + Z twice, it will take you back two steps. These steps that you have performed are stored as a part of the Undo stack.
Any event that changes the worksheet destroys this Undo stack. This means that if I have done 5 things before I trigger an event, I will not be able to use Control + Z to go back to those previous steps. Triggering the event has destroyed that stack for me.
In the below code, I use VBA to enter the timestamp in cell A1 whenever there is a change in the worksheet.
Private Sub Worksheet_Change(ByVal Target As Range) Application.EnableEvents = False Range("A1").Value = Format(Now, "dd-mmm-yyyy hh:mm:ss") Application.EnableEvents = True End Sub
Since I am making a change in the worksheet, this will destroy the undo stack.
Also, note that this is not limited to events only.
If you have a code that is stored in regular VBA module, and you make a change in the worksheet, it would also destroy the undo stack in Excel.
For example, the below code simply enter the text “Hello” in cell A1, but even running this would destroy the undo stack.
Sub TypeHello() Range("A1").Value = "Hello" End Sub
You May Also Like the Following Excel VBA Tutorials:
- Working with Cells and Ranges in Excel VBA.
- Working with Worksheets in Excel VBA.
- Working with Workbooks in Excel VBA.
- Excel VBA Loops – The Ultimate Guide.
- Using IF Then Else Statment in Excel VBA.
- For Next Loop in Excel.
- Creating User-Defined Functions in Excel VBA.
- How to Create and Use Add-ins in Excel.
- Create and Reuse Macros by saving in Personal Macro Workbook.
0 / 0 / 0 Регистрация: 18.07.2011 Сообщений: 117 |
|
1 |
|
29.03.2007, 05:33. Показов 10807. Ответов 11
Доброго всем времени суток! Подскажите пожалуйста мастера VBA , что делаю не так и как надо правильно. Есть DialogSheet на нем три переключателя
0 |
971 / 353 / 135 Регистрация: 27.10.2006 Сообщений: 764 |
|
29.03.2007, 16:58 |
2 |
А что за изменение версии ? чего именно ?
0 |
weeper 0 / 0 / 0 Регистрация: 05.06.2012 Сообщений: 37 |
||||
29.03.2007, 17:56 |
3 |
|||
0 |
0 / 0 / 0 Регистрация: 18.07.2011 Сообщений: 117 |
|
29.03.2007, 20:44 [ТС] |
4 |
Номер версии, что-то типа версия файла. обычный счетчик.
0 |
0 / 0 / 0 Регистрация: 05.03.2007 Сообщений: 23 |
|
29.03.2007, 22:09 |
5 |
Есть такая штука как
0 |
Pavel55 971 / 353 / 135 Регистрация: 27.10.2006 Сообщений: 764 |
||||||||
29.03.2007, 22:50 |
6 |
|||||||
Ну и подводя итог, наш код, наверное будет выглядеть так
В модуле формы:
0 |
Perceff 0 / 0 / 0 Регистрация: 18.07.2011 Сообщений: 117 |
||||
30.03.2007, 01:02 [ТС] |
7 |
|||
спасибо за помощь, только происходит вот что:
С кодом который я приложил происходит следующее. Все работает, но только ОДИН раз, после каждого выполнения кода надо перезагружать Excel. Неработоспособность заключается в том что Excel перестает обрабатывать макросы в именно в этой книге. Имеется ввиду, что я вновь открываю книгу: макрос на открытие не выполняется, на закрытие тоже, просто закрывается книга без всяких предупреждений, даже не смотря на то что в коде стоит breakpoint (F9).
0 |
0 / 0 / 0 Регистрация: 05.03.2007 Сообщений: 23 |
|
30.03.2007, 13:59 |
8 |
Пардон я немного не правильно выразился
0 |
vkodor 0 / 0 / 0 Регистрация: 05.03.2007 Сообщений: 23 |
||||
30.03.2007, 14:08 |
9 |
|||
a помоему достаточно сделать следующее
P.S. Как тут сделать тег кода?
0 |
vkodor 0 / 0 / 0 Регистрация: 05.03.2007 Сообщений: 23 |
||||
30.03.2007, 14:25 |
10 |
|||
а для отмены нужно сделать следующее, я не знаю есть ли в DialogSheet свойство Tag, но наверняка есть (обычно оно везде есть) так вот смысл такой куда-то загнать метку и в Workbook_BeforeClose её проверить
0 |
0 / 0 / 0 Регистрация: 18.07.2011 Сообщений: 117 |
|
30.03.2007, 16:25 [ТС] |
11 |
Спасибо еще раз, все заработало ThisWorkbook.DialogSheets(1).Tag не работает, нашел выход : создал рядом с формой Labels, а в коде написал ThisWorkbook.DialogSheets(1).Labels(1).Text = 1. Для добавления кода в сообщения над окном ввода есть IFCode (не слева) жмем и выбираем Code.
0 |
0 / 0 / 0 Регистрация: 18.07.2011 Сообщений: 117 |
|
30.03.2007, 21:59 [ТС] |
12 |
И с нова я свопросом, есть в возможность в VBA посчитать произодительность выполнения кода с целью его оптимизации, по типу 1С например, а тоне понятно без наличия кода сохраняет файл быстро, а с ним медлено. Хотя вроде тормоза начинаются после его выполнения.
0 |