Основы офисного программирования и язык VBA

Проектирование интерфейса. Диалоговые окна

Разбить на страницы
Показывать лекцию целиком

Программный код большинства примеров данной лекции можно найти в проектах, доступных для просмотра: BookOne12, DocOne12.

Диалоговые окна и элементы управления

Диалоговые окна (формы) и элементы управления составляют основу современного визуального интерфейса. Все эти элементы и технология работы с ними в основном стандартизованы и являются похожими для разных платформ и программных сред. Поэтому не удивительно, что приложения Excel, Word и PowerPoint разделяют единые объекты, задающие диалоговые окна и элементы управления. Эти объекты помещены в специальную библиотеку MSForms. Несколько особняком стоит Access. И здесь все доступно, но по-своему.

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

Выделим некоторые основные моменты, которые следует иметь в виду при создании визуального интерфейса:

Все загруженные диалоговые окна представляют коллекцию UserForms. Формально, это глобальная внутренняя переменная, - Вы не найдете UserForms в окне просмотра объектов. Тем не менее, это нормальная коллекция со стандартными методами и свойствами, - метод Item позволяет по имени или номеру добраться до любого ее элемента, а метод Add добавляет новое диалоговое окно (форму) в коллекцию. Элемент коллекции - объект класса UserForm задает отдельное окно.

Для каждого типа элементов управления в библиотеке MSForms имеется класс объектов, имя которого совпадает с именем элемента управления (его типа). Например, есть классы SpinButton и TextBox.

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

На этапе проектирования, используя окно свойств, можно задать большинство свойств, как самого диалогового окна, так и всех элементов управления, помещенных в это окно. Автоматически, конечно же, меняются и свойства соответствующего объекта. Заметьте, что есть еще две возможности изменения свойств этих объектов. Свойства может менять конечный пользователь. Заметьте, что элементы управления именно для этого и существуют, чтобы конечный пользователь мог определять некоторые (но не все) свойства, например, пользователю разрешается вводить текст в окна редактирования. Но есть и третья возможность - изменение свойств программным путем. Как правило, все свойства, доступные конечному пользователю, либо доступные на этапе проектирования, доступны для изменения программным путем.

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

Есть все-таки одна проблема: куда помещать программный код? Ведь методы объектов жестко запрограммированы и не подлежат изменениям. К счастью есть у объектов события и обработчики событий надо программировать самому. Именно сюда и помещают код. Обработчик события может быть достаточно сложным и по ходу своей работы может вызывать десяток, другой локальных процедур и функций. Как правило, события задают реакцию на действия конечного пользователя, - ответом может быть изменение свойств объектов, вызов их методов, появление новых элементов управления и переход к новым диалоговым окнам.

Поговорим об отладке. Написание обработчиков событий следует относить, по-видимому, к этапу проектирования. Когда этот этап закончен, - окно создано и заселено элементами, их свойства установлены, обработчики событий написаны, - возникает естественный вопрос " А будет ли все это правильно работать?" Чтобы вести отладку, можно, конечно, перейти в режим выполнения приложения. Однако это не эффективно, лучше вести локальную отладку - для этого достаточно выбрать команду Run Sub/UserForm из меню Run в VBA редакторе. Заметьте, что для отображения формы в режиме выполнения должен быть вызван ее метод Show.

Несколько слов следует сказать о методах Show, Hide и Load объекта UserForm. Метод Load загружает диалоговое окно и делает его доступным для программирования (объект определен). Но окно не отображается на экране дисплея и конечный пользователь не может работать с ним и его элементами. Чтобы окно сделать видимым, нужно вызвать его метод Show, чтобы видимое окно спрятать - метод Hide.

Можно прятать не только само окно, но и отдельные его элементы управления. Возможен, например, такой способ, - в одну половину "большого" окна поместить одни элементы управления, в другую - другие. Затем, в режиме выполнения динамически задать размеры окна так, чтобы они определяли только одну половину окна - тогда и видимы будут элементы только этой половины. Затем можно организовать переключение так, чтобы видимой была та или другая половина окна со своими элементами.

В предыдущем пункте мы говорили о том, как сделать некоторые элементы управления невидимыми, а, следовательно, и недоступными для изменений. Чаще, однако, применяется другая стратегия - видимые элементы можно сделать недоступными для изменений. Практически все элементы имеют булево свойство Enabled. Если дать ему значение True, то элемент считается включенным и доступен для изменения. Чтобы "выключить" его и сделать недоступным, достаточно изменить значение свойства Enabled на False. Обычно, программным путем проверяются контекстные условия, при выполнении которых элемент включается и является доступным для изменений.

Объекты, отвечающие за диалоговое окно и элементы управления, определены в период загрузки диалогового окна. Окно можно выгрузить, вызвав метод UnLoad, и тогда сам объект UserForm и все объекты, соответствующие вложенным в него элементам управления, становятся недоступны для программирования, - их свойства теряются. Важно понимать, что, зачастую, необходимо сохранять информацию о свойствах элемента управления долговременно в файлах постоянной памяти, - это и ввод, сделанный пользователем, и полученные в процессе работы результаты. В этих случаях в программу вводятся переменные, предназначенные для хранения значений тех или иных свойств элементов управления. Их срок жизни другой и не связан с загруженной формой. Поэтому перед применением UnLoad следует запомнить значения нужных свойств в переменных программы с возможной записью их в файл перед окончанием работы. Аналогично, при повторном сеансе свойства устанавливаются, используя сохраненные в файле значения.

Еще несколько слов о методах Load и UnLoad. Понятно, что это не совсем обычные методы, особенно Load - он не может быть методом, так как до его выполнения объект UserForm не существует, а не существующий объект не может вызывать никаких методов. Поэтому Load является оператором, синтаксис которого:

Load <объект класса UserForm>.

За компанию и UnLoad является оператором с аналогичным синтаксисом.

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

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

Созданное диалоговое окно в одном приложении можно экспортировать в другие приложения Office 2000. Но нужно быть осторожным - для корректной работы должны использоваться только средства VBA, не содержащие специфических для приложения объектов.

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

В Office 2000 определен весьма полезный элемент управления MultiPage. С его помощью достаточно просто организовать многостраничное диалоговое окно (окно с несколькими вкладками). Вначале в окно помещается этот элемент, устанавливается нужное число страниц, а затем, выбирая вкладку, соответствующую нужной странице, эта страница проектируется обычным способом.

Близким по духу к MultiPage является элемент управления TabStrip. Если первый задает несколько страниц с разнородным составом элементов управления, то второй определяет несколько страниц с одинаковым набором элементов. Типичная ситуация применения TabStrip - диалоговое окно отвечает за обработку данных нескольких отделов. Все формы представления данных по каждому отделу одинаковы и отличаются только содержащейся в этих формах информацией. TabStrip для каждого из отделов создает свою вкладку.

До сих пор мы говорили, что ActiveX и элементы управления можно располагать в диалоговых окнах. Эти окна представляют некоторый способ группирования элементов и придают структуру пользовательскому интерфейсу. Можно, однако, размещать все эти элементы и вне диалогового окна непосредственно на документе Word, рабочем листе или листе диаграмм Excel или на слайде презентации PowerPoint. Иногда, особенно когда число элементов невелико, так поступать удобнее - есть данные, а рядом - кнопка, щелчок которой обрабатывает эти данные. Злоупотреблять такой возможностью мы, правда, не рекомендуем.

Общие сведения и применение

Диалоговое окно представляет собой прямоугольную область экрана, где размещены элементы управления, с которыми работает пользователь. В Office 2000 масса встроенных элементов управления, позволяющих спроектировать и реализовать интерфейс типичной офисной системы. Если же встроенных элементов управления не хватает, Вы можете использовать в своем диалоговом окне произвольные ActiveX -объекты.

Три приложения Office 2000 - Excel, Word и PowerPoint - содержат в редакторе VBA одинаковые средства создания диалоговых окон и программирования процедур обработки событий для них и для их управляющих элементов. В Access наряду с аналогичными средствами создания собственного диалогового окна, включены также мастера, помогающие проектировать специальные диалоговые окна, связанные с вводом и выводом информации, хранящейся в базе данных.

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

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

Встроенные диалоговые окна

Коллекция Dialogs и объект Dialog

Рассматривая общие объекты, используемые при организации пользовательского интерфейса, нельзя не упомянуть коллекцию Dialogs, которую можно использовать в приложениях Word и Excel. Элементы этой коллекции - объекты класса Dialog представляют встроенные в приложение диалоговые окна, появляющиеся по ходу работы с документами. Из этой коллекции ничего нельзя удалить и ничего в нее нельзя добавить. В любой момент можно только открыть любое из существующих встроенных диалоговых окон и предоставить пользователю возможность работы с ним, например, открыть файл или организовать поиск нужной информации. Чтобы добраться до нужного диалогового окна, используется обычная конструкция: Dialogs (<имя окна>), где имя окна задается константой. Все имена констант строятся по одному принципу, - они начинаются с префикса wdDialog или xlDialog (для Word и Excel соответственно), а затем идет имя окна. В приложении Word это полное имя, включающее все меню, которые надо открыть при вызове диалогового окна "вручную". Так, например, для открытия диалогового окна "Open" из меню File в приложении Word следует вызвать метод Show следующим образом:

Dialogs(wdDialogFileOpen).Show

Сразу же появится окно:

(рис 12.1) Диалоговое окно открытия файла

В Excel этот же вызов будет иметь вид:

Application.Dialogs(xlDialogOpen).Show

Заметьте, что в первом случае - это глобальный объект и поэтому его можно вызывать непосредственно, в Excel же необходимо указание корневого объекта Application, чье свойство Dialogs и возвращает коллекцию Dialogs. Но зато в Excel достаточно короткого имени для вызова диалогового окна. Метод Show открывает диалоговое окно и позволяет пользователю работать в нем. В зависимости от того, какую кнопку нажал пользователь при выходе из окна, возвращается результат: в Excel это True или False (нажаты кнопки OK или Cancel), в Word можно точнее проанализировать, какая кнопка была нажата. Метод Show - основа работы с диалоговыми окнами, по сути больше ничего и не нужно: в нужный момент открывается нужное диалоговое окно, пользователь работает в нем и по закрытии можно понять, успешно ли закончилась его работа.

Тем не менее, Word предоставляет некоторые дополнительные возможности. В частности, наряду с методом Show, можно применять метод Display, отличающийся тем, что хотя окно и открывается, но ввод от пользователя оно принять не может и используется только в информационных целях. Word позволяет также создавать объекты класса Dialog и программно устанавливать значения полей диалогового окна, еще до того, как оно будет показано пользователю, беря тем самым на себя часть его работы. Метод Execute позволяет эти установки зафиксировать. Вот пример, в котором делаются некоторые установки в диалоговом окне Replace:

Public Sub Dialogs2()
	Dim MyDialog As Dialog, Answer As Variant
	Set MyDialog = Dialogs(wdDialogEditReplace)
	MyDialog.Find = "коллекция"
	MyDialog.Replace = "семейство"
	MyDialog.FuzzyFind = True
	Answer = MyDialog.Show
	Debug.Print Answer

End Sub

В процессе работы этой процедуры появится окно:

(рис 12.2) Диалоговое окно замены

Обратите внимание, мы используем у объекта MyDialog такие свойства, как Find, Replace и даже FuzzyFind, соответствующие полям диалогового окна (В браузере объектов Вы не найдете поля FuzzyFind ). В документации по Word можно найти список допустимых параметров для каждого типа диалогового окна.

Поскольку действительно важно уметь установить программно некоторые характеристики в диалоговом окне, то и в Excel предусмотрена такая возможность. Здесь всю работу выполняет метод Show,- он имеет до 30 возможных параметров и, используя их, можно передать при открытии окна всю необходимую информацию.

Вывод сообщений. Функция MsgBox

Рассмотрим сейчас встроенные диалоговые окна, которые появляются при вызове некоторых функций VBA. И начнем наше рассмотрение с функции MsgBox, предназначенной для вывода сообщений. Диалоговое окно, создаваемое функцией MsgBox, служит для вывода на экран сообщения программы и получения от пользователя простой реакции на это сообщение в виде щелчка одной из кнопок окна. В простейшем случае эта функция вызывается как процедура. Например, вызов:

MsgBox "Сегодня на календаре"  Date

выведет окно:

(рис 12.3) Пример окна сообщений

