Vba excel события мыши

title keywords f1_keywords ms.prod ms.assetid ms.date ms.localizationpriority

MouseDown, MouseUp events

fm20.chm5224947

fm20.chm5224947

office

760c2492-4a33-8d17-eeef-e52da662d4c4

11/15/2018

medium

Occur when the user clicks a mouse button. MouseDown occurs when the user presses the mouse button; MouseUp occurs when the user releases the mouse button.

Syntax

For MultiPage, TabStrip
Private Subobject _MouseDown(indexAs Long,
ByValButtonAs fmButton,
ByValShiftAs fmShiftState,
ByValXAs Single,
ByValYAs Single) Private Subobject _MouseUp(indexAs Long,
ByValButtonAs fmButton,
ByValShiftAs fmShiftState,
ByValXAs Single,
ByValYAs Single)

For other controls
Private Subobject _MouseDown( ByValButtonAs fmButton,
ByValShiftAs fmShiftState,
ByValXAs Single,
ByValYAs Single) Private Subobject _MouseUp( ByValButtonAs fmButton,
ByValShiftAs fmShiftState,
ByValXAs Single,
ByValYAs Single)

The MouseDown and MouseUp event syntaxes have these parts:

Part Description
object Required. A valid object.
index Required. The index of the page or tab in a MultiPage or TabStrip with the specified event.
Button Required. An integer value that identifies which mouse button caused the event.
Shift Required. The state of SHIFT, CTRL, and ALT.
X, Y Required. The horizontal or vertical position, in points, from the left or top edge of the form, Frame, or Page.

Settings

The settings for Button are:

Constant Value Description
fmButtonLeft 1 The left button was pressed.
fmButtonRight 2 The right button was pressed.
fmButtonMiddle 4 The middle button was pressed.

The settings for Shift are:

Value Description
1 SHIFT was pressed.
2 CTRL was pressed.
3 SHIFT and CTRL were pressed.
4 ALT was pressed.
5 ALT and SHIFT were pressed.
6 ALT and CTRL were pressed.
7 ALT, SHIFT, and CTRL were pressed.

You can identify individual keyboard modifiers by using the following constants:

Constant Value Description
fmShiftMask 1 Mask to detect SHIFT.
fmCtrlMask 2 Mask to detect CTRL.
fmAltMask 4 Mask to detect ALT.

Remarks

For a MultiPage, the MouseDown event occurs when the user presses a mouse button over the control.

For a TabStrip, the index argument identifies the tab where the user clicked. An index of -1 indicates the user did not click a tab. For example, if there are no tabs in the upper-right corner of the control, clicking in the upper-right corner sets the index to -1.

For a form, the user can generate MouseDown and MouseUp events by pressing and releasing a mouse button in a blank area, record selector, or scroll bar on the form.

The sequence of mouse-related events is:

  1. MouseDown
  2. MouseUp
  3. Click
  4. DblClick
  5. MouseUp

MouseDown or MouseUp event procedures specify actions that occur when a mouse button is pressed or released. MouseDown and MouseUp events enable you to distinguish between the left, right, and middle mouse buttons. You can also write code for mouse-keyboard combinations that use the SHIFT, CTRL, and ALT keyboard modifiers.

If a mouse button is pressed while the pointer is over a form or control, that object «captures» the mouse and receives all mouse events up to and including the last MouseUp event. This implies that the X, Y mouse-pointer coordinates returned by a mouse event may not always be within the boundaries of the object that receives them.

If mouse buttons are pressed in succession, the object that captures the mouse receives all successive mouse events until all buttons are released.

Use the Shift argument to identify the state of SHIFT, CTRL, and ALT when the MouseDown or MouseUp event occurred. For example, if both CTRL and ALT are pressed, the value of Shift is 6.

See also

  • Microsoft Forms examples
  • Microsoft Forms reference
  • Microsoft Forms concepts

[!includeSupport and feedback]

На чтение 31 мин. Просмотров 19.4k.

Когда вы создаете или записываете макрос в Excel, вам нужно запустить макрос, чтобы выполнить шаги в коде.

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

Помимо этих запускаемых пользователем макросов, вы также можете использовать события VBA для запуска макроса.

Содержание

  1. События Excel VBA — Введение
  2. Различные типы событий Excel VBA
  3. Где поставить код, связанный с событием
  4. Понимание последовательности событий
  5. Понимание роли аргументов в событиях VBA
  6. События на уровне рабочей книги (поясняются примерами)
  7. События уровня рабочего листа (объясненные с примерами)
  8. Событие Excel VBA OnTime
  9. Событие Excel VBA OnKey
  10. Отключение событий в VBA
  11. Влияние событий Undo Stack

Позвольте мне сначала объяснить, что такое событие в VBA.

Событие — это действие, которое может инициировать выполнение указанного макроса.

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

В VBA есть много таких событий, и вы можете создавать коды для этих событий. Это означает, что как только происходит событие, и если вы указали код для этого события, этот код будет немедленно выполнен.

Excel автоматически сделает это, как только заметит, что событие произошло. Таким образом, вам нужно только написать код и поместить его в правильную подпрограмму события (это будет описано далее в этой статье).

Например, если вы вставляете новый лист и хотите, чтобы он имел префикс года, вы можете написать для него код.

Теперь, когда кто-нибудь вставляет новый лист, этот код будет автоматически выполняться и добавлять префикс года к имени листа.

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

Точно так же вы можете создавать коды VBA для многих таких событий (рассмотрим позже в этой статье).

Ниже приведена краткая картинка, показывающая событие двойного щелчка в действии. Как только я дважды щелкну по ячейке A1. Excel мгновенно открывает окно сообщения, в котором отображается адрес ячейки.

Двойной щелчок — это событие, а отображение окна сообщения — это то, что я указал в коде, когда происходит событие двойного щелчка.

Excel VBA Events Demo Double Click

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

Различные типы событий Excel VBA

В Excel есть разные объекты — например, сам Excel (к которому мы часто обращаемся как приложение), рабочие книги, рабочие таблицы, диаграммы и т.д.

Каждый из этих объектов может иметь различные события, связанные с ним. Например:

  • Если вы создаете новую книгу, это событие уровня приложения.
  • Если вы добавляете новый лист, это событие уровня книги.
  • Если вы измените значение в ячейке на листе, это событие уровня рабочего листа.

Ниже приведены различные типы событий, которые существуют в Excel:

  1. События уровня рабочего листа. Это типы событий, которые запускаются на основе действий, выполненных в рабочем листе. Примеры этих событий включают изменение ячейки на рабочем листе, изменение выделения, двойной щелчок по ячейке, щелчок правой кнопкой мыши по ячейке и т.д.
  2. События на уровне рабочей книги. Эти события будут инициироваться на основе действий на уровне рабочей книги. Примеры таких событий включают добавление новой рабочей таблицы, сохранение рабочей книги, открытие рабочей книги, печать части или всей рабочей книги и т.д.
  3. События уровня приложения: это события, которые происходят в приложении Excel. Примером этого может быть закрытие любой из открытых рабочих книг или открытие новой рабочей книги.
  4. События уровня пользовательской формы: эти события будут инициироваться на основе действий в пользовательской форме. Примеры этого включают инициализацию пользовательской формы или нажатие кнопки в пользовательской форме.
  5. События диаграммы: это события, относящиеся к листу диаграммы. Лист диаграммы отличается от рабочего листа. Примеры таких событий могут включать изменение серии диаграммы или изменение размера диаграммы.
  6. События OnTime и OnKey. Это два события, которые не соответствуют ни одной из перечисленных выше категорий. Поэтому я перечислил их отдельно. Событие «OnTime» позволяет вам выполнить код в определенное время или по истечении определенного времени. Событие «OnKey» позволяет выполнить код, когда используется определенное нажатие клавиши (или комбинация нажатий клавиш).

Где поставить код, связанный с событием

В приведенном выше разделе я рассмотрел различные типы событий.

В зависимости от типа события вам необходимо поместить код в соответствующий объект.

Например, если это событие, связанное с рабочим листом, оно должно идти в окне кода объекта рабочего листа. Если она связана с книгой, она должна идти в окне кода для объекта книги.

В VBA разные объекты — такие как Worksheets, Workbooks, Chart Sheets, UserForms и т.д. Имеют собственные окна кода. Вам необходимо поместить код события в окно кода соответствующего объекта. Например, если это событие уровня рабочей книги, вам нужно иметь код события в окне кода рабочей книги.

Следующие разделы охватывают места, где вы можете поместить код события:

В окне кода Worksheet

Когда вы откроете VB Editor (используя сочетание клавиш ALT + F11), вы заметите объект рабочих таблиц в Project Explorer. Для каждого листа в книге вы увидите один объект.

Excel VBA Events - Worksheets Objects

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

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

Для этого вам нужно сначала выбрать рабочий лист из выпадающего списка в левом верхнем углу окна кода.

Excel VBA Events - Selecting Worksheet Object from the drop down

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

List of Worksheet Events in VBA

Как только вы выберете событие, оно автоматически введет первую и последнюю строку кода для выбранного события. Теперь вы можете добавить свой код между двумя строками.

Your Code Goes Here is the Worksheet Events

Примечание. Как только вы выберете «Worksheet» в раскрывающемся списке, вы увидите две строки кода в окне кода. После того, как вы выбрали событие, для которого вы хотите код, вы можете удалить строки, которые появились по умолчанию.

Обратите внимание, что каждый лист имеет собственное окно кода. Когда вы вводите код для Лист1, он будет работать только в том случае, если событие происходит в Лист1.

В окне кода ThisWorkBook

Точно так же как рабочие листы, если у вас есть код события уровня книги, вы можете поместить его в окно кода ThisWorkbook.

Excel VBA Events - Workbook Objects

Когда вы дважды щелкните на ThisWorkbook, он откроет окно кода для него.

Вам нужно выбрать Workbook из выпадающего списка в верхнем левом углу окна кода.

Select Workbook Object from the drop down

После выбора Workbook из выпадающего списка вы получите список всех событий, связанных с Workbook. Вы можете выбрать тот, который вы хотите использовать, из выпадающего списка в правом верхнем углу окна кода.

List of Workbook Events in VBA

Как только вы выберете событие, оно автоматически введет первую и последнюю строку кода для выбранного события. Теперь вы можете добавить свой код между двумя строками.

Примечание. Как только вы выберете Workbook из выпадающего списка, вы увидите две строки кода в окне кода. После того, как вы выбрали событие, для которого вы хотите код, вы можете удалить строки, которые появились по умолчанию.

В окне кода Userform

Когда вы создаете пользовательские формы в Excel, вы также можете использовать события пользовательской формы для выполнения кодов на основе определенных действий. Например, вы можете указать код, который будет выполняться при нажатии кнопки.

Хотя объекты Sheet и ThisWorkbook уже доступны при открытии редактора VB, пользовательская форма — это то, что вам нужно создать в первую очередь.

Чтобы создать пользовательскую форму, щелкните правой кнопкой мыши любой из объектов, перейдите на вкладку «Вставка» и выберите «UserForm».

Inserting a Userform in Excel

Это вставит объект UserForm в книгу.

Userform inserted in Excel in the VB Editor

Если дважды щелкнуть пользовательскую форму (или любой объект, который вы добавляете в пользовательскую форму), откроется окно кода для пользовательской формы.

Теперь, так же как рабочие листы или ThisWorkbook, вы можете выбрать событие, и оно вставит первую и последнюю строку для этого события. И тогда вы можете добавить код в середине этого.

В окне кода Chart

В Excel вы также можете вставлять листы диаграмм (которые отличаются от листов). Лист диаграмм должен содержать только диаграммы.

Вставив лист диаграммы, вы сможете увидеть объект листа диаграммы в редакторе VB.

Вы можете добавить код события в окно кода листа диаграммы, как мы это делали на листе.

Дважды щелкните объект листа Chart в Project Explorer. Это откроет окно кода для листа диаграммы.

Обработка событий

Теперь вам нужно выбрать Chart из выпадающего списка в верхнем левом углу окна кода.

Excel VBA Events - Select Chart from the drop down

После выбора Chart из выпадающего списка вы получите список всех событий, связанных с листом Chart. Вы можете выбрать тот, который вы хотите использовать, из выпадающего списка в правом верхнем углу окна кода.

List of Chart Sheet Events in VBA

Примечание. Как только вы выберете Chart из выпадающего списка, вы заметите две строки кода в окне кода. После того, как вы выбрали событие, для которого вы хотите код, вы можете удалить строки, которые появились по умолчанию.

В Class Module

Class Module должны быть вставлены так же, как пользовательские формы.

Inserting a Class Module in Excel

Модуль класса может содержать код, связанный с приложением, которым может быть сам Excel и встроенные диаграммы.

Я расскажу о модуле класса в качестве отдельного учебного пособия в ближайшие недели.

Обратите внимание, что кроме событий OnTime и OnKey, ни одно из перечисленных выше событий не может быть сохранено в обычном модуле VBA.

Понимание последовательности событий

Когда вы запускаете событие, оно не происходит изолированно. Это также может привести к последовательности нескольких триггеров.

Например, когда вы вставляете новый лист, происходит следующее:

  1. Добавлен новый рабочий лист
  2. Предыдущая рабочая таблица деактивируется
  3. Новый лист активируется

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

Понимание роли аргументов в событиях 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

Теперь, как только вы откроете рабочую книгу с этим кодом, она покажет вам окно сообщения с указанным сообщением.

Workbook Event code example - show reminder

При работе с этим кодом (или с кодами событий рабочей книги в целом) необходимо знать несколько вещей:

  • Если в книге есть макрос, и вы хотите сохранить его, вам нужно сохранить его в формате .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 возможны два сценария:

  1. Вы сохраняете его в первый раз, и он покажет диалоговое окно Сохранить как.
  2. Вы уже сохранили его ранее, и он просто сохранит и перезапишет изменения в уже сохраненной версии.

Теперь давайте рассмотрим несколько примеров, где вы можете использовать событие 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

Другой пример этого события — когда вы хотите выделить активную строку и столбец выбранной ячейки.

Что-то, как показано ниже:

Excel VBA Events - Selection change event

Следующий код может сделать это:

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, вы можете использовать событие двойного щелчка, чтобы применить формат перечеркивания, чтобы пометить задачу как выполненную.

Как показано ниже:

Excel VBA Event - Double Click Event

Вот код, который сделает это:

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

Excel VBA tutorial and list of eventsOnce you’ve created a macro, you need a way to execute or call it. Otherwise, all of your work designing and coding the VBA application would’ve been in vain.

Within Excel, you have several different options for calling or running a VBA Sub procedure. In fact, in this Excel VBA tutorial alone, I explain 9 different ways in which you can execute a Sub procedure.

A very useful way of executing a macro is by telling Excel that a Sub procedure should be executed when a particular event occurs. As I explain below, knowing how to do this allows you to create VBA applications that are able to do things that would otherwise be impossible.

This blog post focuses on the topic of Excel VBA events. To be more precise:

In this tutorial, I provide all the information you need to understand what are Excel VBA events and how to start using them in your macros.

