Введение в программирование на примере VBA
Часть I Создание макроса Word
Занятие 3. Внесение исправленийЦель занятия – исправление созданного макроса. За основу возьмем информацию, полученную в ходе предыдущего занятия. Планирование корректировки макросаДля правильного планирования изменений, которые мы хотели бы внести в макрос, сначала подведем итоги недостаткам кода, который мы только что рассмотрели.
Условие 4 можно и опустить. Действительно, иногда может возникнуть потребность применить макрос не с начала документа. Другие пункты мы сейчас исправим. Исправление недостатков макросаПриведение документа к «нормальному» видуНачнем с пункта 3 – приведение документа к «нормальному» виду. Запись нового макроса для получения нужного кода Один из способов получить код, выполняющий нужные действия – записать макрос. Действительно, если вы ясно представляете себе последовательность действий, требующихся от Word (или от другого приложения MS Office), то вовсе необязательно идти трудным путем в реализации этого действия в коде. Тем более что вы и сами убедились в сложности и запутанности справочной системы VBA. Можно сделать гораздо проще: записать определенную вами последовательность действий как макрос, а затем, просмотрев результаты записи, выделить нужный код для дальнейшего использования. В течение этого шага работы мы должны добавить в макрос код, приводящий документ к «нормальному» виду. Воспользуемся предложенной методикой и запишем небольшой макрос, выполняющий требуемое. Для выполнения корректировки кода воспользуемся средством автозаписи макросов. Это позволит нам получить желаемый результат быстро, не затрудняясь долгим и малопродуктивным изучением разделов справки. Создайте новый пустой документ Word. Новый макрос будет записан в нем. Это – необязательный шаг, просто вам будет проще разобраться, не отвлекаясь на компоненты, которые могут содержаться в использовавшемся ранее документе. Если вы находитесь в Word:
Дальнейшая работа будет проходить в этом документе. Сначала приведем документ к виду, отличному от «нормального», чтобы будущий макрос смог правильно выполнить свою работу.
Переключение видов документа быстро и просто производить кнопками, которые находятся внизу слева окна документа:
Вот эти кнопки:
На рисунке нажата крайняя левая кнопка – документ в «нормальном» виде. Вместо команды можно щелкнуть на третьей слева кнопке.
Если забыли – повторите материал.
Когда появится панелька с кнопками остановки и паузы, начинайте ввод собственно макроса. Этот макрос будет выполнять только одно действие – приводить документ к «нормальному» виду.
Разбор кода нового макроса Если код макроса не открылся сразу – в окне Project Explorer найдите пункт с надписью NewMacros и выполните на нем двойной щелчок:
Откроется код созданного макроса. Он будет таким: Sub НовыйМакрос() Странно, одно действие привело к записи пяти значимых строк кода – не считая «оболочки» макроса и пояснений. Давайте вкратце разберем значение созданного макроса. Читаем «по-английски» первую строку: If ActiveWindow.View.SplitSpecial = wdPaneNone Then Если АктивноеОкно.Вид.СпециальноеРазделение = wdНетПанели Тогда Как видите, появилась новая конструкция, начинающаяся со слова If – Если. Блок If…Then, его разновидности Язык VBA содержит условные конструкцииb, предназначенные для проверки некоторых условий и выполнения вследствие этого тех или иных действий. Основная условная конструкция – If <условие>
Then По-русски это будет звучать так: Если <условие> То Итак, при выполнении этой конструкции происходит проверка <условия>. В случае, когда <условие> верно, выполняется <действие>, в противном случае выполнение продолжается после строки End If – символа окончания условной конструкции. Более сложный вид этой условной конструкции: If
<условие> Then Слово Else можно перевести как Иначе. Код можно «прочитать» так: Если <условие> То То есть, если <условие> верно, выполняется <действие1>, иначе – <действие2>. Как видно, принципиальной разницы между этим и первоначальным видом условной конструкции нет. Полезное применение слову Else получаем при такой модификации: If
<условие1> Then При разборе конструкции видим: Если <условие1> верно, выполняется <действие1>, Продолжение разбора нового макроса Вернемся к коду нового макроса. Как видно, весь макрос – одна конструкция If...Then...Else. В первой строке проверяется условие: ActiveWindow.View.SplitSpecial = wdPaneNone Не углубляясь в детали кода, понимаем, что речь идет о каком-то «СпециальномРазбиении» Вида АктивногоОкна. Вроде бы ничего такого мы не предпринимали, эта строка, видимо, нам не нужна. В следующей строке кода: ActiveWindow.ActivePane.View.Type = wdNormalView мы видим, что при соблюдении предыдущего условия Тип Вида АктивнойПанели АктивногоОкна назначается к НормальномуВиду – именно так можно «прочитать» эту строку, буквально переводя с английского. Активных панелей мы также не создавали. Пропускаем уже известную нам строку Else и читаем следующую строку, которая выполняется при несоблюдении условия в первой строке кода: ActiveWindow.View.Type = wdNormalView «Читаем»: Тип Вида АктивногоОкна назначить к НормальномуВиду. То, что надо! Мы нашли действие, нужное в нашем случае. Однако если вы предполагаете работать со сложными документами, пользуясь всеми возможностями Word, может быть, вам следует использовать макрос целиком. Давайте внесем первое исправление в наш учебный макрос. Не забудьте открыть Word.
Selection.Find.ClearFormatting
ActiveWindow.View.Type = wdNormalView Пока не будем пробовать работоспособность макроса, внесем сначала все изменения. Как вы понимаете, сохранять новый макрос, записанный только что, не обязательно, но желательно для повторного изучения в дальнейшем… Упорядочение блока WithСледующим шагом нормализуем применение With.
With Selection.Find
Selection.Find.ClearFormatting
Сейчас код макроса выглядит так: ActiveWindow.View.Type
= wdNormalView Других изменений, связанных с With, пока делать не будем, потом будет понятно, почему. Комментирование кодаТеперь попробуем сделать код более понятным. Обратите внимание, как оформлена пометка в начале макроса. Sub СтильСноска() Очевидно, что эти строки – кроме первой, – должны игнорироваться языком. Так и происходит. В языке VBA любая строка кода, начинающаяся со знака ‘ – апостроф – языком не обрабатывается. Такие строки называются комментариями. Обратите внимание на следующее. Так как комментарии не оказывают никакого влияния на действия, выполняемые языком VBA, у начинающих возникает соблазн не использовать комментариев вообще. Ни в коем случае не поступайте так! ВСЕГДА вносите комментарии в код. Содержание комментариев произвольно. Обычно в них поясняются действия, выполняемые кодом. К комментариям предъявляются два требования: чтобы они были, и чтобы они были ясны для вас. Наилучшая проверка качества комментирования кода такова. Откройте написанный и прокомментированный вами код после двух-трехмесячного перерыва в работе. Если вам придется вновь вникать в смысл каждой строки подобно тому, как мы это делаем сейчас – то ваши комментарии неудовлетворительны.
Комментируйте каждую строку кроме совершенно очевидных, таких, как строки окончания конструкций и т.п. Код должен приобрести вид, подобный следующему: ‘документ переводится в «нормальный» вид и так далее. Не пытайтесь экономить время на комментариях! Впоследствии вы можете потерять гораздо больше. Перед тем, как продолжить корректирование кода, сделаем пробный запуск.
Откроется окно выбора макроса для запуска.
Если вы все делали правильно, первый участок текста, помеченный стилем «примечание», будет преобразован в сноску.
Мы выполнили пробный прогон макроса. Он должен пройти без проблем. Если что-то не получается – внимательно перечитайте руководство и проверьте каждый шаг создания макроса. Сокращение макросаТеперь давайте попробуем сократить код макроса. Как мы видели при разборе кода, в нем есть избыточные, ненужные строки. Можно сразу удалять строки, которые покажутся вам ненужными, но обычно так делать не рекомендуется. Всегда остается опасность утратить нужные участки кода. Выход из этой ситуации прост. Вспомните – любая строка, начинающаяся с апострофа (‘) – комментарий, – игнорируется языком. Следовательно, чтобы исключить строку из выполняемого кода, достаточно поместить в начале этой строки апостроф. Иначе говоря – закомментировать строку.
Начнем с заведомо ненужных строк.
' .MatchCase = False
Не забудьте перед запуском сохранить документ! Как видите, результат не отличается от бывшего ранее, то есть закомментированные строки не оказывали никакого влияния на работу макроса.
Попробуйте закомментировать другие строки, входящие в блок With, запуская макрос каждый раз и наблюдая результат. После каждого запуска возвращайте документ к начальному виду. Оказывается, блок With можно значительно сократить, не теряя функциональности макроса: With Selection.Find Пока оставим код в таком виде. Удалить ненужное всегда успеется. Зацикливание макросаНаконец, перейдем к зацикливанию выполнения макроса. Вспомните условие задачи. Действия по преобразованию текста в сноски следует повторять до тех пор, пока не будет достигнут конец документа. Вновь обратимся к основам VBA. Циклы VBA VBA, как и другие языки программирования, предоставляет возможность зацикливания участков программы. Циклы VBA можно разделить на две группы – For...Next и Do...Loop. Цикл For…NextЦиклы For...Next имеют следующую схематическую структуру: For <index> =
0 to 25 Здесь <index> – особая сущность языка, называемая переменная. Переменная – именованное хранилище данных. При выполнении программы в переменной могут сохраняться промежуточные результаты вычислений с тем, чтобы использовать их в дальнейшем. В переменную можно помещать данные, а можно считывать их из переменной. В начале цикла For...Next создается переменная <index>. Имя переменной может быть любым – но структура имени должна подчиняться тем же правилам, что и имена макросов. Перед первым проходом цикла – то есть перед первым выполнением <действия>, – индексной переменной присваивается начальное значение. В данном примере – 0. При достижении строки Next <index> индексная переменная увеличивается на единицу, и выполнение переходит к <действию>. Первая строка For... больше не выполняется. Последний проход цикла совершается со вторым значением индексной переменной. В примере – 25. Итак, в нашем примере <действие> совершится 26 раз (от 0 до 25). Очевидно, что данная конструкция цикла полезна в случаях, когда заранее известно число повторений. В нашем макросе количество создаваемых сносок неизвестно. Лучше, нежели цикл For...Next, нам подойдет конструкция Do...Loop. Цикл Do…LoopЦикл Do...Loop имеет следующую структуру: Do Слово Do обозначает начало области, которая будет повторяться. Первое найденное после этого слово Loop отмечает конец области. Цикл в таком виде будет повторяться бесконечно, то есть необходимо предусматривать условия остановки. Чаще всего применяются модификации цикла с пред- или постусловиями. Do Until <условие> Эта модификация будет выполнять до тех пор, пока <условие> не станет истинным – не выполнится. Причем <условие> проверяется до первого выполнения <действия>, и возможны случаи, когда <условие> изначально истинно – и <действие> не выполнится ни разу. Если требуется хотя бы одно выполнение <действия>, цикл модифицируют так: Do Смысл тот же, но проверка <условия> – после выполнения <действия>. Есть «зеркальная» противоположность этому циклу: Do While <условие> Здесь цикл выполняется до тех пор, пока <условие> выполняется. Как только <условие> станет ложным, цикл прекратится. Также есть модификация с проверкой после прохода цикла. Очевидно, что принципиальной разницы между циклами Do Until и Do While нет. Действительно, любое условие можно перефразировать в свою противоположность, эффективность кода при этом не изменится, так что применение того или другого цикла – вопрос личного предпочтения. Поиск конца документа Далее следует определиться, какое условие мы будем проверять по мере повторения кода макроса. К сожалению, документы Word не имеют метки конца документа, как, к примеру, некоторые объекты баз данных. Придется искать обходные пути. Метод Execute Логично обратиться к тому действию макроса, которое вызывает перемещение по документу. Если помните, это – метод Execute: Selection.Find.Execute
Для вызова справки поместите текстовый курсор на слове Execute в окне кода IDE VBA (одиночным щелчком) и нажмите [F1]. Вы увидите окно с перечислением объектов, к которым применим метод Execute.
Перед вами – довольно обширное описание метода. Но обратите внимание на первую строку. Там дано краткое описание действия метода (что он запускает определенную операцию поиска), а далее написано не вполне понятно: «возвращает True, если операция поиска успешна». Что значит возвращает? Оказывается, многие методы и подпрограммы после выполнения предоставляют вызвавшему их коду какие-то значения. Синтаксис применения методов в таком случае аналогичен синтаксису свойств, когда производится чтение значения. Подпрограмма или метод, возвращающие значение, имеют специальное название – функция. В тех случаях, когда возвращаемое значение не нужно, VBA позволяет игнорировать его и использовать синтаксис обычной подпрограммы-процедуры. Теперь можно дать еще одно определение процедуре. Процедура – это подпрограмма или метод, не возвращающие значения. Еще немного остановимся на значении True (Правда, Истина). Это значение так называемого логического типа. Возможны лишь два таких значения – True и False (Ложь). Дадим пример из обыденной жизни. Когда задают вопрос: «Как дела?», обычно следует ответ: «Нормально!». Это – аналог значению True. Ответ «Плохо…» будет аналогичен False. Логический тип обычно применяется при проверке условий. Тогда значение выражения True соответствует выполнению условия, а значение False – невыполнению. Итак, метод Execute объекта Find – это функция, возвращающая значение True при успешном выполнении. Представим ситуацию, когда поиск дошел до конца документа, а искомый участок не найден. Вероятно, выполнение метода Execute должно закончиться неудачей. Зацикливание кода Давайте определим, какой участок кода будем зацикливать. Весь макрос? Не стоит. В самом начале мы производим действия, которые достаточно сделать один раз. Это – перевод документа в «нормальный» вид и настройка параметров поиска. А вот сам поиск и преобразование текста в сноску будем повторять.
ActiveWindow.View.Type
= wdNormalView Логично? Проверим работоспособность макроса. Не забудьте сохраниться!
Что-то не то! Почему участки текста преобразуются «через один»? Обратите внимание на следующие строки кода: Do Until
Selection.Find.Execute = False Заметьте, что выражение Selection.Find.Execute встречается два раза подряд! То есть метод вызывается дважды, и лишь потом происходит преобразование текста в сноску.
Selection.Find.Execute Код приобретет вид: Sub СтильСноска() Внимательно сверьте код вашего макроса с помещенным здесь.
Все получилось! Оказывается, если функция используется как источник значения – даже и при проверке условия, – это не исключает ее выполнения. Не забывайте об этом. Теперь можете удалить закомментированные строки кода, если вы хотите уменьшить размер макроса. Но большой экономии размера вы не получите, а эти строки, возможно, пригодятся вам потом, если вы захотите изменить свой макрос. Наверное, не стоит их удалять. А вот текстовые комментарии, поясняющие суть кода, следует добавить незамедлительно.
Первая часть нашего учебника подошла к концу. Хотелось бы немного остановиться на тонкостях настройки Word, упрощающих применение созданных макросов. Создание панели быстрого запускаВажная концепция, о которой зачастую забывают начинающие – и не очень, – программисты, но выполнение которой настоятельно требуют пользователи – юзабельность (от use – Использовать). Можно дать краткое определение этому понятию так: Приложение можно считать юзабельным, если с ним удобно работать незнакомому с ним пользователю. Мерой юзабельности следовало бы считать скорость освоения приложения незнакомым с ним пользователем. Если выразить то же самое другими словами, то концепция юзабельности подразумевает простоту и интуитивную понятность приложений – даже для неопытного пользователя. Созданный и исправленный нами макрос не имеет каких-либо компонентов, взаимодействующих с пользователем, поэтому сложно говорить о юзабельности… Стоп! В этом-то и дело! Необходимо добавить средства взаимодействия с пользователем! Давайте создадим панель кнопок, аналогичную тем, что имеются в Word, и разместим на ней кнопку для вызова нашего макроса.
Например, здесь:
Появится контекстное меню со списков всех существующих панелей кнопок Word.
Появится диалоговое окно:
Например, Мои макросы.
Появится заготовка новой панели:
Но кнопок на ней нет. Добавим их.
Вы видите два списка. Левый список содержит категории команд Word, которые вы можете назначить кнопкам, правый список содержит команды выбранной категории.
Справа появится список всех макросов Word, доступных вам. Он может отличаться от приведенного на рисунке.
Если помните, макрос делался доступным только для данного документа, значит и назначить его кнопке получится только для этого документа. В других документах макрос работать не будет. Чтобы макрос работал везде, следовало назначать его доступным всем документам (шаблон Normal.dot).
Должно получиться примерно так:
Здесь панель кнопок не переименована. Как видите, надпись на кнопке непонятна, да и сама кнопка получилась слишком большая. Исправим положение следующим образом.
Возникнет контекстное меню:
При помощи этого меню вы можете настраивать внешний вид кнопки.
Как видите, внешний вид кнопки изменился.
Созданная вами панелька готова к использованию.
Если вы все сделали правильно – макрос сработает точно так же, как и при вызове «классическим» способом. Итог занятияСначала, пожалуйста, составьте конспект. Вот примерный план:
Остальное вы найдете в справочной системе VBA. Помимо теоретических сведений и практических навыков, полученных в ходе этого занятия, хочется обратить внимание на некую абстрактную парадигму, намеки на которую встречались очень часто. А именно – следует стремиться к наибольшей простоте, краткости и быстроте. Можно сказать, что программа должна быть аскетичной. В нашем случае это достигалось путем удаления неработающих участков – а их оказалось довольно много, – и упорядочением конструкции With. Как вы убедились, средство автоматической записи макросов не всегда может сделать то, что хотелось бы, поэтому приходится дорабатывать код вручную. Это относится, в частности, к обработке целого документа. «Зацикливать» макрос приходится вручную. Важная теоретическая концепция, упомянутая в ходе занятия – юзабельность. Любое приложение должно отвечать требованию быть удобным в использовании. В идеале «правильным» приложением сможет эффективно пользоваться человек, впервые его увидевший. Несколько слов о логических выражениях. Условные выражения в VBA обычно формулируются таким образом: <значение1><условный оператор><значение2> Здесь <значения> – сравниваемые конструкции, а <условный оператор> определяет разновидность сравнивания, это может быть знак равенства =, знаки сравнение <, >, <=, >=, <>, и специальные слова VBA – операторы AND, NOT, OR или XOR. Применение знаков равенства и сравнения не требует особых пояснений: Конструкция a = b будет истинной, если aравноb, a > b если a больше b, a >= b если a больше или равно b и так далее. Сложнее уяснить использование логических операторов. Вот выражение a = b AND c Здесь a будет истинным, если истинно b И истинно c. a = b OR c a истинно, если истинно b ИЛИ истинно c ИЛИ истинны и b и c. a = b XOR c a истинно, если истинно b ИЛИ истинно c, но не оба сразу. Так же, как и обычные арифметические выражения, логические конструкции могут быть сложными и составляться с использованием скобок, определяющих последовательность вычислений. Подробнее – в справке VBA. |