Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

VBA_ЛБ_13v2

.pdf
Скачиваний:
308
Добавлен:
07.02.2015
Размер:
1.87 Mб
Скачать

Стеценко А. А.

51

К13. Какое значение имеет переменная цикла, если выполнено заданное количество повторений?

К14. Объясните, как подсчитывается в первом цикле программы Separate количество заполненных ячеек.

К15. Что делает функция IsEmpty?

К16. Почему не рекомендуется объединять в одном цикле блоки ввода, обработки и вывода?

К17. Возможно ли досрочное прекращение выполнения цикла (например, до исчерпания списка цикла)?

Работа VBA9. Циклы и массивы (2)

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

Введение

Программы в предыдущих работах VBA7 и VBA8 сделаны на любительском уровне и очень ненадёжны в работе. Разберём основные недостатки.

Подпрограмма Раздел (листинг 19) правильно работает, если в исходной строке ИсхСтрока будет ровно три слова, не больше и не меньше. Если входная строка окажется пустой, то выполнение инструкции

PosBlank = InStr(sloc, " ")

даст нулевое значение переменной PosBlank и выполнение инструкции

s1 = Left(sloc, PosBlank – 1)

приведёт к ошибке, потому что функция Left не может вернуть -1 символ.

К такому же результату придёт выполнение подпрограммы Раздел, если входная строка содержит одно или два слова. При первом или втором вычислении переменной PosBlank будет получен 0 и функция Left не сможет вернуть -1 символ.

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

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

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

52

Программирование в среде электронных таблиц Microsoft Excel

Программа Separate (листинг 24) правильно работает, если диапазон "СписокГруппы" начинается в строке 2 и рабочая часть списка не содержит пропуски строк. Когда в цикле

For Each Ячейка In Selection.Cells

If Not IsEmpty(Ячейка) Then KolStud = KolStud + 1

Next Ячейка

подсчитывается число KolStud, то все пустые строки игнорируются, а в цикле ввода

For i = 1 To KolStud

GroupFio(i) = Cells(i + 1, NumCol).Value

Next i

считываются подряд первые KolStud строк, начиная со строки 2, хотя строка 2 необязательно входит в диапазон.

В подпрограмме Раздел2 (листинг 25) исходная строка разделяется на столько слов, сколько она содержит. Выделенные из строки слова записываются в формальный массив Slova. Обратите внимание: для удаления из исходной строки лишних пробелов используется функция Trim рабочего листа, а не функция VBA:

sloc = WorksheetFunction.Trim(ИсхСтрока) & SP

Дело в том, что функция Trim рабочего листа (функция СЖПРОБЕЛЫ в русифицированных версиях Excel) удаляет из строки все пробелы, кроме единичных пробелов между словами, тогда как функция Trim VBA удаляет пробелы в начале и в конце строки, но не трогает пробелы между словами.

Пробел в конце строки sloc "приклеивается" для того, чтобы унифицировать определение границы очередного слова и выполнять эту работу в цикле. Переменная q выполняет роль индекса в массиве Slova. Переменные Pos1 и Pos2 хранят позиции пробелов перед очередным словом и после него. Цикл While…Loop завершается, когда Pos1 выходит на позицию "приклеенного" пробела.

В программе Separate2 (листинг 26) исходный диапазон представляет объектная переменная Group, этой цели служит инструкция

Set Group = Range("СписокГруппы")

После подсчёта числа непустых ячеек в исходном диапазоне рабочие массивы GroupFio, Slova и KS переопределяются на KolStud строк (нижний индекс равен 0), а массив Slova переопределяются, кроме того, как двумерный на KolSlov столбцов. Ввод исходного списка в массив GroupFio выполняется из непустых ячеек диапазона.

При обращении к подпрограмме Раздел2 вторым фактическим аргументом указывается локальный пустой строковый вектор V. Подпрограмма Раздел2 запишет в него KS(i) слов, которые обнаружит в первом аргументе GroupFio(i). В i-ю строку массива Slova из вектора V переписываются KolSlov слов.

Стеценко А. А.

53

Вывод результатов на рабочий лист почти не отличается от вывода в программе Separate: вместо элементов массивов Fam, Imja и Otch в строку Excel выводится строка двумерного массива Slova.

Рабочее задание. Создать и опробовать вариант программы, взаимодействующей с именованным диапазоном рабочего листа