I also provide a complete list of Application events, workbook events, worksheet events, chart events, and non-object events. This Excel VBA Events Tutorial is accompanied by a Cheat Sheet with a shorter version of this list of VBA events. You can get immediate free access to this Cheat Sheet by subscribing to the Power Spreadsheets Newsletter.

The following table of contents lists the main topics I cover in this tutorial:

Let’s start by taking a look at…

What Are Excel VBA Events

In regular English, an event is something that happens.

You can, from a broad perspective, use the same definition for an event within Visual Basic for Applications. In other words, an Excel VBA event is something that happens while you’re working on Excel.

Events happen all the time while you’re working in Excel. As explained in both Excel Macros for Dummies and Excel 2016 Power Programming with VBA:

Everything that happens in Excel happens to an object through an event.

I provide a very detailed list of events below.

The concept of an Excel VBA event is relatively simple. Therefore, you might be wondering…

Why Are Excel VBA Events Useful

The main reason why you may find events useful is because you can create macros that are automatically executed when a certain event occurs. This allows you to, among other things:

  • Add interactivity to your Excel workbooks.
  • Improve user experience.
  • Perform activities that would otherwise (without VBA events) be impossible.

The Sub procedures that are automatically executed when a particular event occurs are usually known as event-handler procedures. Note that event-handler procedures are always Sub procedures. You generally don’t handle events with Function procedures.

Now that you understand what is an Excel VBA event, and why it’s useful, let’s start to check out the…

Main Categories Of Excel VBA Events

Most Excel experts classify Excel VBA events on the basis of which is the object of the event. In other words, they take into consideration the VBA object where the event occurs.

On the basis of this criteria, you can classify events in the following categories:

  • Application Events, which occur to the Excel Application itself.
  • Workbook Events, which happen when something happens to a workbook.
  • Worksheet Events, which are triggered whenever something happens to a worksheet.
  • Chart Events, which occur when something happens to a chart.
  • UserForm Events, which happen to a UserForm or an object within a UserForm.

    This VBA tutorial doesn’t cover the topic of UserForms or UserForm events. I may write about this in the future. If you want to receive an email whenever I publish new tutorials in Power Spreadsheets, please make sure to register for our Newsletter by entering your email address below:

  • Non-object Events, which aren’t associated with a particular object. These events work different from the previous categories. In fact, you access these events through VBA methods of the Application object.

Before we dig deeper into the events themselves, let’s see…

How To Create Event-Handler Procedures

In certain respects, the process of creating an event-handler procedure is the same that you would follow when crafting regular Sub procedures.

However, there are 2 characteristics that are particular to event-handler procedures and have a material effect on the way you should proceed:

  • Characteristic #1: As a general rule, event-handler procedures must be stored in the module that corresponds to the relevant object where the event happens.

    This is very important: Event-handler procedures generally don’t go in a standard module. As explained in Excel VBA Programming for Dummies, if you store an event-handler procedure in a standard module:

    #1: The procedure won’t be executed when the event occurs.

    #2: You won’t receive an error message.

    The exceptions to this rule are: (i) non-object events which go in a standard module, and (ii) Application and embedded Chart events which go in a Class Module.

    Even though you can only store event-handler procedures within certain modules, those event-handler procedures can still call other procedures that you store within other modules (including normal modules).

  • Characteristic #2: The structure of the names of event-handler procedures are generally composed of 3 items:

    Item #1: The relevant object.

    Item #2: An underscore (_).

    Item #3: The name of the event that triggers the Sub procedure.

    Furthermore, several event-handler procedures have arguments passed to the procedure. The names of the arguments vary depending on the particular case. You can find several examples of event-handler procedures that use arguments below.

Fortunately, you can easily handle both of these characteristics by following the steps I describe below. In the words of Excel guru John Walkenbach (in Excel VBA Programming for Dummies):

Writing these event-handlers is relatively straightforward after you understand how the process works.

Let’s take a look at the basics of this process:

Step #1: Go To The Appropriate Module

As a general rule, event-handler procedures must be stored within a particular module. In the following sections, I explain:

  • In which module should you store a particular event-handler procedure, depending on its characteristics.
  • How can you get to (or create) that module.

The sections below aren’t applicable to the non-object events (OnTime and OnKey) which I explain below. In those cases, you can store the relevant procedures within a normal module.

In the case of Application, Workbook, Worksheet and Chart events (which are the bulk of what I cover in this blog post), the following are the 2 rules you must consider to determine where to store your VBA code:

  • Rule #1: If you’re working with Workbook, Worksheet or Chart (for chart sheet) events, you use the code module of the corresponding object.
  • Rule #2: If you want to work with Application or Chart (for embedded charts) events, you use a Class Module.

Let’s start by taking a look at rule #1. In other words, let’s see…

How To Go To An Object Code Module: Usual Process

In most cases, you can easily get to the Code module you want to go to in the following 2 simple steps:

Step #1: Go To The Visual Basic Editor.

First, you must go to the Visual Basic Editor. You can easily do this in either of the following ways:

  • Select “Visual Basic” within the Developer Tab of the Ribbon.

    Excel Developer tab and Visual Basic button

  • Use the keyboard shortcut “Alt + F11”.

Step #2: Display The Code Of The Appropriate Module

Once you’re within the environment of the Visual Basic Editor, go to the Project Window. This is window is usually located on the upper-left side of the screen.

Project Window in VBE

Within the Project Window, each workbook or add-in that’s currently open appears as a separate project. In the screenshot above, there’s only 1 project (Book1.xlsx).

VBAProject in Project Window

Each project may contain several nodes. Regardless of the number of nodes, focus on the Microsoft Excel Objects node.

Microsoft Excel Objects in Project Window

The Microsoft Excel Objects node usually contains the following items:

  • Each worksheet within the relevant workbook.

    You should use the appropriate Sheet module for event-handler procedures that refer to a particular worksheet (worksheet events).

    Worksheet Module in Project Window

  • Each chart sheet within the workbook.

    Similar to worksheets, you use the relevant Chart module for event-handler procedures that refer to a certain chart sheet (chart events).

    Chart Module in Project Explorer

  • The workbook itself.

    You use the ThisWorkbook module for event-handler procedures that deal with the workbook (workbook events).

    ThisWorkbook Module in VBE

For these purposes, each separate worksheet and chart sheet is a separate object. In order to display the code of the specific module you want to work with, you can do either of the following:

  • Double-click on the object module.
  • Right-click on the object module and select “View Code”.

    For example, the following image shows how it looks like when I ask the VBE to display the code within ThisWorkbook.

ThisWorkbook and View Code in VBE

How To Go To A Worksheet Or Chart Sheet Code Module (Alternative)

In the case of sheets, you can also get to the relevant module in the following 2 easy steps:

  • Step #1: Right-click on the relevant worksheet or chart sheet.

    Excel sheet tabs

  • Step #2: Select “View Code” within the context menu that Excel displays.

    Context Menu and View Code

Now that you know how to get to the modules that correspond to workbooks, worksheets and chart sheets, let’s take a look at…

How To Create A Class Module For Dealing With Application Events

As I explain above, in order to work with Application and embedded Chart events, you must work with a Class Module. This section covers how to create a Class Module to work with Application events. The following section does the same thing for embedded Chart events.

In order to create a Class Module for purposes of dealing with Application events, you just need to follow these 7 easy steps:

  • Step #1: Go to the Visual Basic Editor by following the explanation I provide above.
  • Step #2: Insert a Class Module. You can do this by (i) right-clicking on the relevant VBA project within the Project Explorer window, (ii) selecting “Insert” and “Class Module”.

    VBAProject and Insert and Class Module

    Alternatively, you can insert a Class Module by going to the Insert menu of the VBE and selecting “Class Module”. If you want to work with keyboard shortcuts, you can use “Alt, I, C”.

    Insert and Class Module

  • Step #3: Assign a new name to the Class Module you just created. You can easily do this by typing the name you want in the (Name) field within the Properties Window of the VBE.

    Class Module Properties and (Name)

    For this particular example, I name the module “applicationClassModule”.

    New name of Application Class Module

  • Step #4: Use the WithEvents keyword to declare a Public Application object. The basic form of this statement is as follows:

    Public WithEvents applicationObjectName As Application

    For these purposes, applicationObjectName is the name of the declared Application object. In the example below, I use the name “applicationObject”.

    Public WithEvents applicationObject As Application

  • Step #5: If you’ve not inserted a regular VBA module yet, do this. You can insert a module by (i) right-clicking on the appropriate VBA Project, and (ii) selecting to Insert a Module.

    VBAProject and Insert and Module

    Alternatively, you can select “Module” from within the Insert menu or use the keyboard shortcut “Alt, I, M”.

    Insert and Module

  • Step #6: Declare a module-level object variable within the appropriate module. The module in which you declare the variable must be the one in which you store the Sub procedure to which I make reference in step #7 below.

    The purpose of this object variable is to refer to the Public Application object that you’ve declared in step #4 above. You can use a statement of the following form in order to do this declaration:

    Dim objectVariableName As New classModuleName

    For these purposes: (i) objectVariableName is the name you want to assign to the newly declared object variable, and (ii) classModuleName is the name of the Class Module you created in step #2 above. In the example below, classModuleName is “applicationClassModule” and objectVariableName “classApplication”. The variable is declared in a normal module.

    Dim classApplication As New applicationClassModule

  • Step #7: Connect the object variable you declared in step #6 with the Application object you declared in step #4. You do this by executing a Sub procedure that uses the following Set statement to make the appropriate assignment:

    Set objectVariableName.applicationObjectName = Application

    For these purposes: (i) objectVariableName is the name you assigned to the object variable in step #6, (ii) applicationObjectName is the name you assigned to the Application object in step #4. In the following example, objectVariableName is “classApplication” and applicationObjectName is “applicationObject”.

    Set classApplication.applicationObject = Application

    If this statement isn’t executed, the Application-level event-handler procedures won’t work appropriately.

    In the example above, I include the assignment statement within a macro stored in a regular VBA module. You can, however, include the Set statement is in the Workbook_Open Sub event-handler procedure. This procedure is triggered when the Workbook.Open event (the workbook is opened) occurs.

    Private Sub Workbook_Open code

    If you change the module in which you store the procedure that connects the object variable and Application object, remember to adjust the location of the object variable declaration made in step #6 above. In other words, make the object variable declaration in the same module.

If you want to create a Class Module for purposes of working with Chart events, the process is substantially similar to that above. However, since there are a couple of differences, let’s take a closer look at…

How To Create A Class Module For Dealing With (Embedded) Chart Events

The process of creating a Class Module for purposes of working with Chart events for embedded charts, is very similar to the one I describe above for Application events. In fact, as you’ll notice below, all of the steps are either identical or materially the same.

You can use a Class Module for purposes of working with both embedded charts and chart sheets.

The 5 easy steps you must follow to create such a Class Module are as follows.

  • Step #1: Follow steps #1, through #3 of the process I describe above for purposes of creating a Class Module. In other words:

    #1: Go to the Visual Basic Editor.

    #2: Create a Class Module.

    #3: Rename the Class Module.

    In this example, I create a Class Module named “embeddedChartClassModule”.

    Class Module for embedded Chart

  • Step #2: Declare a Public Chart object within the newly created Class Module by using the WithEvents keyword. In this particular case, the basic structure of the statement is as follows:

    Public WithEvents chartObjectName As Chart

    chartObjectName is the name you want to assign to the newly declared Chart object. In the example below, chartObjectName is “embeddedChartObject”.

    Public WithEvents embeddedChartObject As Chart

  • Step #3: If necessary, insert a regular VBA module, as I explain in step #5 of the process to create a Class Module to deal with Application events.
  • Step #4: Declare a module-level object variable within the module in which you’ll store the Sub procedure to which I refer to in step #5 below.

    This object variable makes reference to the Public Chart object you declared in step #2 above. The basic form of the statement you can use for the declaration is pretty much the same as that in step #6 of the process to create a Class Module when working with Application events.

    Dim objectVariableName As New classModuleName

    objectVariableName is the name of the newly declared object variable. classModuleName is the name of the Class Module you created in step #1 above. In the following example, objectVariableName is “classEmbeddedChart”. classModuleName is “embeddedChartClassModule”, which is the name I assigned to the ClassModule in step #1.

    Dim classEmbeddedChart As New embeddedChartClassModule

    In this particular case, I’m using the same regular module as I used when explaining how to create a Class Module to deal with Application events. This may help you notice the similarities between both statements.

  • Step #5: Connect the object variable you declared in step #4 and the Chart object you declared in step #2. You do this by executing a Sub procedure that uses the following Set statement to make an assignment:

    Set objectVariableName.chartObjectName = Chart

    objectVariableName is the name you assigned to the object variable in step #4 (classEmbeddedChart in the example below). chartObjectName is the name you assigned to the Chart object in step #2 (embeddedChartObject in this example). Chart is the relevant embedded Chart object.

    In the example below, Chart makes reference to Chart 1 (ChartObjects(“Chart 1”).Chart) within Sheet1 of the active workbook (Worksheets(“Sheet1”)). This statement uses the ChartObject.Chart property for purposes of returning the appropriate chart.

    Set classEmbeddedChart.embeddedChartObject = Worksheets.ChartObjects.Chart

    Just as is the case when working with Application events, the statement above must be executed in order for the embedded chart event-handler procedures to work appropriately. Therefore, you may want to include the statement within the Workbook_Open Sub procedure. In such case, my comments above (when discussing the same situation for Application events) are generally applicable.

As explained by Bill Jelen and Tracy Syrstad in Excel 2016 VBA and Macros, chart events are the same for both chart sheets and embedded charts. I include these events in the list that you can find below.

