[an error occurred while processing this directive]

В начало

Введение

1-й час. Знакомство с Visual Basic for Applications

2-й час. Работа с макросами

3-й час. Работа с элементами управления

4-й час. Переменные и константы

5-й час. Ввод данных

6-й час. Логика условных операторов

7-й час. Циклические вычисления

8-й час. Введение в объекты

9-й час. Основные объекты Excel

10-й час. Объект Range

11-й час. Редактор Visual Basic

12-й час. Отладка программ

13-й час. Обработка ошибок

14-й час. Экранные формы

15-й час. Автоматизация экранных форм

16-й час. Панели инструментов

17-й час. Работа с меню

18-й час. Диаграммы

19-й час. Сводные таблицы

20-й час. Получение внешних данных

21-й час. Доступ к данным с помощью ADO

22-й час. Еще об ADO

23-й час. Автоматизация

24-й час. Выполнение процедур

Приложение. Ответы

15-й час. Автоматизация экранных форм

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

В этом часе будут рассмотрены следующие вопросы.

  • Инициализация значений экранной формы.
  • Код VBA, используемый для отображения экранных форм.
  • Управление поведением элементов экранной формы.
  • Проверка вводимых данных.
  • Перемещение данных из формы в рабочий лист.

Инициализация значений экранной формы

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

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

  1. Перейдите в текущую рабочую книгу. Переименуйте рабочий лист Лист2 на Списки.
  2. На рабочем листе Списки перейдите в ячейку А1 и введите заголовок Типы расходов.
  3. Начиная с ячейки В2, введите следующие значения:

в ячейку В2: Пляжный зонтик,

в ячейку B3: Аренда велосипеда,

в ячейку В4: Уроки гольфа,

в ячейку В5: Гольф, 18 лунок,

в ячейку В6: Гольф, 9 лунок,

в ячейку В7: Полотенце для бассейна,

в ячейку В8: Теннисный корт,

в ячейку В9: Уроки тенниса.

  1. Выделите диапазон В2:В9 и задайте ему имя Расходы.

Чтобы задать имя диапазону ячеек, выделите этот диапазон и в поле Имя (с левой стороны в строке формул) введите имя диапазона. Нажмите клавишу <Enter>.

  1. Перейдите в ячейку Е1 и введите заголовок Типы кредитных карт.
  2. Начиная с ячейки F2, введите следующие значения:

в ячейку F2: Mastercard,

в ячейку F2: Visa,

в ячейку F2: American Express,

в ячейку F2: Diner's Club.

  1. Выделите диапазон F2:F5 и задайте ему имя ТипыКарт.
  2. Сохраните рабочую книгу.
  3. Нажмите <Alt+F11> для возврата в редактор Visual Basic.

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

  1. Дважды щелкните на экранной форме (не на элементах управления, а именно на форме). Откроется окно кода с заголовком процедуры UserForm_Click (Щелчок на экранной форме) (рис. 15.1).
  2. Нам пока не нужна процедура UserForm_Click, которая вызывается на исполнение после щелчка на экранной форме. Нам нужна процедура, выполняющаяся при открытии формы. На языке программистов такая процедура называется процедурой, обрабатывающей событие Activate (Активизация). Чтобы создать эту процедуру, щелкните на кнопке со стрелкой, направленной вниз, в правой части раскрывающегося списка возможных событий (рис. 15.1). В этом списке выберите событие Activate. В окне кода появится заголовок процедуры UserForm_Activate.
  3. Введите код процедуры UserForm_Activate.

With lstExpenseType

 .RowSource = "Расходы"

 .ListIndex =0

End With

txtDate.Text = Format(Now, "dd/mm/yy")

With lstCardType

 .RowSource = "ТипыКарт"

 .ListIndex = 0

End With

Рис. 15.1. Окно кода для создания и редактирования процедур, управляющих экранной формой

  1. Нажмите клавишу <F5> для выполнения процедуры. Отобразится экранная форма с заполненными списками Типы расходов и Типы карт, а также заполненным полем Дата (рис. 15.2).
  2. Закройте форму и вернитесь в редактор Visual Basic.

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