Р1. Сделать критический анализ программы Separate (листинг 24) и подпрограммы Раздел (листинг 19), отметить положительные стороны и недостатки.

Р2. Проработать текст подпрограммы Раздел2 (листинг 25). Отметить, какие недостатки подпрограммы Раздел и как именно устранены в подпрограмме Раздел2.

Листинг 25

Sub Раздел2(ИсхСтрока As String, Slova() As String, _ КСлов As Integer)

'Разделение строки ИсхСтрока на слова

'Слова записываются в строковый вектор Slova 'КСлов - количество найденных слов 'Разделителями слов считаются пробелы

'

А. Стеценко, 15.05.13.

Dim sloc

As String

Dim Pos1

As Integer, Pos2 As Integer

Dim Dlina As

Integer

Dim p As

Integer, q As Integer

Const SP

= "

"

'Убираем

все

лишние пробелы и добавляем пробел в конце

sloc = WorksheetFunction.Trim(ИсхСтрока) & SP

'Разделение строки на слова, слова записываются в

' вектор Slova Dlina = Len(sloc) q = 0

Pos1 = 0

Do While Pos1 < Dlina

Pos2 = InStr(Pos1 + 1, sloc, SP, vbBinaryCompare) ReDim Preserve Slova(q)

Slova(q) = Mid(sloc, Pos1 + 1, Pos2 - Pos1 - 1) Pos1 = Pos2

q = q + 1

If q > 3 Then

MsgBox "Слишком много слов!"

Exit Do End If

Loop

КСлов = q End Sub

Р3. Составьте главную программу tstРаздел2 для испытания подпрограммы Раздел2. В качестве образца можете взять программу tstРаздел (листинг 20).

54

Программирование в среде электронных таблиц Microsoft Excel

Р4. В среде VBA добавьте новый модуль, дайте ему имя Разделение2 и наберите в нём тексты подпрограммы Раздел2 и программы tstРаздел2.

Покажите результат преподавателю.

Р5. Отладьте и выполните подготовленные программы Раздел2 и tstРаздел2. Р6. Проработайте текст программы Separate2 (листинг 26). Отметьте, с какими

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

Листинг 26

Sub Separate2 ()

'Читает список из диапазона, разделяет строки на слова

'и выводит их в соседние столбцы на том же листе

'

А. Стеценко, 15.05.13.

Dim Ячейка As Range, Group As

Range

Dim KolStud

As Integer, KS() As Integer

Dim NumCol As Integer, NumRow

As Integer

Dim GroupFio() As String

 

Dim Words()

As String, V() As

String

Dim i As Integer, j As Integer, KolSlov As Integer

KolSlov = 3

'Сколько слов

брать из строки

Set Group =

Range("СписокГруппы")

' Подсчёт числа непустых строк в диапазоне "СписокГруппы"

KolStud = 0

For Each Ячейка In Group.Cells

If Not IsEmpty(Ячейка) Then KolStud = KolStud + 1

Next Ячейка

'Переопределение рабочих массивов

ReDim GroupFio(KolStud - 1)

ReDim Words(KolStud - 1, KolSlov - 1) ReDim KS(KolStud - 1)

'Ввод исходного списка в массив GroupFio i = 0

For Each Ячейка In Group

If Not IsEmpty(Ячейка) Then _

GroupFio(i) = Ячейка.Value

i = i + 1

Next Ячейка

'Разделение строк массива GroupFio на составляющие ' с использованием подпрограммы Раздел2

For i = 0 To KolStud - 1

Call Раздел2(GroupFio(i), V, KS(i)) For j = 0 To KolSlov - 1

Words(i, j) = V(j) Next j

Next i

'Вывод результатов на рабочий лист

Стеценко А. А.

55

'Активизация рабочего листа

Worksheets("Группа").Activate

'Координаты диапазона

NumCol = Group.Column NumRow = Group.Row

'Вывод заголовков граф

Cells(NumRow - 1, NumCol + 1) = "Фамилия" Cells(NumRow - 1, NumCol + 2) = "Имя" Cells(NumRow - 1, NumCol + 3) = "Отчество"

'Вывод результатов

For i = 0 To KolStud - 1 For j = 1 To KS(j)

Cells(NumRow + i, NumCol + j) = Words(i, j - 1) Next j

Next i End Sub

Р7. В новом модуле среде VBA наберите текст программы Separate2, отладьте и выполните программу.

Покажите результат преподавателю.

Р8. Проработать текст подпрограммы Razdel3 (листинг 27).