The main difference between an event-handler procedure that deals with chart sheets and an event-handler dealing with embedded charts is related to the Sub procedure name. More precisely:

  • When you’re dealing with a chart sheet, the name of the Sub procedure is generally of the following form:

    Chart_Event

    The following image shows how this looks like when working with the Chart.Activate event. Activate is the default event of the Chart object.

    Private Sub Chart_Activate

  • When you’re working with an embedded chart, the Sub procedure’s name usually uses the following structure:

    chartObjectName_Event

    chartObjectName is the name you assign to the Public Chart object you declared in the relevant Class Module (step #2 above). If we continue with the same example as above, the name of the Sub procedure corresponding to the Chart.Activate event (which I explain below) is as follows:

    Private Sub embeddedChartObject Activate

Step #2: Start Writing The Code For Your Event-Handler Procedure

Strictly speaking, once you’re within the appropriate Code module, you can simply start writing the VBA code for your event-handler procedure.

However, as I mention above, (i) the names of event-handler procedures must follow certain rules and (ii) sometimes you’ll have to deal with the appropriate arguments.

You may be able to memorize the appropriate declaration statement (including name and arguments) for certain events. However, learning all of these details for the large number of existing events isn’t efficient. In fact…

It isn’t really necessary.

As I show below, the Visual Basic Editor can help you create your event-handler procedures by entering the appropriate declaration statement. This guarantees that you’re always using the appropriate procedure name and arguments.

Getting this declaration statement right is very important. As explained by John Walkenbach in Excel VBA Programming for Dummies:

If you don’t get the name exactly right, the procedure won’t work.

Step #1: Select The Appropriate Object

At the top of the Code Window for a particular object there are 2 drop-downs. Their default labels are usually as follows:

  • (General).

    This is the Object drop-down list.

  • (Declarations).

    This is the Procedure drop-down list.

Object and Procedure drop-downs

Click on the Object drop-down menu and select the object you’re going to be working with. Within Object modules, there’s usually only 1 other option in addition to the default (General).

In other words:

  • If you’re in a workbook module, select “Workbook”.

    (General) and Workbook

  • If you’re in a worksheet module, select “Worksheet”,

    (General) and Worksheet

  • If you’re in a chart module, select “Chart”.

    (General) and Chart

Within Class Modules, you’ll have 3 options: (i) (General), (ii) (Class), and (iii) the public Application or Chart object that you declared within the module. In this case, you should select the Application or Chart object. For example, in the screenshot below, I select applicationObject. applicationObject is the name I assigned to the public Application object in step #1 of the process to create a Class Module to deal with Application events above.

(General) and applicationObject and Class

Once you’ve selected the appropriate object, the Visual Basic Editor includes the declaration and End statements for a particular Sub procedure. This Sub procedure is that corresponding to the default event of the applicable object. For example, in the screenshot below, my Visual Basic Editor has included the following statements:

  • Private Sub Workbook_Open().
  • End Sub

Private Sub Workbook_Open

These statements make reference to an event-handler procedure that deals with the Workbook.Open event. I explain this particular event below. Open is the default event of the Workbook object.

If you want to work with the event to which the VBA code proposed by the VBE responds to (Workbook.Open in this example), you can start crafting your Sub procedure as usual. In other words, you can proceed to step #4 below.

However, the event to which the code suggested by the Visual Basic Editor makes reference to (Open in the example above) may not be the one you want to work with. In these cases, proceed to…

Step #2: Select The Appropriate Event

Click on the Procedure drop-down on the right side of the screen. The expanded drop-down list shows the events that apply to the object that you’ve selected in step #1 above.

For example, the following screenshot shows the drop-down list of events corresponding to the Workbook object:

Event drop-down for Workbook object

You can scroll up or down as required. I provide a complete list of all the events that you can work with below.

From within this drop-down list, choose the event you want to work with. For example, in the case below, I select the Workbook.BeforeClose event.

Workbook.BeforeClose event in VBE

Once you’ve selected the appropriate event, the Visual Basic Editor automatically enters new declaration and End statements for the Sub procedure that corresponds to the object and event you’ve selected in the previous step #1 and this step #2.

In the example above, these statements are the following:

  • Private Sub Workbook_BeforeClose(Cancel As Boolean).
  • End Sub

Private Sub Workbook_BeforeClose

When entering the new declaration and End statements, the Visual Basic Editor doesn’t delete the previous suggestion.

Private Sub Workbook_Open

Therefore, to maintain a clean module, you may want to proceed to…

Step #3: Delete The Code For The Sub Procedure You Aren’t Creating

If you won’t be working with the event to which the suggestion made by the VBE in step #1 above made reference to (the default event for the chosen object), you can delete it.

In the example we’re looking at, I delete the declaration and End statements for the Private Sub Workbook_Open.

Workbook.BeforeClose event-handler procedure

Once you’ve completed the 3 steps above, you’re ready to move to…

Step #4: Code Your Sub Procedure

The statements of your VBA procedure go between the declaration and End statements that the Visual Basic Editor entered in the appropriate Object module or Class Module.

The following screenshot shows where this is for the Private Sub Workbook_BeforeClose.

Location of code in Private Sub Workbook_BeforeClose

Some event-handler procedures use arguments. For example, the Private Sub Workbook_BeforeClose procedure above uses one parameter called Cancel.

Cancel as Boolean

Your VBA code can work with these parameters. Usually, you can do either of the following within your event-handler procedure:

  • Use the data that is passed.
  • Change the value of the parameter.

    In particular, the Cancel parameter (in the example above) is a common event argument (as you’ll see below). Its default value is False, which indicates that the relevant event (closing the workbook in the example above) occurs. However, if your VBA code sets Cancel to True, the event (closing the workbook) is cancelled.

In the following sections, I provide a comprehensive list of Excel VBA events that will help you create your event-handler procedures. However, before we dig into that topic, it’s important to understand how I’ve organized this list.

List Of Excel VBA Events: Organization And Levels At Which You Can Monitor Events

In the following sections, I provide a comprehensive list of Excel VBA events. This list of events includes the following:

  • Application events.
  • Workbook events.
  • Worksheet events.
  • Chart events.

By my count, I’ve listed 115 events.

Explaining each event individually would make this VBA tutorial even longer. Therefore, I’ve grouped certain events into groups. The basic criteria I’ve used to group the events are the following:

  • Criterion #1: What triggers them.

    Generally, if a few events are triggered by the same action, I group them together.

  • Criterion #2: At what level (Application, workbook, worksheet or chart) can you monitor the occurrence of the event.

    Most of the events that I group together are triggered by the same action, but you can monitor them at different levels.

This VBA tutorial doesn’t focus on the topic of event sequencing. However, as you go through this list, please be aware that, as explained by Excel authorities Mike Alexander and Dick Kusleika in Excel 2016 Power Programming with VBA:

Some actions trigger multiple events.

In such case, the events occur in a particular sequence. This order may be relevant for certain of your event-handler procedures.

If you’re interested in learning more about which events fire when you do something in Excel, you can find applications that track which events are fire and in which sequence.

I may write further about the topic of event sequencing in future VBA tutorials. If you want to receive an email whenever I publish new material within Power Spreadsheets, please make sure to register for our Newsletter by entering your email address below:

Furthermore, some events that are substantially the same are available at different levels. An example of such group of events is composed of Application.SheetActivate, Workbook.SheetActivate, Worksheet.Activate and Chart.Activate (which I explain here). All of these events are triggered by the activation of an object. This object can be a sheet (both worksheet or chart) and, in the case of Chart.Activate, an embedded chart.

However, the scope at which these events are monitored varies:

  • The Application-level event (Application.SheetActivate) is triggered when any sheet in any workbook is activated. In other words, it monitors the event at the Excel Application level.
  • The Workbook-level event (Workbook.SheetActivate) occurs when any sheet within the relevant workbook is activated. In this case, the monitoring occurs at the workbook level.
  • The Worksheet and Chart-level events fire when the object itself (worksheet, chart sheet or embedded chart) is activated. Therefore, the monitoring happens at the worksheet or chart level.

I’ve organized this list in these groups for convenience purposes only. There are, certainly, other ways in which you could classify the events.

In fact, if you don’t agree with the way in which I’ve organized the list of VBA events, you can:

  1. Download the VBA Event Cheat Sheet by following the link above.
  2. Quickly convert the PDF file to Excel using one of the methods I explain here.
  3. Re-organize it to better suit your needs.

Now that this is clear, let’s start taking a look at the list of Excel VBA events:

Events Related To New Object Creation Or Deletion

Application.NewWorkbook

The Application.NewWorkbook event is triggered by the creation of a new workbook.

The event has a single parameter: Wb. Wb represents the newly created workbook.

Application.WorkbookNewSheet And Workbook.NewSheet

The NewSheet event is triggered whenever a new sheet (includes both worksheets and chart sheets) is created within a workbook.

NewSheet is available at the following levels:

  • Application: With the Application.WorkbookNewSheet event.
  • Workbook: With the Workbook.NewSheet event.

NewSheet has the following parameters:

  • Wb: The workbook where the new sheet is created.

    Wb is only relevant at the Application level (Application.WorkbookNewSheet).

  • Sh: Sh represents the newly created sheet.

Application.WorkbookNewChart And Workbook.NewChart

From a broad perspective, the NewChart event fires when you create a new chart in a workbook.

The NewChart event is available at the following levels:

  • Application: With the Application.WorkbookNewChart event.
  • Workbook: With the Workbook.NewChart event.

As a general rule, NewChart occurs when you either (i) insert or (ii) paste a new chart within a sheet. This includes both worksheets and chart sheets. However, the NewChart event doesn’t happen in the following 6 situations:

  • Case #1: When you move a chart (object or sheet) from one location to another.

    There’s, however, an exception to this rule. If you move a chart from a chart object to a chart sheet, the event occurs. This is because, in such cases, Excel actually must “create” a new chart.

  • Case #2: If you copy/paste a chart sheet.
  • Case #3: Changing the chart type.
  • Case #4: If you change the data source of a chart.
  • Case #5: When you undo or redo a chart insertion or pasting.
  • Case #6: Loading a workbook that contains charts.

If you insert or paste more than 1 new chart, the NewChart event occurs with respect to each of those charts. The order in which you insert the charts determines the order in which the NewChart event happens for each chart. In other words, in such cases, NewChart happens:

  • First for the chart that you inserted first.
  • Second for the chart that you inserted second.
  • Last for the chart you inserted last.

The NewChart event has the following arguments:

  • Wb: The workbook where the new chart is created.

    Wb is only applicable to the Application.WorkbookNewChart event. It isn’t relevant for the Workbook.NewChart event.

  • Ch: Ch is of the data type Chart. It represents the newly inserted chart.

Application.SheetBeforeDelete, Workbook.SheetBeforeDelete And Worksheet.BeforeDelete

The BeforeDelete event is triggered when a sheet is deleted.

BeforeDelete has the following versions:

  • Application Level: The Application.SheetBeforeDelete event.
  • Workbook Level: The Workbook.SheetBeforeDelete event.
  • Worksheet Level: The Worksheet.BeforeDelete event.

At the Application (Application.SheetBeforeDelete) and workbook levels (Workbook.SheetBeforeDelete), this event applies to any sheet. This includes both worksheets and chart sheets. In such cases, the only parameter is Sh. Sh is the deleted sheet.

Events Related To Opening, Closing, Printing And Saving

Application.WorkbookOpen And Workbook.Open

The Open event happens when a workbook is opened.

You can work with the following versions of the event:

  • Application Level: With the Application.WorkbookOpen event.
  • Workbook Level: Using the Workbook.Open event.

The Application.WorkbookOpen event has a single parameter: Wb. Wb is the opened workbook.

The Workbook.Open event has no arguments.

Application.WorkbookBeforeSave And Workbook.BeforeSave

The BeforeSave event is triggered before an open workbook is saved.

You can monitor the BeforeSave event at the following levels:

  • Application: With the Application.WorkbookBeforeSave event.
  • Workbook: Using the Workbook.BeforeSave event.

BeforeSave has the following parameters:

  • Wb: The saved workbook.

    Wb is only necessary for the Application.WorkbookBeforeSave event. It isn’t applicable to the Workbook.BeforeSave event.

  • SaveAsUI: A Boolean. It’s True if Excel must display the Save As dialog box due to the existence of unsaved workbook changes.
  • Cancel: A Boolean. By default, Cancel is False and the event occurs. You can set Cancel to True, in which case the workbook isn’t saved.

Application.WorkbookAfterSave And Workbook.AfterSave

The AfterSave event happens after a workbook is saved.

You can use the following versions of AfterSave:

  • Application Level: The Application.WorkbookAfterSave event.
  • Workbook Level: The Workbook.AfterSave event.

AfterSave has the following parameters:

  • Wb: The saved workbook.

    Wb is only relevant for the Application.WorkbookAfterSave event.

  • Success: Success returns True is the saving operation is successful. If the saving operation is unsuccessful, Success returns False.

Application.WorkbookBeforeClose And Workbook.BeforeClose

The rules that determine when the BeforeClose event happens are the following:

  • Rule #1: If you’ve made changes to the workbook since it was last saved, BeforeClose happens before you’re asked to save the changes.

    Dialog box: Want to save your changes to Book1?

    Understanding this rule #1 is important. If you click the Cancel button in the dialog box above, Excel cancels the process of closing the workbook.

    Want to save your changes to Book1 and Cancel

    However, by that point, the BeforeClose event has already been executed. This means, in effect, that the BeforeClose event can occur even without the workbook being actually closed.

  • Rule #2: Other than the above rule #1, the general rule is that BeforeClose occurs before the workbook closes.

You can monitor the BeforeClose event at the following levels:

  • Application: With the Application.WorkbookBeforeClose event.
  • Workbook: Using the Workbook.BeforeClose event.

The BeforeClose event has the following parameters

  • Wb: The closed workbook.

    This argument only applies to the Application-level event (Application.WorkbookBeforeClose).

  • Cancel: A Boolean with the following possibilities:

    False: This is the default value passed to the procedure. In such a case, the event occurs.

    True: You can set Cancel to True within the procedure. In such case, (i) the operation of closing the workbook stops, and (ii) the workbook continues to be open.

Application.WorkbookBeforePrint And Workbook.BeforePrint

The BeforePrint event occurs before anything within the workbook (including the workbook as a whole) is printed. As explained in Excel 2016 Power Programming with VBA, the BeforePrint event also occurs if you preview the printing.

You can use the following versions of BeforePrint:

  • Application Level: The Application.WorkbookBeforePrint event.
  • Workbook Level: The Workbook.BeforePrint event.

The BeforePrint event has the following arguments:

  • Wb: The printed workbook.

    Wb applies only to the Application.WorkbookBeforePrint event.

  • Cancel: The Cancel parameter of BeforePrint behaves in a very similar manner to the Cancel parameter of the BeforeClose event above. More precisely:

    False: Is the value passed to the procedure. The event occurs.

    True: If you sent Cancel to True within the procedure, there’s no printing operation.

Events Related To Object Activation, Selection, Resizing And Mouse Clicks

Application.WorkbookActivate And Workbook.Activate

The Activate event (for a workbook) is triggered when a workbook is activated.

You can monitor the Activate event at the following levels:

  • Application: Application.WorkbookActivate.
  • Workbook: Workbook.Activate event.

If you’re working at the Application level (with Application.WorkbookActivate), the event has a parameter: Wb. Wb is the activated workbook.

Application.SheetActivate, Workbook.SheetActivate, Worksheet.Activate And Chart.Activate

The Activate event (for a sheet or chart) is triggered whenever a sheet or chart is activated.

You can monitor this event at the following levels:

  • Application Level: Using the Application.SheetActivate event.
  • Workbook Level: Use the Workbook.SheetActivate event.
  • Worksheet Level: With the Worksheet.Activate event.
  • Chart Level: Using the Chart.Activate event.

The Application.SheetActivate and Workbook.SheetActivate events apply to any sheet and include both worksheets and chart sheets.

In addition to occurring when a chart sheet is activated, the Chart.Activate event also fires when an embedded chart is activated.

For the cases of Application.SheetActivate and Workbook.SheetActivate, the only parameter of the event is Sh. Sh represents the activated sheet.

Worksheet.Activate and Chart.Activate don’t have parameters.

Application.WorkbookDeactivate And Workbook.Deactivate

The Deactivate (for a workbook) event fires when the relevant workbook is deactivated.

You can use Deactivate at the following levels:

  • Application: With the Application.WorkbookDeactivate event.
  • Workbook: With the Workbook.Deactivate event.

Application.SheetDeactivate, Workbook.SheetDeactivate And Worksheet.Deactivate

The Deactivate (for a sheet or chart) event happens when a sheet or chart is deactivated.

The Deactivate event is available in the following versions:

  • Application Level: The Application.SheetDeactivate event.
  • Workbook Level: The Workbook.SheetDeactivate event.
  • Worksheet Level: The Worksheet.Deactivate event.
  • Chart Level: The Chart.Deactivate event.

Application.SheetDeactivate and Workbook.SheetDeactivate apply to both worksheets and chart sheets. Both of these events have a single parameter: Sh. Sh is the relevant sheet.

Application.WindowActivate, Workbook.WindowActivate, Application.WindowDeactivate And Workbook.WindowDeactivate

The WindowActivate event happens when the workbook window is activated.

The opposite of WindowActivate is WindowDeactivate. The WindowDeactivate event occurs when a workbook window is deactivated.

You can refer to both the WindowActivate and WindowActivate events at the following levels:

  • Application: Where the relevant events are Application.WindowActivate and Application.WindowDeactivate.
  • Workbook: In which case you work with the Workbook.WindowActivate and Workbook.WindowDeactivate events.

Both WindowActivate and WindowDeactivate have the following parameters:

  • Wb: The workbook that is displayed in the window that is activated or deactivated.

    The Wb parameter applies only to the Application-level events. That is, you only use Wb when working with Application.WindowActivate or Application.WindowDeactivate.

  • Wn: The window that is activated or deactivated.

Application.SheetSelectionChange, Workbook.SheetSelectionChange And Worksheet.SelectionChange

The SelectionChange event occurs when the selection (cell or object) changes.

You can work with the following versions of this event:

  • Application Level: The Application.SheetSelectionChange event.
  • Workbook Level: The Workbook.SheetSelectionChange event.
  • Worksheet Level: The Worksheet.SelectionChange event.

The Application.SheetSelectionChange and Workbook.SheetSelectionChange events don’t apply to selection changes in chart sheets.

SelectionChange has the following 1 or 2 parameters, depending on which version you’re using:

  • Sh: The worksheet containing the new selection.

    Sh is only relevant for the Application.SheetSelectionChange and Workbook.SheetSelectionChange event.

  • Target: The newly selected range.

Application.SheetBeforeDoubleClick, Workbook.SheetBeforeDoubleClick And Worksheet.BeforeDoubleClick

The BeforeDoubleClick event happens when a worksheet is double-clicked. However, the event doesn’t fire when you double-click the border of a cell.

You can use the following versions of the BeforeDoubleClick event:

  • Application: With the Application.SheetBeforeDoubleClick event.
  • Workbook: Using the Workbook.SheetBeforeDoubleClick event.
  • Worksheet: With the Worksheet.BeforeDoubleClick event.

The Application.SheetBeforeDoubleClick and Workbook.SheetBeforeDoubleClick events don’t apply to chart sheets.

The BeforeDoubleClick event occurs just before the action that’s usually triggered by the double-click. For example, when you double-click on a cell, you can edit directly in the cell. In such a situation, the sequence goes roughly as follows:

  • #1: You double-click on the cell.
  • #2: The BeforeDoubleClick event occurs.
  • #3: You can edit directly in the cell.

The BeforeDoubleClick event has the following parameters:

  • Sh: The relevant worksheet (a Worksheet object).

    This parameter is only applicable for the Application.SheetBeforeDoubleClick and Workbook.SheetBeforeDoubleClick events. The Worksheet.BeforeDoubleClick event doesn’t have a Sh parameter.

  • Target: A Range representing the “cell nearest to the mouse pointer” at the moment you double-click.
  • Cancel: A Boolean which, by default, is False (the event occurs). You can set the Cancel argument to True, in which case Excel doesn’t carry out the default double-click action (editing directly in the cell in the example above).

Chart.BeforeDoubleClick

The Chart.BeforeDoubleClick event fires when a chart element is double-clicked.

Just as the SheetBeforeDoubleClick and Worksheet.BeforeDoubleClick events above, Chart.BeforeDoubleClick:

  • Happens before the action that corresponds to the double-click by default.
  • Isn’t triggered if you double-click the border of a cell.

The Chart.BeforeDoubleClick event has the following 4 parameters:

  • Cancel: A Boolean whose default value is False (event occurs). If you set the Cancel argument to True, Excel doesn’t perform the default double-click action.
  • Arg1: Additional event information, which depends on the value of ElementID. You can find the different ElementIDs and their meanings below.
  • Arg2: Just as Arg1, Arg2 is additional event information that depends on ElementID’s value.
  • ElementID: The object that you or the user actually double-click.

    As I mention above, the value of ElementID is what “determines the expected values of Arg1 and Arg2”.

Let’s take a look at the different ElementIDs you’re likely to find, as well as the consequences of each of these ElementIDs for the values of the Arg1 and Arg2 parameters:

ElementID Group #1: xlAxis, xlAxisTitle, xlDisplayUnitLabel, xlMajorGridlines and xlMinorGridlines

This first group of ElementIDs is composed of the following IDs:

  • xlAxis.
  • xlAxisTitle.
  • xlDisplayUnitLabel.
  • xlMajorGridlines.
  • xlMinorGridlines

In all of these cases, the meaning of Arg1 and Arg2 is as follows:

  • Arg1: AxisIndex.

    AxisIndex can take either of 2 xlAxisGroup constants:

    xlPrimary (1), indicating that the axis is primary.

    xlSecondary (2), which indicates that the axis is secondary.

  • Arg2: AxisType.

    AxisType takes one of the following xlAxisType constants:

    xlCategory (1): Indicates that the axis displays categories.

    xlValue (2): Specifies an axis that displays values.

    xlSeriesAxis (3): Specifies that the axis displays data series.

ElementID Group #2: xlPivotChartDropZone

The meaning of Arg1 when the ElementID is xlPivotChartDropZone is DropZoneType. Arg2’s meaning is None.

DropZoneType specifies the drop zone type and can take the following values from the xlPivotFieldOrientation enumeration:

  • xlRowField (1): Row.

    Row specifies the Category field.

  • xlColumnField (2): Column.

    Column specifies the Series field.

  • xlPageField (3): Page.
  • xlDataField (4): Data.

ElementID Group #3: xlPivotChartFieldButton

When ElementID is xlPivotChartFieldButton, Arg1 and Arg2 have the following meanings:

  • Arg1: DropZoneType.

    I introduce DropZoneType in the previous section.

  • Arg2: PivotFieldIndex.

    PivotFieldIndex specifies the offset within the PivotFields collection for one of the following fields:

    #1: A specific Column (Series).

    #2: Specific Data.

    #3: A specific Page.

    #4: A specific Row (Category).

    The PivotFields object is a collection of all PivotField objects within a PivotTable report. The PivotField object represents a particular field within the PivotTable report.

ElementID Group #4: xlDownBars, xlDropLines, xlHiLoLines, xlRadarAxisLabels, xlSeriesLines and xlUpBars

This section covers the following ElementIDs:

  • xlDownBars.
  • xlDropLines.
  • xlHiLoLines.
  • xlRadarAxisLabels.
  • xlSeriesLines.
  • xlUpBars.

In any of such cases, the meaning of Arg1 is GroupIndex. Arg2’s meaning is None.

GroupIndex specifies the offset within the ChartsGroup collection for a particular chart group. The ChartGroups collection represents the series that are plotted in a particular chart and share the same format.

ElementID Group #5: xlChartArea, xlChartTitle, xlCorners, xlDataTable, xlFloor, xlLegend, xlNothing, xlPlotArea and xlWalls

This ElementID group is composed of the following:

  • xlChartArea.
  • xlChartTitle.
  • xlCorners.
  • xlDataTable.
  • xlFloor.
  • xlLegend.
  • xlNothing.
  • xlPlotArea.
  • xlWalls

In any of these cases, the meaning of both Arg1 and Arg2 is None.

ElementID Group #6: xlErrorBars, xlLegendEntry, xlLegendKey, xlXErrorBars and xlYErrorBars

ElementID Group #6 is composed of the following:

  • xlErrorBars.
  • xlLegendEntry.
  • xlLegendKey.
  • xlXErrorBars.
  • xlYErrorBars.

For these ElementIDs, Arg1 means SeriesIndex. SeriesIndex specifies the offset within the Series collection for a particular series. The Series collection contains all the series within a chart or chart group.

Arg2’s meaning is None.

ElementID Group #7: xlDataLabel and xlSeries

This section covers 2 ElementIDs:

  • xlDataLabel.
  • xlSeries

In both cases:

  • Arg1’s meaning is SeriesIndex.

    I introduce SeriesIndex in the previous section.

  • Arg2’s meaning is PointIndex.

    PointIndex specifies the offset within the Points collection for a particular point within a series. The Points collection contains all of the points within a chart series.

ElementID Group #8: xlTrendline

If ElementID is xlTrendline:

  • The meaning of Arg1 is SeriesIndex.

    I provide an introduction to SeriesIndex in the section covering ElementID group #6 above.

  • The meaning of Arg2 is TrendLineIndex.

    TrendlineIndex specifies the offset within the Trendlines collection for a particular trendline within a series. The Trendlines collection contains all of the trendlines for a particular chart series.

ElementID Group #9: xlShape

If ElementID is xlShape:

  • Arg1’s meaning is ShapeIndex.

    ShapeIndex specifies the offset within the Shapes collection” for a particular shape. The Shapes collection contains all the shapes within a particular sheet.

  • Arg2’s meaning is None.

Application.SheetBeforeRightClick, Workbook.SheetBeforeRightClick, Worksheet.BeforeRightClick And Chart.BeforeRightClick

The BeforeRightClick event is, to a certain extent, substantially similar to the previous BeforeDoubleClick event.

The main difference between BeforeRightClick and BeforeDoubleClick, as implied by their names, is on the way you click the mouse:

  • BeforeDoubleClick occurs when a worksheet is double-clicked.
  • BeforeRightClick happens (i) when a worksheet is right-clicked or (ii) in the case of the Chart.BeforeRightClick, when a chart element is right-clicked.

In other words, the BeforeRightClick event occurs (i) when a worksheet or chart element (for Chart.BeforeRightClick) is right-clicked, but (ii) before the default action that’s usually triggered by the right-click. For example, when you right-click on a cell, Excel generally displays a context menu.

Context menu in BeforeRightClick event

Therefore, if you’re working with the BeforeRightClick event and right-click on a cell, the sequence occurs as follows:

  • #1: You right-click.
  • #2: The BeforeRightClick event fires.
  • #3: Excel displays the contextual menu.

The RightClick event doesn’t fire if, when right-clicking, you place the mouse pointer on items such as a shape or command bar.

You can use the BeforeRightClick event at the following levels:

  • Application: Use the Application.SheetBeforeRightClick event.
  • Workbook: With the Workbook.SheetBeforeRightClick event.
  • Worksheet: Using the Worksheet.BeforeRightClick event.
  • Chart: Use the Chart.BeforeRightClick event.

Just as the SheetBeforeDoubleClick event above, Application.SheetBeforeRightClick and Workbook.SheetBeforeRightClick don’t apply to chart sheets.

BeforeRightClick has the same parameters as BeforeDoubleClick. More precisely:

  • Sh: The Worksheet object that represents the worksheet.

    Sh is an argument only when you’re working at the Application (Application.SheetBeforeRightClick) or workbook level (Workbook.SheetBeforeRightClick). The Worksheet.BeforeRightClick event doesn’t have a Sh parameter.

  • Target: The cell that is nearest to the mouse pointer when you right-click.
  • Cancel: A Boolean with a default value of False (event occurs). If you set Cancel to True, the default right-click action (displaying a context menu in the example above) doesn’t happen.

Chart.Select

The Chart.Select event occurs when an element of the chart is selected.

The Chart.Select event has the 3 following parameters:

  • ElementID: The chart element that is selected.
  • Arg1: Additional information that depends on the value of ElementID.
  • Arg2: Just as Arg1, additional event information dependent on the value of ElementID.

I provide a thorough description of ElementID, Arg1 and Arg2, as well as their relationship, in this section above.

Chart.MouseDown, Chart.MouseMove And Chart.MouseUp

The MouseDown, MouseMove and MouseUp events are all related to mouse movements over a chart. More precisely, these events are triggered when the following actions happen over a chart:

  • Chart.MouseDown: A mouse button is pressed.
  • Chart.MouseMove: The position of the mouse pointer changes.
  • Chart.MouseUp: The mouse button is released.

All of these events have the same 4 parameters:

  • Button: Indicates the mouse button that is pressed or released. It also indicates if no mouse button is pressed or released.

    The Button argument can be 1 of the 3 xlMouseButton constants:

    xlNoButton (0): No button.

    xlPrimaryButton (1): The primary mouse button. This is usually the left mouse button.

    xlSecondaryButton (2): The secondary mouse button. Usually, the right button is the secondary mouse button.

  • Shift: Indicates the state of the Shift, Ctrl and Alt keys. Shift can be one of (or a sum of) values.
  • x: The x coordinate of the mouse pointer. This is in chart object client coordinates.
  • y: The y coordinate of the mouse pointer. This, just as x, is in chart object client coordinates.

Application.WindowResize And Workbook.WindowResize

The WindowResize event fires when the workbook window is resized.

You can monitor the WindowResize event at the following levels:

  • Application: Application.WindowResize.
  • Workbook: Workbook.WindowResize.

WindowResize has the following parameters:

  • Wb: The workbook that is displayed within the resized window.

    Wb only applies to the Application.WindowResize event.

  • Wn: The resized window.

Chart.Resize

The Chart.Resize event is triggered when the relevant chart is resized.

In Excel 2016 VBA and Macros, authors Bill Jelen (Mr. Excel) and Tracy Syrstad explain that Chart.Resize doesn’t occur if the size is changed by using the controls within “the Chart Tools, Format tab or Format Chart area task pane”.

Events Related To Changes And Calculations

Application.AfterCalculate

The Application.AfterCalculate event fires once the following activities and conditions are met:

  • Condition #1: All refresh activity is completed. This includes both synchronous and asynchronous refresh activity.
  • Condition #2: All calculation activities are completed.
  • Condition #3: There aren’t any outstanding queries.

As a general rule, this event is the last calculation-related event to occur. What I mean is that it happens after the following:

  • Application.SheetCalculate, Workbook.SheetCalculate, Worksheet.Calculate and Chart.Calculate.
  • Application.SheetChange, Workbook.SheetChange and Worksheet.Change.
  • QueryTable.AfterRefresh.
  • The Application.CalculationState property is set to xlDone (meaning calculations are complete).

As a consequence of the above, the AfterCalculate event is commonly used to determine the moment in which all the data in a workbook has been completely updated by any applicable queries or calculations.

You can use the Applicaton.AfterCalculate event even if there’s no sheet data in the workbook.

Application.SheetCalculate, Workbook.SheetCalculate, Worksheet.Calculate And Chart.Calculate

You can work with the Calculate event at the following levels:

  • Application: With the Application.SheetCalculate event.
  • Workbook: With the Workbook.SheetCalculate event.
  • Worksheet: Using the Worksheet.Calculate event.
  • Chart: With the Chart.Calculate event.

The rules for triggering the event differ depending on the level you’re working at.

The Application.SheetCalculate and the Workbook.SheetCalculate events occur in the following 2 cases:

  • Case #1: Any worksheet is recalculated.
  • Case #2: Any changed or updated data is plotted on a chart.

The Worksheet.SheetCalculate event is triggered when the worksheet itself is recalculated.

The Chart.Calculate event fires when the relevant chart plots data that’s new or has changed.

At the Application (Application.SheetCalculate) and workbook levels (Workbook.SheetCalculate), the Sh parameter is used. Sh is the relevant chart or worksheet.

Application.SheetChange, Workbook.SheetChange And Worksheet.Change

The Change event fires when 1 or more cells in a worksheet are changed by either of the following:

  • The user.
  • A VBA Procedure.
  • An external link.

The Change event isn’t triggered by a recalculation. For those purposes, please refer to the Calculate event.

Further to the above, as explained in Excel 2016 Power Programming with VBA, the Change event may behave unexpectedly. More precisely:

Some actions that should trigger the event don’t, and other actions that shouldn’t trigger the event do!

For example:

  • The following actions trigger the Change event: (i) copying and pasting, or clearing, the formatting, (ii) deleting the contents of an empty cell, (iii) using the spell checker, (iv) doing a Find and Replace operation, (v) using AutoSum, or (vi) adding the Total Row to a table.
  • The following don’t trigger the Change event: (i) merging cells, (ii) adding, editing or deleting cell comments, (iii) sorting a range, or (iv) using Goal Seek.

You can monitor the Change event at the following levels:

  • Application: Using the Application.SheetChange event.
  • Workbook: With the Workbook.SheetChange event.
  • Worksheet: Use the Worksheet.Change event.

Application.SheetChange and Workbook.SheetChange don’t apply to chart sheets.

The SheetChange event has the following parameters:

  • Sh: The relevant worksheet.

    This parameter applies only at the Application (Application.SheetChange) and workbook levels (Workbook.SheetChange).

  • Target: The cell range that changes.

Events Related To Protected View Windows

Application.ProtectedViewWindowOpen

The Application.ProtectedViewWindowOpen event fires when an Excel workbook is opened within a Protected View window.

ProtectedViewWindowOpen has a single parameter: Pvw. Pvw represents the newly opened Protected View window.

Application.ProtectedViewWindowActivate And Application.ProtectedViewWindowDeactivate

The Application.ProtectedViewWindowActivate event fires when a Protected View window is activated.

The opposite event is Application.ProtectedViewWindowDeactivate. Application.ProtectedViewWindowDeactivate occurs when a Protected View window is deactivated.

The only parameter of both Application.ProtectedViewWindowActivate and Application.ProtectedViewWindowDeactivate is Pvw. Pvw is the activated or deactivated Protected View window.

Application.ProtectedViewWindowResize

The Application.ProtectedViewWindow event occurs when any Protected View window is resized.

The only argument of ProtectedViewWindowResize is Pvw. Pvw stands for the resized Protected View window.

Application.ProtectedViewWindowBeforeEdit

The Application.ProtectedViewWindowBeforeEdit event is triggered immediately before Excel enables editing on the workbook within a Protected View window.

ProtectedViewWindowBeforeEdit has the following 2 arguments:

  • Pvw: The Protected View window holding the workbook with enabled editing.
  • Cancel: A Boolean which is False by default (the event occurs).

    You can set the Cancel parameter to True. In such case, editing isn’t enabled on the applicable workbook.

Application.ProtectedViewWindowBeforeClose

The Application.ProtectedViewWindowBeforeClose event occurs immediately prior to the closure of either of the following:

  • A Protected View window.
  • A workbook in a Protected View window.

The ProtectedViewWindowBeforeClose event has the following 3 parameters:

  • Pvw: The relevant Protected View window.
  • Reason: A constant from the XlProtectedViewCloseReason enumeration that specifies how (the reason) the Protected View window is closed.

    Reason can take either of the following values:

    xlProtectedViewCloseEdit (1), which indicates that the user clicked on the Enable Editing button.

    xlProtectedViewCloseForced (2), indicating that Excel closed the Protected View window forcefully or stopped responding.

    xlProtectedViewCloseNormal (0), corresponding to the Protected View window being closed normally.

  • Cancel: A Boolean which is False by default. In such a case, the event occurs.

    You can set Cancel to True within the procedure. In such case, Excel doesn’t close the Protected View window.

Events Related To PivotTables

Application.SheetPivotTableAfterValueChange, Workbook.SheetPivotTableAfterValueChange And Worksheet.PivotTableAfterValueChange

The PivotTableAfterValueChange happens after one or more cells within a PivotTable are either:

  • Edited; or
  • If the cell (or range of cells) contains formulas, recalculated.

The PivotTableAfterValueChange event only happens in these 2 cases. Therefore, the event isn’t triggered by (among others) any of the following operations:

  • Operation #1: Refreshing the PivotTable.
  • Operation #2: Sorting the PivotTable.
  • Operation #3: Filtering the PivotTable.
  • Operation #4: Drilling down on the PivotTable.

These 4 operations may result in changes in the PivotTable. Examples of this are the potential movement of cells or the retrieving of new values from the data source. Despite these potential effects in the PivotTable, the event we’re looking at isn’t triggered.

You can work with the following versions of PivotTableAfterValueChange:

  • Application Level: Using the Application.SheetPivotTableAfterValueChange event.
  • Workbook Level: With the Workbook.SheetPivotTableAfterValueChange event.
  • Worksheet Level: Using the Worksheet.PivotTableAfterValueChange event.

PivotTableAfterValueChange has the following parameters:

  • Sh: The worksheet containing the PivotTable.

    The Sh parameter is only relevant if you’re working with Application.SheetPivotTableAfterValueChange or Workbook.SheetPivotTableAfterValueChange. It doesn’t apply to the Worksheet.PivotTableAfterValueChange event.

  • TargetPivotTable: The PivotTable containing the cell(s) that change(s).
  • TargetRange: The range within the PivotTable containing the edited/recalculated cells.

Workbook.SheetPivotTableChangeSync And Worksheet.PivotTableChangeSync

The PivotTableChangeSync event occurs after most changes to a PivotTable. Some of the changes that are covered by the SheetPivotTableChangeSync event are the following:

  • Clearing.
  • Grouping.
  • Refreshing.

PivotTableChangeSync is available at the workbook and worksheet level:

  • Workbook: With the Workbook.SheetPivotTableChangeSync event.
  • Worksheet: Using the Worksheet.PivotTableChangeSync event.

The PivotTableChangeSync event has 1 or 2 parameters, depending on whether you’re working at the workbook or the worksheet level. The possible arguments are as follows:

  • Sh: The worksheet containing the PivotTable.

    This argument is only for the Workbook.SheetPivotTableChangeSync event. It’s not applicable for the Worksheet.PivotTableChangeSync event.

  • Target: The PivotTable that changes.

Application.SheetPivotTableUpdate, Workbook.SheetPivotTableUpdate And Worksheet.PivotTableUpdate

The PivotTableUpdate event occurs after a PivotTable report is updated.

You can monitor the SheetPivotTableUpdate event at the Application, workbook and worksheet level:

  • Application: Using the Application.SheetPivotTableUpdate event.
  • Workbook: With the Workbook.SheetPivotTableUpdate event.
  • Worksheet: Using the Worksheet.PivotTableUpdate event.

PivotTableUpdate has the 1 or 2 parameters depending on whether you’re working with the workbook or worksheet version. There arguments are virtually the same as those of PivotTableChangeSync above:

  • Sh: The selected sheet.

    This applies only to the Application.SheetPivotTableUpdate and Workbook.SheetPivotTableUpdate events.

  • Target: The selected PivotTable.

Application.WorkbookPivotTableCloseConnection, Workbook.PivotTableCloseConnection, Application.WorkbookPivotTableOpenConnection And Workbook.PivotTableOpenConnection

Both of these events (PivotTableCloseConnection and PivotTableOpenConnection) are related to the status of the connection between a PivotTable report and its data source. More precisely:

  • PivotTableCloseConnection happens after a PivotTable report closes that connection.
  • PivotTableOpenConnection occurs after the PivotTable report opens the connection.

These events are available at the following levels:

  • Application: With the Application.WorkbookPivotTableCloseConnection and Application.WorkbookPivotTableOpenConnection events.
  • Workbook: Using the Workbook.PivotTableCloseConnection and the Workbook.PivotTableOpenConnection events.

PivotTableCloseConnection and PivotTableOpenConnection have the following parameters:

  • Wb: Wb is the relevant workbook.

    Wb is only applicable at the Application level. Therefore, it applies to the Application.WorkbookPivotTableCloseConnection and Application.WorkbookPivotTableOpenConnection events only.

  • Target: The chosen PivotTable report.

PivotTableBeforeAllocateChanges, PivotTableBeforeCommitChanges And PivotTableBeforeDiscardChanges

All of the following events deal with changes to PivotTables and, therefore, the PivotTableChangeList collection. I explain each of these events individually in the following sections.

However, in order to understand how each of these events works, it may help if you have a basic idea about the following VBA constructs:

PivotTableChangeList Collection, ValueChange Object And ValueChange.Order Property

The PivotTableChangeList collection represents all of the changes you’ve made to the value cells within a PivotTable report that is based on an OLAP data source.

Each of the individual changes is represented by a ValueChange object.

ValueChange contains several properties that specify the details about the change(s) you’ve made. One of these properties is ValueChange.Order.

The Order property of ValueChange returns a value indicating the order in which a particular change (represented by a ValueChange object) is performed relative to the other changes held within the PivotTableChangeList collection. Excel assigns the value held by the ValueChange.Order property automatically. As a general rule, the value assigned corresponds to the order in which you’ve applied the changes to the PivotTable report. However, if a single operation results in multiple changes, the value assignment within that set of changes is made arbitrarily.

With these in mind, let’s start taking a look at the events covered in this section:

Application.SheetPivotTableBeforeAllocateChanges, Workbook.SheetPivotTableBeforeAllocateChanges And Worksheet.PivotTableBeforeAllocateChanges

PivotTableBeforeAllocateChanges happens before changes are applied to a PivotTable. More precisely, SheetPivotTableBeforeAllocateChanges occurs in the following sequence:

  • #1: You (the user) chooses to apply changes to the PivotTable.
  • #2: The SheetPivotTableBeforeAllocateChanges event happens.
  • #3: Excel executes an UPDATE CUBE statement. This applies all the changes to the PivotTable.

The SheetPivotTableBeforeAllocateChanges event is available at the Application, workbook and worksheet levels:

  • Application: Application.SheetPivotTableBeforeAllocateChanges.
  • Workbook: Workbook.SheetPivotTableBeforeAllocateChanges.
  • Worksheet: Worksheet.PivotTableBeforeAllocateChanges.

PivotTableBeforeAllocateChanges has the following 5 arguments:

  • Sh: The worksheet with the PivotTable.

    This parameter is only relevant if you’re working with the Application.SheetPivotTableBeforeAllocateChanges or Workbook.SheetPivotTableBeforeAllocateChanges events. It doesn’t apply to the Worksheet.PivotTableBeforeAllocateChanges event.

  • TargetPivotTable: The PivotTable containing the changes that the UPDATE CUBE statement applies.
  • ValueChangeStart: The index to the first change within the applicable PivotTableChangeList collection. The index to this first change is specified by the ValueChange.Order property which I explain above.
  • ValueChangeEnd: The index to the last change within the relevant PivotTableChangeList collection. Just as with ValueChangeStart, the index is specified by the Order property of the ValueChange object within the collection.
  • Cancel: A Boolean that, by default is False. In such case, the event occurs.

    You can set Cancel to True within the relevant procedure. In such case: (i) changes aren’t applied, and (ii) edits are lost.

Application.SheetPivotTableBeforecommitChanges, Workbook.SheetPivotTableBeforeCommitChanges And Worksheet.PivotTableBeforeCommitChanges

The PivotTableBeforeCommitChanges occurs before changes are committed against the OLAP data source of a PivotTable. To be more precise, the relevant sequence is as follows:

  • #1: You choose to save changes for the PivotTable.
  • #2: The SheetPivotTableBeforeCommitChanges event occurs.
  • #3: Excel executes a COMMIT TRANSACTION against the OLAP data source.

You can work with the following versions of this event:

  • Application: The Application.SheetPivotTableBeforeCommitChanges event.
  • Workbook: The Workbook.SheetPivotTableBeforeCommitChanges event.
  • Worksheet: The Worksheet.PivotTableBeforeCommitChanges event.

The 5 parameters of PivotTableBeforeCommitChanges are virtually the same as those of PivotTableBeforeAllocateChanges above. Therefore, they’re as follows:

  • Sh: The worksheet containing the relevant PivotTable.

    Sh only applies when you’re working at the Application or workbook levels with Application.SheetPivotTableBeforeCommitChanges or Workbook.SheetPivotTableBeforeCommitChanges. It doesn’t apply to Worksheet.PivotTableBeforeCommitChanges.

  • TargetPivotTable: The PivotTable with the changes to commit.
  • ValueChangeStart: The index to the first change within the PivotTableChangeList collection. The index is specified by the Order property I introduce above.
  • ValueChangeEnd: The index to the last change within the PivotTableChangeList collection. This is also specified by the ValueChange.Order property.
  • Cancel: False by default (event occurs). If you set Cancel to True, the changes “aren’t committed against the OLAP data source”.

Application.SheetPivotTableBeforeDiscardChanges, Workbook.SheetPivotTableBeforeDiscardChanges And Worksheet.PivotTableBeforeDiscardChanges

The PivotTableBeforeDiscardChanges event is triggered before changes to a particular PivotTable are discarded. The sequence in which PivotTableBeforeDiscardChanges occurs is quite similar to that of the previous PivotTableBeforeAllocateChanges and PivotTableBeforeCommitChanges events. More precisely:

  • #1: You choose to discard changes.
  • #2: SheetPivotTableBeforeDiscardChanges occurs.
  • #3: Excel “executes a ROLLBACK TRANSACTION statement against the OLAP data source” if there’s an active transaction and the changed values are discarded.

You can work with the following versions of the PivotTableBeforeDiscardChanges event:

  • Application Lever: Using the Application.SheetPivotTableBeforeDiscardChanges event.
  • Workbook Level: With the Workbook.SheetPivotTableBeforeDiscardChanges event.
  • Worksheet Level: Using the Worksheet.PivotTableBeforeDiscardChanges event.

The PivotTableBeforeDiscard event has the following arguments. Notice that they’re substantially the similar to the equivalent parameters of the previously explained events:

  • Sh: The worksheet that contains the PivotTable.

    This parameter is only relevant for the Application.SheetPivotTableBeforediscardChanges and the Workbook.SheetPivotTableBeforeDiscardChanges events. It doesn’t apply to Worksheet.PivotTableBeforeDiscardChanges.

  • TargetPivotTable: The PivotTable with the discarded changes.
  • ValueChangeStart: The index to the first change within the PivotTableChangeList collection. This index is specified by the Order property, which I cover above.
  • ValueChangeEnd: The index to the last change within the PivotTableChangeList collection. Just as in the case of ValueChangeStart, the index is specified by the ValueChange.Order property.

Application.WorkbookRowsetComplete And Workbook.RowsetComplete

The RowsetComplete event may help if you work with OLAP PivotTables. More precisely, RowsetComplete occurs when either of the following actions is completed in connection with an OLAP PivotTable:

  • Action #1: Drill through a recordset.
  • Action #2: Calls the rowset action.

You can monitor the RowsetComplete event at the following levels:

  • Application: With the Application.WorkbookRowsetComplete event.
  • Workbook: With the Workbook.RowsetComplete event.

RowsetComplete isn’t available at the worksheet level. The reason for this is that (generally) the recordset is created on a separate sheet. As a consequence of this, the event needs to be at the workbook or Application level.

RowsetComplete has the following parameters:

  • Wb: The workbook for which the Application.WorkbookRowsetComplete event happens.

    This argument isn’t applicable to the Workbook.RowsetComplete event.

  • Description: A string that describes the event.
  • Sheet: The worksheet in which the relevant recordset is created.
  • Success: A Boolean indicating success or failure.

Events Related To Add-Ins: Application.WorkbookAddinInstall, Workbook.AddinInstall, Application.WorkbookAddinUninstall And Workbook.AddinUninstall

The AddinInstall event occurs when the relevant workbook is installed as an add-in.

The AddinUninstall event is the opposite. Therefore, it happens when the workbook is uninstalled as an add-in.

As explained by Bill Jelen (Mr. Excel) and Tracy Syrstad in Excel 2016 VBA and Macros:

  • The events make reference to installation and uninstallation of an add-in. The events aren’t triggered by the mere opening or closing of a workbook.
  • The AddinUninstall event doesn’t close the workbook automatically.

You can monitor both of these events at the following levels:

  • Application Level: With the Application.WorkbookAddinInstall and Application.WorkbookAddinUninstall events.
  • Workbook Level: With the Workbook.AddinInstall event and the Workbook.AddinUninstall event.

The Application-level events (Application.WorkbookAddinInstall and Application.WorkbookAddinUninstall) have a parameter: Wb. This argument represents the relevant (installed) workbook.

Events Related To The Excel Data Model

Application.WorkbookModelChange And Workbook.ModelChange

The ModelChange event is triggered after there’s a change to Excel’s data model.

You can use the following versions of the ModelChange event:

  • Application Level: Application.WorkbookModelChange.
  • Workbook Level: Workbook.ModelChange event.

The ModelChange event has the following arguments:

  • Wb: The relevant workbook.

    This argument is only relevant for the Application.WorkbookModelChange event.

  • Changes: Changes is a ModelChanges object.

    The ModelChanges object represents the changes made to the data model. In other words, ModelChanges has information about which are the changes (you can make several in a single operation) made to the data model when a model change (the ModelChange event) occurs.

Application.SheetTableUpdate, Workbook.SheetTableUpdate And Worksheet.TableUpdate

TableUpdate is triggered after a Query table that is connected to the data model is updated.

The TableUpdate event is available at the Application, workbook and worksheet levels:

  • Application: Using the Application.SheetTableUpdate event.
  • Workbook: With the Workbook.SheetTableUpdate event.
  • Worksheet: Using the Worksheet.TableUpdate event.

The TableUpdate event has the following parameters:

  • Sh: The relevant worksheet.

    You only need to consider Sh when working with Application.SheetTableUpdate or Workbook.SheetTableUpdate. It’s not applicable to Worksheet.TableUpdate.

  • Target: The relevant Query table with data from the data model.

Events Related To XML Data

Application.WorkbookAfterXmlExport, Workbook.AfterXmlExport, Application.WorkbookBeforeXmlExport And Workbook.BeforeXmlExport

The AfterXmlExport and BeforeXmlExport events are connected to either the (i) saving or (ii) exporting of XML data from the relevant workbook.

More precisely:

  • AfterXmlExport occurs after Excel either (i) saves or (ii) exports XML data from the relevant workbook.
  • BeforeXmlExport happens before Excel carries out either of these actions.

You can monitor these events at the following levels:

  • Application: With the Application.WorkbookAfterXmlExport and Application.WorkbookBeforeXmlExport events.
  • Workbook: With the Workbook.AfterXmlExport event and the Workbook.BeforeXmlExport event.

AfterXmlExport has the following parameters:

  • Wb: The relevant target workbook.

    Wb is only applicable to the Application.WorkbookAfterXmlExport event.

  • Map: The XML schema map used for the saving or exporting of the data. Map is of the data type XmlMap.
  • Url: The location of the exported XML file. You specify Url as a string.
  • Result: The result of the saving or exporting operation. This can be one of the 2 xlXmlExportResult constants:

    xlXmlExportSuccess (0): The operation was successful.

    xlXmlExportValidationFailed (1): The contents of the XML file don’t match the schema map.

BeforeXmlExport has the following parameters. Only the fourth parameter (Cancel in BeforeXmlExport vs. Result in AfterXmlExport) differs materially from the arguments of AfterXmlExport above:

  • Wb, which is only applicable for purposes of using the Application.WorkbookBeforeXmlExport event.
  • Map.
  • Url.
  • Cancel: A Boolean. The default value is False. If you set Cancel to True, the save or export operation is cancelled.

The BeforeXmlExport doesn’t happen when you’re saving to the XML Spreadsheet file format.

Application.WorkbookAfterXmlImport, Workbook.AfterXmlImport, Application.WorkbookBeforeXmlImport And Workbook.BeforeXmlImport

The AfterXmlImport and BeforeXmlImport events are related to either the (i) refreshment of existing XML data connections, or (ii) import of new XML data into the workbook. AfterXmlImport occurs after either of these. BeforeXmlImport is triggered before them.

These events are available at the following levels:

  • Application: With the Application.WorkbookAfterXmlImport event and the Application.WorkbookBeforeXmlImport event.
  • Workbook: With the Workbook.AfterXmlImport event and the Workbook.BeforeXmlImport event.

Similar to what occurs with the previous events (AfterXmlExport and BeforeXmlExport), AfterXmlImport has the following parameters:

  • Wb: The relevant workbook.

    Wb is only applicable to the Application.WorkbookAfterXmlImport event. It’s not an argument of the Workbook.AfterXmlImport event.

  • Map: The XML map used for the import of data. As I explain above, Map is of the data type XmlMap.
  • IsRefresh: A Boolean making reference to the way in which the AfterXmlImport event is triggered. More precisely:

    If the AfterXmlImport event is triggered because an existing connection to XML data is refreshed, IsRefresh is True.

    If the event is triggered due to the data being imported from a different data source, IsRefresh is False.

  • Result: Just as in the case of the AfterXmlExport event, Result indicates the result of the operation. However, in the case of AfterXmlImport, the relevant operation is a refresh or import. In this case, Result can be one of the 3 xlXmlImportResult constants:

    #1: xlXmlImportSuccess (0): The XML data file import was successful.

    #2: xlXmlImportElementsTruncated (1): The XML data file is too large for the relevant worksheet. Therefore, the contents of the XML data file are truncated.

    #3: xlXmlImportValidationFailed (2): The contents of the XML data file don’t match the relevant schema map.

BeforeXmlImport, on the other hand, has the following arguments. 2 of those arguments (Map and Refresh) are substantially similar to those of the AfterXmlImport event. The other parameters (Wb, Url and Cancel) are quite similar to the relevant parameters of BeforeXmlExport above.

  • Wb: The workbook. This argument is only relevant for the Application.WorkbookBeforeXmlImport event.
  • Map.
  • Url: The location of the exported XML file. Just as in the case of AfterXmlExport and BeforeXmlExport, you specify Url as a string.
  • IsRefresh.
  • Cancel: A Boolean which you can set to True in order to cancel the import/refresh operation.

Other Events

Application.SheetFollowHyperlink, Workbook.SheetFollowHyperlink And Worksheet.FollowHyperlink

The FollowHyperlink event is triggered whenever you click a hyperlink.

You have access to the FollowHyperlink event at the following levels:

  • Application: Using the Application.SheetFollowHyperlink event.
  • Workbook: With the Workbook.SheetFollowHyperlink event.
  • Worksheet: Using the Worksheet.FollowHyperlink event.

FollowHyperlink has the following arguments:

  • Sh: The Worksheet object where the hyperlink is.

    Sh is only applicable to the Application.SheetFollowHyperlink and Workbook.SheetFollowHyperlink events. It doesn’t apply at the worksheet level with Worksheet.FollowHyperlink.

  • Target: The relevant Hyperlink object.

Application.SheetLensGalleryRenderComplete, Workbook.SheetLensGalleryRenderComplete And Worksheet.LensGalleryRenderComplete

As explained in Excel 2016 VBA and Macros, the LensGalleryRenderComplete event fires when you select the Quick Analysis Tool.

You can use the following versions of LensGalleryRenderComplete:

  • Application: The Application.SheetLensGalleryRenderComplete event.
  • Workbook: The Workbook.SheetLensGalleryRenderComplete event.
  • Worksheet: Worksheet.LensGalleryRenderComplete.

At the Application (Application.SheetLensGalleryRenderComplete) and workbook (Workbook.SheetLensGalleryRenderComplete) levels, the only parameter of the event is Sh. Sh is a Worksheet object.

Non-Object Events

There are 2 events that aren’t associated with a certain object from within Excel’s object model. You access both of the following events through methods of the Application object.

As explained by John Walkenbach in Excel VBA Programming for Dummies:

Because time and keypresses aren’t associated with a particular object such as a workbook or a worksheet, you program these events in a normal VBA module.

Application.OnTime

You can use the Application.OnTime method for purposes of specifying that a particular procedure runs at a certain time in the future. You can specify the time either of the following ways:

  • As a specific time of the day.
  • As a time occurring after a certain amount of time passes.

The basic syntax of Application.OnTime is as follows:

expression.OnTime(EarliestTime, Procedure, LatestTime, Schedule)

The following are the 4 parameters of this method:

  • EarliestTime: A required argument. You use it to specify the time where you want the procedure to be executed. The value you provide is rounded to the nearest second.
  • Procedure: A required parameter that you use to specify (as a String) the name of the procedure that should run at EarliestTime.
  • LatestTime: An optional parameter. You can use LatestTime to specify the latest time at which the procedure can be executed. If you specify LatestTime and, by that time, Excel isn’t ready to execute the procedure, the procedure doesn’t run at all.

    If you omit LatestTime, Excel simply waits as long as necessary until it can execute the procedure.

  • Schedule: Another optional parameter that can take the values of True and False. Schedule allows you to determine whether to (i) schedule a new procedure (True), or (ii) clear a previously set OnTime procedure (False). This may be relevant if you need to clear “a procedure previously set with the same Procedure and EarliestTime values”.

    Schedule’s default value is False, which clears a previously set procedure.

As explained by Excel guru John Walkenbach in Excel VBA Programming for Dummies, “the OnTime event persists even after the workbook is closed” if you leave Excel open. Therefore, make sure that you set up the appropriate VBA code to clear as necessary. You can do this by, for example, setting up a procedure that:

  • #1: Is triggered when the BeforeClose event occurs.
  • #2: Sets the Schedule parameter of the Application.OnTime method to False.

Application.OnKey

The Application.OnKey method allows you to specify a key or key combination that, when pressed, executes a particular procedure.

The OnKey method works because Excel is always monitoring the keys you press. This allows you to set up the equivalent of a keyboard shortcut: a particular key or key combination executes a procedure.

As explained by Excel authorities Mike Alexander and Dick Kusleika in Excel 2016 Power Programming with VBA, there are 2 cases that are an exception to the rule above. In the following situations, Excel doesn’t apply the OnKey method:

  • If you’re entering a formula.
  • If you’re working with a dialog box.

Even though, strictly speaking, you can use Application.OnKey for purposes of creating a keyboard shortcut for your macros, that’s not the most appropriate way to proceed. In order to assign a keyboard shortcut to execute a Sub procedure, you should generally rely on Excel’s built-in tools. These are the Record Macro dialog (if you’re using the macro recorder) or the Macro dialog box.

The syntax of Application.OnKey is as follows:

expression.OnKey(Key, Procedure)

The OnKey method has the 2 following parameters:

  • Key: The key or key combination that triggers the procedure execution.

    You specify Key as a string. I explain the main rules you must consider for purposes of specifying Key below.

  • Procedure: The procedure that Excel should run when you press Key. There are a couple of special cases that you should consider:

    Case #1: If you specify Procedure as empty text (“”), Excel doesn’t do anything when Key is pressed. Specifying Procedure as empty text, then, has the consequence of disabling the keystroke or keystroke combination you specify as Key. In other words, Excel simply ignores that you pressed the key or key combination.

    Case #2: If you omit Procedure, (i) any previous assignments done with OnKey are cleared, and (ii) the keystroke combination specified as Key returns to its default meaning.

Key can be (i) a single key combined with Alt, Ctrl or Shift, or (ii) a combination of these keys. The following are the main rules you should consider when specifying Key:

  • Rule #1: Every key is represented by a particular character or group of characters.
  • Rule #2: Numbers, letters and other characters that are displayed upon you pressing the relevant key, are specified by that key.

    For example, in order to specify the letter a, you include “a” in your code.

  • Rule #3: In order to specify characters that aren’t displayed when you press a key (for example Backspace, Delete or Esc), you use the codes that appear in the following table:
    Key OnKey Code
    Backspace {BACKSPACE} or {BS}
    Break {BREAK}
    Caps Lock {CAPSLOCK}
    Clear {CLEAR}
    Delete or Del {DELETE} or {DEL}
    Down Arrow {DOWN}
    End {END}
    Enter {ENTER} (numeric keypad) or ~ (tilde)
    Esc {ESCAPE} or {ESC}
    Help {HELP}
    Home {HOME}
    Ins {INSERT}
    Left Arrow {LEFT}
    Num Lock {NUMLOCK}
    Page Down {PGDN}
    Page Up {PGUP}
    Return {RETURN}
    Right Arrow {RIGHT}
    Scroll Lock {SCROLLLOCK}
    Tab {TAB}
    Up Arrow {UP}
    F1 through F15 {F1} through {F15}
  • Rule #4: If you want to specify a combination of a key with (i) Shift, (ii) Ctrl or (iii) Alt, use the following codes:
    Key OnKey Code
    Shift + (plus)
    Ctrl ^ (caret)
    Alt % (percent)
  • Rule #5: In order to specify some characters whose keys have special meanings, you must surround them with curly braces ({ }). Some of the keys falling within the scope of this rule #5 are plus (+), caret (^), parentheses (( )), tilde (~), brackets ([ ]) and curly braces themselves ({ }).

Similar to the previously explained Application.OnTime method, Application.OnKey doesn’t reset when you close the workbook and leave Excel open. Therefore, it’s also important that you set up the appropriate code to clear the assignments done with OnKey. You can do this by creating a procedure that:

  • #1: Is launched upon the BeforeClose event occurring.
  • #2: Omits the Procedure argument of Application.OnKey.

Deprecated Or Non-Functional Events

There are some events that have been deprecated and/or are non-functional. Microsoft keeps them within the object model for purposes of backward compatibility. Generally, you should avoid using this events within your VBA applications.

The following are these deprecated/non-functional events:

  • Application.WorkbookSync and Workbook.Sync.
  • Chart.SeriesChange.

Why An Event-Handler Procedure Isn’t Automatically Executed And Possible Solutions

Once you’ve created an event-handler procedure, you probably want to ensure that Excel runs the macro when the relevant event happens.

There are a few reasons why an event-handler procedure isn’t triggered when you expect it to. However, in my experience, one of the most common reasons why a particular event-handler procedure isn’t executed when expected is that macros aren’t enabled.

I cover the topic of enabling macros in the Complete Guide On How To Enable Macros In Excel. In that blog post, I cover topics such as the following:

  • How to change your macro security settings in order to enable macros by default.
  • How to enable macros for certain Excel files.
  • How to enable macros for a single time.

Event-handler procedures may also fail to execute if events are disabled. Events are, by default, enabled. However, you can control whether events are enabled or disabled through the Application.EnableEvents property.

More precisely, the following VBA statements allow you to enable or disable events:

  • To enable events, set the EnableEvents property to True.

    Application.EnableEvents = True

  • To disable events, set Application.EnableEvents to False.

    Application.EnableEvents = False

Note that, since EnableEvents is a property of the Application object, it applies to all Excel workbooks.

There are some legitimate reasons why you would want to disable events in certain circumstances. As explained in Excel 2016 Power Programming with VBA:

One common reason is to prevent an infinite loop of cascading events.

An infinite loop of cascading events may occur if, for example, in the following situation:

  • Step #1: You set up an event-handler procedure that is triggered by a particular event (let’s call it “X”).
  • Step #2: X occurs and, therefore, Excel executes the event-handler procedure.
  • Step #3: The event-handler procedure itself causes changes that result in event X occurring again.
  • Step #4: Since X occurs again, Excel executes the event-handler procedure again.
  • Step #5: Step #3 occurs again.

Such a loop looks roughly as follows:

Diagram for infinite loop of recursive events

There are several ways in which you can avoid the problem of potential infinite loops of cascading events. The following is a common suggestion:

  1. Disable events at the beginning of your event-handler Sub procedure.
  2. Re-enable events just before the end of the event-handler procedure.

You disable and re-enable events using the statements I explain above.

There are other ways in which you can deal with the potential problem of infinite loops of recursive events. The following are 2 examples:

  1. Using a global variable. Although this isn’t a great programming practice.
  2. Using a Boolean variable within the Class Module containing the relevant events.

Conclusion

After reading this tutorial, you’re ready to start using Excel VBA events within your macros.

In addition to knowing what are VBA events and why are they useful, you have a thorough knowledge of the most relevant events. For example, you’re aware of:

  • The differences between Application, workbook, worksheet and chart events.
  • How to create event-handler procedures for all of these events.
  • What are the main events at the Application, workbook, worksheet and chart level to which your VBA applications can respond to.

    This Excel VBA Events Tutorial is accompanied by a Cheat Sheet. You can get immediate free access to this Cheat Sheet by subscribing to the Power Spreadsheets Newsletter.

  • What are the Application.OnTime and Application.OnKey methods, and how you can use them.

You also know what are the most common reasons explaining why an event-handler procedure isn’t triggered when the corresponding event occurs, and how you can address some of these problems.

Books Referenced In This Excel VBA Tutorial

  • Alexander, Michael (2015). Excel Macros for Dummies. Hoboken, NJ: John Wiley & Sons Inc.
  • Alexander, Michael and Kusleika, Dick (2016). Excel 2016 Power Programming with VBA. Indianapolis, IN: John Wiley & Sons Inc.
  • Jelen, Bill and Syrstad, Tracy (2015). Excel 2016 VBA and Macros. United States of America: Pearson Education, Inc.
  • Walkenbach, John (2015). Excel VBA Programming for Dummies. Hoboken, NJ: John Wiley & Sons Inc.

Пособие-самоучитель
on-line

«Visual Basic с нуля»

Глава
14. События мыши. Работа с мышью. Рисование фигур программными методами.
Методы Line и Circle.

Скачать
исходник программы Mouse

Дата
создания 08.02.2005 {Автор 4us}

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

События.

Прежде всего хочу сказать, что ранее, при создании процедуры объекта
мы довольствовались тем событием, которое нам предоставлял VB по умолчанию.
Например для формы — это загрузка Form1_Load(), для кнопки — щелчок мыши
Command1_Click и так далее. Однако для почти каждого объекта есть довольно-таки
большой список и других доступных событий, которые можно посмотреть в правом
поле вверху окна кода. То есть, если мы создали процедуру для формы, реагирующую
на загрузку формы Form_Load, то щелкнув по полю, где находится надпись
Load, мы в выпавшем списке видим еще массу событий и с каждым мы можем создать
свою процедуру, например Form_Click, или там Form_MouseMove.
По-сути событие — это машинное прерывание, вызванное пользователем, другой программой
или системой или еще чем-нибудь. Таким образом, выполнение процедуры для объекта
начинается когда наступает событие этой процедуры.
Почему мы программный код обычно начинаем с процедуры Form_Load? Потому-что
при загрузке программы наша форма автоматически загружается, и хочешь-нехочешь,
наступает событие Load, начинается выполнение процедуры Form_Load,
в которой поэтому удобно выполнять предварительные действия по подготовке программы
к работе: загрузка служебных файлов, установка свойств объектов, присвоение
начальных значений переменным и т.п. А уж далее, либо из этой процедуры происходит
переход к другим процедурам, либо программа ожидает наступления других событий
для объектов, под которые должны быть написаны свои процедуры. Те же процедуры,
которые мы писали сами, обзывали, как хотели, не будут выполнятся никогда, пока
мы конкретно не вызовем их по имени. Эти процедуры ни с объектом, ни с событием
никак не связаны.

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


Private
Sub объект_MouseMove ([индекс As Integer,] клавиша As Integer,
shift As Integer, x As Single, y As Single)

Возникает при перемешении мыши над объектом.
По значению необязательной переменной индекс можно отследить, над
каким элементом массива объектов Control Array (если массив существует)
происходит перемещение.
Переменная клавиша указывает состояние всех клавиш мыши, а не указывает
на какую-нибудь одну, как при событиях _MouseDown или _MouseUp.
Поэтому значения клавиш (1-левая, 2 — правая, 4 — средняя, 0 — никакая)
складываются (1+2=3 нажаты левая и правая клавиши мыши одновременно).
Переменная shift возвращает состояние кнопок shift, alt и ctrl в
момент нажатия клавиш мыши (1- shift, 2- alt и 4 — ctrl). При удержании
больше одной кнопки их значения складываются (ctrl-alt = 4+2=6).
Значения переменных x и y возвращают текущие координаты курсора
мыши (x — по-горизонтали, y — по-вертикали) в единицах измерения, заданных
свойствами ScaleHeight, ScaleWidth.

Private Sub объект_MouseDown
([индекс As Integer,] клавиша As Integer, shift As
Integer, x As Single, y As Single)

и
Private Sub объект_MouseUp
([индекс As Integer,] клавиша As Integer, shift As
Integer, x As Single, y As Single)

Возникает при нажатии (_MouseDown) или
отпускании (_MouseUp) клавиши мыши, при нахождении курсора мыши над
объектом.
При этом по значению необязательной переменной индекс можно отследить,
над каким элементом массива объектов Control Array (если массив существует)
нажата клавиша.
Также позволяет отследить, какая клавиша мыши нажата (не показывает состояние
всех клавиш одновременно, как событие _MouseMove), по состоянию переменной
кнопка (1- левая клавиша, 2 — правая клавиша, 4 — средняя клавиша).

Переменная shift возвращает состояние кнопок shift, alt и ctrl в
момент нажатия клавиш мыши (1- shift, 2- alt и 4 — ctrl). При удержании
больше одной кнопки их значения складываются (ctrl-alt = 4+2=6).
Значения переменных x и y возвращают текущие координаты курсора
мыши (x — по-горизонтали, y — по-вертикали) в единицах измерения, заданных
свойствами ScaleHeight, ScaleWidth.

Private
Sub объект_Click()
Возникает при щелчке левой или правой клавиши
мыши, при нахождении курсора мыши над объектом.
Объекты CheckBox, CommandButton, Listbox или OptionButton
реагируют только на щелчок левой клавиши. Кроме того, если у нас существует
массив объектов Control Array (см. Главу 13), то введя переменную индекс
в объявление процедуры, можно определить, по какому элементу массива щелкнула
мышь. В этом случае объявлять процедуру надо так:
Private Sub объект_Click
(индекс As Integer)
.

Индекс

и возвратит номер элемента массива.
Вот пример кода, когда на форме имеется массив Control Array из трех текстбоксов
Text1(0), Text1(1) и Text1(2) и текстбокс Text2. При щелчке мышью по одному
из элементов Text1 в текстбокс Text2 будет выводится индекс элемента Control
Array.
Private
Sub
Text1_Click(Nomer As Integer)
Text2.Text = «Щелкнуто по номеру» & » » &
Nomer
End Sub
При возникновении этого события порождаются события
MouseUp и MouseDown.
Чтобы различать нажатия клавиш, надо использовать события MouseUp
и MouseDown.


Private
Sub объект_DblClick()
Возникает при двойном щелчке клавиши мыши, при нахождении
курсора мыши над объектом.
Private Sub объект_DblClick
(индекс As Integer)
.
Аналогичен событию _Click.

Тут надо помнить один очень важный момент. Порядок наступления
событий различен для различных элементов. Нужно следить, чтобы события (время
их наступления) не противоречили друг другу. Если написать две процедуры, одну
на событие _Click, а вторую — на _DblClick в надежде, что они
будут выполнятся в зависимости от наступившего события, то процедура _DblClick
не будет выполнятся никогда, поскольку событие _Click наступит раньше,
начнется выполнение ее процедуры и на _DblClick можно будет наплевать.

Рассмотрим самое мощное событие — _MouseMove на примере
(поскольку остальные события используются аналогично) программки Mouse:
сделаем новый exe-проект и для наших опытов в верхней части формы создадим массив
из пяти TextBox’ов Text1(0), Text1(1), Text1(2), Text1(3), Text1(4), и положим
один PictureBox. (Рис. 25).


Рисунок 25.

А в нижней части формы расположим шесть лейблов. В первый будем записывать,
с каким объектом работает мышь, во второй — состояние клавиш мыши, в третий
— состояние кнопок SHIFT-CTRL-ALT, в четвертый и пятый — координаты мыши, а
в шестой -номер элемента массива TextBox’ов, с которым работает мышь.

'Объявим пару переменных для записи пометок в
лейблах

Option Explicit
Dim ValButton As String
Dim
ValShift As String

'

и создадим процедуру для нашей формы с событием _MouseMove
и напишем код:

Private Sub Form_MouseMove(Button As
Integer
, Shift As Integer, X As
Single
, Y As Single)
Label1.Caption = "Мышь работает с формой"
'в зависимости от значения Button определяем, какая клавиша
мыши нажата

If Button = 0 Then
ValButton = " Ни одной клавиши мыши не нажато"
ElseIf Button = 1 Then
ValButton = " Нажата левая клавиша мыши"
ElseIf Button = 2 Then
ValButton = " Нажата правая клавиша мыши"
ElseIf Button = 4 Then
ValButton = " Нажата средняя клавиша мыши"
ElseIf Button = 3 Then
ValButton = " Нажаты левая и правая клавиши мыши"
ElseIf Button = 7 Then
ValButton = " Нажаты все три клавиши мыши"
End If
Label2.Caption = "Значение Button= " & Button & ValButton

'в зависимости от значения Shift определяем,
какая комбинация из кнопок SHIFT-CTRL-ALT нажата

If Shift = 0 Then
ValShift = " Ни одна из кнопок не нажата"
ElseIf Shift = 1 Then
ValShift = " Нажата кнопка SHIFT"
ElseIf Shift = 2 Then
ValShift = " Нажата кнопка CTRL"
ElseIf Shift = 4 Then
ValShift = " Нажата кнопка ALT"
ElseIf Shift = 3 Then
ValShift = " Нажаты кнопки SHIFT и CTRL"
ElseIf Shift = 6 Then
ValShift = " Нажаты кнопки ALT и CTRL"
ElseIf Shift = 5 Then
ValShift = " Нажаты кнопки SHIFT и ALT"
ElseIf Shift = 7 Then
ValShift = " Нажаты все три кнопки SHIFT-CTRL-ALT"
End If
Label3.Caption = "Общее состояние кнопок SHIFT-CTRL-ALT - " &
Shift & " ;" & ValShift
'выводим координаты мыши
Label4.Caption = "Координата x= " & X & " твипов"
Label5.Caption = "Координата y= " & Y & " твипов"
Label6.Caption = "Массива из форм Control Array быть не может"
End Sub


Обратите внимание, что все кнопки и клавиши отслеживаются только тогда, когда
мышь движется. Ждать результатов на неподвижной мыши бесполезно.
Теперь, если мы запустим программу, то увидим, что все нажатия кнопок и клавиш,
а также изменение координат происходит только тогда, когда курсор мыши находтся
над формой. Как только мы перемещаемся на любой объект, TextBox или PictureBox,
видимых изменений не происходит. Поскольку мы написали процедуру для формы,
над другими объектами она не работает. Кроме того, координаты возвращаются внутри
именно того объекта, над которым находится мышь. Т.е., если мышь находится над
PictureBox’ом, значит и координаты будут PictureBox’а, а не формы Form1.
Для того, чтобы наша программка работала над всеми объектами, создадим аналогичные
процедуры для объектов PictureBox и массива TextBox’ов Text1:

Private Sub Picture1_MouseMove(Button
As Integer, Shift As Integer,
X As Single, Y As Single)
Label1.Caption = "Мышь работает с PictureBox"
If Button = 0 Then
ValButton = " Ни одной клавиши мыши не нажато"
ElseIf Button = 1 Then
ValButton = " Нажата левая клавиша мыши"
ElseIf Button = 2 Then
ValButton = " Нажата правая клавиша мыши"
ElseIf Button = 4 Then
ValButton = " Нажата средняя клавиша мыши"
ElseIf Button = 3 Then
ValButton = " Нажаты левая и правая клавиши мыши"
ElseIf Button = 7 Then
ValButton = " Нажаты все три клавиши мыши"
End If

Label2.Caption = "Значение Button= " & Button &
ValButton

If Shift = 0 Then
ValShift = " Ни одна из кнопок не нажата"
ElseIf Shift = 1 Then
ValShift = " Нажата кнопка SHIFT"
ElseIf Shift = 2 Then
ValShift = " Нажата кнопка CTRL"
ElseIf Shift = 4 Then
ValShift = " Нажата кнопка ALT"
ElseIf Shift = 3 Then
ValShift = " Нажаты кнопки SHIFT и CTRL"
ElseIf Shift = 6 Then
ValShift = " Нажаты кнопки ALT и CTRL"
ElseIf Shift = 5 Then
ValShift = " Нажаты кнопки SHIFT и ALT"
ElseIf Shift = 7 Then
ValShift = " Нажаты все три кнопки SHIFT-CTRL-ALT"
End If
Label3.Caption = "Общее состояние кнопок SHIFT-CTRL-ALT - " &
Shift & " ;" & ValShift
Label4.Caption = "Координата x= " & X & " твипов"
Label5.Caption = "Координата y= " & Y & " твипов"
Label6.Caption = "Массива из PictureBox'ов сейчас нет"
End Sub

Private Sub Text1_MouseMove(Index As
Integer
, Button As Integer, Shift As
Integer
, X As Single, Y As
Single
)
Label1.Caption = "Мышь работает с массивом TextBox'ов"
If Button = 0 Then
ValButton = " Ни одной клавиши мыши не нажато"
ElseIf Button = 1 Then
ValButton = " Нажата левая клавиша мыши"
ElseIf Button = 2 Then
ValButton = " Нажата правая клавиша мыши"
ElseIf Button = 4 Then
ValButton = " Нажата средняя клавиша мыши"
ElseIf Button = 3 Then
ValButton = " Нажаты левая и правая клавиши мыши"
ElseIf Button = 7 Then
ValButton = " Нажаты все три клавиши мыши"
End If

Label2.Caption = "Значение Button= " & Button &
ValButton

If Shift = 0 Then
ValShift = " Ни одна из кнопок не нажата"
ElseIf Shift = 1 Then
ValShift = " Нажата кнопка SHIFT"
ElseIf Shift = 2 Then
ValShift = " Нажата кнопка CTRL"
ElseIf Shift = 4 Then
ValShift = " Нажата кнопка ALT"
ElseIf Shift = 3 Then
ValShift = " Нажаты кнопки SHIFT и CTRL"
ElseIf Shift = 6 Then
ValShift = " Нажаты кнопки ALT и CTRL"
ElseIf Shift = 5 Then
ValShift = " Нажаты кнопки SHIFT и ALT"
ElseIf Shift = 7 Then
ValShift = " Нажаты все три кнопки SHIFT-CTRL-ALT"
End If
Label3.Caption = "Общее состояние кнопок SHIFT-CTRL-ALT - " &
Shift & " ;" & ValShift
Label4.Caption = "Координата x= " & X & " твипов"
Label5.Caption = "Координата y= " & Y & " твипов"
Label6.Caption = "Мышь находится над " & "Text1(" &
Index & ")"
End Sub

Конечно, все это можно написать короче, используя одну собственную
процедуру — ведь код этих процедур почти одинаков, но сейчас так будет яснее.

Теперь нажатия и координаты отслеживаются над всеми объектами, кроме лейблов.
Для устранения этого, мы можем в их свойствах поставить значение свойства .Enabled
в окне свойств в положение False. Тогда при нахождении курсора мыши над
лейблами будут показываться нажатия кнопок и координаты мыши при событии _MouseMove,
наступающем для формы. Однако текст в лейблах изменится на серенький.
Скачать исходник программы Mouse можно вверху страницы.

Рисование
фигур программными методами.

Теперь я скажу, что рисовать такие фигуры, как круг, овал, прямоугольник,
линия можно не только с помощью объекта Shape, но и программно, путем написания
операторов. Это очень просто.

Прямоугольник, линия — метод Line.
Для рисования на объекте линии или прямоугольника существует метод Line.
Синтаксис его такой

объект.Line
[Step] (x1, y1) [Step] (x2, y2), [color], [B][F]
Где

объект это объект на котором рисуется фигура. Если не
задан, то используется объект на котором в этот момент установлен фокус.
Step необязательное ключевое слово, устанавливает,
что начальная точка прямоугольника — верхний левый угол, (или линии) задается
не по абсолютными координатами x1, y1, а относительно текущих
координат, определяемых значениями свойств CurrentX и CurrentY.
x1,
y1
координаты начальной точки прямоугольника (верхний
левый угол) или линии (единицы измерения определяются свойством ScaleMode).
Step необязательное ключевое слово, устанавливает,
что конечная точка прямоугольника — нижний правый угол, (или линии) задается
не по абсолютыми координатами x2, y2, а относительно координат
начальной точки прямоугольника x1,y1.
x2,
y2
координаты конечной точки прямоугольника (нижний
правый угол) или линии (единицы измерения определяются свойством ScaleMode).
color определяет цвет линии или прямоугольника. Может
задаваться как RGB — в формате шестнадцатиричного числа VB (&HFF0033),
либо цветом, определяемым ключевыми словами Visual Basic (vbRed). Можно
использовать функции RGB или QBColor. Если не задан, цвет
устанавливается тот, что задан свойством .ForeColor.
B определяет, что будет прямоугольник. Если его
опустить, рисоваться будет линия.
F определяет, что прямоугольник будет закрашен
тем же цветом, что и его границы (заливка). Используется с опцией B.

Таким образом, чтобы нарисовать линию, например, в объекте Picture1,
можно использовать такой код:

Private Sub
Form_Load()
'задаем единицы измерения пиксели
Picture1.ScaleMode = vbPixels
'устанавливаем свойство AutoRedraw в True, а то нашего
рисования видно не будет

Picture1.AutoRedraw = True
'ширину лини устанавливаем в 3 пикселя
Picture1.DrawWidth = 3
'ставим цвет в свойстве ForeColor в фиолетовый
Picture1.ForeColor = &HFF00FF
'рисум линию с начальной координатой X1=10, Y1=10 и конечной
X2=150, Y2=150 пикселей
'поскольку цвет не задаем, линия будет фиолетовой по свойству ForeColor

Picture1.Line Step(10, 10)-(150, 150)
End Sub

Если мы в оператор Picture.Line добавим B, то у нас получится
прямоугольник (в общем-то квадрат)
Picture1.Line (10, 10)-(150, 150), , B
Чтобы изменить цвет линий, например, на красный, независимо от .ForeColor:
Picture1.Line (10, 10)-(150, 150), vbRed,
B


И наконец можем залить наш квадратик
Picture1.Line
(10, 10)-(150, 150), vbRed, BF
Ключевое слово Step можно использовать, если нужно
привязаться к постоянно меняющимся значениям свойств .CurrentX и .CurrentY.
Так, например, мы можем нарисовать наш квадратик там, куда щелкнем мышкой.

Private Sub Form_Load()
Picture1.ScaleMode = vbPixels
Picture1.AutoRedraw = True
Picture1.DrawWidth = 3
Picture1.ForeColor = &HFF00FF
End Sub

Private Sub Picture1_MouseDown(Button
As Integer, Shift As Integer,
X As Single, Y As Single)
Picture1.Cls 'очищаем Picture1 перед каждым кликом
Picture1.CurrentX = X
Picture1.CurrentY = Y
Picture1.Line Step(0, 0)-Step(150,
150), vbRed, B
End Sub

Окружность, эллипс, дуга — метод Circle.
Для рисования на объекте окружности, эллипса или дуги применяется метод Circle.
Его синтаксис:

объект.Circle [Step] (x, y), радиус, [color, start, end, aspect],
Где

объект это объект на котором рисуется фигура. Если не
задан, то используется объект на котором в этот момент установлен фокус.
Step необязательное ключевое слово, устанавливает,
что центр окружности задается не по абсолютным координатам x, y,
а относительно текущих координат, определяемых значениями свойств CurrentX
и CurrentY.
x,
y
координаты центра окружности (единицы
измерения определяются свойством ScaleMode)
радиус радиус окружности, эллипса ил дуги (единицы измерения
определяются свойством ScaleMode).
color определяет цвет окружности, эллипса или дуги.
Может задаваться как RGB — в формате шестнадцатиричного числа VB (&HFF0033),
либо цветом, определяемым ключевыми словами Visual Basic (vbRed). Можно
использовать функции RGB или QBColor. Если не задан, цвет
устанавливается тот, что задан свойством .ForeColor.
start,
end
при создании дуги задают начальное и конечное
значение угла дуги в радианах (от -2pi до 2pi)
aspect коэффициент сжатия эллипса. По умолчанию равен
1,0, т.е. сжатия нет, выводится окружность.

Ну-с, опять в нашем Picture1 рисуем окружность. Все происходит
аналогично методу .Line

Private Sub Form_Load()
Picture1.ScaleMode = vbPixels
Picture1.AutoRedraw = True
Picture1.DrawWidth = 3
Picture1.ForeColor = &HFF00FF
Picture1.Circle (200, 120), 70
End Sub

Мы нарисовали фиолетную окружность с центром в точке X=200, Y=120 и и диаметром
70 пикселей.
Теперь превратим ее в эллипс синего (&HFF0000) цвета. Коэффициент aspect
установим в 0,5, т.е сожмем окружность в 2 раза.
Picture1.Circle (200, 120), 70, &HFF0000,
, , 0.5

Попробуем теперь нарисовать дугу окружности. Коэффициент эллипcности убираем
(дуга эллипса — некрасиво). Цвет определим зеленый (&H8000&)

Picture1.Circle
(200, 120), 70, &H8000&, 0, 1

А вот пример маленького кода, где мы можем использовать «мышиные»
события и рисование фигур. Эта программка рисует окружность, причем радиус и
положение задается нажатием клавиши мыши. Когда клавиша отпускается, окружность
фиксируется.

Dim OldX As
Single
Dim
OldY As Single
Private Sub Form_Load()
Picture1.ScaleMode = vbPixels
Picture1.AutoRedraw = True
Picture1.DrawWidth = 3
Picture1.ForeColor = &H8000&
End Sub
Private Sub Picture1_MouseDown(Button As
Integer
, Shift As Integer, X As
Single
, Y As Single)
OldX = X
OldY = Y
End Sub

Private Sub Picture1_MouseMove(Button
As Integer, Shift As Integer,
X As Single, Y As Single)
Picture1.CurrentX = X
Picture1.CurrentY = Y
If Button = 1 Then
Picture1.Cls
Picture1.Circle Step(OldX, OldY), Sqr((X - OldX)
^ 2 + (Y - OldY) ^ 2), &H8000&
Center = Sqr((X - OldX) ^ 2 + (Y - OldY) ^ 2)
End If
End Sub

Сайт создан в системе uCoz

Имитация движения и кликов левой и правой кнопками мыши из кода VBA Excel. Эмуляция перемещения курсора и определение его текущих координат.

В VBA Excel нет методов и функций для имитации движения мыши и эмуляции кликов ее левой и правой кнопками. Но для этих целей, а также для определения текущих координат курсора, можно использовать встроенные функции Windows API — GetCursorPos, SetCursorPos и mouse_event.

Если эти функции Windows API объявить без ключевого слова Private, они будут доступны во всех модулях текущего проекта VBA.

Определение координат курсора

Определение текущих координат курсора из кода VBA Excel:

Option Explicit

Declare PtrSafe Function GetCursorPos Lib «user32» (lpPoint As POINTAPI) As Long

Type POINTAPI

   X As Long

   Y As Long

End Type

Sub Get_Cursor()

    Dim myPoint As POINTAPI

    GetCursorPos myPoint

    Debug.Print «Координата X: « & myPoint.X & vbNewLine & _

    «Координата Y: « & myPoint.Y & vbNewLine

End Sub

Скопируйте представленный выше код в стандартный модуль и кликните мышью внутри процедуры Get_Cursor(). Затем, перемещайте курсор мыши по экрану, не нажимая кнопок, чтобы мигающая вертикальная линия (точка вставки) не ушла из процедуры, и нажимайте клавишу F5. В окне Immediate будут печататься текущие координаты курсора. Клавишу F5 можно нажимать одновременно с процессом перемещения мыши. Значения координат X и Y отображаются в пикселях.

Имитация движения мыши

Имитация движения мыши, а, точнее, перескока мыши из одной точки в другую, осуществляется из кода VBA Excel путем задания новых координат курсору:

Option Explicit

Declare PtrSafe Function SetCursorPos Lib «user32» (ByVal X As Long, ByVal Y As Long) As Long

Sub Set_Cursor()

    Dim myX As Long, myY As Long

    myX = 600

    myY = 400

    ‘Задаем курсору новые координаты

    SetCursorPos myX, myY

End Sub

Переменные добавлены в пример для наглядности, их можно не использовать:

А так можно задать множественные перескоки курсора мыши:

Sub Many_Set_Cursor()

Dim i As Long

    For i = 1 To 600 Step 20

        Application.Wait Now + TimeValue(«0:00:01»)

        SetCursorPos i, i

    Next

End Sub

Здесь перескок мыши происходит один раз в секунду.

Уменьшив задержку выполнения цикла предыдущего примера с помощью другого цикла, можно ускорить перемещение курсора и сделать его более плавным:

Sub Many_Set_Cursor_2()

Dim i As Long, i2 As Long, a As Long

    For i = 1 To 600

        For i2 = 1 To 100000

            a = i2 / 2

        Next

        SetCursorPos i, i

    Next

End Sub

Здесь уже более похоже на имитацию движения мыши.

Имитация кликов мыши

Чтобы воспроизвести имитацию кликов левой и правой кнопками мыши, нам понадобятся коды событий кнопок мыши:

Событие Код
Нажать левую кнопку &H2
Отпустить левую кнопку &H4
Нажать правую кнопку &H8
Отпустить правую кнопку &H10

Следующий пример показывает, как установить курсор мыши в заданное место экрана и сымитировать клик правой кнопкой мыши:

Option Explicit

Declare PtrSafe Function SetCursorPos Lib «user32» (ByVal X As Long, ByVal Y As Long) As Long

Declare PtrSafe Sub mouse_event Lib «user32» (ByVal dwFlags As Long, ByVal dx As Long, ByVal dy As Long, ByVal cButtons As Long, ByVal dwExtraInfo As Long)

Sub Set_Cursor_and_RightClick()

    ‘Устанавливаем курсор в нужную точку экрана

    SetCursorPos 800, 600

    ‘Нажимаем правую кнопку мыши

    mouse_event &H8, 0, 0, 0, 0

    ‘Отпускаем правую кнопку мыши

    mouse_event &H10, 0, 0, 0, 0

End Sub

Я выбрал для примера имитацию клика правой кнопкой мыши из-за большей наглядности (за счет отображения контекстного меню).

Обратите внимание, что функции Windows API, используемые в примерах, должны быть объявлены только один раз.


Фразы для контекстного поиска: положение курсора, имитация клика, эмуляция клика, эмуляция движения, имитация мыши, эмуляция мыши, координаты мыши, расположение мыши, расположение курсора.


Понравилась статья? Поделить с друзьями:
  • Vba excel события для combobox
  • Vba excel событие при изменении ячейки
  • Vba excel событие при изменении ячеек
  • Vba excel событие нажатия клавиши
  • Vba excel событие на изменение ячейки excel