Рис. 15.2. Автоматическое заполнение списков и полей формы при ее открытии Полный код процедуры UserForm_Activate приведен в листинге 15.1.

Листинг 15.1. Процедура UserForm Activate

1: Private Sub UserForm_Activate()

2:  With lstExpenseType

3:   .RowSource = "Расходы"

4:   .ListIndex =0

5:  End With

6:

7:  txtDate.Text = Format(Now, "dd/mm/yy")

8:

9:  With lstCardType

10:   .RowSource = "ТипыКарт"

11:   .ListIndex = 0

12:  End With

13: End Sub

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

With lstExpenseType

 .RowSource = "Расходы"

 .ListIndex = 0

End With

Свойство RowSource ссылается на имя диапазона, где хранятся значения элементов списка. (Очевидно преимущество использования имени диапазона по сравнению с адресом диапазона - меньше вероятность неправильно ввести ссылку, возможность в дальнейшем переопределить диапазон без изменения кода процедуры, лучшая читаемость кода.) Свойство ListIndex определяет, какой элемент списка будет отображаться при открытии формы - все элементы списка пронумерованы, начиная с нуля.

По-иному задается значение для поля Дата:

txtDate.Text = Format(Now, "dd/mm/yy")

Функция Now возвращает текущую дату, функция Format форматирует текущую дату в соответствии с форматом dd/mm/yy (день месяца, порядковый номер месяца, две цифры года).

Вызов экранной формы

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

В следующем 16-м часе "Панели инструментов" мы подробно рассмотрим методы работы с панелями инструментов, а в 17-м часе "Работа с меню" - методы работы с меню.

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

frmGuestExpenses.Show

Метод Show загружает экранную форму в память компьютера и выводит ее на экран. Для создания такой процедуры выполните следующее.

  1. Перейдите в редактор Visual Basic (если вы находитесь не в нем) и вставьте новый модуль в рабочую книгу.
  2. Создайте новую процедуру и назовите ее ЗагрузкаФормы.
  3. Введите код процедуры

frmGuestExpenses.Show

  1. Перейдите в рабочую книгу на Лист1 и вставьте в этот рабочий лист командную кнопку.

Для вставки в рабочий лист командной кнопки надо отобразить панель инструментов Формы.

  1. Когда откроется диалоговое окно Назначить макрос объекту, выберите в списке Имя макроса пункт ЗагрузкаФормы.
  2. Задайте название командной кнопке Карточка гостевых расходов и щелкните вне кнопки, чтобы снять с нее выделение.
  3. Щелкните на этой командной кнопке. Откроется наша форма. Отметьте, что списки Типы расходов и Типы карт заполнены, как и поле Дата.
  4. Закройте форму.

Итак, вызов экранной формы осуществляется с помощью метода Show. В следующих главах книги созданную здесь процедуру ЗагрузкаФормы мы будем использовать для назначения ее кнопке панели инструментов и пункту меню.

Управление поведением формы

Процедура, выводящая форму на экран, создана. Теперь надо подумать о том, как форма будет себя вести на экране, т.е. продумать реакцию ее элементов на различные события, вызываемые действиями пользователя. Например, при установке флажка Включить в группе элементов Дополнительно надо снять блокировку с поля ввода сумму. Надо также снять блокировку с полей, принимающих информацию о кредитной карте, если выбран переключатель Кредитная карта. За подобные действия должна отвечать процедура, вызываемая событием Change (Изменить). Это событие генерируется всякий раз, когда изменяется значение свойства Value (Значение) какого-либо элемента управления. В данном случае, чтобы изменить свойства связанных элементов, надо сначала изменить значение свойства Value на True флажка Включить и переключателя Кредитная карта.

Выполните следующую последовательность действий.

  1. Перейдите в редактор Visual Basic (если вы находитесь не в нем) и откройте форму frmGuestExpense.
  2. Дважды щелкните на флажке Включить, чтобы открыть окно кода.
  3. В списке событий в верхней части окна кода выберите событие Change и в процедуру chkTipIncluded_Change введите следующий код:

If chkTipIncluded.Value = True Then

 lblTipAmount. Enabled = True

 txtTipAmount.Enabled = True

