Введение в программирование на примере VBA
Часть II. Создание макроса-приложения
Занятие 11. Проектирование новой версии приложенияЦель занятия – определиться с улучшениями, которые мы хотели бы произвести с нашим приложением. Цикл 2На протяжении предыдущих занятий мы создали вполне работоспособное приложение, имеющее минимальную, но законченную функциональность. Настало время нового «витка» работы. На основе работоспособного приложения, используя имеющиеся наработки, следует создать новую, расширенную и более функциональную версию. ТребованияВыдвинем требования к новой версии. Приложение позволяет возврат по списку вопросов. При этом следует восстанавливать значение ответа, данного на предыдущий вопрос, для того, чтобы пользователь мог внести коррективы. Взаимосвязано с этим другое требование. Приложение позволяет вернуться вперед по списку вопросов, если был совершен возврат назад. Отсюда вытекает третье требование. Следует воспретить пропуск неотвеченных вопросов при продвижении вперед. Пояснение. Предположим, что в тесте шесть вопросов. Пользователь ответил на первые четыре вопроса и хочет исправить ответ на второй. Приложение позволяет вернуться ко второму вопросу и затем продвинуться обратно к четвертому, данные ранее ответы сохраняются. Но перейти к шестому вопросу, не ответив на пятый, нельзя. АнализВыделим виды деятельности, которые приложение должно осуществлять соответственно этим требованиям.
Явно не указаны, но подразумеваются такие виды деятельности:
На схеме словом <<внешний>> помечены виды деятельности, уже реализованные нами. Они – внешние по отношению к текущей задаче. Внимательно изучив схему, вы увидите, что есть пара – «сохранение-восстановление». Это подразумевает хранилище для ответа. Сейчас речь не идет о долговременном хранилище, с котором мы определились ранее. Определение, дан ли ответ на вопрос, так и напрашивается на применение флага. При «отвеченном» вопросе флаг установлен, иначе – сброшен. Подобный флаг должен быть для каждого вопроса. Не совсем наглядные рассуждения, не правда ли? Моделирование нового объекта – временного хранилищаЕще один прием, который правомерно применить при создании программы, заключается в следующем. Представьте себе, как подобную задачу вы стали бы выполнять самостоятельно, вручную. Подробное описание ваших действий – фактически, готовый алгоритм, который, возможно, вы впоследствии улучшите, но у вас будет, с чего начать.
Правильно, будете составлять таблицу примерно такого вида:
Мы получим структуру хранилища, строение и реализацию которого подробно рассмотрим далее. Несколько слов о порядке заполнения хранилища данными. Столбец правильных ответов, очевидно, заполняется данными из основного хранилища приложения, которым является таблицы Excel. Целесообразно делать это при запуске приложения. Для экономии ресурсов компьютера это можно делать и в процессе теста, но потом вы увидите, что это временное хранилище очень компактно, реализация заполнения в процессе работы принесет гораздо больше неудобств, нежели преимуществ. Только в случае очень больших – десятки тысяч и более, – вопросов, следует обращаться к динамическому считыванию данных из основного хранилища. Столбец полученных ответов получает данные в процессе работы приложения. Но в дальнейшем нам потребуется возможность восстанавливать результаты предыдущего теста (в следующей версии приложения), поэтому, также как и в случае правильных ответов, будем считывать данные из основного хранилища при запуске приложения. Это не усложнит работу, как вы убедитесь далее. Последний столбец содержит флаги. Он заполняется только при работе приложения. Первый (крайний левый) столбец фиктивный, эти данные не существуют, а помещены в таблицу лишь для наглядности. Далее вы увидите, что имеется в виду. Теперь определимся с объектами, нужными для выполнения требований к приложению.
Схема взаимодействия Очередная разновидность схем, используемых при создании приложений – схемы взаимодействия. Компоненты схем взаимодействия – объекты, найденные при анализе требований. Отличие от схемы объектов в том, что все объекты на схеме взаимодействия должны соединяться с другими при помощи связей. Для наглядности на связях указывается вид взаимодействия. Если для объекта на схеме вы не можете указать ни одной связи-взаимодействия, наверное, следует вовсе исключить этот объект из данной схемы или пересмотреть всю схему.
Вот что, например, может у вас получиться: Схема взаимодействия объектов при запуске приложения:
Схема взаимодействия объектов в процессе работы (тестирования):
При изображении «множественного» объекта или набора допустимо использовать «двойной» значок. На данной схеме так выглядит объект Переключатели. Схема взаимодействия объектов при переходе по списку вопросов:
На последней схеме вы видите, что некоторым связям соответствуют стрелки с описанием. Это – дополнительное уточнение взаимодействия. Так, этот фрагмент схемы:
следует читать так: «Ограничитель пропуска неотвеченного вопроса ограничивает функциональность кнопок перехода путем изменения их состояния». При схематическом отображении взаимодействия мы использовали объекты, найденные на предыдущем этапе. Не следует излишне детализировать – точность будет достигнута позже. Как видите, произошло уточнение перечня найденных объектов – оказывается, объект определитель отвеченного вопроса должен существовать в двух видах. Первый задействуется при обычном тестировании, и, в случае ответа на вопрос, устанавливает соответствующий флаг во временном хранилище, – как и предполагалось раньше. Другой делает обратную задачу – проверяет значение флага и производит какие-то действия.
РеализацияТеперь займемся реализацией временного хранилища. Проектирование структуры временного хранилища Вспомните примерную структуру хранилища, определенную нами ранее. Как видите, оно состоит из повторяющихся строк, несущих несколько единиц информации.
Подобные конструкции нам уже знакомы. Это – наборы VBA. Вы уже работали со встроенными наборами MS Office. Недостаток большинства встроенных наборов MS Office – их низкое быстродействие. В случае больших наборов, содержащих несколько сотен элементов и более, падение скорости приложений бывает значительным. Кроме того, ни один из существующих встроенных наборов не удовлетворит нашим требованиям. Набор придется создавать самостоятельно. Далее вы увидите, что это несложно. Но не спешите. Видно, что схема хранилища, помимо однообразных рядов, число которых не определено и может быть большим, включает также несколько колонок. Число колонок предопределено (в нашем случае – три, колонка с порядковыми номерами рядов не нужна), и невелико.
Казалось бы, это тоже набор. Не совсем так. Как мы уже условились, первые две ячейки содержат числовые значения, а третья – флаги, имеющие логический тип. Наборы же содержат однотипные ячейки. Для манипуляции с подобными конструкциями, содержащими несколько (немного) значений различных типов, выступающих как одно концептуальное целое, в VBA имеется специальное средство – пользовательский тип. Пользовательский тип Пользовательский тип – разновидность переменной особого типа, определяемого пользователем (как следует из названия). В большинстве других языков программирования (в том числе и в новых версиях VB) подобные конструкции называются структурами, в данном учебнике эти термины будут использоваться как равноправные, хотя это и не совсем верно с точки зрения академического VBA. Синтаксис пользовательского типа таков: Type
<имя_типа> <имя_типа> будет использоваться при объявлении переменной – обычным способом. <элемент_N> – имя ячейки пользовательского типа. Это имя будет в дальнейшем использоваться программой. Определение пользовательского типа помещается в разделе глобальных объявлений модуля. Могут применяться квалификаторы Public- Private. Подробности вы найдете в справке VBA по запросу Type Statement. Давайте определимся с нашим типом, предназначенным для хранения «строки» хранилища. Пусть новый тип называется tStore – сокращенно от Type–Store (Тип–Хранилище). Тогда описание типа будет таким: Type tStore В «строке» нашего хранилища три ячейки. Первая содержит числовое значение правильного ответа, вторая – полученного ответа, третья – флага. Пусть ячейки носят имена: Well – от Верный, Правильный, Answ – от Answer – Ответ, Flag – Флаг.
Type tStore Необходимо в каждую строку включить явное объявление типа. Тип третьей строки очевиден – логический: Type tStore Остальные строки будут нести целое числовое значение. Можно использовать уже знакомый нам Integer, но, так как следует заранее заботиться о размерах хранилища – ведь заранее неизвестно, сколько вопросов будет в тесте, – примем тип Byte. Этот целочисленный тип может принимать значения от 0 до 255. В нашем случае значения будут от 1 до 3 – хватит с запасом. А экономия памяти при работе приложения может быть значительной, особенно при больших размерах теста. Итак, вновь созданный тип будет определен так: Type tStore
Это – заготовка «ячейки» временного хранилища. Массив Само по себе хранилище будет содержать некоторое, не определенное заранее количество таких «ячеек», пронумерованных по порядку. Оказывается, VBA имеет набор, полностью удовлетворяющий этим требованиям. Такие наборы называются массивами. Массив – набор некоторого числа элементов одинакового типа. Элементы набора нумеруются по порядку. Максимальное число элементов массива – 32768 (при нумерации с 0 до 32767). В справке VBA это явно не указано, подразумевается, что нумерация элементов производится при помощи числа типа Integer, максимально допустимое значение которого и есть 32767. Массив объявляется подобно обычной переменной: Dim <имя_массива>(<нижняя_граница> To <верхняя_граница>) As <тип_элемента> Например: Dim arSample (0 To 15) As Integer Объявленный здесь массив arSample содержит 16 (от 0 до 15) элементов типа Integer. Обратиться, к примеру, к элементу номер 5 можно так: arSample(5) Работа с элементом массива происходит точно так же, как и с обычной переменной. Например, так назначается значение 24 элементу номер 10: arSample(10) = 24 <тип_элемента> при объявлении массива может быть любым из допустимых для переменных, в том числе и вновь созданным пользовательским типом. Значит, для нашего теста из четырех вопросов можно объявить хранилище так: Dim arStore (1 To 4) As tStore Тогда прочитать из хранилища значение правильного ответа на вопрос номер 3 можно так: <значение> = arStore(3).Well Как видно, применение пользовательских типов схоже с обращением к свойствам объектов. Но, как мы условились, число вопросов теста заранее не определено. Подобное объявление массива не удовлетворяет условиям. И для такого случая VBA имеет готовое решение. Можно объявить массив без указания нижней и верхней границы, а потом, в начале работы программы, присвоить ему требуемые размеры. Объявление так называемого динамического массива будет выглядеть так: Dim arStore() As tStore А где-то в начале выполнения приложения (но уже после подсчета числа вопросов) понадобится сделать так: ReDim arStore (<нижняя_граница> To <верхняя_граница>) Подобное переопределение может изменить только границы массива. Тип элементов переопределить невозможно. Решим, когда же следует производить переопределение. Очевидно, после подсчета числа вопросов теста. Этот подсчет производится в процедуре StartTest. Реализация временного хранилища
Dim arStore() As tStore
Public Sub StartTest()
Все должно пройти без ошибок. Кажется, нет большого смысла в этом запуске – мы еще не сделали значимых изменений программы. Тем не менее, при каждом запуске VBA автоматически проверяет допустимость кода – получается своеобразная проверка ошибок. Мы нечувствительно реализовали найденный ранее объект создатель хранилища и произвели первый подцикл второго цикла создания приложения. Итог занятияВ ходе занятия мы повторили формулирование требований, анализ и проектирование приложения, точнее – новой версии приложения. Новой для вас должна стать схема взаимодействия объектов. Такой уж большой надобности в ней, вроде бы, и не было – но с помощью схем взаимодействия мы увидели, что пропустили объект на предыдущей стадии анализа. Обычно же схема взаимодействия служит основой для дальнейшего составления схем последовательности действий. Основная же тема занятия – массивы, пользовательские типы и работа с ними. Для повторения и закрепления материала сделайте конспект:
Весь материал доступен в этом занятии, искать в справке VBA вам не придется. |