Листинг 27

Sub Razdel3(ИсхСтрока As String, Words() As String, _

КСлов As Integer)

'Разделение исходной строки на слова 'Разделители слов: пробел, знак табуляции, знак препинания

'Последовательные разделители считаются одним разделителем 'Слова записываются в строковый вектор Words

'КСлов --

количество слов в строке

'

 

 

А. Стеценко, 14.05.13.

Dim

sIn

As String, sOut As String

Dim

sym

As String * 1

Dim

Dlina As Integer

Dim

p

As Integer, q As Integer

Dim

abc

As Boolean

'Разделители и их коды

Const

BL = 32, HT = 9

Const

ЗПТ = 44, ТЧК = 46, ВОСКЛ = 33, ВОПР = 63

sIn

=

WorksheetFunction.Trim(ИсхСтрока) & Chr(BL)

Dlina

=

Len(sIn)

sOut = ""

abc

=

False

q =

0

 

 

For

p

=

1 To Dlina

 

sym

= Mid(sIn, p, 1)

 

Select Case Asc(sym)

 

 

 

Case BL, HT, ЗПТ, ТЧК, ВОСКЛ, ВОПР

56

Программирование в среде электронных таблиц Microsoft Excel

 

 

 

If abc Then

 

'Предыдущий символ не был разделителем,

 

' слово завершилось

 

abc = False

 

ReDim Preserve Words(q)

 

Words(q) = sOut

 

sOut = ""

 

q = q + 1

 

End If

 

 

Case Else

'sym - не разделитель, добавляем sym

 

 

' к текущему слову

 

abc = True

 

sOut = sOut & sym

End Select Next p

КСлов = q

End Sub

Р9. Подготовьте и согласуйте с преподавателем изменения в программе Separate2, чтобы она могла работать с подпрограммой Razdel3.

Р10. В отдельном модуле наберите, отладьте и выполните подготовленную программу.

Покажите результаты преподавателю.

Р11. Сохраните и закройте свою книгу, скопируйте на личный носитель.

Контрольные вопросы к работе VBA9

К1. Что будет делать подпрограмма Раздел, если аргумент ИсхСтрока будет пустой строкой?

К2. Что будет делать подпрограмма Раздел, если аргумент ИсхСтрока будет содержать меньше или больше трёх слов?

К3. К какому результату приведёт выполнение подпрограммы Раздел, если входная строка содержит одно или два слова?

К4. В подпрограмме Раздел2 имеется инструкция

sloc = WorksheetFunction.Trim(ИсхСтрока) & SP

Объясните: а) назначение ключевого слова WorksheetFunction; б) какие действия выполняются над переменной ИсхСтрока; в) для чего к результату, возвращённому функцией Trim, добавляется константа SP?

К5. Объясните формальные аргументы подпрограммы Раздел2.

К6. На сколько слов может разделить строку подпрограмма Раздел2? К7. Объясните инструкцию

Pos2 = InStr(Pos1 + 1, sloc, SP, vbBinaryCompare)

К8. Объясните инструкцию

Slova(q) = Mid(sloc, Pos1 + 1, Pos2 - Pos1 - 1)

К9. Объясните, как программа Separate2 находит исходные данные.

Стеценко А. А.

57

К10. Сформулируйте требования к исходным данным программы Separate2, если для разделения строки на слова используется подпрограмма Раздел2.

К11. Объясните, как в программе Separate2 определяются значения перемен-

ных NumCol и NumRow.

К12. Какие изменения нужно сделать в программе Separate2, чтобы заменить обращение к подпрограмме Раздел2 обращением к подпрограмме Razdel3? К13. Объясните, по каким признакам подпрограмма Razdel3 обнаруживает слова в строке?

К14. Как изменится ответ на вопрос К10, если заменить Раздел2 на Razdel3?

Работа VBA10. Разработка диалогового окна

Цель работы: приобретение навыка создания пользовательской формы и программы в модуле формы, ознакомление со статусом программы UserForm_Initialize, ознакомление с приёмами использования элементов управления в форме.

Введение

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

После команды вставки модуля формы появляются полотно формы UserForm1 и панель инструментов Toolbox (рис. 5). Чтобы переставить элемент управления с панели инструментов на полотно формы, нужно выбрать элемент на панели инструментов и щёлкнуть в нужное место полотна формы или обри-

Рис. 5. Полотно формы и панель инструментов в окне VB

58