Else

 lblTipAmount.Enabled = False

 txtTipAmount.Enabled = False

End If

  1. В левом верхнем списке над окном кода (где сейчас отображается chkTipIncluded) щелкните на кнопке со стрелкой, направленной вниз. В открывшемся списке выберите optCreditCard (переключатель Кредитная карта).
  2. В списке событий выберите событие Change. В окне кода отобразится заголовок процедуры optCreditCard_Change.
  3. Введите код этой процедуры:

If.optCreditCard.Value = True Then

 lblCardType.Enabled = True

 lstCardType.Enabled = True

 lblCardNumber.Enabled = True

 txtCardNumber.Enabled = True lblExpires.Enabled = True

 txtExpires.Enabled = True

Else

 lblCardType.Enabled = False lstCardType.Enabled = False

 lblCardNumber.Enabled = False txtCardNumber.Enabled = False

 lblExpires.Enabled = False

 txtExpires.Enabled = False

End If

  1. Перейдите в рабочую книгу на Лист1 и щелкните на командной кнопке. Отобразится форма (рис. 15.3).
  2. Установите флажок Включить. Поле ввода сумму станет доступным.
  3. Установите переключатель Кредитная карта. Связанные с этим переключателем поля станут также доступными (рис. 15.4).
  4. Закройте форму и сохраните рабочую книгу. Возвратитесь в редактор Visual Basic.

Рис. 15.3. После открытия формы некоторые элементы недоступны

Рис. 15.4. С помощью события Change все элементы стали доступны

В процедуре optCreditCard_Change событие Change использовалось для проверки значения свойства Value, и в зависимости от этого значения блокировка элементов управления или снималась (свойство Enabled равно True) или устанавливалась (свойство Enabled равно False). Но при обработке события Change вы не ограничены работой только со свойством Enabled, можно изменить значения таких свойств элементов управления, как Text, Value или Caption.

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

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

Начнем с проверки правильности данных. Понятие правильности (корректности) данных зависит от выполняемого приложения. Поле ввода может принять все, что вы способны ввести с клавиатуры. И если вы ввели какую-нибудь абракадабру, то это не значит, что введенное значение некорректно. Все зависит от тех ограничений, которые накладывает приложение на вводимые данные. Например, на разрабатываемой нами экранной форме есть поле ввода Номер комнаты. Очевидно, что корректными значениями для этого поля будут целые положительные числа. Далее предположим, что в нашем отеле сдаются только комнаты с номерами от 101 до 730. В этом случае корректными данными для поля будут лишь целые числа из указанного интервала. Аналогичные ограничения должны накладываться на значения полей Тип расходов, Сумма, Дата, а также на значения полей группы Способ оплаты. (Обратите внимание на маленькую, но существенную деталь: проверку поля сумму и полей с данными о кредитной карте надо выполнять только тогда, когда эти поля разблокированы.)

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

  1. В редакторе Visual Basic отобразите разрабатываемую форму.
  2. Дважды щелкните на кнопке Сохранить. В окне кода появится заголовок процедуры cmdSave_Click.
  3. Введите следующий код этой процедуры:

If Val(txtRoomNumber.Text) < 101 Or _

Val(txtRoomNumber.Text) > 730 Then

 MsgBox "Неправильный номер комнаты"

 txtRoomNumber.SetFocus

 Exit Sub

End If

If txtGuestName.Text = "" Then

 MsgBox "Пожалуйста, введите имя гостя"

 txtGuestName.SetFocus

 Exit Sub

End If

If chkTipIncluded.Value = True Then

 If txtTipAmount = " " Then

  MsgBox "Если установлен флажок "Включить", _

   то надо ввести число в поле "сумму" "

  txtTipAmount.SetFocus

  Exit Sub

 End If

End If

If txtAmount.Text = "" Then

 MsgBox "Пожалуйста, введите сумму расходов"

 txtAmount.SetFocus

 Exit Sub

End If

If IsNumeric(txtAmount.Text) = False Then

 MsgBox "Сумма должна быть числом"

 txtAmount.SetFocus

 Exit Sub

End If

If txtDate.Text = "" Then

 MsgBox "Необходимо ввести дату"

 txtDate.SetFocus

 Exit Sub