После щелчка кнопки OK вызов функции завершится, и выполнение программы возобновится с оператора, стоящего непосредственно за этим вызовом.

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

MsgBox(prompt[, buttons] [, title] [, helpfile, context])

Здесь параметр prompt (сообщение) - строковое выражение, значение которого выводится в окне. Его максимальная длина не должна превышать 1024 символов. Разбиение на строки в этом выражении можно производить, используя символ возврата каретки ( Chr(13) ), символ перевода строки ( Chr(10) ), их комбинацию ( Chr(13) Chr(10) ) или константу vbCrLf. Числовой параметр buttons (кнопки) задает виды командных кнопок, помещаемых в окне, кнопку, выбираемую по умолчанию, и модальность диалогового окна. Он получается как сумма кодов соответствующих кнопок и свойств. Явно не заданный, этот параметр считается равным 0. Строковое выражение title (заголовок) задает заголовок окна. Если его нет, заголовком становится имя приложения (см. пример, приведенный выше, где мы использовали Word). Параметры helpfile (файл справки) и context (контекст) должны присутствовать (или отсутствовать) вместе. Первый из них - имя файла, содержащего справку, которая будет выведена при нажатии клавиши F1, а второй - числовое выражение, задающее номер темы со справкой в этом файле.

Вот коды кнопок и других свойств окна функции MsgBox:

Имя константы Код Описание
Коды наборов командных кнопок
vbOKOnly 0 только кнопка OK (Готово)
VbOKCancel 1 кнопки OK и Cancel (Отказ)
VbAbortRetryIgnore 2 кнопки Abort (Прервать), Retry (Продолжить) и Ignore (Игнорировать)
VbYesNoCancel 3 кнопки Yes (Да), No (Нет) и Cancel
VbYesNo 4 кнопки Yes и No
VbRetryCancel 5 кнопки Retry и Cancel
Коды пиктограмм
VbCritical 16 важное сообщение (крестик в круге)
VbQuestion 32 запрос (вопросительный знак)
VbExclamation 48 предупреждение (восклицательный знак)
VbInformation 64 информационное сообщение (i в круге)
Кнопка, выбранная по умолчанию
VbDefaultButton1 0 первая кнопка
VbDefaultButton2 256 вторая кнопка
VbDefaultButton3 512 третья кнопка
VbDefaultButton4 768 четвертая кнопка
Модальность диалога
VbApplicationModal 0 модален относительно приложения
VbSystemModal 4096 модален относительно системы

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

Может показаться странным, что константа VbDefaultButton4 указывает на четвертую кнопку, хотя максимальное количество кнопок, определяемых кодами от 0 до 5, - три. Дело в том, что некоторые приложения (например, Excel) при наличии параметров справка и контекст могут автоматически добавить в окно кнопку справки Help, вызывающую окно справки.

Результирующее значение параметра buttons получается как сумма кодов по одному из каждой группы. Например, значение 36 = 4 + 32 = VbYesNo + VbQuestion означает, что в окне будет пиктограмма с вопросительным знаком и две кнопки Yes и No, причем первая из них будет считаться выбранной, если пользователь ее щелкнет или нажмет клавишу Enter.

Как узнать, какую кнопку выбрал пользователь? Присвоить значение функции MsgBox некоторой целочисленной переменной и проверить его. Возвращаемые MsgBox значения приведены в таблице:

Имя константы Значение Нажатая кнопка
vbOK 1 OK
vbCancel 2 Cancel
vbAbort 3 Abort
vbRetry 4 Retry
vbIgnore 5 Ignore
vbYes 6 Yes
vbNo 7 No

Если в окне есть кнопка Cancel, нажатие клавиши Esc завершает работу в окне и возвращается тот же код vbCancel, что и при выборе кнопки Cancel.

В следующем примере создается окно с сообщением об ошибке и вопросом о продолжении вычисления. В нем пиктограмма важного сообщения и кнопки Yes и No, причем вторая - кнопка, выбираемая по умолчанию. Файл со справкой называется ERRORS.HLP, а номер контекстной справки в этом файле равен 200.

Public Sub Mes2()
	Dim Msg As String, MyString As String
	Dim Btns As Integer
	Dim Title As String, Help As String
	Dim NmbCont As Integer, Result As Integer
	
	Title = " Вы ввели неверные данные !"           ' заголовок окна.
	Msg = "Будем продолжать работу ?"               ' сообщение.
	Btns = vbYesNo + vbCritical + vbDefaultButton2  ' кнопки и свойства
	Help = "ERRORS.HLP"                             ' имя файла со справкой
	NmbCont = 200                                   ' номер темы
			' Вывод сообщения.
	Result = MsgBox(Msg, Btns, Title, Help, NmbCont)
	If Result = vbYes Then	         ' пользователь нажал кнопку Yes.
		MyString = "Да"              ' действия по продолжению работы
	'...
	Else                             ' пользователь нажал кнопку No.
		MyString = "Нет"             ' действия по прекращению работы
	'...
End If

End Sub

При этом вызове на экране появится окно:

(рис 12.4) Сообщение о неверных данных

Окно ввода данных. Функция InputBox

Окно, создаваемое функцией InputBox, предназначено для ввода строки и содержит однострочное окно редактирования, сообщение и кнопки OK и Cancel. При выборе кнопки OK (или нажатии клавиши Enter) строка, введенная пользователем в окне редактирования, передается в программу; щелчок кнопки Cancel (нажатие клавиши Esc) означает отказ от ввода - InputBox возвращает пустую строку.

Синтаксис вызова функции InputBox таков:

InputBox(prompt [,title ] [,default] [, xpos] [, ypos] [,helpfile, context])

Здесь параметры prompt (сообщение), title (заголовок), helpfile и context имеют тот же смысл, что и для функции MsgBox. Параметр default является строкой, задающей подсказку, появляющуюся в текстовом окне редактирования. Если пользователь не введет новый текст, то эта подсказка и будет служить его ответом. Когда этот параметр не задан, то окно редактирования при открытии пусто. Числовое выражение xpos задает расстояние по горизонтали левой границы окна от левой границы экрана. Если его нет, окно центрируется по горизонтали. ypos - расстояние верхней границы окна от верхней границы экрана. Если его нет, окно центрируется по вертикали.

В следующем примере в окно функции InputBox пользователь должен ввести дату рождения. Далее она проверяется. Если она в интервале от 01.01.1900 до 01.01.1985, запрашивается имя пользователя еще одним вызовом функции InputBox, иначе выдаются информационные сообщения с помощью функции MsgBox. Так как возвращаемое при первом вызове функции InputBox значение - строка, для его преобразования в дату применяется функция DateValue (для преобразования вводимых строк в числовые значения используется функция Val ).

Sub ExInput()
	Dim Msg As String, Title As String, Имя As String
	Dim Birthday As Date
	
	Msg = "Введите, пожалуйста, "  vbCrLf  "дату своего рождения."  'сообщение.
	Title = "Окно для ввода даты"            'заголовок.
	'	Вывод окна для ввода даты в позицию (1500,1000):
	Birthday = DateValue(InputBox(Msg, Title,, 1500, 1000))
	
	' Проверка даты:
	If Birthday < "01/01/1900" Then
		MsgBox "Вы выглядите гораздо моложе!", vbExclamation
	ElseIf Birthday > "01/01/1983" Then
		MsgBox "Эта программа не для детей до 16!", vbExclamation
	Else				' Дата корректна. Запрос имени пользователя:
		Имя = InputBox("Здравствуйте! Как Вас зовут?", "Знакомство", _
		"Владимир Биллиг",,, "My.hlp", 12)
		MsgBox Имя  ", рады Вам помочь.", vbExclamation, "Проверка ввода"
	End If
End Sub

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

(рис 12.6) Окно для ввода даты(рис 12.5) Окно для ввода имени(рис 12.7) Окно приветствия

Создание пользовательских диалоговых окон

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

Для создания новой формы нужно в меню редактора VBA выбрать выпадающее меню Вставка (Insert), а в нем - команду UserForm. На экране появится новое окно с пустой формой и расположенной рядом панелью элементов (Toolbox).

Щелкните это окно правой кнопкой мыши и выберите в появившемся контекстном меню команду Свойства (Properties). На экране появится окно Свойства-UserForm со списком свойств нового окна. Если выбрать вкладку По категориям, будет показан список свойств, сгруппированных по категориям. В частности, в категории Вид можно задать цвета окна и его границ и установить нужный заголовок окна в свойстве Caption. Свойства из других групп позволяют установить шрифт, используемый в окне, положение и размер окна и др. Чтобы подробнее узнать о свойстве, щелкните его и нажмите клавишу F1.

(рис 12.8) Заготовка диалогового окна

Затем нужно расположить в окне управляющие элементы (controls). Они выбираются на панели элементов Toolbox Если ее нет на экране, выберите команду Панель элементов (Toolbox) в меню Вид или щелкните ее пиктограмму на панели инструментов VBA. На панели элементов управляющие элементы представлены пиктограммами. Вы увидите имя элемента, установив указатель мыши на его пиктограмме.

Перетащите нужный элемент с панели элементов на предназначенное место в окно формы. Когда вы отпустите кнопку мыши, вокруг элемента появится прямоугольная рамка с выделенными точками, за которые ее можно перемещать по экрану, чтобы точнее расположить элемент управления в диалоговом окне и установить его размеры. Уточнить положения элемента в окне можно командами меню Формат (Format). Порядок обхода управляющих элементов формы устанавливает команда Последовательность перехода (TabOrder)из меню Вид или контекстного меню формы. Чтобы данный управляющий элемент никогда не попадал в фокус, щелкните его правой кнопкой мыши, выберите в появившемся контекстном меню команду Свойства, а затем в появившемся списке установите для свойства TabStop значение False. Отметим, что для текстовых надписей (элементов вида Label) это значение устанавливается по умолчанию. В окне "Свойства-элемента" можно установить при проектировании и другие свойства элемента управления. Списки свойств появляются в этом окне на вкладках По алфавиту (Alphabetic) и По категориям (Categorized) на первой - в алфавитном порядке, на второй - сгруппированы по категориям. Устанавливать значение свойства можно на любой из них.

Система автоматически именует новые элементы управления, образуя имя из типа элемента и его порядкового номера среди элементов данного типа. Например, у второй командной кнопки по умолчанию будет имя CommandButton2. Элементу можно присвоить новое имя, установив его в качестве значения свойства ( Name ). Помните, что имя идентифицирует объект (элемент управления или форму) в программе, поэтому изменение имени должно повлечь изменения в текстах процедур, его использующих. Не надо путать имя объекта ( Name ) со свойством Caption (заголовок, надпись), имеющимся у многих элементов управления. По умолчанию при создании элемента система присваивает этому свойству то же значение, что и имени Name. Изменение свойства Caption отражается на "внешности" элемента (надписи на экране), а на доступ к объекту из программы не влияет.

Можно одновременно изменить значение свойства для нескольких одновременно выделенных элементов управления (щелкните их при нажатой клавише Ctrl), установив нужное значение свойства для одного из этих элементов.

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

Создание страниц и вкладок в диалоговых окнах

В одном диалоговом окне можно разместить несколько страниц и вкладок со своими управляющими элементами. Страницы и вкладки стали непременными элементами интерфейса систем, работающих с Windows. Отметим, что названия этих элементов в Office 2000 отличаются от принятых, например, в Windows 95: элемент MultiPage (набор страниц) позволяет создавать страницы с разными элементами управления (традиционно они назывались вкладками), а новый элемент TabStrip (полоса вкладок) создает "вкладки" с одинаковыми наборами элементов управления. Чтобы создать новый набор страниц, нужно перетащить на форму элемент MultiPage. Вначале будут созданы две страницы, которым можно дать нужные заголовки, сделав их значениями свойства Caption в списке свойств. На следующем рисунке эти страницы получили имена "Ссуды" и "Ренты".

(рис 12.9) Создание страниц

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

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

Добавление дополнительных элементов управления

На панели элементов находятся пиктограммы не всех элементов управления, доступных в Office 2000. Доступ к дополнительным элементам управления Вы получите, щелкнув правой кнопкой панель элементов и выбрав в появившемся контекстном меню команду Дополнительные элементы (Additional Controls). На экране появится одноименное окно со списком доступных элементов управления (Available Controls).

(рис 12.10) Окно Дополнительные элементы

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

Пример создания диалогового окна

