- •Объекты Excel
- •Объектная модель Excel
- •Объект Excel Application
- •Терминальные свойства
- •Методы объекта Application
- •События объекта Excel.Application
- •Создание объекта Application, реагирующего на события
- •Пример обработки события Change
- •Объект Workbook
- •Свойства-участники объекта Workbook
- •Группа свойств, возвращающих основные объекты рабочей книги. К ним я отношу следующие свойства:
- •К третьей группе относятся свойства, возвращающие объекты, специфические для рабочих книг Excel. К ним относятся:
- •Изменения в объектной модели объекта WorkSheet
- •Методы - "незнакомцы"
- •Методы – свойства
- •События объекта Worksheet
- •Объекты Range и Selection
- •Смещение и свойство Offset
- •Методы объекта Range
События объекта Excel.Application
Объект Excel.Application может обрабатывать 21 событие, возникающие при работе с теми или иными объектами приложения Excel. Почти половина из этих событий возникает в процессе работы с объектом Workbook, другая половина событий связана с такими объектами, как страница документа (объект Sheet) и окно (объект Window). Практически все события, за исключением одного события NewWorkBook, могут быть обработаны на двух уровнях – объектом Application и объектом Workbook. Но прежде чем поговорить, о том, какие события может обрабатывать объект Application, в каких случаях следует проводить обработку события на уровне объекта Application, а в каких - на уровне объекта Workbook, давайте разберемся, как заставить объект Excel.Application вообще реагировать на события.
Создание объекта Application, реагирующего на события
Для всех приложений Office 2000 соответствующие объекты Application хотя и могут реагировать на события, но появляются как объекты без событий. И нужно приложить некоторые усилия, чтобы создать новый объект Application With Events, который может реагировать на события. Причина возникающих сложностей кроется в логике построения программного проекта, изначально принятой в Office. Дело в том, что обработчики событий, возникающих при работе с теми или иными объектами, следует размещать в специальных модулях – обработчиках событий. Для большинства стандартных объектов Office эти модули создаются автоматически в момент создания основного объекта. Так, например, при создании документа в его проекте автоматически создается модуль, обрабатывающий события этого документа, - для Excel это модуль с именем «ЭтаКнига» (ThisWorkbook). Только в этом модуле и можно создать обработчики событий объекта Workbook и всех объектов, реагирующих на события, например, элементов управления, встраиваемых непосредственно в документ.
Объект Application, единый для всех рабочих книг, по понятным причинам не вписывается в эту общую схему и для него такой модуль автоматически не создается, потому, естественно, эту работу приходится выполнять программисту. Я напомню, что о структуре программного проекта и модулях-обработчиках событий я подробно рассказывал в [2, гл.2], об общей ситуации создания собственного класса объектов, реагирующих на события, написано в [2, гл.4], о создании объекта Word.Application With Events рассказано в [3, гл. 9].
Для того чтобы заставить реагировать на события объект Excel.Application, необходимо выполнить четыре шага:
Создать модуль, задающий собственный класс для объекта Excel.Application, в котором можно будет размещать обработчики возникающих событий. Устроен этот класс очень просто и состоит в момент создания из одной строчки, поскольку класс не имеет методов и имеет ровно одно свойство, задающее объект Application с событиями. Конечно, позже этот класс будет пополняться обработчиками событий. Вот как выглядит на этапе создания описание этого класса, которому я в своем примере дал имя AppWithEvents.
Option Explicit 'Класс, описывающий объект Application With Events. 'Класс не имеет методов, задается одним свойством. Public WithEvents ExApp As Application
Следующее, что необходимо сделать – это определить объект вновь созданного класса AppWithEvents. И эта задача решается в одну строчку. Объявление объекта я поместил в раздел объявлений созданного ранее стандартного модуля. Заметьте, необходимо не только объявить объект, но и создать его, используя спецификатор New.
Public AppWithEv As New AppWithEvents
Третьим шагом является связывание двух объектов Application, стандартного и созданного объекта, умеющего реагировать на события. По-видимому, лучшим местом, где следует осуществить связывание, является обработчик события Open того документа, в котором описан класс AppWithEvents. Тогда после открытия этого документа и вплоть до его закрытия Excel будет реагировать на события, связанные с объектом Excel.Application. Вот как осуществляется связывание:
Private Sub Workbook_Open() 'Связывание двух объектов Application - 'стандартного и реагирующего на события. Set AppWithEv.ExApp = Excel.Application End Sub
На этом шаге созданный класс AppWithEvents можно расширить, добавив в него обработчики событий объекта. Application. Я приведу пока текст только одного обработчика, который обрабатывает событие NewWorkBook, возникающее при создании новой книги.
Private Sub ExApp_NewWorkbook(ByVal Wb As Workbook) 'Обработка события - создание новой книги. Static Num As Integer Num = Num + 1 MsgBox ("Число вновь созданных книг - " & Num _ & vbCrLf & "Новая книга - " & Wb.Name _ & " открыта в " & Time) End Sub
Вот как выглядит сообщение, появляющееся при открытии новой книги:
Рис. 2 Сообщение об открытии новой книги
События, связанные с рабочей книгой
В нижеследующей таблице 1 дана сводка всех событий, которые возникают при работе с рабочими книгами – объектами Workbook, и которые могут быть обработаны объектом Application.
Таблица 3 События, возникающие при работе с объектом Workbook
Событие |
Когда возникает |
Параметры события |
NewWorkbook(Wb As Workbook) |
При создании новой книги. Единственное событие этой группы, которое может обработать только объект Application. |
Обработчику события передается объект Wb, представляющий вновь созданную книгу. |
WorkbookActivate(Wb As Workbook) |
Книга становится активной. |
Вновь активированная книга передается обработчику события в качестве параметра. |
WorkbookAddinInstall(Wb As Workbook) |
При установке рабочей книги в качестве AddIn. |
Рабочая книга, представляющая AddIn. |
WorkbookAddinUninstall(Wb As Workbook) |
Отменяется установка рабочей книги в качестве AddIn. Закрытие книги при этом не происходит. |
Рабочая книга, представляющая AddIn. |
WorkbookBeforeClose(Wb As Workbook, Cancel As Boolean) |
При попытке закрыть рабочую книгу, но до того, как она будет закрыта. |
Параметр Wb задает закрываемую книгу. Параметр Cancel позволяет отменить закрытие, если в обработчике события его значение будет установлено как True. |
WorkbookBeforePrint(Wb As Workbook, Cancel As Boolean) |
При попытке распечатать содержимое рабочей книги, но до того, как произойдет печать. |
Параметр Wb задает печатаемую книгу. Параметр Cancel позволяет отменить печать, если в обработчике события его значение будет установлено как True. |
WorkbookBeforeSave(Wb As Workbook, SaveAsUI As Boolean, Cancel As Boolean) |
При попытке сохранить содержимое рабочей книги, но до того, как произойдет сохранение. |
Параметр Wb задает сохраняемую книгу. Параметр Cancel позволяет отменить сохранение, если в обработчике события его значение будет установлено как True. Параметр SaveAsUI показывает, как идет сохранение, его значение равно true, если при сохранении открывается диалоговое окно «Сохранить как ». |
WorkbookDeactivate(Wb As Workbook) |
Книга перестает быть активной, поскольку активной становится другая книга. |
Деактивированная книга передается обработчику события в качестве параметра. |
WorkbookNewSheet(Wb As Workbook, Sh As Object) |
При добавлении новой страницы в рабочую книгу. |
Объект Wb задает книгу, а Sh – страницу, добавленную в эту книгу. |
WorkbookOpen(Wb As Workbook) |
При открытии уже существующей рабочей книги. |
Обработчику события передается объект Wb, представляющий вновь открытую книгу. |
Практически все события, происходящие с объектом Workbook, могут быть обработаны на двух уровнях – объектом Application и самим объектом Workbook. Разница лишь состоит в том, что если у объекта Application есть, например, событие WorkbookOpen, то у объекта Workbook есть событие Open. При возникновении данного события операционная система посылает соответствующее сообщение двум объектам - Application и Workbook. Обработчику сообщения WorkbookOpen передается параметр Wb, задающий открываемую книгу. Понятно, что при посылке аналогичного сообщения объекту Workbook передавать этот параметр не имеет смысла, поскольку он и так знает сам себя, так что обработчик события Open объекта Workbook параметров не имеет.
Возникает естественный вопрос, в каких случаях следует вести обработку события, происходящего с объектом Workbook, на уровне объекта Application. Ответ понятен – в тех случаях, когда обработчик события выполняет действия, общие для всех рабочих книг. В тех же случаях, когда предполагается специфическая обработка события, характерная только для данной конкретной книги, обработчик события связывается с объектом Workbook. Что происходит, если обработка одного и того же события предусмотрена на двух уровнях? В этом случае вначале выполнится обработчик события, связанный с объектом Workbook, - он выполнит специфическую для данной книги обработку, а потом начнет работать обработчик этого же события, связанный с объектом Application, выполняющий ту часть работы, которая является общей для всех рабочих книг.
Приведу пример, в котором предусмотрена общая для всех рабочих книг обработка события BeforeSave:
Private Sub ExApp_WorkbookBeforeSave(ByVal Wb As Workbook, _ ByVal SaveAsUI As Boolean, Cancel As Boolean) Dim YesNo As Variant YesNo = MsgBox("Вы действительно хотите сохранить этот документ?", vbYesNo) If YesNo = vbNo Then Cancel = True End Sub
Предупреждающее сообщение будет появляться для всех рабочих книг. Рассмотрим теперь пример, когда обработка события BeforePrint предусмотрена на двух уровнях:
Private Sub Workbook_BeforePrint(Cancel As Boolean) 'Обработка события - печать содержимого книги. MsgBox ("Эту книгу - " & ThisWorkbook.Name _ & " печатать запрещено!") Cancel = True End Sub
Private Sub ExApp_WorkbookBeforePrint(ByVal Wb As Workbook, Cancel As Boolean) 'Обработка события - печать содержимого книги. If Wb.ActiveSheet.Name = "Лист1" Then MsgBox ("Эту страницу книги - " & Wb.Name _ & " печатать запрещено!") Cancel = True End If End Sub
Специальный обработчик события объекта Workbook книги BookOne запрещает печать только этой книги, а общий для всех книг обработчик того же события, но находящийся в объекте Application, запрещает печать только первого листа, но для всех рабочих книг. Вот как выглядит сообщение, выданное для книги BookOne общим обработчиком при попытке распечатать содержимое первого листа книги:
Рис. 3 Сообщение, выданное обработчиком события WorkbookBeforePrint
События, связанные с объектом Sheet
Ряд событий, которые возникают в процессе работы со страницами той или иной рабочей книги, также могут быть обработаны на уровне объекта Application. Естественно, что эти события могут быть обработаны и на более низких уровнях – как на уровне объекта Workbook, так и на следующем уровне объектами, задающими саму страницу - Worksheet и Chart. Понятно, что на самом верхнем уровне задается обработка, общая для всех страниц всех книг, на следующем уровне обработка, общая для страниц конкретной книги, и на нижнем уровне – обработка, специфическая для данной страницы. В таблице 4 дана сводка событий, связанных с объектом Sheet, обрабатываемых на уровне объекта Application.
Таблица 4 События, возникающие при работе с объектом Sheet
Событие |
Когда возникает |
Параметры события |
SheetActivate(Sh As Object) |
Страница становится активной. |
Вновь активированная страница передается обработчику события в качестве параметра. |
SheetBeforeDoubleClick(Sh As Object, Target As Range, Cancel As Boolean) |
При двойном щелчке левой клавиши мыши на рабочей странице, но до того, как выполнится макрос, задающий реакцию на щелчок. Событие не возникает на Chart-страницах. |
Первый параметр передает обработчику события объект Sh, задающий рабочую страницу, на которой был произведен двойной щелчок. Второй параметр Target возвращает ячейку (объект Range), ближайшую к указателю мыши в тот момент, когда был произведен щелчок. Если в обработчике события изменить значение параметра Cancel на True, то отменится выполнение макроса, задающего реакцию на двойной щелчок. |
SheetBeforeRightClick(Sh As Object, Target As Range, Cancel As Boolean) |
Аналогично двойному щелчку, но при нажатии правой клавиши мыши. |
Параметры сохраняют смысл, описанный для обработчика событий двойного щелчка. |
SheetCalculate(Sh As Object) |
При перевычислениях рабочей страницы или при любых изменениях данных, отображаемых на диаграмме страницы диаграмм. |
В зависимости от того, на странице какого типа произошло событие, параметр Sh представляет либо объект Workbook либо объект Chart. |
SheetChange(Sh As Object, Target As Range) |
При изменениях в ячейках рабочей книги, инициированные пользователем или внешней ссылкой. Не возникает для Chart-страниц. |
Параметр Sh задает объект WorkSheet – страницу, в ячейках которой произошли изменения. Параметр Target задает область изменения – объект Range. |
SheetDeactivate(Sh As Object) |
Страница перестает быть активной, поскольку активной становится другая страница. |
Деактивированная страница передается обработчику события в качестве параметра. |
SheetFollowHyperlink(Sh As Object, Target As Hyperlink) |
При щелчке по гиперссылке на рабочей странице. Не возникает для Chart-страниц. |
В качестве параметров обработчику события передаются два объекта, представляющие рабочую страницу и гиперссылку, задающую переход. |
SheetSelectionChange(Sh As Object, Target As Range) |
При изменении области выделения рабочей страницы. Не возникает для Chart-страниц. |
Параметр Sh задает объект WorkSheet –страницу, содержащую новую область выделения. Параметр Target задает новую область выделения – объект Range. |