End If

If optCreditCard.Value = True Then

 If txtCardNumber = "" Then

  MsgBox "Пожалуйста, введите номер кредитной карты"

  txtCardNumber.SetFocus

  Exit Sub

 End If

 If txtExpires.Text = "" Then

  MsgBox "Введите дату окончания карты"

  txtExpires.SetFocus

  Exit Sub

 End If

End If

Unload Me

  1. Перейдите в рабочую книгу и щелкните на командной кнопке, отрывающей форму.
  2. Щелкните на кнопке Сохранить. Появится окно с сообщением: "Неправильный номер комнаты" (рис. 15.5).
  3. Щелкните на кнопке ОК, чтобы закрыть окно сообщения. Введите 121 в поле Номер комнаты и щелкните на кнопке Сохранить. В другом появившемся окне сообщения щелкните на кнопке ОК.
  4. Введите свое имя как имя гостя. Введите 20 в поле Сумма.
  5. Щелкните на флажке Включить, а затем на кнопке Сохранить. Появится очередное окно сообщения с предложением ввести данные в поле сумму. Щелкните на кнопке ОК, чтобы закрыть это окно.
  6. Введите число 2 в поле сумму и щелкните на кнопке Сохранить. Форма исчезнет с экрана.

Вы, конечно, заметили, что в этой процедуре проверялись свойства Text и Value элементов управления. Рассмотрим подробнее код одной такой проверки, показанный в листинге 15.2.

Листинг 15.2. Проверка значения поля Номер комнаты

1: If Val(txtRoomNumber.Text)<101 Or Val(txtRoomNumber.Text)>730 Then

2:  MsgBox "Неправильный номер комнаты"

3:  txtRoomNumber.SetFocus

4:  Exit Sub

5: End If

Здесь оператор If проверяет, находится ли значение поля txtRoomNumber (Номер комнаты) в интервале от 101 до 730. Отметим применение функции Val, преобразующей строковое значение в числовое. Она необходима из-за того, что значение свойства Text (т.е. введенное в поле значение) имеет строковый (текстовый) тип данных. Вы обратили внимание, что здесь нет проверки той ситуации, когда пользователь вообще ничего не ввел в это поле? Просто эта ситуация подпадает под тот случай, когда введенное значение меньше 101.

Рис. 15.5. Одно из многих окон с сообщениями о некорректности введенных данных

Метод SetFocus делает активным указанный элемент управления формы. Оператор выхода из процедуры Exit Sub используется после каждой проверки, так как нет смысла продолжать процедуру, если ошибка обнаружена и выведено соответствующее окно сообщения. Если ошибки не обнаружены, то с помощью оператора Unload Me форма выгружается из памяти компьютера и удаляется с экрана.

Сохранение данных, введенных в форму

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

  1. Перейдите на рабочий лист Лист3 и переименуйте его на Расходы.
  2. В первой строке листа создайте строку заголовков, повторяющую названия элементов управления формы. За образец возьмите рабочий лист, показанный на рис. 15.6.
  3. Перейдите в редактор Visual Basic и отобразите экранную форму.
  4. Чтобы открыть окно кода, дважды щелкните на кнопке Сохранить.
  5. Введите в процедуру cmdSave_Click перед оператором Unload Me следующий код:

Worksheets("Расходы").Activate

Range("A2").Select

If Range("A2").Value = "" Then

 Range("A2").Activate

Else

 Range("A2").CurrentRegion.Select

 ActiveCell.Offset(Selection.Rows.Count, 0).Activate

End If

With ActiveCell

 .Value = txtRoomNumber.Text

 .Offset(0, 1).Value = txtGuestName.Text

 .Offset(0,2).Value = lstExpenseType.Text

 .Offset(0, 3).Value = txtAmount.Text

 .Offset(0, 4).Value = txtDate.Text

 If chkTipIncluded.Value = True Then

  .Offset(0,5).Value=txtTipAmount.Text

 End If

 If optBillToRoom.Value = True Then

  .Offset(0, 6).Value = "В счет"

 ElseIf optCash.Value = True Then

  .Offset(0, 6).Value = "Наличные"

 ElseIf optCheck.Value = True Then

  .Offset(0, 6).Value = "Чеком"

 ElseIf optCreditCard.Value = True Then

  .Offset(0, 6).Value = "Кредитная карта"

  .Offset(0, 7).Value = lstCardType.Text

  .Offset(0, 8).Value = txtCardNumber.Text

  .Offset(0, 9).Value = txtExpires.Text

 End If