Давайте создадим диалоговое окно "Цветная форма", в котором будут расположены изображение (Image), поле ввода (TextBox) и командная кнопка (CommandButton).

  • В меню Вставка выберите команду UserForm для создания нового диалогового окна.
  • Щелкнув правой кнопкой появившееся окно UserForm1, выберите в контекстном меню команду Свойства. Введите новое имя ColorForm1 в правом столбце строки со свойством (Name), в качестве значения свойства Caption введите заголовок окна: "Цветная форма". Щелкните правый столбец в строке со свойством BackColor (Цвет фона), затем - появившийся справа значок списка. В таблице появившегося окна щелчком выберите понравившийся цвет. Окно "перекрасится". Закройте окно свойств.
  • Перетащите с панели инструментов на окно элемент Image (изображение). Щелкните его правой кнопкой и снова выберите команду Свойства. В появившемся окне со списком свойств отыщите строку со свойством Picture (Рисунок). Чтобы перейти к поиску нужного файла с картинкой, щелкните кнопку с многоточием (…) справа в этой строке. В диалоговом окне Загрузка рисунка (Load Picture) выберите файл с симпатичной картинкой и щелкните кнопку OK.
  • Перетащите на диалоговое окно элемент управления поле ввода (TextBox). Как и в п. 3, щелкнув его правой кнопкой, вызовите окно Свойства. Введите в качестве значения свойства Value название выбранной вами картинки - оно появится в окне редактора. Затем выберите свойство Font Справа появится кнопка (…). Щелкните ее и в появившемся списке шрифтов выберите шрифт для редактора.
  • Перетащите на диалоговое окно командную кнопку (CommandButton). Вызовите окно Свойства для этой кнопки, и измените в нем значение свойства Caption (Заголовок) на "Нажми меня" - текст станет именем кнопки. Измените имя кнопки (Name) на cmdClickMe. По этому имени к кнопке будут обращаться процедуры и методы в программе. Введите справку "Командная кнопка" как значение свойства ControlTipText - надпись будет появляться на экране под кнопкой всякий раз, когда на ней окажется указатель. Установите для кнопки ключ быстрого выбора: найдите в списке свойств строку со свойством Accelerator (Ускоритель) и введите в поле справа букву "Н" - в имени кнопки первый символ "Н" будет подчеркнут и нажатие клавиш Alt+Н будет эквивалентно выбору кнопки. Установите также подходящий шрифт с помощью свойства Font, как и для поля ввода.
  • В меню Запуск выберите команду "Запуск подпрограммы/UserForm". На экране приложения появится спроектированное диалоговое окно.(рис 12.11) Цветная форма
  • Щелкните кнопку Close на заголовке диалогового окна, чтобы выйти из него.
  • Разработка процедур, обрабатывающих события диалогового окна и его устройств

    Процедуры, обрабатывающие события, связанные с диалоговыми окнами и элементами управления, - это частный случай процедур, обрабатывающих события объектов Office 2000. С диалоговым окном (формой) и с элементом управления каждого типа связан заранее определенный набор событий, возникающих для этого объекта по инициативе пользователя или системы. Например, одно из связанных с формой событий Initialize (Инициализация) возникает при загрузке формы, а связанное с командной кнопкой (CommandButton) событие Click возникает, когда пользователь щелкает эту кнопку (или нажимает клавишу Enter, если эта кнопка определена как нажимаемая по умолчанию). Процедуры обработки событий позволяют описать поведение диалогового окна или отдельного элемента управления при наступлении того или иного события.

    Чтобы перейти в окно редактора для ввода текста процедуры обработки события, щелкните дважды объект, к которому оно относится (элемент управления или свободную от элементов часть формы). Появится окно Code (Код). В раскрывающемся списке слева вверху перечислены все объекты формы; при выборе объекта в этом списке справа вверху появляются события, связанные с данным объектом. Ниже на рис. 12.10 показан список событий для командной кнопки.

    События, для обработки которых процедуры уже написаны, выделены полужирным начертанием. Чтобы создать новую процедуру или отредактировать имеющуюся, нужно щелкнуть в списке соответствующее событие. На экране появится шаблон новой процедуры или текст написанной. Имя такой процедуры состоит из имени устройства или формы, за которым после подчеркивания идет имя события. Так, процедура, обрабатывающая событие Click для командной кнопки CommandButton1, называется CommandButton1_Click. Из-за такого способа именования процедур будьте осторожны при переименовании элементов управления. Если Вы сначала определили для элемента процедуры обработки событий, а затем переименовали его (изменив свойство Name ), никаких процедур обработки событий у элемента с новым именем не будет (их придется перенести с помощью редактора).

    (рис 12.12) События элемента CommandButton

    Взгляните на процедуру обработки события Click для командной кнопки cmdClickMe диалогового окна "Цветная форма":

    Private Sub cmdClickMe_Click()
    	MsgBox "Поздравляю !"
    	ColorForm1.TextBox1.Value = "Симпатичный, правда?"
    
    End Sub

    Эта процедура автоматически вызывается при выборе кнопки "Нажми меня" и выводит на экран поздравление, а затем заменяет название картинки в окне редактирования.

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

    Вызов собственного диалогового окна

    Диалоговое окно нуждается в отладке. В редакторе VBA Вы видите его изображение, но управляющие элементы находятся в "замороженном" состоянии, и их реакция на действия пользователя - это реакция редактора, а не самих элементов. Диалоговое окно запускается на исполнение командой запуска процедуры или формы Запуск подпрограммы/UserForm меню Запуск редактора или нажатием клавиши F5. - Ваше диалоговое окно появится в рабочем состоянии на основной панели того приложения Office 2000, в котором оно создано.

    А вызывается диалоговое окно в прикладной системе методом Show (Показать). Он позволяет выводить окно на экран в качестве реакции на выбор соответствующей команды меню или командной кнопки в другом окне и т. п. Например, диалоговое окно MyForm выводится так:

    MyForm.Show

    Установка начальных значений свойств элементов управления

    Начальное значение (или значение по умолчанию) свойства элемента управления можно установить в процедуре, обрабатывающей событие Initialize (Инициализация) диалогового окна, содержащего данный элемент. Это событие возникает всякий раз при выводе диалогового окна на экран и запускает на выполнение процедуру без аргументов с именем ИмяОкна_Initialize. Поэтому установленные в ней значения свойств всегда будут начальными. Это не значит, что они должны быть постоянными. Значения могут зависеть от текущей даты, данных в ячейках рабочего листа Excel, некоторых записей в базе данных Access и т. п.

    Давайте создадим диалоговое окно с процедурой инициализации.

  • Создайте новое диалоговое окно и разместите в нем статический текст Label (Метка), поле ввода TextBox, окно списка ListBox и кнопку независимого выбора (флажок) CheckBox.
  • В окне Свойства, измените их имена (свойство Name): Label - на (рис 12.13) Окно до инициализации
  • Дважды щелкните диалоговое окно, чтобы вызвать окно с кодом (Code). Установите в списке объектов слева вверху UserForm (по умолчанию этот объект и будет выбран при вызове окна кода) и выберите команду Initialize в списке процедур справа вверху. На экране появится шаблон процедуры инициализации диалогового окна UserForm_Initialize. Введите текст следующей процедуры.
    Private Sub UserForm_Initialize()
    	With frmInit
    		.Caption = "Окно после инициализации"    ' заголовок диалогового окна
    		.CurrDate.Caption = "Сегодня "  Format(Date, "dd/mm/yy")
    		                                         'метка - текущая дата
    		.MyText.Text = "Любимый цвет:"           'начальный текст в редакторе
    		.chkGood.Value = True                    'включение флажка
    		.chkGood.Caption = " Хороший день"       ' заголовок флажка
    		With.lstColors                           'задание элементов списка:
    			.AddItem "белый"
    			.AddItem "черный"
    			.AddItem "синий"
    			.AddItem "красный"
    			.AddItem "зеленый"
    			.AddItem "желтый"
    			.AddItem "голубой"
    			.ListIndex = 4   'выбор 5-го элемента в списке ("зеленый")
    		End With
    	End With
    
    End Sub
    Нумерация элементов массивов и коллекций, связанных с формами, начинается с 0. Поэтому, чтобы выделить при выводе окна пятый элемент в списке цветов, свойству ListIndex присвоено значение 4.
  • Запустите диалоговое окно в отладчике. На экране оно будет выглядеть так:(рис 12.14) Окно после инициализацииЩелкнув кнопку Close (Закрыть) на строке заголовка окна, возвратитесь в режим проектирования.
  • Использование Me в качестве имени текущего диалогового окна

    Для упрощения написания кода процедур VBA позволяет в качестве имени текущего диалогового окна применять ключевое слово Me (это похоже на использование указателя текущего объекта This в С++). В частности, в предыдущем примере вместо оператора:

    With frmInit

    можно было использовать:

    With Me

    Модификация управляющих элементов во время работы

    Устанавливать программно новые значения свойств элементов управления можно не только при инициализации диалогового окна, но и во время работы пользователя (и системы) в нем. В любой процедуре обработки события, связанного со всем диалоговым окном или его отдельным элементом, можно присвоить значение свойству или вызвать метод любого управляющего элемента. Например, эти команды изменяют текст в окне редактора и снимают флажок в окне предыдущего примера:

    Public Sub ChangeForm()
    	With Me
    		.MyText.Text = "Нелюбимый цвет:"  'новый текст в редакторе
    		.lstColors.ListIndex = 1	  'черный
    		.chkGood.Value = False	          'отключение флажка
    	End With
    
    End Sub

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

    Управление доступом к элементу

    Все элементы управления обладают свойством Enabled (Доступен), позволяющим управлять их доступностью. В результате действий пользователя или системы доступный элемент может стать активным - получить фокус клавиатуры. Если свойству Enabled присвоить False, элемент управления становится недоступен ("сереет") и не может попасть в фокус. Управление доступностью производится динамически и зависит от задач, решаемых в диалоговом окне. Типичный случай - запрет на доступ к окну поля ввода (TextBox) после того, как система поместила в него данные, которые не должны далее изменяться пользователем (например, текст справки, которую можно только прочесть и распечатать). Другой случай - отключение/включение доступа к группам переключателей или кнопок зависимого выбора (OptionButton) или отдельным таким кнопкам в зависимости от состояния флажка (CheckBox). При этом действия по изменению доступа надо проводить в процедуре, обрабатывающей событие Change (Изменение), автоматически вызываемой в тот момент, когда флажок меняет свое состояние, т. е. становится неотмеченным или отмеченным.

    Выполните следующие действия:

  • Создайте новое диалоговое окно (UserForm) и включите в него флажок (CheckBox), управляющий элемент Frame (Рамка), и командную кнопку (ComandButton). Поместите в рамку еще 4 флажка (CheckBox). Заголовки управляющих элементов (значения свойства (рис 12.15) Окно "Пример управления доступом"
  • Дважды щелкните верхний флажок, чтобы вывести окно с кодом процедур, выберите в списке объектов слева вверху CheckBox1 (это имя присвоила флажку система), затем в списке процедур обработки событий справа вверху щелкните событие Change. Дополните появившуюся заготовку процедуры CheckBox1_Change:
    Private Sub CheckBox1_Change()
    	With Me
    		If.CheckBox1.Value Then          'отключение опций
    			.CheckBox4.Enabled = False
    			.CheckBox5.Enabled = False
    		Else                             'включение опций
    			.CheckBox4.Enabled = True
    			.CheckBox5.Enabled = True
    		End If
    	End With
    
    End Sub
  • Создайте стандартный модуль и напишите в нем две процедуры:
    Public Sub CheckOptions()
    	'Проверка на дорогах
    	Dim Msg As String
    	Msg = "Выполняю проверку на "
    	With frmChecking
    		
    		If.CheckBox2.Value Then Msg = Msg  vbCrLf  "корректность дат"
    		If.CheckBox3.Value Then Msg = Msg  vbCrLf  "согласованность данных"
    		If.CheckBox4.Value Then Msg = Msg  vbCrLf  "правильность расходов"
    		If.CheckBox5.Value Then Msg = Msg  vbCrLf  "правильность доходов"
    		MsgBox (Msg)
    		.Hide
    	End With
    End Sub
    
    Public Sub SetOptions()
    	frmChecking.Show
    End Sub
    Процедура SetOptions открывает нашу форму, предоставляя пользователю возможность включать или выключать те или иные флажки. Установив нужные значения, он может затем щелкнуть кнопку "Проверка". Обработчик этого события будет вызывать функцию CheckOptions, которая и производит проверку состояния каждого из четырех флажков группы. Заметьте, что проверка свойства Value не зависит от состояния свойства Enabled. Если даже флажок недоступен, но включен ( Value = True ), то появится сообщение о выполнении проверки. Недоступный флажок не позволяет пользователю изменить его состояние, но программно ѕ все в Ваших руках. Сделаем еще одно замечание. Реально, верхний флажок, управляющий проверкой, должен находиться в другой форме, более высокого уровня, но мы уже не стали усложнять задачу.
  • Напишите обработчик события командной кнопки:
    Private Sub CommandButton1_Click()
    	CheckOptions
    End Sub
  • Теперь, если выполнить процедуру (рис 12.16) Окно проверки в процессе работы
  • Если в этом состоянии окна щелкнуть командную кнопку "Проверка", то будет выведено сообщение о двух выполняемых проверках:(рис 12.17) Окно сообщений о выполняемых проверках
  • Перемещение фокуса на элемент управления

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

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

    Private Sub CommandButton1_Click()
    	With Me
    		If.TextBox1.Text = "" Then
    Beep: Beep: Beep
    			.TextBox1.SetFocus
    		Else
    			GlobeVar =.TextBox1.Text
    			MsgBox GlobeVar
    			.Hide
    		End If
    	End With
    End Sub

    Вот как выглядит эта простая форма ввода в процессе работы с ней:

    (рис 12.18) Простая форма ввода

    Изменение размеров диалогового окна

    Из процедур обработки событий можно менять свойства не только отдельных элементов управления, но и всего окна. В качестве примера рассмотрим динамическое изменение его размеров. Ранее мы уже говорили о том, что, изменяя размеры окна, можно скрывать те или иные элементы управления. Сейчас продемонстрируем это на примере. На стадии проектирования разместим в окне элементы управления, которые при первоначальном открытии окна не должны быть видны, но должны появиться в процессе работы пользователя с этим окном. Пусть в форме Cutting есть командная кнопка "Получить данные", и поля ввода "Доходы" и "Расходы" При открытии окна поля ввода недоступны, что достигается "отсечением" нижней части формы в процедуре инициализации. Вот как выглядит обработчик события Initialize нашей формы:

    Private Sub UserForm_Initialize()
    	'Отсечение нижней части формы
    	Me.Height = 90
    End Sub

    Так выглядит форма при ее открытии:

    (рис 12.19) Усеченная форма в момент ее открытия

    После щелчка командной кнопки обработчик события Click восстанавливает размер, заданный при проектировании формы. Он задает также и значения скрытых ранее полей:

    Private Sub CommandButton1_Click()
    	With Me
    		'Установить нормальную высоту формы
    		.Height = 200
    		'Задать значения ранее не видимых полей
    		.Доходы = 1570
    		.Расходы = 1500
    	End With
    	
    End Sub

    А так выглядит эта же форма после щелчка командной кнопки:

    (рис 12.20) Форма Cutting со скрытыми ранее полями

    Проверка корректности данных

    Одна из важных функций диалоговых окон, - прием и передача данных, введенных пользователем, для хранения и дальнейшей обработки в систему. Основной вид элементов управления, предназначенных для ввода, - это окна редактирования (TextBox). Для предотвращения ошибок, связанных с неверным типом введенных данных или нарушением некоторых условий, которым эти данные должны удовлетворять следует проверять их корректность до выхода из диалогового окна. Чуть выше мы приводили пример работы с простой формой ввода, где проверялась ситуация, когда пользователь "забыл" ввести данные в окно ввода. Сейчас мы рассмотрим ситуацию, в которой пользователь пытается ввести некорректные данные в поле ввода. Возникает вопрос, где следует проводить проверку на корректность данных? По-видимому, одним из лучших мест является обработчик события Exit, которым обладает элемент управления TextBox. Обработчик этого события вызывается при попытке выхода из окна редактирования. Здесь и следует проводить проверку введенных данных, чтобы не допустить выхода, если данные заданы некорректно.

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

    Private Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean)
    	Dim Msg As String
    	Const MinTemp = 34
    	Const MaxTemp = 42
    	Msg = "Ошибка ввода:"  vbCrLf
    	'Проверка, являются ли данные числовыми
    	If Not IsNumeric(TextBox1.Text) Then
    		Msg = Msg  "Введите числовые данные в формате: ##.#"
    		MsgBox Msg
    		Cancel = True	'Оставляет фокус в поле ввода
    		
    	ElseIf TextBox1.Text < MinTemp Then
    		Msg = Msg  "Температура слишком низкая"  vbCrLf _
    			 "Проверьте, что с Вашим больным!"
    		MsgBox Msg
    		Cancel = True	'Оставляет фокус в поле ввода
    	ElseIf TextBox1.Text > MaxTemp Then
    		Msg = Msg  "Температура слишком высокая"  vbCrLf _
    			 "Проверьте, что с Вашим больным!"
    		MsgBox Msg
    		Cancel = True	'Оставляет фокус в поле ввода
    	Else
    		GlobeVar = TextBox1.Text
    		Debug.Print GlobeVar
    	End If
    	
    End Sub

    Событие Exit имеет параметр Cancel, значение которого следует установить в обработчике события. Если параметру присвоить значение True, то фокус остается на текущем элементе, в противном случае он переходит к элементу, следующему согласно Tab - порядка. Вот как выглядит форма при попытке задания некорректного значения температуры:

    (рис 12.21) Проверка корректности ввода данных

    Обмен данными с диалоговым окном

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

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

    (рис 12.22) Лист Excel, хранящий информацию о состоянии элементов формы

    Пять ячеек листа SavedData рабочей книги BookOne12 хранят нужную информацию. Заметьте, ячейка A1 именована. Ее имя "Данные" будет использовано в обработчиках событий. На этом же листе расположена командная кнопка "Вызов Формы". Ее обработчик события очень прост, ѕ он вызывает форму:

    Private Sub CommandButton1_Click()
    	frmInit.Show
    End Sub

    А вот как выглядит сама форма в момент ее открытия:

    (рис 12.23) Форма при ее открытии

    Эта форма уже использовалась в наших примерах. Ранее она была связана с документом Word, а теперь мы перетащили ее в рабочую книгу Excel, используя операции Export - Import. После чего форма была слегка модифицирована добавлением в нее новых командных кнопок ѕ Save, Reset и Cancel. Прежде, чем рассказать о них подробнее, приведем уже встречавшиеся обработчики событий. Наша форма одинаково реагирует на два события Initialize и Activate. Первое из них возникает, когда форма открывается после того, как она была выгружена. Если же форма удаляется с экрана методом Hide, то при ее повторном открытии событие Initialize не возникает. Поскольку мы хотим, чтобы и в этом случае происходила инициализация свойств формы, то определен и обработчик события Activate, выполняющий те же действия. Поскольку оба обработчика эквивалентны, то приведем текст только одного из них:

    Private Sub UserForm_Activate()
    	With frmInit
    		.Caption = "Окно после инициализации"      ' заголовок диалогового окна
    		.CurrDate.Caption = "Сегодня "  Format(Date, "dd/mm/yy")
                                                       'метка - текущая дата
    		.MyText.Text = "Любимый цвет:"             'начальный текст в редакторе
    		.chkGood.Value = True                      'включение флажка
    		.chkGood.Caption = " Хороший день"         ' заголовок флажка
    		With.lstColors                             'задание элементов списка:
    			.AddItem "белый"
    			.AddItem "черный"
    			.AddItem "синий"
    			.AddItem "красный"
    			.AddItem "зеленый"
    			.AddItem "желтый"
    			.AddItem "голубой"
    			.ListIndex = 4              'выбор 5-го элемента в списке ("зеленый")
    		End With
    	End With
    
    End Sub

    Этот обработчик задает начальные свойства элементов управления ѕ объектов формы в момент ее открытия. После чего с формой работает пользователь. Форма простая, поэтому возможностей у него не много, тем не менее, он может выбрать из списка понравившийся ему цвет, отключить флажок, щелкнуть по командной кнопке "Change". В ответ на последнее действие будет вызван соответствующий обработчик, который программно изменит состояние объектов формы. Текст этого обработчика уже приводился ранее, напомним его:

    Private Sub CommandButton1_Click()
    	ChangeForm
    End Sub
    Public Sub ChangeForm()
    	With Me
    		.MyText.Text = "Нелюбимый цвет:"    'новый текст
    		.lstColors.ListIndex = 1	    'черный
    		.chkGood.Value = False	            'отключение флажка
    	End With
    
    End Sub

    Нам осталось рассмотреть действие новых командных кнопок. Обработчик события Click кнопки Save позволяет сохранить текущее состояние элементов управления формы. Затем это состояние может быть проанализировано, например, для того, чтобы выдать психологический портрет пользователя. Цель сохранения может быть и другая, ѕ иметь возможность вернуться к текущему состоянию при повторном открытии формы. С чисто программистской точки зрения задача сохранения состояния решается просто, главный вопрос это, где и в какой форме хранить состояние элементов управления. В данном случае мы выбрали ячейки листа Excel. Вот текст этого обработчика:

    Private Sub cmdSave_Click()
    	'Сохранение данных формы в ячейках листа SavedData книги BookOne12
    	Dim Beg As Range
    	Set Beg = Range("[BookOne12.xls]SavedData!Данные")
    	With frmInit
    		Beg.Offset(1, 0) =.CurrDate.Caption	'дата
    		Beg.Offset(1, 1) =.lstColors.ListIndex  'индекс в списке
    		Beg.Offset(1, 2) =.lstColors.Value	'цвет
    		Beg.Offset(1, 3) =.chkGood.Value        'состояние флажка
    		Beg.Offset(1, 4) =.MyText.Text		'текст в окне ввода
    		'Форма прячется
    		.Hide
    	End With
    		
    End Sub

    Обратите внимание, при работе с ячейками Excel используется техника, основанная на смещении Offset. Вначале фиксируется начальная ячейка, имеющая имя "Данные", и уже относительно ее выполняются действия над остальными ячейками.

    Командная кнопка Reset позволяет восстановить сохраненное состояние элементов управления формы. Обработчик события Click для этой кнопки выполняет действия, обратные тем, что делаются при сохранении состояния. Вот текст этого обработчика:

    Private Sub cmdReset_Click()
    	 'Восстановление данных формы из ячеек листа SavedData книги BookOne12
    	Dim Beg As Range
    	Set Beg = Range("[BookOne12.xls]SavedData!Данные")
    	With frmInit
    		.CurrDate.Caption = Beg.Offset(1, 0)
    		.lstColors.ListIndex = Beg.Offset(1, 1)
    		.lstColors.Value = Beg.Offset(1, 2)
    		.chkGood.Value = Beg.Offset(1, 3)
    		.MyText.Text = Beg.Offset(1, 4)
    	End With
    End Sub

    Обработчик события Click для кнопки Cancel просто закрывает форму без сохранения состояния элементов:

    Private Sub cmdCancel_Click()
    	frmInit.Hide
    End Sub

    Закрытие диалогового окна

    Диалоговые окна в Office 2000 всегда работают в режиме модального диалога. Это значит, что пользователь должен полностью завершить работу в окне и закрыть его, прежде чем сможет перейти к действиям, не связанным с работой в этом диалоговом окне. Заметим, что немодальный диалог в Office 2000 также можно организовать, но для этого потребуется использовать объект Assistant с его баллончиками ѕ объектами Balloon. Для завершения работы с диалоговым окном применяется оператор UnLoad или метод Hide, вызываемые в обработчиках события, завершающих работу в диалоговом окне. Обычно в диалоговое окно включается одна или несколько кнопок, выбор которых приводит к завершению работы в нем ("Отказ", "Выход", "Сохранить", "Готово", "Конец работы" и т. п.).

    Ранее мы уже говорили о разнице между UnLoad и Hide, первый ѕ выгружает форму, второй только прячет ее. Есть и синтаксическая разница, Hide - это метод формы, в то время как UnLoad и Load - это встроенные функции, которым в качестве параметра передается имя формы. Мы обращали также внимание и на то, что при открытии спрятанной формы не возникает событие Initialize. В заключение, скажем, что в Office 97 были проблемы с методом Hide, поэтому я всегда пользовался только методом UnLoad, в Office 2000 метод Hide работает должным образом.

    Страницы:

    Программный код большинства примеров данной лекции можно найти в проектах, доступных для просмотра: BookOne12, DocOne12.

    Диалоговые окна и элементы управления

    Диалоговые окна (формы) и элементы управления составляют основу современного визуального интерфейса. Все эти элементы и технология работы с ними в основном стандартизованы и являются похожими для разных платформ и программных сред. Поэтому не удивительно, что приложения Excel, Word и PowerPoint разделяют единые объекты, задающие диалоговые окна и элементы управления. Эти объекты помещены в специальную библиотеку MSForms. Несколько особняком стоит Access. И здесь все доступно, но по-своему.

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

    Выделим некоторые основные моменты, которые следует иметь в виду при создании визуального интерфейса:

    Все загруженные диалоговые окна представляют коллекцию UserForms. Формально, это глобальная внутренняя переменная, - Вы не найдете UserForms в окне просмотра объектов. Тем не менее, это нормальная коллекция со стандартными методами и свойствами, - метод Item позволяет по имени или номеру добраться до любого ее элемента, а метод Add добавляет новое диалоговое окно (форму) в коллекцию. Элемент коллекции - объект класса UserForm задает отдельное окно.

    Для каждого типа элементов управления в библиотеке MSForms имеется класс объектов, имя которого совпадает с именем элемента управления (его типа). Например, есть классы SpinButton и TextBox.

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

    На этапе проектирования, используя окно свойств, можно задать большинство свойств, как самого диалогового окна, так и всех элементов управления, помещенных в это окно. Автоматически, конечно же, меняются и свойства соответствующего объекта. Заметьте, что есть еще две возможности изменения свойств этих объектов. Свойства может менять конечный пользователь. Заметьте, что элементы управления именно для этого и существуют, чтобы конечный пользователь мог определять некоторые (но не все) свойства, например, пользователю разрешается вводить текст в окна редактирования. Но есть и третья возможность - изменение свойств программным путем. Как правило, все свойства, доступные конечному пользователю, либо доступные на этапе проектирования, доступны для изменения программным путем.

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

    Есть все-таки одна проблема: куда помещать программный код? Ведь методы объектов жестко запрограммированы и не подлежат изменениям. К счастью есть у объектов события и обработчики событий надо программировать самому. Именно сюда и помещают код. Обработчик события может быть достаточно сложным и по ходу своей работы может вызывать десяток, другой локальных процедур и функций. Как правило, события задают реакцию на действия конечного пользователя, - ответом может быть изменение свойств объектов, вызов их методов, появление новых элементов управления и переход к новым диалоговым окнам.

    Поговорим об отладке. Написание обработчиков событий следует относить, по-видимому, к этапу проектирования. Когда этот этап закончен, - окно создано и заселено элементами, их свойства установлены, обработчики событий написаны, - возникает естественный вопрос " А будет ли все это правильно работать?" Чтобы вести отладку, можно, конечно, перейти в режим выполнения приложения. Однако это не эффективно, лучше вести локальную отладку - для этого достаточно выбрать команду Run Sub/UserForm из меню Run в VBA редакторе. Заметьте, что для отображения формы в режиме выполнения должен быть вызван ее метод Show.

    Несколько слов следует сказать о методах Show, Hide и Load объекта UserForm. Метод Load загружает диалоговое окно и делает его доступным для программирования (объект определен). Но окно не отображается на экране дисплея и конечный пользователь не может работать с ним и его элементами. Чтобы окно сделать видимым, нужно вызвать его метод Show, чтобы видимое окно спрятать - метод Hide.

    Можно прятать не только само окно, но и отдельные его элементы управления. Возможен, например, такой способ, - в одну половину "большого" окна поместить одни элементы управления, в другую - другие. Затем, в режиме выполнения динамически задать размеры окна так, чтобы они определяли только одну половину окна - тогда и видимы будут элементы только этой половины. Затем можно организовать переключение так, чтобы видимой была та или другая половина окна со своими элементами.

    В предыдущем пункте мы говорили о том, как сделать некоторые элементы управления невидимыми, а, следовательно, и недоступными для изменений. Чаще, однако, применяется другая стратегия - видимые элементы можно сделать недоступными для изменений. Практически все элементы имеют булево свойство Enabled. Если дать ему значение True, то элемент считается включенным и доступен для изменения. Чтобы "выключить" его и сделать недоступным, достаточно изменить значение свойства Enabled на False. Обычно, программным путем проверяются контекстные условия, при выполнении которых элемент включается и является доступным для изменений.

    Объекты, отвечающие за диалоговое окно и элементы управления, определены в период загрузки диалогового окна. Окно можно выгрузить, вызвав метод UnLoad, и тогда сам объект UserForm и все объекты, соответствующие вложенным в него элементам управления, становятся недоступны для программирования, - их свойства теряются. Важно понимать, что, зачастую, необходимо сохранять информацию о свойствах элемента управления долговременно в файлах постоянной памяти, - это и ввод, сделанный пользователем, и полученные в процессе работы результаты. В этих случаях в программу вводятся переменные, предназначенные для хранения значений тех или иных свойств элементов управления. Их срок жизни другой и не связан с загруженной формой. Поэтому перед применением UnLoad следует запомнить значения нужных свойств в переменных программы с возможной записью их в файл перед окончанием работы. Аналогично, при повторном сеансе свойства устанавливаются, используя сохраненные в файле значения.

    Еще несколько слов о методах Load и UnLoad. Понятно, что это не совсем обычные методы, особенно Load - он не может быть методом, так как до его выполнения объект UserForm не существует, а не существующий объект не может вызывать никаких методов. Поэтому Load является оператором, синтаксис которого:

    Load <объект класса UserForm>.

    За компанию и UnLoad является оператором с аналогичным синтаксисом.

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

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

    Созданное диалоговое окно в одном приложении можно экспортировать в другие приложения Office 2000. Но нужно быть осторожным - для корректной работы должны использоваться только средства VBA, не содержащие специфических для приложения объектов.

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

    В Office 2000 определен весьма полезный элемент управления MultiPage. С его помощью достаточно просто организовать многостраничное диалоговое окно (окно с несколькими вкладками). Вначале в окно помещается этот элемент, устанавливается нужное число страниц, а затем, выбирая вкладку, соответствующую нужной странице, эта страница проектируется обычным способом.

    Близким по духу к MultiPage является элемент управления TabStrip. Если первый задает несколько страниц с разнородным составом элементов управления, то второй определяет несколько страниц с одинаковым набором элементов. Типичная ситуация применения TabStrip - диалоговое окно отвечает за обработку данных нескольких отделов. Все формы представления данных по каждому отделу одинаковы и отличаются только содержащейся в этих формах информацией. TabStrip для каждого из отделов создает свою вкладку.

    До сих пор мы говорили, что ActiveX и элементы управления можно располагать в диалоговых окнах. Эти окна представляют некоторый способ группирования элементов и придают структуру пользовательскому интерфейсу. Можно, однако, размещать все эти элементы и вне диалогового окна непосредственно на документе Word, рабочем листе или листе диаграмм Excel или на слайде презентации PowerPoint. Иногда, особенно когда число элементов невелико, так поступать удобнее - есть данные, а рядом - кнопка, щелчок которой обрабатывает эти данные. Злоупотреблять такой возможностью мы, правда, не рекомендуем.

    Общие сведения и применение

    Диалоговое окно представляет собой прямоугольную область экрана, где размещены элементы управления, с которыми работает пользователь. В Office 2000 масса встроенных элементов управления, позволяющих спроектировать и реализовать интерфейс типичной офисной системы. Если же встроенных элементов управления не хватает, Вы можете использовать в своем диалоговом окне произвольные ActiveX -объекты.

    Три приложения Office 2000 - Excel, Word и PowerPoint - содержат в редакторе VBA одинаковые средства создания диалоговых окон и программирования процедур обработки событий для них и для их управляющих элементов. В Access наряду с аналогичными средствами создания собственного диалогового окна, включены также мастера, помогающие проектировать специальные диалоговые окна, связанные с вводом и выводом информации, хранящейся в базе данных.

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

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

    Встроенные диалоговые окна

    Коллекция Dialogs и объект Dialog

    Рассматривая общие объекты, используемые при организации пользовательского интерфейса, нельзя не упомянуть коллекцию Dialogs, которую можно использовать в приложениях Word и Excel. Элементы этой коллекции - объекты класса Dialog представляют встроенные в приложение диалоговые окна, появляющиеся по ходу работы с документами. Из этой коллекции ничего нельзя удалить и ничего в нее нельзя добавить. В любой момент можно только открыть любое из существующих встроенных диалоговых окон и предоставить пользователю возможность работы с ним, например, открыть файл или организовать поиск нужной информации. Чтобы добраться до нужного диалогового окна, используется обычная конструкция: Dialogs (<имя окна>), где имя окна задается константой. Все имена констант строятся по одному принципу, - они начинаются с префикса wdDialog или xlDialog (для Word и Excel соответственно), а затем идет имя окна. В приложении Word это полное имя, включающее все меню, которые надо открыть при вызове диалогового окна "вручную". Так, например, для открытия диалогового окна "Open" из меню File в приложении Word следует вызвать метод Show следующим образом:

    Dialogs(wdDialogFileOpen).Show

    Сразу же появится окно:

    (рис 12.1) Диалоговое окно открытия файла

    В Excel этот же вызов будет иметь вид:

    Application.Dialogs(xlDialogOpen).Show

    Заметьте, что в первом случае - это глобальный объект и поэтому его можно вызывать непосредственно, в Excel же необходимо указание корневого объекта Application, чье свойство Dialogs и возвращает коллекцию Dialogs. Но зато в Excel достаточно короткого имени для вызова диалогового окна. Метод Show открывает диалоговое окно и позволяет пользователю работать в нем. В зависимости от того, какую кнопку нажал пользователь при выходе из окна, возвращается результат: в Excel это True или False (нажаты кнопки OK или Cancel), в Word можно точнее проанализировать, какая кнопка была нажата. Метод Show - основа работы с диалоговыми окнами, по сути больше ничего и не нужно: в нужный момент открывается нужное диалоговое окно, пользователь работает в нем и по закрытии можно понять, успешно ли закончилась его работа.

    Тем не менее, Word предоставляет некоторые дополнительные возможности. В частности, наряду с методом Show, можно применять метод Display, отличающийся тем, что хотя окно и открывается, но ввод от пользователя оно принять не может и используется только в информационных целях. Word позволяет также создавать объекты класса Dialog и программно устанавливать значения полей диалогового окна, еще до того, как оно будет показано пользователю, беря тем самым на себя часть его работы. Метод Execute позволяет эти установки зафиксировать. Вот пример, в котором делаются некоторые установки в диалоговом окне Replace:

    Public Sub Dialogs2()
    	Dim MyDialog As Dialog, Answer As Variant
    	Set MyDialog = Dialogs(wdDialogEditReplace)
    	MyDialog.Find = "коллекция"
    	MyDialog.Replace = "семейство"
    	MyDialog.FuzzyFind = True
    	Answer = MyDialog.Show
    	Debug.Print Answer
    
    End Sub

    В процессе работы этой процедуры появится окно:

    (рис 12.2) Диалоговое окно замены

    Обратите внимание, мы используем у объекта MyDialog такие свойства, как Find, Replace и даже FuzzyFind, соответствующие полям диалогового окна (В браузере объектов Вы не найдете поля FuzzyFind ). В документации по Word можно найти список допустимых параметров для каждого типа диалогового окна.

    Поскольку действительно важно уметь установить программно некоторые характеристики в диалоговом окне, то и в Excel предусмотрена такая возможность. Здесь всю работу выполняет метод Show,- он имеет до 30 возможных параметров и, используя их, можно передать при открытии окна всю необходимую информацию.

    Вывод сообщений. Функция MsgBox

    Рассмотрим сейчас встроенные диалоговые окна, которые появляются при вызове некоторых функций VBA. И начнем наше рассмотрение с функции MsgBox, предназначенной для вывода сообщений. Диалоговое окно, создаваемое функцией MsgBox, служит для вывода на экран сообщения программы и получения от пользователя простой реакции на это сообщение в виде щелчка одной из кнопок окна. В простейшем случае эта функция вызывается как процедура. Например, вызов:

    MsgBox "Сегодня на календаре"  Date

    выведет окно:

    (рис 12.3) Пример окна сообщений

    После щелчка кнопки OK вызов функции завершится, и выполнение программы возобновится с оператора, стоящего непосредственно за этим вызовом.

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

    MsgBox(prompt[, buttons] [, title] [, helpfile, context])

    Здесь параметр prompt (сообщение) - строковое выражение, значение которого выводится в окне. Его максимальная длина не должна превышать 1024 символов. Разбиение на строки в этом выражении можно производить, используя символ возврата каретки ( Chr(13) ), символ перевода строки ( Chr(10) ), их комбинацию ( Chr(13) Chr(10) ) или константу vbCrLf. Числовой параметр buttons (кнопки) задает виды командных кнопок, помещаемых в окне, кнопку, выбираемую по умолчанию, и модальность диалогового окна. Он получается как сумма кодов соответствующих кнопок и свойств. Явно не заданный, этот параметр считается равным 0. Строковое выражение title (заголовок) задает заголовок окна. Если его нет, заголовком становится имя приложения (см. пример, приведенный выше, где мы использовали Word). Параметры helpfile (файл справки) и context (контекст) должны присутствовать (или отсутствовать) вместе. Первый из них - имя файла, содержащего справку, которая будет выведена при нажатии клавиши F1, а второй - числовое выражение, задающее номер темы со справкой в этом файле.

    Вот коды кнопок и других свойств окна функции MsgBox:

    Имя константы Код Описание
    Коды наборов командных кнопок
    vbOKOnly 0 только кнопка OK (Готово)
    VbOKCancel 1 кнопки OK и Cancel (Отказ)
    VbAbortRetryIgnore 2 кнопки Abort (Прервать), Retry (Продолжить) и Ignore (Игнорировать)
    VbYesNoCancel 3 кнопки Yes (Да), No (Нет) и Cancel
    VbYesNo 4 кнопки Yes и No
    VbRetryCancel 5 кнопки Retry и Cancel
    Коды пиктограмм
    VbCritical 16 важное сообщение (крестик в круге)
    VbQuestion 32 запрос (вопросительный знак)
    VbExclamation 48 предупреждение (восклицательный знак)
    VbInformation 64 информационное сообщение (i в круге)
    Кнопка, выбранная по умолчанию
    VbDefaultButton1 0 первая кнопка
    VbDefaultButton2 256 вторая кнопка
    VbDefaultButton3 512 третья кнопка
    VbDefaultButton4 768 четвертая кнопка
    Модальность диалога
    VbApplicationModal 0 модален относительно приложения
    VbSystemModal 4096 модален относительно системы

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

    Может показаться странным, что константа VbDefaultButton4 указывает на четвертую кнопку, хотя максимальное количество кнопок, определяемых кодами от 0 до 5, - три. Дело в том, что некоторые приложения (например, Excel) при наличии параметров справка и контекст могут автоматически добавить в окно кнопку справки Help, вызывающую окно справки.

    Результирующее значение параметра buttons получается как сумма кодов по одному из каждой группы. Например, значение 36 = 4 + 32 = VbYesNo + VbQuestion означает, что в окне будет пиктограмма с вопросительным знаком и две кнопки Yes и No, причем первая из них будет считаться выбранной, если пользователь ее щелкнет или нажмет клавишу Enter.

    Как узнать, какую кнопку выбрал пользователь? Присвоить значение функции MsgBox некоторой целочисленной переменной и проверить его. Возвращаемые MsgBox значения приведены в таблице:

    Имя константы Значение Нажатая кнопка
    vbOK 1 OK
    vbCancel 2 Cancel
    vbAbort 3 Abort
    vbRetry 4 Retry
    vbIgnore 5 Ignore
    vbYes 6 Yes
    vbNo 7 No

    Если в окне есть кнопка Cancel, нажатие клавиши Esc завершает работу в окне и возвращается тот же код vbCancel, что и при выборе кнопки Cancel.

    В следующем примере создается окно с сообщением об ошибке и вопросом о продолжении вычисления. В нем пиктограмма важного сообщения и кнопки Yes и No, причем вторая - кнопка, выбираемая по умолчанию. Файл со справкой называется ERRORS.HLP, а номер контекстной справки в этом файле равен 200.

    Public Sub Mes2()
    	Dim Msg As String, MyString As String
    	Dim Btns As Integer
    	Dim Title As String, Help As String
    	Dim NmbCont As Integer, Result As Integer
    	
    	Title = " Вы ввели неверные данные !"           ' заголовок окна.
    	Msg = "Будем продолжать работу ?"               ' сообщение.
    	Btns = vbYesNo + vbCritical + vbDefaultButton2  ' кнопки и свойства
    	Help = "ERRORS.HLP"                             ' имя файла со справкой
    	NmbCont = 200                                   ' номер темы
    			' Вывод сообщения.
    	Result = MsgBox(Msg, Btns, Title, Help, NmbCont)
    	If Result = vbYes Then	         ' пользователь нажал кнопку Yes.
    		MyString = "Да"              ' действия по продолжению работы
    	'...
    	Else                             ' пользователь нажал кнопку No.
    		MyString = "Нет"             ' действия по прекращению работы
    	'...
    End If
    
    End Sub

    При этом вызове на экране появится окно:

    (рис 12.4) Сообщение о неверных данных

    Окно ввода данных. Функция InputBox

    Окно, создаваемое функцией InputBox, предназначено для ввода строки и содержит однострочное окно редактирования, сообщение и кнопки OK и Cancel. При выборе кнопки OK (или нажатии клавиши Enter) строка, введенная пользователем в окне редактирования, передается в программу; щелчок кнопки Cancel (нажатие клавиши Esc) означает отказ от ввода - InputBox возвращает пустую строку.

    Синтаксис вызова функции InputBox таков:

    InputBox(prompt [,title ] [,default] [, xpos] [, ypos] [,helpfile, context])

    Здесь параметры prompt (сообщение), title (заголовок), helpfile и context имеют тот же смысл, что и для функции MsgBox. Параметр default является строкой, задающей подсказку, появляющуюся в текстовом окне редактирования. Если пользователь не введет новый текст, то эта подсказка и будет служить его ответом. Когда этот параметр не задан, то окно редактирования при открытии пусто. Числовое выражение xpos задает расстояние по горизонтали левой границы окна от левой границы экрана. Если его нет, окно центрируется по горизонтали. ypos - расстояние верхней границы окна от верхней границы экрана. Если его нет, окно центрируется по вертикали.

    В следующем примере в окно функции InputBox пользователь должен ввести дату рождения. Далее она проверяется. Если она в интервале от 01.01.1900 до 01.01.1985, запрашивается имя пользователя еще одним вызовом функции InputBox, иначе выдаются информационные сообщения с помощью функции MsgBox. Так как возвращаемое при первом вызове функции InputBox значение - строка, для его преобразования в дату применяется функция DateValue (для преобразования вводимых строк в числовые значения используется функция Val ).

    Sub ExInput()
    	Dim Msg As String, Title As String, Имя As String
    	Dim Birthday As Date
    	
    	Msg = "Введите, пожалуйста, "  vbCrLf  "дату своего рождения."  'сообщение.
    	Title = "Окно для ввода даты"            'заголовок.
    	'	Вывод окна для ввода даты в позицию (1500,1000):
    	Birthday = DateValue(InputBox(Msg, Title,, 1500, 1000))
    	
    	' Проверка даты:
    	If Birthday < "01/01/1900" Then
    		MsgBox "Вы выглядите гораздо моложе!", vbExclamation
    	ElseIf Birthday > "01/01/1983" Then
    		MsgBox "Эта программа не для детей до 16!", vbExclamation
    	Else				' Дата корректна. Запрос имени пользователя:
    		Имя = InputBox("Здравствуйте! Как Вас зовут?", "Знакомство", _
    		"Владимир Биллиг",,, "My.hlp", 12)
    		MsgBox Имя  ", рады Вам помочь.", vbExclamation, "Проверка ввода"
    	End If
    End Sub

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

    (рис 12.6) Окно для ввода даты(рис 12.5) Окно для ввода имени(рис 12.7) Окно приветствия

    Создание пользовательских диалоговых окон

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

    Для создания новой формы нужно в меню редактора VBA выбрать выпадающее меню Вставка (Insert), а в нем - команду UserForm. На экране появится новое окно с пустой формой и расположенной рядом панелью элементов (Toolbox).

    Щелкните это окно правой кнопкой мыши и выберите в появившемся контекстном меню команду Свойства (Properties). На экране появится окно Свойства-UserForm со списком свойств нового окна. Если выбрать вкладку По категориям, будет показан список свойств, сгруппированных по категориям. В частности, в категории Вид можно задать цвета окна и его границ и установить нужный заголовок окна в свойстве Caption. Свойства из других групп позволяют установить шрифт, используемый в окне, положение и размер окна и др. Чтобы подробнее узнать о свойстве, щелкните его и нажмите клавишу F1.

    (рис 12.8) Заготовка диалогового окна

    Затем нужно расположить в окне управляющие элементы (controls). Они выбираются на панели элементов Toolbox Если ее нет на экране, выберите команду Панель элементов (Toolbox) в меню Вид или щелкните ее пиктограмму на панели инструментов VBA. На панели элементов управляющие элементы представлены пиктограммами. Вы увидите имя элемента, установив указатель мыши на его пиктограмме.

    Перетащите нужный элемент с панели элементов на предназначенное место в окно формы. Когда вы отпустите кнопку мыши, вокруг элемента появится прямоугольная рамка с выделенными точками, за которые ее можно перемещать по экрану, чтобы точнее расположить элемент управления в диалоговом окне и установить его размеры. Уточнить положения элемента в окне можно командами меню Формат (Format). Порядок обхода управляющих элементов формы устанавливает команда Последовательность перехода (TabOrder)из меню Вид или контекстного меню формы. Чтобы данный управляющий элемент никогда не попадал в фокус, щелкните его правой кнопкой мыши, выберите в появившемся контекстном меню команду Свойства, а затем в появившемся списке установите для свойства TabStop значение False. Отметим, что для текстовых надписей (элементов вида Label) это значение устанавливается по умолчанию. В окне "Свойства-элемента" можно установить при проектировании и другие свойства элемента управления. Списки свойств появляются в этом окне на вкладках По алфавиту (Alphabetic) и По категориям (Categorized) на первой - в алфавитном порядке, на второй - сгруппированы по категориям. Устанавливать значение свойства можно на любой из них.

    Система автоматически именует новые элементы управления, образуя имя из типа элемента и его порядкового номера среди элементов данного типа. Например, у второй командной кнопки по умолчанию будет имя CommandButton2. Элементу можно присвоить новое имя, установив его в качестве значения свойства ( Name ). Помните, что имя идентифицирует объект (элемент управления или форму) в программе, поэтому изменение имени должно повлечь изменения в текстах процедур, его использующих. Не надо путать имя объекта ( Name ) со свойством Caption (заголовок, надпись), имеющимся у многих элементов управления. По умолчанию при создании элемента система присваивает этому свойству то же значение, что и имени Name. Изменение свойства Caption отражается на "внешности" элемента (надписи на экране), а на доступ к объекту из программы не влияет.

    Можно одновременно изменить значение свойства для нескольких одновременно выделенных элементов управления (щелкните их при нажатой клавише Ctrl), установив нужное значение свойства для одного из этих элементов.

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

    Создание страниц и вкладок в диалоговых окнах

    В одном диалоговом окне можно разместить несколько страниц и вкладок со своими управляющими элементами. Страницы и вкладки стали непременными элементами интерфейса систем, работающих с Windows. Отметим, что названия этих элементов в Office 2000 отличаются от принятых, например, в Windows 95: элемент MultiPage (набор страниц) позволяет создавать страницы с разными элементами управления (традиционно они назывались вкладками), а новый элемент TabStrip (полоса вкладок) создает "вкладки" с одинаковыми наборами элементов управления. Чтобы создать новый набор страниц, нужно перетащить на форму элемент MultiPage. Вначале будут созданы две страницы, которым можно дать нужные заголовки, сделав их значениями свойства Caption в списке свойств. На следующем рисунке эти страницы получили имена "Ссуды" и "Ренты".

    (рис 12.9) Создание страниц

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

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

    Добавление дополнительных элементов управления

    На панели элементов находятся пиктограммы не всех элементов управления, доступных в Office 2000. Доступ к дополнительным элементам управления Вы получите, щелкнув правой кнопкой панель элементов и выбрав в появившемся контекстном меню команду Дополнительные элементы (Additional Controls). На экране появится одноименное окно со списком доступных элементов управления (Available Controls).

    (рис 12.10) Окно Дополнительные элементы

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

    Пример создания диалогового окна

    Давайте создадим диалоговое окно "Цветная форма", в котором будут расположены изображение (Image), поле ввода (TextBox) и командная кнопка (CommandButton).

  • В меню Вставка выберите команду UserForm для создания нового диалогового окна.
  • Щелкнув правой кнопкой появившееся окно UserForm1, выберите в контекстном меню команду Свойства. Введите новое имя ColorForm1 в правом столбце строки со свойством (Name), в качестве значения свойства Caption введите заголовок окна: "Цветная форма". Щелкните правый столбец в строке со свойством BackColor (Цвет фона), затем - появившийся справа значок списка. В таблице появившегося окна щелчком выберите понравившийся цвет. Окно "перекрасится". Закройте окно свойств.
  • Перетащите с панели инструментов на окно элемент Image (изображение). Щелкните его правой кнопкой и снова выберите команду Свойства. В появившемся окне со списком свойств отыщите строку со свойством Picture (Рисунок). Чтобы перейти к поиску нужного файла с картинкой, щелкните кнопку с многоточием (…) справа в этой строке. В диалоговом окне Загрузка рисунка (Load Picture) выберите файл с симпатичной картинкой и щелкните кнопку OK.
  • Перетащите на диалоговое окно элемент управления поле ввода (TextBox). Как и в п. 3, щелкнув его правой кнопкой, вызовите окно Свойства. Введите в качестве значения свойства Value название выбранной вами картинки - оно появится в окне редактора. Затем выберите свойство Font Справа появится кнопка (…). Щелкните ее и в появившемся списке шрифтов выберите шрифт для редактора.
  • Перетащите на диалоговое окно командную кнопку (CommandButton). Вызовите окно Свойства для этой кнопки, и измените в нем значение свойства Caption (Заголовок) на "Нажми меня" - текст станет именем кнопки. Измените имя кнопки (Name) на cmdClickMe. По этому имени к кнопке будут обращаться процедуры и методы в программе. Введите справку "Командная кнопка" как значение свойства ControlTipText - надпись будет появляться на экране под кнопкой всякий раз, когда на ней окажется указатель. Установите для кнопки ключ быстрого выбора: найдите в списке свойств строку со свойством Accelerator (Ускоритель) и введите в поле справа букву "Н" - в имени кнопки первый символ "Н" будет подчеркнут и нажатие клавиш Alt+Н будет эквивалентно выбору кнопки. Установите также подходящий шрифт с помощью свойства Font, как и для поля ввода.
  • В меню Запуск выберите команду "Запуск подпрограммы/UserForm". На экране приложения появится спроектированное диалоговое окно.(рис 12.11) Цветная форма
  • Щелкните кнопку Close на заголовке диалогового окна, чтобы выйти из него.
  • Разработка процедур, обрабатывающих события диалогового окна и его устройств

    Процедуры, обрабатывающие события, связанные с диалоговыми окнами и элементами управления, - это частный случай процедур, обрабатывающих события объектов Office 2000. С диалоговым окном (формой) и с элементом управления каждого типа связан заранее определенный набор событий, возникающих для этого объекта по инициативе пользователя или системы. Например, одно из связанных с формой событий Initialize (Инициализация) возникает при загрузке формы, а связанное с командной кнопкой (CommandButton) событие Click возникает, когда пользователь щелкает эту кнопку (или нажимает клавишу Enter, если эта кнопка определена как нажимаемая по умолчанию). Процедуры обработки событий позволяют описать поведение диалогового окна или отдельного элемента управления при наступлении того или иного события.

    Чтобы перейти в окно редактора для ввода текста процедуры обработки события, щелкните дважды объект, к которому оно относится (элемент управления или свободную от элементов часть формы). Появится окно Code (Код). В раскрывающемся списке слева вверху перечислены все объекты формы; при выборе объекта в этом списке справа вверху появляются события, связанные с данным объектом. Ниже на рис. 12.10 показан список событий для командной кнопки.

    События, для обработки которых процедуры уже написаны, выделены полужирным начертанием. Чтобы создать новую процедуру или отредактировать имеющуюся, нужно щелкнуть в списке соответствующее событие. На экране появится шаблон новой процедуры или текст написанной. Имя такой процедуры состоит из имени устройства или формы, за которым после подчеркивания идет имя события. Так, процедура, обрабатывающая событие Click для командной кнопки CommandButton1, называется CommandButton1_Click. Из-за такого способа именования процедур будьте осторожны при переименовании элементов управления. Если Вы сначала определили для элемента процедуры обработки событий, а затем переименовали его (изменив свойство Name ), никаких процедур обработки событий у элемента с новым именем не будет (их придется перенести с помощью редактора).

    (рис 12.12) События элемента CommandButton

    Взгляните на процедуру обработки события Click для командной кнопки cmdClickMe диалогового окна "Цветная форма":

    Private Sub cmdClickMe_Click()
    	MsgBox "Поздравляю !"
    	ColorForm1.TextBox1.Value = "Симпатичный, правда?"
    
    End Sub

    Эта процедура автоматически вызывается при выборе кнопки "Нажми меня" и выводит на экран поздравление, а затем заменяет название картинки в окне редактирования.

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

    Вызов собственного диалогового окна

    Диалоговое окно нуждается в отладке. В редакторе VBA Вы видите его изображение, но управляющие элементы находятся в "замороженном" состоянии, и их реакция на действия пользователя - это реакция редактора, а не самих элементов. Диалоговое окно запускается на исполнение командой запуска процедуры или формы Запуск подпрограммы/UserForm меню Запуск редактора или нажатием клавиши F5. - Ваше диалоговое окно появится в рабочем состоянии на основной панели того приложения Office 2000, в котором оно создано.

    А вызывается диалоговое окно в прикладной системе методом Show (Показать). Он позволяет выводить окно на экран в качестве реакции на выбор соответствующей команды меню или командной кнопки в другом окне и т. п. Например, диалоговое окно MyForm выводится так:

    MyForm.Show

    Установка начальных значений свойств элементов управления

    Начальное значение (или значение по умолчанию) свойства элемента управления можно установить в процедуре, обрабатывающей событие Initialize (Инициализация) диалогового окна, содержащего данный элемент. Это событие возникает всякий раз при выводе диалогового окна на экран и запускает на выполнение процедуру без аргументов с именем ИмяОкна_Initialize. Поэтому установленные в ней значения свойств всегда будут начальными. Это не значит, что они должны быть постоянными. Значения могут зависеть от текущей даты, данных в ячейках рабочего листа Excel, некоторых записей в базе данных Access и т. п.

    Давайте создадим диалоговое окно с процедурой инициализации.

  • Создайте новое диалоговое окно и разместите в нем статический текст Label (Метка), поле ввода TextBox, окно списка ListBox и кнопку независимого выбора (флажок) CheckBox.
  • В окне Свойства, измените их имена (свойство Name): Label - на (рис 12.13) Окно до инициализации
  • Дважды щелкните диалоговое окно, чтобы вызвать окно с кодом (Code). Установите в списке объектов слева вверху UserForm (по умолчанию этот объект и будет выбран при вызове окна кода) и выберите команду Initialize в списке процедур справа вверху. На экране появится шаблон процедуры инициализации диалогового окна UserForm_Initialize. Введите текст следующей процедуры.
    Private Sub UserForm_Initialize()
    	With frmInit
    		.Caption = "Окно после инициализации"    ' заголовок диалогового окна
    		.CurrDate.Caption = "Сегодня "  Format(Date, "dd/mm/yy")
    		                                         'метка - текущая дата
    		.MyText.Text = "Любимый цвет:"           'начальный текст в редакторе
    		.chkGood.Value = True                    'включение флажка
    		.chkGood.Caption = " Хороший день"       ' заголовок флажка
    		With.lstColors                           'задание элементов списка:
    			.AddItem "белый"
    			.AddItem "черный"
    			.AddItem "синий"
    			.AddItem "красный"
    			.AddItem "зеленый"
    			.AddItem "желтый"
    			.AddItem "голубой"
    			.ListIndex = 4   'выбор 5-го элемента в списке ("зеленый")
    		End With
    	End With
    
    End Sub
    Нумерация элементов массивов и коллекций, связанных с формами, начинается с 0. Поэтому, чтобы выделить при выводе окна пятый элемент в списке цветов, свойству ListIndex присвоено значение 4.
  • Запустите диалоговое окно в отладчике. На экране оно будет выглядеть так:(рис 12.14) Окно после инициализацииЩелкнув кнопку Close (Закрыть) на строке заголовка окна, возвратитесь в режим проектирования.
  • Использование Me в качестве имени текущего диалогового окна

    Для упрощения написания кода процедур VBA позволяет в качестве имени текущего диалогового окна применять ключевое слово Me (это похоже на использование указателя текущего объекта This в С++). В частности, в предыдущем примере вместо оператора:

    With frmInit

    можно было использовать:

    With Me

    Модификация управляющих элементов во время работы

    Устанавливать программно новые значения свойств элементов управления можно не только при инициализации диалогового окна, но и во время работы пользователя (и системы) в нем. В любой процедуре обработки события, связанного со всем диалоговым окном или его отдельным элементом, можно присвоить значение свойству или вызвать метод любого управляющего элемента. Например, эти команды изменяют текст в окне редактора и снимают флажок в окне предыдущего примера:

    Public Sub ChangeForm()
    	With Me
    		.MyText.Text = "Нелюбимый цвет:"  'новый текст в редакторе
    		.lstColors.ListIndex = 1	  'черный
    		.chkGood.Value = False	          'отключение флажка
    	End With
    
    End Sub

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

    Управление доступом к элементу

    Все элементы управления обладают свойством Enabled (Доступен), позволяющим управлять их доступностью. В результате действий пользователя или системы доступный элемент может стать активным - получить фокус клавиатуры. Если свойству Enabled присвоить False, элемент управления становится недоступен ("сереет") и не может попасть в фокус. Управление доступностью производится динамически и зависит от задач, решаемых в диалоговом окне. Типичный случай - запрет на доступ к окну поля ввода (TextBox) после того, как система поместила в него данные, которые не должны далее изменяться пользователем (например, текст справки, которую можно только прочесть и распечатать). Другой случай - отключение/включение доступа к группам переключателей или кнопок зависимого выбора (OptionButton) или отдельным таким кнопкам в зависимости от состояния флажка (CheckBox). При этом действия по изменению доступа надо проводить в процедуре, обрабатывающей событие Change (Изменение), автоматически вызываемой в тот момент, когда флажок меняет свое состояние, т. е. становится неотмеченным или отмеченным.

    Выполните следующие действия:

  • Создайте новое диалоговое окно (UserForm) и включите в него флажок (CheckBox), управляющий элемент Frame (Рамка), и командную кнопку (ComandButton). Поместите в рамку еще 4 флажка (CheckBox). Заголовки управляющих элементов (значения свойства (рис 12.15) Окно "Пример управления доступом"
  • Дважды щелкните верхний флажок, чтобы вывести окно с кодом процедур, выберите в списке объектов слева вверху CheckBox1 (это имя присвоила флажку система), затем в списке процедур обработки событий справа вверху щелкните событие Change. Дополните появившуюся заготовку процедуры CheckBox1_Change:
    Private Sub CheckBox1_Change()
    	With Me
    		If.CheckBox1.Value Then          'отключение опций
    			.CheckBox4.Enabled = False
    			.CheckBox5.Enabled = False
    		Else                             'включение опций
    			.CheckBox4.Enabled = True
    			.CheckBox5.Enabled = True
    		End If
    	End With
    
    End Sub
  • Создайте стандартный модуль и напишите в нем две процедуры:
    Public Sub CheckOptions()
    	'Проверка на дорогах
    	Dim Msg As String
    	Msg = "Выполняю проверку на "
    	With frmChecking
    		
    		If.CheckBox2.Value Then Msg = Msg  vbCrLf  "корректность дат"
    		If.CheckBox3.Value Then Msg = Msg  vbCrLf  "согласованность данных"
    		If.CheckBox4.Value Then Msg = Msg  vbCrLf  "правильность расходов"
    		If.CheckBox5.Value Then Msg = Msg  vbCrLf  "правильность доходов"
    		MsgBox (Msg)
    		.Hide
    	End With
    End Sub
    
    Public Sub SetOptions()
    	frmChecking.Show
    End Sub
    Процедура SetOptions открывает нашу форму, предоставляя пользователю возможность включать или выключать те или иные флажки. Установив нужные значения, он может затем щелкнуть кнопку "Проверка". Обработчик этого события будет вызывать функцию CheckOptions, которая и производит проверку состояния каждого из четырех флажков группы. Заметьте, что проверка свойства Value не зависит от состояния свойства Enabled. Если даже флажок недоступен, но включен ( Value = True ), то появится сообщение о выполнении проверки. Недоступный флажок не позволяет пользователю изменить его состояние, но программно ѕ все в Ваших руках. Сделаем еще одно замечание. Реально, верхний флажок, управляющий проверкой, должен находиться в другой форме, более высокого уровня, но мы уже не стали усложнять задачу.
  • Напишите обработчик события командной кнопки:
    Private Sub CommandButton1_Click()
    	CheckOptions
    End Sub
  • Теперь, если выполнить процедуру (рис 12.16) Окно проверки в процессе работы
  • Если в этом состоянии окна щелкнуть командную кнопку "Проверка", то будет выведено сообщение о двух выполняемых проверках:(рис 12.17) Окно сообщений о выполняемых проверках
  • Перемещение фокуса на элемент управления

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

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

    Private Sub CommandButton1_Click()
    	With Me
    		If.TextBox1.Text = "" Then
    Beep: Beep: Beep
    			.TextBox1.SetFocus
    		Else
    			GlobeVar =.TextBox1.Text
    			MsgBox GlobeVar
    			.Hide
    		End If
    	End With
    End Sub

    Вот как выглядит эта простая форма ввода в процессе работы с ней:

    (рис 12.18) Простая форма ввода

    Изменение размеров диалогового окна

    Из процедур обработки событий можно менять свойства не только отдельных элементов управления, но и всего окна. В качестве примера рассмотрим динамическое изменение его размеров. Ранее мы уже говорили о том, что, изменяя размеры окна, можно скрывать те или иные элементы управления. Сейчас продемонстрируем это на примере. На стадии проектирования разместим в окне элементы управления, которые при первоначальном открытии окна не должны быть видны, но должны появиться в процессе работы пользователя с этим окном. Пусть в форме Cutting есть командная кнопка "Получить данные", и поля ввода "Доходы" и "Расходы" При открытии окна поля ввода недоступны, что достигается "отсечением" нижней части формы в процедуре инициализации. Вот как выглядит обработчик события Initialize нашей формы:

    Private Sub UserForm_Initialize()
    	'Отсечение нижней части формы
    	Me.Height = 90
    End Sub

    Так выглядит форма при ее открытии:

    (рис 12.19) Усеченная форма в момент ее открытия

    После щелчка командной кнопки обработчик события Click восстанавливает размер, заданный при проектировании формы. Он задает также и значения скрытых ранее полей:

    Private Sub CommandButton1_Click()
    	With Me
    		'Установить нормальную высоту формы
    		.Height = 200
    		'Задать значения ранее не видимых полей
    		.Доходы = 1570
    		.Расходы = 1500
    	End With
    	
    End Sub

    А так выглядит эта же форма после щелчка командной кнопки:

    (рис 12.20) Форма Cutting со скрытыми ранее полями

    Проверка корректности данных

    Одна из важных функций диалоговых окон, - прием и передача данных, введенных пользователем, для хранения и дальнейшей обработки в систему. Основной вид элементов управления, предназначенных для ввода, - это окна редактирования (TextBox). Для предотвращения ошибок, связанных с неверным типом введенных данных или нарушением некоторых условий, которым эти данные должны удовлетворять следует проверять их корректность до выхода из диалогового окна. Чуть выше мы приводили пример работы с простой формой ввода, где проверялась ситуация, когда пользователь "забыл" ввести данные в окно ввода. Сейчас мы рассмотрим ситуацию, в которой пользователь пытается ввести некорректные данные в поле ввода. Возникает вопрос, где следует проводить проверку на корректность данных? По-видимому, одним из лучших мест является обработчик события Exit, которым обладает элемент управления TextBox. Обработчик этого события вызывается при попытке выхода из окна редактирования. Здесь и следует проводить проверку введенных данных, чтобы не допустить выхода, если данные заданы некорректно.

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

    Private Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean)
    	Dim Msg As String
    	Const MinTemp = 34
    	Const MaxTemp = 42
    	Msg = "Ошибка ввода:"  vbCrLf
    	'Проверка, являются ли данные числовыми
    	If Not IsNumeric(TextBox1.Text) Then
    		Msg = Msg  "Введите числовые данные в формате: ##.#"
    		MsgBox Msg
    		Cancel = True	'Оставляет фокус в поле ввода
    		
    	ElseIf TextBox1.Text < MinTemp Then
    		Msg = Msg  "Температура слишком низкая"  vbCrLf _
    			 "Проверьте, что с Вашим больным!"
    		MsgBox Msg
    		Cancel = True	'Оставляет фокус в поле ввода
    	ElseIf TextBox1.Text > MaxTemp Then
    		Msg = Msg  "Температура слишком высокая"  vbCrLf _
    			 "Проверьте, что с Вашим больным!"
    		MsgBox Msg
    		Cancel = True	'Оставляет фокус в поле ввода
    	Else
    		GlobeVar = TextBox1.Text
    		Debug.Print GlobeVar
    	End If
    	
    End Sub

    Событие Exit имеет параметр Cancel, значение которого следует установить в обработчике события. Если параметру присвоить значение True, то фокус остается на текущем элементе, в противном случае он переходит к элементу, следующему согласно Tab - порядка. Вот как выглядит форма при попытке задания некорректного значения температуры:

    (рис 12.21) Проверка корректности ввода данных

    Обмен данными с диалоговым окном

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

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

    (рис 12.22) Лист Excel, хранящий информацию о состоянии элементов формы

    Пять ячеек листа SavedData рабочей книги BookOne12 хранят нужную информацию. Заметьте, ячейка A1 именована. Ее имя "Данные" будет использовано в обработчиках событий. На этом же листе расположена командная кнопка "Вызов Формы". Ее обработчик события очень прост, ѕ он вызывает форму:

    Private Sub CommandButton1_Click()
    	frmInit.Show
    End Sub

    А вот как выглядит сама форма в момент ее открытия:

    (рис 12.23) Форма при ее открытии

    Эта форма уже использовалась в наших примерах. Ранее она была связана с документом Word, а теперь мы перетащили ее в рабочую книгу Excel, используя операции Export - Import. После чего форма была слегка модифицирована добавлением в нее новых командных кнопок ѕ Save, Reset и Cancel. Прежде, чем рассказать о них подробнее, приведем уже встречавшиеся обработчики событий. Наша форма одинаково реагирует на два события Initialize и Activate. Первое из них возникает, когда форма открывается после того, как она была выгружена. Если же форма удаляется с экрана методом Hide, то при ее повторном открытии событие Initialize не возникает. Поскольку мы хотим, чтобы и в этом случае происходила инициализация свойств формы, то определен и обработчик события Activate, выполняющий те же действия. Поскольку оба обработчика эквивалентны, то приведем текст только одного из них:

    Private Sub UserForm_Activate()
    	With frmInit
    		.Caption = "Окно после инициализации"      ' заголовок диалогового окна
    		.CurrDate.Caption = "Сегодня "  Format(Date, "dd/mm/yy")
                                                       'метка - текущая дата
    		.MyText.Text = "Любимый цвет:"             'начальный текст в редакторе
    		.chkGood.Value = True                      'включение флажка
    		.chkGood.Caption = " Хороший день"         ' заголовок флажка
    		With.lstColors                             'задание элементов списка:
    			.AddItem "белый"
    			.AddItem "черный"
    			.AddItem "синий"
    			.AddItem "красный"
    			.AddItem "зеленый"
    			.AddItem "желтый"
    			.AddItem "голубой"
    			.ListIndex = 4              'выбор 5-го элемента в списке ("зеленый")
    		End With
    	End With
    
    End Sub

    Этот обработчик задает начальные свойства элементов управления ѕ объектов формы в момент ее открытия. После чего с формой работает пользователь. Форма простая, поэтому возможностей у него не много, тем не менее, он может выбрать из списка понравившийся ему цвет, отключить флажок, щелкнуть по командной кнопке "Change". В ответ на последнее действие будет вызван соответствующий обработчик, который программно изменит состояние объектов формы. Текст этого обработчика уже приводился ранее, напомним его:

    Private Sub CommandButton1_Click()
    	ChangeForm
    End Sub
    Public Sub ChangeForm()
    	With Me
    		.MyText.Text = "Нелюбимый цвет:"    'новый текст
    		.lstColors.ListIndex = 1	    'черный
    		.chkGood.Value = False	            'отключение флажка
    	End With
    
    End Sub

    Нам осталось рассмотреть действие новых командных кнопок. Обработчик события Click кнопки Save позволяет сохранить текущее состояние элементов управления формы. Затем это состояние может быть проанализировано, например, для того, чтобы выдать психологический портрет пользователя. Цель сохранения может быть и другая, ѕ иметь возможность вернуться к текущему состоянию при повторном открытии формы. С чисто программистской точки зрения задача сохранения состояния решается просто, главный вопрос это, где и в какой форме хранить состояние элементов управления. В данном случае мы выбрали ячейки листа Excel. Вот текст этого обработчика:

    Private Sub cmdSave_Click()
    	'Сохранение данных формы в ячейках листа SavedData книги BookOne12
    	Dim Beg As Range
    	Set Beg = Range("[BookOne12.xls]SavedData!Данные")
    	With frmInit
    		Beg.Offset(1, 0) =.CurrDate.Caption	'дата
    		Beg.Offset(1, 1) =.lstColors.ListIndex  'индекс в списке
    		Beg.Offset(1, 2) =.lstColors.Value	'цвет
    		Beg.Offset(1, 3) =.chkGood.Value        'состояние флажка
    		Beg.Offset(1, 4) =.MyText.Text		'текст в окне ввода
    		'Форма прячется
    		.Hide
    	End With
    		
    End Sub

    Обратите внимание, при работе с ячейками Excel используется техника, основанная на смещении Offset. Вначале фиксируется начальная ячейка, имеющая имя "Данные", и уже относительно ее выполняются действия над остальными ячейками.

    Командная кнопка Reset позволяет восстановить сохраненное состояние элементов управления формы. Обработчик события Click для этой кнопки выполняет действия, обратные тем, что делаются при сохранении состояния. Вот текст этого обработчика:

    Private Sub cmdReset_Click()
    	 'Восстановление данных формы из ячеек листа SavedData книги BookOne12
    	Dim Beg As Range
    	Set Beg = Range("[BookOne12.xls]SavedData!Данные")
    	With frmInit
    		.CurrDate.Caption = Beg.Offset(1, 0)
    		.lstColors.ListIndex = Beg.Offset(1, 1)
    		.lstColors.Value = Beg.Offset(1, 2)
    		.chkGood.Value = Beg.Offset(1, 3)
    		.MyText.Text = Beg.Offset(1, 4)
    	End With
    End Sub

    Обработчик события Click для кнопки Cancel просто закрывает форму без сохранения состояния элементов:

    Private Sub cmdCancel_Click()
    	frmInit.Hide
    End Sub

    Закрытие диалогового окна

    Диалоговые окна в Office 2000 всегда работают в режиме модального диалога. Это значит, что пользователь должен полностью завершить работу в окне и закрыть его, прежде чем сможет перейти к действиям, не связанным с работой в этом диалоговом окне. Заметим, что немодальный диалог в Office 2000 также можно организовать, но для этого потребуется использовать объект Assistant с его баллончиками ѕ объектами Balloon. Для завершения работы с диалоговым окном применяется оператор UnLoad или метод Hide, вызываемые в обработчиках события, завершающих работу в диалоговом окне. Обычно в диалоговое окно включается одна или несколько кнопок, выбор которых приводит к завершению работы в нем ("Отказ", "Выход", "Сохранить", "Готово", "Конец работы" и т. п.).

    Ранее мы уже говорили о разнице между UnLoad и Hide, первый ѕ выгружает форму, второй только прячет ее. Есть и синтаксическая разница, Hide - это метод формы, в то время как UnLoad и Load - это встроенные функции, которым в качестве параметра передается имя формы. Мы обращали также внимание и на то, что при открытии спрятанной формы не возникает событие Initialize. В заключение, скажем, что в Office 97 были проблемы с методом Hide, поэтому я всегда пользовался только методом UnLoad, в Office 2000 метод Hide работает должным образом.

    Вернуться к учебному плану