Программирование в среде электронных таблиц Microsoft Excel

совать прямоугольник на полотне. В окне Properties автоматически появляются свойства соответствующего элемента.

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

Рабочее задание. Создать пользовательскую форму для регистрации клиентов туристской фирмы “Будьте здоровы”.

Р1. Откройте свою книгу, прочтите ещё раз приветствие, которое Вы сделали в работе VBA2. Дайте листу "Лист2" название “БудьтеЗдоровы”.

Р2. В первую строку листа “БудьтеЗдоровы”, начиная с ячейки А1, введите названия граф:

Поз. Фамилия Имя Отчество Пол Тур Срок

Р3. Перейдите в среду VBA и дайте команду на вставку модуля UserForm. В

окне Properties замените имя (Name) UserForm1 на frmБудьтеЗдоровы.

Р4. Раздвиньте полотно формы до размеров 12 10 см (приблизительно), расположите в удобном месте панель элементов управления (Toolbox) и заполните полотно формы элементами управления в соответствии с рис. 6. В настоящий момент не имеют значения точные размеры и координаты элементов, они потом будут определены программно.

Рис. 6. Полотно формы в режиме Конструктора со вставленными элементами управления (к п. Р4).

Стеценко А. А.

59

Сейчас важно не пропустить тот или иной элемент управления. Заполняя

полотно формы, не забывайте, что редактор VBA поддерживает метод “Перенести и оставить” (Drag & Drop), который при нажатой клавише Ctrl копирует выделенный фрагмент (элемент или группу элементов) в новое место.

Рекомендуется следующий порядок размещения элементов управления:

а) в левый верхний угол поставьте элемент Label (при выборе элемента следите за всплывающими подсказками), рядом поставьте элемент TextBox;

б) выделите вставленные элементы и скопируйте два раза вниз и один раз вправо, чтобы получились 4 одинаковые пары;

в) скопируйте элемент Label вправо; г) поставьте элемент ComboBoox; д) поставьте элемент SpinButton;

е) поставьте элемент Frame;

ж) в элемент поставьте два элемента OptionButton; з) поставьте три элемента CommandButton.

Р7. Присвойте элементам управления программные имена. Для этого в окне Properties (оно вызывается нажатием клавиши F4) в верхней строке замените свойство (Name) на имя, указанное на рис. 7.

Обратите внимание: все именования выполняются только в окне Properties, в полотне формы никакие действия не производятся.

Рис. 7 Имена элементов управления даются в соответствии с венгерской нотацией.

Назначение программных имён – одна из головных болей программиста. В настоящей работе имена элементам управления даются в соответствии с венгерской нотацией, называемой также "соглашениями о наименованиях Реддика", предложившего эту нотацию.

В соответствии с венгерской нотацией программное имя начинается приставкой, обозначающей тип именуемого объекта.

60

Программирование в среде электронных таблиц Microsoft Excel

Венгерская нотация широко используется в программных разработках баз данных.

Р5. Следующая часть работы – написание программы UserForm_Initialize (листинг 28). Не отчаивайтесь, глядя на длинный текст: добрую половину работы за Вас сделает редактор VBE с помощью своих подсказок, значительную часть оставшейся работы поможет выполнить метод Drag & Drop.

Выполните двойной щелчок по свободной части полотна формы и вы попадете в окно кода (текста программы). В правой части окна VBE раскройте список и выберите Initialize (рис. 8). Заготовку программы UserForm_Click удалите. Затем набирайте остальные строки программы. Внимательно следите за текстом, подсказками на экране, при всякой возможности используйте

Drag & Drop. Click

Рис. 8. Создание заготовки программы UserForm_Initialize.

Листинг 28 Программа инициализации формы

Private Sub UserForm_Initialize() 'Инициализация формы frmБудьтеЗдоровы

'

А.Стеценко, 18.04.13.

 

Dim snp As String

 

'Задание заголовка окна приложения

 

Application.Caption = "Регистрация"

 

'Формирование строки заголовка формы

 

snp = "Регистрация туристов фирмы "

 

snp = snp & "Будьте здоровы!"

 

'Задание заголовка, размеров и цвета формы

 

With frmБудьтеЗдоровы

 

.Caption = snp

 

.BackColor = RGB(0, 255, 255)

 

.Height = 200

 

.Width = 300

 

End With

 

'Задание свойств надписей и текстовых полей

 

With lblFam

 

.Caption = "Фамилия:"

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]