End With

  1. Перейдите в рабочую книгу на Лист1.
  2. Сохраните рабочую книгу. (Вообще возьмите себе за правило сохранять рабочую книгу после создания каждой процедуры.)
  3. Щелкните на кнопке, вызывающей экранную форму. Введите 430 в поле Номер комнаты и ваше имя в качестве имени гостя. Выберите в списке Тип расходов пункт Уроки гольфа. В поле сумма введите число 100. Установите флажок Включить и в поле сумму введите 10. Установите переключатель Кредитная карта и выберите тип карты Visa. Введите номер кредитной карты 112233, а срок окончания годности карты - 1.01.01. Щелкните на кнопке Сохранить.
  4. Форма закроется, а введенные в нее данные будут записаны в ячейки рабочего листа Расходы (рис. 15.6).

Теперь изучим подробнее вторую часть кода процедуры. Рассмотрим начало записи данных в рабочий лист.

Worksheets("Расходы").Activate

Range("A2").Select

If Range("A2").Value = "" Then

 Range("A2").Activate

Else

 Range("A2").CurrentRegion.Select

 ActiveCell.Offset(Selection.Rows.Count, 0).Activate

End If

Рис. 15.6. Все введенные в форму данные скопированы в рабочий лист

Здесь сначала делается текущим рабочий лист Расходы, а затем - ячейка А2. Ввод данных начинается со второй строки рабочего листа, так как в первой размещены заголовки столбцов. Далее проверяется, занята ли ячейка А2. Если нет, то начинается запись данных. Если ячейка А2 занята, то находится последняя занятая ячейка. Здесь ведущую роль играет свойство CurrentRegion (Текущая область) объекта Range. После выделения текущей области можно определить ее размеры и, следовательно, найти первую свободную строку. Для этого используется свойство Offset (Смешение).

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

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

  1. Перейдите в редактор Visual Basic и дважды щелкните на кнопке Отмена. Откроется окно кода с заголовком процедуры cmdCancel_Click.
  2. В эту процедуру введите следующую строку кода:

Unload Me.

  1. Сохраните рабочую книгу.

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

Резюме

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

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

Вопросы и ответы

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

Ответ. Смотрите следующую таблицу.

Элемент управления Свойство
Надпись Caption
Поле Text
Список Text
Поле со списком Text
Переключатель Value
Флажок Value
Счетчик Value

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

Ответ. Есть несколько способов. Первый: с помощью команды Excel Формат > Лист > Скрыть можно скрыть этот рабочий лист. Другой путь программный: в процедуре рабочей книги Auto_Open установите свойство Visible (Видимый) рабочего листа как False.

Практикум

С помощью тестов и упражнений вы проверите, насколько хорошо усвоили изложенный материал. Ответы на вопросы смотрите в Приложении.

Тесты

  1. Как установить блокировку элемента управления?
  2. Как вызвать форму на экран?
  3. В какой процедуре находится код инициализации значений элементов формы?
  4. Как удалить экранную форму из памяти компьютера?
  5. Если необходимо вернуться к какому-либо элементу управления посредством кода, какой метод следует применить?
  6. Где хранятся элементы списков?
  7. Какое свойство списков задает элемент, отображаемый в списке по умолчанию?
  8. В какой процедуре обычно проверяются на корректность данные, вводимые пользователем?

Упражнение

Создайте процедуру под именем ПоказФормы, которая должна выводить на экран форму frmSplash, созданную как упражнение в 14-м часе.

Создайте код, с помощью которого после щелчка на кнопке ОК в форме frmSplash будет открываться форма Гостевые расходы.

Перейдите на Лист1 в рабочей книге Гость и назначьте процедуру ПоказФормы командной кнопке.

[an error occurred while processing this directive]