ПРОГРАММИРОВАНИЕ

VBA: для тех, кто любит думать

Орлов А. А.



ВВЕДЕНИЕ

Вашему вниманию предлагается книга, посвященная весьма интересной теме — возможностям и способам создания программ, работающих в среде пакета программ Microsoft Office. Нет нужды говорить о популярности этого пакета в нашей стране, однако, к сожалению, немногие пользователи знают и применяют в своей деятельности возможности его компонентов в области автоматизации своей работы с помощью макросов. И уж совсем единицы используют Microsoft Office как среду разработки программных продуктов. Отчасти такая ситуация вызвана несколько пренебрежительным отношением многих профессиональных разработчиков программ к Visual Basic for Applications — языку программирования, "встроенному" во все компоненты пакета программ Microsoft Office (начиная с версии 95). Однако Visual Basic for Applications (сокращенно — VBA) — вполне полнофункциональный язык программирования, с помощью которого можно создавать вполне законченные и работоспособные программы, как просто облегчающие работу с Microsoft Office, так и предназначенные для проведения расчетов, обработки данных.

Но самое главное — на VBA могут создавать программы даже те, кто ранее никогда не занимался программированием, причем для этого не потребуются ни толстые книги, ни дорогие курсы обучения. Необходимо лишь уметь думать: наблюдать, исследовать, ставить эксперименты, делать выводы, — проявлять способности к научному подходу.

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

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

Программы на VBA — макросы — можно создавать для любой программы пакета Microsoft Office: для Word, Excel, Access, PowerPoint и даже Outlook. В этой книге будет преимущественно рассмотрен процесс создания макросов для Microsoft Word. Среда Microsoft Word выбрана для начального изучения работы с Редактором VBA и принципов программирования на Visual Basic for Applications из-за того, что, во-первых, именно Word является наиболее популярной программой из всего пакета Microsoft Office (по подсчетам исследователей из Microsoft, из каждой сотни запусков программ из комплекта Microsoft Office в 60 % случаев запускаемой программой будет именно Word), а, во-вторых, писать программы, работающие в среде данного текстового редактора, несколько проще, чем дополнения для других компонентов Office. Научившись работать с VBA в Word, вам будет довольно просто перейти к программированию для остальных компонентов Office.

Не обязательно читать все главы книги подряд. После небольшого экскурса в историю программирования второй главы в третьей и четвертой главах будут описаны основные компоненты Microsoft Office, предназначенные для написания программ, рассказано о работе с ними, а также описан сам язык VBA, его синтаксис. Они скорее представляют собой небольшой справочник, полезный на первых порах, к которому иногда стоит возвращаться. Следующие три главы посвящены написанию программ на VBA, в них подробно описаны все шаги такой работы. Еще одна глава расскажет вам о полезных и интересных приемах программирования. В последней главе вы найдете краткий обзор некоторых интересных программ на VBA, которые можно использовать для обучения в качестве примеров. А в Приложении вы узнаете о том, какие игры есть в Microsoft Office (да-да, именно игры — посмотрите первую главу Приложения!) и о новых возможностях новой версии Microsoft Office — Microsoft Office XP.

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

Предполагается, что читатели знакомы с программой Microsoft Word и знают основные приемы работы в этом текстовом процессоре.

* * *

На настоящее время выпущено три версии Microsoft Office, содержащие в себе возможности работы с VBA — 97, 2000 и 2002, иначе именуемая ХР. За некоторыми исключениями все они между собой совместимы "сверху вниз", то есть программа, написанная для Word97 и в среде этого редактора, будет работать и в Word2000, и в WordXP. Обратное же верно не всегда: в Word2000 и особенно в WordXP добавлены новые команды VBA, и программа, их использующая, в Word97 уже не заработает.

В предстоящих главах в качестве основной среды программирования рассматривается Microsoft Office 97, так как вследствие вышесказанного наиболее разумным будет использовать в качестве среды разработки именно 97-ю версию Microsoft Office, в частности, для того, чтобы создаваемую программу могли применять пользователи всех версий Office. Кроме того, только в Microsoft Office 97 часть Справочной системы по VBA, входящей в состав Microsoft Office, русифицирована. Об особенностях же программирования для Office 2000 и Office ХР сообщается отдельно там, где эти особенности имеют какое-либо значение.


О ЦЕННОСТИ ИНФОРМАЦИИ. НЕМНОГО ФИЛОСОФИИ…

С появлением информационных технологий человеческое общество фактически перешло в новую фазу развития. И связано это с тем, что достижения компьютерной техники позволяют неограниченно и крайне дешево размножать такую вещь, как информацию. Ранее, например, лет пятьсот назад, для получения новой копии информации приходилось прилагать немало усилий: переписать книгу (а перед этим еще подготовить листы для книги из пергамента), прочитать и выучить текст, нарисовать копию картины, перед этим подготовив холст и краски. Зачастую усилия на создание новой копии источника информации были сравнимы с усилиями на создание самого этого источника, — например, переписывание книг занимало года. И создавать новые копии могли лишь специально подготовленные люди: ученые монахи-переписчики, художники, поэты. С появлением книгопечатания процесс облегчился: теперь книгу, ставшую основным носителем информации, можно было распечатать в большом количестве, и для этого не требовалось квалифицированного творческого труда. Но все равно затраты на размножение информации оставались немалыми: книгу надо сверстать, напечатать, сшить, распространить…

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

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

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

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

Тем более что объективных предпосылок для такого мировоззрения нет. Стоит помнить, что те, кто сейчас создает информационные ресурсы и получает огромные прибыли за счет их продажи из-за разницы в себестоимости и доходе, фактически стоят "на плечах предков". Миллионы людей работали долгие годы для того, чтобы сейчас у человечества появилась возможность копировать информацию почти без затрат сил и ресурсов, зачастую не получая достаточного вознаграждения своего труда. И они тоже могут рассчитывать на прибыль от распространения информации в настоящее время. Ну, уже, увы, не они — так их потомки, дети и внуки. А в то время, когда ученые разрабатывали первые компьютеры, без которых было бы невозможно создание современных компьютерных систем, этих ученых кто-то должен был кормить, одевать, кто-то строил им дома. Значит, и эти люди имеют право на долю прибыли от продажи информации, созданной и распространяемой с помощью компьютеров! Так что все здесь взаимосвязано, и выяснить, кто конкретно имеет право на доходы от продажи той или иной информации, нельзя.

Поэтому развитие технологии, появление компьютерных систем и глобальных информационных сетей требует создания новой системы межчеловеческих взаимоотношений. Только отказ от принципа "продажи" информации, только связанное с этим изменение мировоззрения людей позволят максимально использовать открывшиеся новые возможности. Только восприятие денег, выплачиваемых за информацию, как вознаграждение ее автору за его тяжелый труд, а не как стоимость этой информации, только отказ от принципов "охраны интеллектуальной собственности" (но не авторского права!)[225] даст возможность человечеству приумножить свое совокупное богатство во много раз практически без затрат труда и ресурсов.

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

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


VBA: ИСТОРИЯ

Язык программирования Visual Basic for Applications, о котором пойдет речь в этой книге, является результатом пересечения двух ветвей развития информационных технологий, — языка программирования Basic и макроязыков текстовых редакторов, программ работы с электронными таблицами и других приложений.


Basic

Basic, язык, чье название является аббревиатурой от английского "Beginner's All-purpose Symbolic Instruction Code" (в переводе — "язык из символьных команд для широкого применения начинающими"), был разработан профессорами американского Дартмутского колледжа Кемени и Курцом в далеком 1965 году. Целью языка было облегчение освоения учениками колледжа, да и вообще начинающими программистами основ создания алгоритмического кода, поэтому его возможности были довольно серьезно ограничены по сравнению с другими языками ради того, чтобы иметь возможность добавить в него обучающие функции. Так, в Basic'е программы могли выполняться построчно, поскольку сам язык был интерпретируемым, — программы хранились не в машинных кодах, а в исходном тексте, и переводились в машинный код при своем запуске. Первые версии Basic'а были довольно примитивными, однако с течением времени язык получил свое развитие. Многие читатели этой книги наверняка еще застали то время, когда "классический" Basic изучали на уроках информатики в школах, помнят пронумерованные строки, односложные команды, элементарный синтаксис.

Для фирмы Microsoft язык Basic имеет особое значение, — в свое время разработка варианта Basic для компьютера Altaiг 8800 положила начало трудовому программистскому пути ее основателей, Билла Гейтса и Пола Аллена. Поэтому в свое время — в 1989 году, когда пришла пора распределить основные направления создания сред разработки на различных языках программирования между различными фирмами, Microsoft оставила за собой QuickBasic — среду разработки программ на Basic'е, отказавшись, к примеру, от дальнейшей работы над языком программирования Pascal, оставив его фирме Borland, которая, в свою очередь, остановила работы над своей версией Basic'а (впоследствии Pascal стал языком Delphi). QuickBasic даже включался в состав некоторых версий MS-DOS в виде усеченной версии — QBasic (рис. 2.1). В итоге Basic стал тесно связан с операционными системами от Microsoft и на иных платформах практически неизвестен.



Рис. 2.1. QBasic — предшественник нынешних Basic'ов.


С созданием первых версий операционной системы Windows фирма Microsoft стала выпускать и средства разработки программ на Basic'е, предназначенные для этой операционной системы. Однако концепция программирования в новых версиях Basic'а изменилась. Так, среда разработки получила визуальный графический интерфейс — такой же, как и у других приложений Windows (что и послужило поводом для перемены названия языка — теперь он стал именоваться Visual Basic). За счет нового интерфейса процесс создания программ стал значительно легче и удобнее, хоть и потребовал определенных усилий по освоению от программистов "старой закалки", привыкших к прежним "орудиям труда".

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

Первая версия Visual Basic была еще очень несовершенной. Но с 1991 года Visual Basic прошел немало этапов развития, и в настоящее время достиг уже своей 6-й версии, позволяющей даже начинающим программистам быстро создавать мощные и удобные приложения.


Макросы

Еще в старом добром русском Lexicon'е, царствовавшем в эпоху 286-х компьютеров и операционной системы MS-DOS первых версий, был встроенный язык программирования. С его помощью можно было несколько автоматизировать работу с текстом. Несмотря на ограниченность набора команд, присутствующих этом языке, некоторые пользователи Lexicon'а умудрялись писать на нем длинные программы…

Да, действительно, — макрокоманды, то есть программы, работающие в среде другой программы, не являющейся операционной системой, широко использовались и используются в различных приложениях[226]. Например, такие крупные программные комплексы, как CorelDraw, AutoCad обзавелись возможностью создания макрокоманд довольно давно.

Первое время макрокоманды представляли собой простое перечисление в нужном порядке применяемых к данным пользователя встроенных функций программы (например, набор команд работы над текстом в Lexicon'e) и служили простым автоматически выполняемым заменителем действий пользователя. Впоследствии в макроязыках стали предусматриваться и операторы условного перехода (т. е. If…Then) или цикла, что стало приводить к все большей их схожести с реальными языками программирования.


VBA

В программах Microsoft при разработке средств создания макросов за основу был взят, что естественно было ожидать, Visual Basic. В 1993 году этой фирмой было официально заявлено, что ее сотрудники приступают к разработке универсальной системы программирования для Microsoft'овских офисных программ Visual Basic for Applications. В скором времени все новые версии компонентов Microsoft Office стали снабжаться специальными средствами, позволяющими создавать достаточно мощные макрокоманды.

В Microsoft Office 4.0, включающем в себя Word 6.0, Access 2.0, Excel 4.0, Project 6.0, только два последних компонента включали в себя относительно полноценные версии объектно-ориентированного языка Visual Basic for Applications (тогда еще самой первой версии — 1.0). В Word 6.0 для создания макрокоманд использовался WordBasic (рис. 2.2), состоящий из набора команд работы с текстом документа и нескольких функций работы с файловой системой, примерно такой же язык присутствовал и в Access 2.0. В улучшенной и приспособленной для работы в Windows 95 версии Office — Microsofi Office 95 — положение не изменилось, и в каждом из приложений Office так и осталась собственная среда программирования.

При разработке Microsoft Office 97 в его состав была включена переработанная среда разработки Microsoft Visual Basic 5.0, которая с учетом особенностей программирования в среде офисного пакета получила название Visual Basic for Applications 5.0 — по номеру исходной среды. Ее основой стал Редактор VBA — "Visual Basic Editor", в котором, собственно, и создавался программный код. Полностью Visual Basic for Applications применялся в трех приложениях Microsoft Office 97 — Word, Excel и PowerPoint. В Microsoft Access по-прежнему использовалась оригинальная среда программирования, а в Microsoft Outlook применялась серьезно урезанная версия Visual Basic for Applications — VBScript, не включавшая в себя и половины возможностей исходного языка.



Рис. 2.2. WordBasic — предшественник VBA в Microsoft Word.


Новое развитие Visual Basic for Applications получил в юбилейной, 2000-й версии офисного пакета. На этот раз все компоненты Office получили в свое распоряжение полноценную среду разработки программ: Visual Basic Editor стало можно использовать и в Access, и в Outlook, и даже в Frontpage, вошедшую в состав нового Офиса. В Visual Basic for Applications 6.0, версию, используемую в Microsoft Office 2000, были добавлены многие новые команды, в частности, уже имеющиеся в Visual Basic for Windows версии 6.0. В следующей версии Microsoft Office, Office ХР, развитие Visual Basic for Applications было продолжено, хотя нововведения коснулись уже лишь набора команд, который был несколько расширен. В Microsoft Office ХР также появилась возможность создания так называемых "смарт-тэгов", компонентов Office, отслеживающих определенные, задаваемые разработчиком смарт-тэга действия пользователя и выполняющих определенную функцию при таких действиях (в случае согласия пользователя). Однако смарт-тэги создаются с помощью специальной среды разработки и с Visual Basic for Applications напрямую не связаны.

Visual Basic for Applications — это не просто язык программирования, а целая технология, которую вполне можно распространить и на другие приложения сторонних производителей, подарив их пользователям возможность создавать программы, работающие в их среде. В настоящее время фирма Microsoft активно распространяет лицензии на право использования Visual Basic for Applications в продуктах, создаваемых их покупателями, так что, возможно, в скором времени средства VBA можно будет применять едва ли не в каждой более-менее крупной программе.


СРЕДСТВА ПРОГРАММИРОВАНИЯ НА VBA

В отличие от других средств разработки программного обеспечения, где единственным способом создания новой программы является написание ее кода и создание в визуальных редакторах диалоговых окон или использование уже готовых фрагментов кода других программ, в Visual Basic for Applications есть уникальное средство разработки, не присутствующее более нигде и позволяющее быстро научиться создавать простые макросы для Word, Excel и PowerPoint даже без использования учебников, описаний языка и даже чтения Справочной системы. Это средство — так называемая "запись макросов". При работе в любом из вышеперечисленных компонентов Microsoft Office можно включить специальный режим записи макросов, и тогда все действия пользователя в редакторе будут автоматически "переводиться" на язык Visual Basic for Applications и записываться в виде текста программы. Этот текст можно потом изучить для выяснения синтаксиса и устройства языка, а также необходимым образом его модифицировать. Разумеется, отнюдь не все возможности Visual Basic for Applications реализуются простой записью действий пользователя, однако для простых макрокоманд и для обучающих целей этого средства хватит.

В Microsoft Word для записи макроса надо выбрать из меню "Сервис" пункт "Макросы", а затем из выпадающего подменю — пункт "Начать запись" (рис. 3.1).



Рис. 3.1. Запись макроса


Документы Microsoft Word — собственно документы с расширением".doc" и шаблоны документов с расширением".dot" — устроены так, что могут хранить в себе программы на Visual Basic for Applications. Каждую программу, хранящуюся в документе Word, может вызывать на исполнение либо кнопка на панели инструментов, либо сочетание клавиш, либо пункт меню, либо другая программа (ну и, естественно, выбор этой программы из списка макрокоманд в диалоговом окне "Сервис-Макрос-Макросы". Возможно любое сочетание способов вызовов. Поэтому перед началом записи макроса пользователю предлагается сразу назначить записываемому макросу способ его вызова (рис. 3.2).



Рис. 3.2. Назначение макросу способа вызова.


Если на данном этапе для вызова макроса не будет назначена кнопка или сочетание клавиш, то это всегда можно будет сделать впоследствии с помощью диалогового окна "Настройка" (рис. 3.3) так же, как и для любой другой команды Word. Названия макросов, которые могут быть запущены пользователем, перечисляются в разделе "Макросы" этого окна и состоят из названия проекта (обычно совпадает с названием шаблона или документа, в котором макрос содержится), имени модуля и имени макроса в модуле (что это такое — смотрите ниже).



Рис. 3.3. Диалоговое окно "Настройка".


После нажатия кнопки "Ок" в окне Word появится панель "Запись макроса" (рис. 3.4).



Рис. 3.4. Панель "Запись макроса".


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

После окончания выполнения необходимых действий необходимо нажать левую кнопку на панели — "Остановка записи". Если необходимо прерваться и все же выделить какой-нибудь объект мышью, то необходимо нажать правую кнопку на этой панели "Пауза". При повторном ее нажатии процесс записи продолжится.

Пример подробного анализа результатов подобной записи будет показан в следующей части. А сейчас рассмотрим другой, более традиционный способ написания программ на Visual Basic for Applications — посредством Редактора VBA.


Редактор VBA.

Этот редактор вызывается из меню "Сервис"-"Макросы"-"Редактор Visual Basic" или нажатием клавиш Alt-F11. Его внешний вид таков — см. рис. 3.5.



Рис. 3.5. Редактор VBA


Стоит сразу сказать об отношениях Редактора VBA и Справочной системы по Visual Basic for Applications с русским языком. Наиболее доброжелательна к русскоязычным пользователям в этом плане была 97-я версия Microsoft Office, в которой как интерфейс Редактора VBA, так и значительная часть Справочной системы по Visual Basic for Applications были переведены на русский язык. Большинство изображений экрана в этой книге сделано именно в русской версии Microsoft Office 97, в частности, для того, чтобы не приходилось переводить надписи на элементах интерфейса. К сожалению, в более новых версиях Microsoft Office их создатели такими вещами, как русификация программистской части этого пакета и тем более Справки ко встроенному языку, решили не заниматься, и в итоге в Microsoft Office 2000 и Microsoft Office ХР ни интерфейс

Редактора VBA, ни Справочная система по Visual Basic for Applications не русифицированы. Поэтому если для вас восприятие английских названий пунктов меню и чтение Справочной системы на английском языке представляют определенные сложности, то вам лучше начать изучение Visual Basic for Applications именно на основе русской версии Microsoft Office 97, не смущаясь ее устареванием к сегодняшнему дню. В этом случае новые возможности и ограничения более современных версий Microsoft Office вы сможете узнать после, непосредственно при работе с ними.

Для упрощения изложения в дальнейшем тексте будет подразумеваться, что процесс создания программ и изучения языка Visual Basic for Applications проводится в среде Microsoft Word. Поскольку интерфейс Редактора VBA для всех компонентов Microsoft Office одинаков (за исключением Microsoft Access, да и то лишь в 97-й версии пакета), то перейти из среды Word на его использование в остальных компонентах офисного пакета от Microsoft будет нетрудно.

Окно редактора Visual Basic for Applications состоит из следующих частей: Менеджер проектов (в английской версии Редактора VBA — Project Explorer), Окно свойств (в английской версии — Properties Window), Окна текста программ и дизайна форм (Code Window), Окно отладки (Immediate Window), Окно контрольного значения (Watch Window), Окно локальных переменных (Locals Window), Стек вызова (Call Stack), Окно просмотра объектов (Object Browser). Ниже мы рассмотрим все эти компоненты подробнее.

Программы на Visual Basic for Applications хранятся в документах Microsoft Office. Так, в среде Word, как уже говорилось, они могут находиться в документах и шаблонах Word, а в среде Excel — в книгах с электронными таблицами, создаваемыми в этой программе.

Каждый файл, содержащий макросы, называется проектом. В окне Менеджера проектов (Project Explorer) отображаются названия всех доступных Редактору VBA проектов, в состав которых в Word входят открытые документы и шаблоны, а также шаблоны, загруженные глобально — через помещение их в папку автозагружаемых файлов Word, с помощью размещения в ней ярлыков на них или с помощью подключения через диалоговое окно "Сервис — Шаблоны и надстройки". Кроме того, при работе в Microsoft Word всегда в этом окне отображается шаблон Normal.dot со всеми макросами, сохраненными в нем (см. рис. 3.6).



Рис. 3.6. Менеджер проекта


Щелкнув мышью по знаку "+" слева от названия проекта, можно открыть список имеющихся его компонентов. Однако так можно поступить лишь с проектами, открытыми в Word: шаблон, загруженный глобально, через папку автозагружаемых файлов или путем "подключения" в диалоговом окне "Сервис — Шаблоны и надстройки", так открыть нельзя, — чтобы получить доступ к его коду для редактирования, необходимо открыть его как файл. Иначе при попытке просмотра будет выдано сообщение "Проект недоступен для просмотра" и доступ к коду будет невозможен (рис. 3.7).



Рис. 3.7. Запрет доступа к коду шаблона, загруженного глобально


Просмотр компонентов проекта можно запретить путем задания пароля. Но подобные действия являются признаком очень дурного тона в программировании.

В случае попытки открытия запароленного проекта в той же версии Office, что и та, в которой он был создан (или в более современной) пользователю будет выдан запрос на ввод пароля. Если же макросы в запароленном проекте, созданном в Microsoft Office 2000 или ХР, пытаться открыть в более ранней версии Office — Microsoft Office 97, то на экран будет выдано такое же сообщение, как и при попытке просмотреть макросы в загруженном глобально проекте — "Проект недоступен для просмотра" (в английской версии — Project is unviewable). Вызвано это тем, что в новых версиях Office парольная защита от просмотра кода программ на Visual Basic for Applications значительно усовершенствована, в частности, добавлены новые алгоритмы зашифровывания этого кода.

В Microsoft Word компоненты проекта делятся на пять больших категорий:

1. "Microsoft Word. объекты". Здесь имеется только один объект называющийся по умолчанию ThisDocument (имя можно изменить). Его контекстное меню, появляющееся при нажатии правой кнопки мыши, выглядит так, как показано на рис. 3.8.



Рис. 3.8. Контекстное меню объекта ThisDocument


При выборе пункта Объект произойдет переход к соответствующему документу — к его содержимому: тексту, графике (этот пункт недоступен для шаблонов, на которых основаны созданные документы, — в этом случае шаблоны, тот же Normal.dot, открываются как проекты и позволяют изменять содержащиеся в них макросы, но не позволяют редактировать собственно свое содержимое). В документ Microsoft Word можно вставить специальные объекты — кнопки, поля ввода текста, поля выбора вариантов и др). В этом случае после выбора пункта Программа контекстного меню объекта ThisDocument можно написать программу, которая будет выполняться при нажатии соответствующей кнопки, введении текста и др. К написанию такой программы можно перейти и из контекстного меню самого специального объекта — выделив его, нажав правую кнопку и выбрав пункт "Исходный текст".

(В Microsoft Excel в качестве объектов представлены все листы рабочей книги Excel по отдельности, а также сама книга как целое.)

2. "Модули." Модули — это и есть собственно программы в Word, макросы. Щелкнув два раза мышью на имени модуля, можно получить доступ к тексту программы или начать ее создавать. Программы, записанные пользователем с помощью средства записи макросов, хранятся по умолчанию в модуле NewMacros шаблона Normal.dot.

Для того, чтобы создать новый модуль, необходимо из контекстного меню Менеджере проектов выбрать пункт "Вставить"-"Модуль" (рис. 3.9).



Рис. 3.9. Вставка модуля


Для начала написания программы надо в окне программы написать "Sub Имя программы", после чего Редактор VBA сам добавит фразу "End Sub", и между этими двумя фразами должен заключаться текст основной части программы (рис. 3.10).



Рис. 3.10. Начало создания программы


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

К примеру, надо написать программу, которая работает с электронными версиями классных журналов в школе. В каждом журнале есть множество подразделов: и список учеников, и список их оценок, и система вычисления средней оценки каждого из учеников, и список предметов, и много чего еще… Можно, конечно, на Visual Basic for Applications описать устройство каждого классного журнала: создать списки учеников, организовать таблицы с оценками, но тогда при однотипных действиях с группой журналов (например, надо посчитать средний балл оценок всех учащихся седьмых и восьмых классов) придется включать в код очень много операций с каждым компонентом журнала. Также при добавлении нового журнала придется писать программный код для создания списка учащихся, списка предметов и др. Это все очень усложнит программу и потребует большой затраты труда программиста. Поэтому в Visual Basic for Applications имеется понятие класса — то есть нового типа объектов, могущих содержать программный код для своей обработки. Так, можно создать класс "Журналы" и описать в его модуле класса содержимое объектов этого класса: список учеников — (Public Ученики(40) As String), предметов (Public Предметы(20) As String) и др. Теперь для создания нового объекта класса "Журналы" — нового журнала — не надо заниматься утомительным описанием вновь создаваемых списков учеников и предметов: будет достаточно в одной строчке написать команду "Объявить новую переменную класса Журналы" (Dim Журнал25 As Журналы) и присвоить нужные значения соответствующим разделам этого новосозданного журнала (Журнал25.Ученики(1)="Андреев" и.т.д.). Теперь можно в модуле класса написать программу вычисления средней оценки всех учащихся, и при необходимости сделать такой подсчет вызывать ее одной командой.

4. "Формы". Формы — это диалоговые окна программ, которые можно разработать по своему вкусу. Для того, чтобы в проект добавить форму, надо из контекстного меню в Менеджере проектов выбрать пункт "Вставить"-"UserForm". Будет создано пустое диалоговое окно, в которое можно поместить кнопки, картинки, текст и др. Пример сложной пользовательской формы — на рис. 3.11.



Рис. 3.11. Пример сложной пользовательской формы


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

Подробнее о формах будет рассказано в следующей главе.

5. "Ссылки". Программы могут запускаться на выполнение не только в результате действий пользователя, но и в результате вызова из другой программы. Однако запустить программу можно только из загруженного в Word проекта (шаблона или документа). Если постоянно загружать проект нецелесообразно (например, подобный вызов используется достаточно редко), то для запуска из загруженного проекта программы из другого, незагруженного шаблона нужно поставить на него ссылку (делается это путем простого перетаскивания иконки шаблона в окно Менеджера проектов). В таком случае будет возможен доступ ко всем программам в этом шаблоне из программ проекта, в котором находится ссылка.

Кроме того, с помощью диалогового окна Редактора VBA "Сервис — Ссылки" можно создать ссылки на различные программные компоненты — библиотеки[227]. В этом случае у вас появится возможность использовать эти компоненты, не включая их в свою программу, а просто вызвав по имени. (Для создания ссылки на какую-либо библиотеку достаточно поставить галочку против ее названия.) Например, если в какой-нибудь библиотеке содержится программа отображения на экране циферблата часов с определенным временем, то, подключив ее к своей программе — создав на нее ссылку — можно отображать эти часы простым вызовом данной программы (возможно, с определенными параметрами — скажем, временем, которое эти часы должны показывать).

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

Окно текста программ и дизайна форм (Code Window). Это и есть основное рабочее место программиста на Visual Basic for Applications. Именно здесь пишется текст программ и разрабатываются диалоговые окна. Для того, чтобы открыть его для какого-либо компонента проекта, надо просто два раза щелкнуть на нем мышью или выбрать из контекстного меню пункт "Программа".

Редактор Visual Basic for Applications — очень дружественный редактор. Он постоянно подсказывает программисту, какие параметры имеет та или иная команда, как надо корректно ее написать. Например, если набрать команду MsgBox (эта команда вызывает на экран диалоговое окно, например, такое, как всем известное окошко "Сохранить изменения в документе?") и набрать после нее открывающую круглую скобку, то над курсором сразу же появится подсказка (см. рис. 3.12.), из которой можно получить информацию о синтаксисе данной команды, то есть о том, как конкретно нужно задавать ее параметры (в данном случае текст окошка, количество кнопок, значок и звук при появлении) в тексте программы.



Рис. 3.12. Контекстная подсказка редактора VBA


Язык Visual Basic for Applications называется объектно-ориентированнным. Это значит, что очень многие его команды имеют особенный формат, отличный, скажем, от формата Basic или Pascal, которые изучались в школах лет десять назад. Типичная команда Visual Basic for Applications имеет такой вид: <Объект>.<Объект, входящий в первый объект>.<.„>.<Тот объект, с которым нужно произвести действие>. «Собственно действие>. Иными словами, каждая команда пишется как бы "с конца": вначале определяется то, над чем надо произвести действие — объект, а затем само действие — метод. Разделителями компонентов команды служат знаки "точка". Вот пример такой команды:

Application.ActiveDocument.PageSetup.Orientation = wdOrientLandscape.

Эта команда устанавливает альбомную ориентацию листа в документе. У объекта Application (то есть приложение, программа, в данном случае — Word) есть подобъект — ActiveDocument (активный документ, а есть еще другие, неактивные документы, тоже загруженные в Word), у этого подобъекта есть подобъект — PageSetup (параметры страницы; а есть еще подобъекты Selection — то, что в данный момент выделено, Characters — все буквы в тексте и др.), у него есть подобъект Orientation (ориентация листа; а есть еще BottomMargin — нижний отступ, LeftMargin — левый отступ и др.), которому присваивается "=" значение wdOrientLandscape — то есть альбомная ориентация листа. Такой же вид имеет и команда получения информации об ориентации листа — она будет выглядеть так:

р = Application.ActiveDocument.PageSetup.Orientation,

и после ее выполнения значение переменной р будет wdOrientLandscape или wdOrientPortrait соответственно. (Более подробно синтаксис языка Visual Basic for Applications будет рассмотрен позже.)

При написании команд редактор Visual Basic for Applications постоянно подсказывает возможные варианты следующего шага. Так, например, стоит написать в тексте программы слово Application и поставить точку, как сразу появятся возможные варианты продолжения (рис. 3.13).



Рис. 3.13. Дружественный интерфейс редактора VBA.


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

Есть также команда завершения слова — можно не писать целиком слово Application, а набрать Appli и нажать Ctrl и пробел. Редактор допишет слово до конца сам или предоставит возможность выбора слова, если его однозначно нельзя определить по первым буквам. Он как бы "ведет" программиста по процессу написания программы, позволяя ему сосредоточиться не на банальном синтаксисе языка, а на решаемой программой проблеме, не держа в памяти правила написания каждой команды.

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



Рис. 3.14. Ошибка компиляции.


Редактор, безусловно, не может найти ошибку, если неверен алгоритм программы — это уже дело программиста. Он не увидит ошибку и в неправильно написанном слове команды, так как посчитает тогда ее функцией — новой командой, созданной самим программистом. Но вот неправильно написанную известную ему команду отследить он может. (В приведенной на рисунке примере программист хотел заменить выделенный текст новым, написав Selection.Text="Новый текст", но забыл этот самый новый текст написать.)

Другим серьезным достоинством редактора Visual Basic for Applications является наличие прекрасной справочной системы. Поставив курсор на любую команду или название объекта Visual Basic for Applications и нажав клавишу F1, можно получить подробную справку о том, зачем нужна эта команда, каков ее синтаксис и даже посмотреть пример ее использования и скопировать его себе, если необходимо (рис. 3.15).



Рис. 3.15. Окно справочной системы. Справка по команде Str$().


К сожалению, как уже говорилось, Справка по VBA на русском языке есть лишь в Microsoft Office 97, да и то переведенная часть составляет не очень-то и большую долю от всего ее объема.

В справке Visual Basic for Applications очень часто приводятся фрагменты кода программ, иллюстрирующие использование той или иной команды. Их можно копировать в свою программу и изменять так, как необходимо.

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

Поставив перед любой командой знак апострофа (') или команду "rem", можно ее закомментировать — то есть исключить из выполнения. В этом случае Редактор VBA не будет ее выполнять. Кроме того, после знака апострофа можно написать пояснения к соответствующей части программы для себя и других программистов.

Все комментарии отображаются в редакторе VBA зеленым цветом.

Щелкнув два раза на названии формы, можно открыть окно Дизайна форм (рис. 3.16.).



Рис. 3.16. Окно Дизайна форм.


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

Если выбрать какой-нибудь элемент формы и из его контекстного меню выбрать пункт "Свойства" (или нажать клавишу F4), то откроется Окно свойств (Properties Window) — рис. 3.17.



Рис. 3.17. Окно свойств элементов формы


Здесь можно задать все доступные свойства каждого элемента, например, его цвет, цвет границы, надпись, состояние — доступно/недоступно для изменений, поместить на элемент картинку из внешнего файла (пункт "Picture"). Все эти свойства также можно задавать программно, однако, некоторые, вроде той же картинки, стоит задавать только в этом окне. Для получения подробного описания функции каждого элемента окна свойств (а состав этих элементов различен для каждого элемента формы) достаточно просто поставить на него курсор и нажать F1. Настоятельно рекомендуется подробно изучить предназначение всех элементов данного окна, как с помощью вызова справки, так и с помощью изучения изменений в состоянии объекта после изменения значения свойства.

Окно Просмотр объектов (Object Browser), вызываемый кнопкой F2 или из меню Вид (рис. 3.18), является кратким справочником по всем возможным свойствам и методам (то есть действиям, командам) объектов Visual Basic for Applications. Можно посмотреть, какие свойства или методы доступны для каждого объекта, какие объекты в принципе существуют в Visual Basic for Applications, вызвать справочный файл для каждого объекта, свойства или метода.



Рис. 3.18. Окно Просмотр объектов


На панели инструментов "Правка" Редактора VBA имеются соответствующие кнопки для вызова вышеописанных функций. Так, кнопка "Список свойств/методов" позволяет увидеть возможные продолжения любой команды (то же самое можно получить, поставив после команды точку, но так неудобно делать в уже написанном тексте), а кнопка "Сведения" выводит информацию о переменной, которая в данный момент выделена. Как и в самом редакторе Word, в Редакторе VBA можно вставлять закладки в текст программы для более удобного перехода к соответствующим его частям.

Модули, входящие в состав проекта, можно сохранить в текстовом файле. Для этого в Менеджере проектов из контекстного меню правой кнопки мыши соответствующего модуля надо выбрать функцию "Экспорт файла" (рис. 3.19). Модуль будет сохранен в текстовом файле с расширением".bas". Можно просто перетащить название модуля в окно Проводника, держа нажатой левую кнопку мыши Редактор VBA поддерживает механизм Drag-and-Drop. Вставить ранее сохраненный модуль можно через команду "Импорт файла" того же меню или путем перетаскивания его иконки в окно Редактора VBA.



Рис. 3.19. Экспортирование модуля


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


Отладка программы

Редактор VBA обладает очень большими возможностями отладки программы, то есть поиска в ней алгоритмических и языковых ошибок. Поскольку язык Visual Basic for Applications — не компилируемый, а интерпретируемый (то есть готовая программа представляет собой текст исходного кода, хранящийся в шаблоне или документе, который переводится в машинные коды при каждом ее запуске, в то время как конечный продукт средств создания программ на остальных языках программирования практически всегда представляет собой файл с исполняемым машинным кодом), то после завершения написания кода и успешной его отладки программа готова к использованию.

Для запуска на выполнение готовой или записанной программы из редактора Visual Basic for Applications необходимо нажать клавишу F5 или выбрать соответствующий пункт из меню "Запуск" (в английской версии — Run). Программа начнет выполняться и, если в ней вдруг найдутся ошибки в записи команд или обращения к неизвестным командам, будет выдано соответствующее сообщение (рис. 3.20).



Рис. 3.20. Сообщение об ошибке компиляции


Данное сообщение означает, что эта команда редактору Visual Basic for Applications неизвестна. Значит — надо изменить код программы, соответственно исправив его.

(В Visual Basic for Applications можно создавать собственные команды — функции или процедуры, которые могут вызываться так же, как и встроенные. Об этом будет рассказано ниже.)

Если возникает ошибка вследствие неправильного использования команд Word, то редактор Visual Basic for Applications выдает диалоговое окно, в котором приводится некоторое описание ошибки. Так, при попытке выделить жирным шрифтом десятимиллионное слово в документе было выдано сообщение "Запрашиваемый номер семейства не существует" (рис. 3.21), так как десятимиллионного слова в документе не было.



Рис. 3.21. Сообщение об ошибке из-за неправильного использования команд VBA


В последнем диалоговом окне, как можно видеть, есть кнопка под названием "Отладка". Нажав на нее, можно перейти в режим отладки программы — то есть специального состояния Редактора Visual Basic for Applications, в котором программа может исполняться построчно, а программист имеет возможность видеть значения всех переменных программы и даже принудительно задавать эти значения. Также в режим отладки можно перейти из Редактора VBA, поставив курсор внутрь программы и нажав клавишу F8.

Если ошибка произошла в макросе, находящемся в недоступном шаблоне (например, загруженным глобально через папку автозагружаемых файлов Word), то кнопка "Отладка" будет неактивна.

В режиме отладки программисту доступны следующие возможности:

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

2. Просмотр значений переменных. Подведя в режиме отладки курсор к имени любой переменной, можно увидеть ее значение (рис. 3.22).



Рис. 3.22. Просмотр значения переменной в режиме отладки


Кроме того, значения всех переменных программы можно увидеть в окне Локальные переменные (Local Window), рис. 3.23.



Рис. 3.23. Окно локальных переменных.


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

3. Точки останова. Если программа длинная, то проходить по всем ее строчкам с помощью кнопки F8 — занятие не слишком интересное и приятное. В этом случае лучше использовать точки останова: то есть отметки в тексте программы, где ее исполнение должно остановиться, а сама программа — перейти в режим отладки. Для установки точки останова нужно щелкнуть левой кнопкой мыши на сером левом поле окна модуля, и тогда появится коричневая строка с кружочком на месте точки останова (рис. 3.24).



Рис. 3.24. Точка останова.


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

4. Окно контрольного значения (Watch Window). В этом окне можно задать определенное выражение, значение которого будет подсчитываться параллельно с выполнением программы. Кроме того, выделив в режиме отладки какое-нибудь выражение и нажав Shift и F9, можно увидеть его значение, а также добавить это выражение в окно контрольного значения и отслеживать его дальнейшие изменения.

Такая возможность необходима, например, при отладке длинной программы с множеством арифметических выражений, одно из которых дает ошибку. С помощью этого окна можно отследить, когда, при изменении какого параметра значение выражения станет неприемлемым. К примеру, идет вычисление оптимального количества учеников в каждом классе с учетом множества параметров и где-то подозревается наличие ошибки: не сходится сумма количеств всех учеников во всех классах с количеством учеников в школе. Можно, конечно, обойтись без всяких там окон контрольного значения и вставить в текст программы после каждого вычисления проверку равенства суммы количества всех учеников во всех классах с численностью учеников школы, но это очень усложнит программу, да и потом придется удалять все эти добавления, — а если программа большая, то сделать это не так просто. Гораздо лучше поставить контрольное значение — сумму количеств всех учеников во всех классах — и при пошаговом исполнении программы отследить, где, на каком этапе происходит ее ненужное изменение.

5. Окно проверки или Отладки (Immediate Window). Это окно вызывается из меню Вид — Окно отладки. В текст программы можно вставить специальные команды — Debug.Print (а+b, например). Тогда при выполнении этой команды в Окно отладки будет печататься то, что задано в ее параметрах (рис. 3.25).



Рис. 3.25. Окно отладки.


Возможности применения этого окна многообразны. Можно выводить в него сообщения в случае выполнения какого-либо условия. Можно отображать в нем промежуточные результаты вычислений для контроля их правильности — чтобы не смотреть и искать нужное выражение в окнах Локальных переменных или Контрольного значения, а получать их сразу, перед глазами. Можно даже использовать это окно как маленький калькулятор или командную строку (рис. 3.26), и тогда при нажатии Enter после ввода команды она будет тут же выполнена! Надо только перед самой командой писать слово Print, если команда должна выдать какой-нибудь результат в этом же окне.



Рис. 3.26. Калькулятор в окне отладки


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

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

Во время работы макрокоманды ее можно прервать в любой момент нажатием клавиш Ctrl и Break. После этого будет возможен переход в режим отладки с места остановки или завершение программы.

Для выхода из режима отладки до завершения полного выполнения программы необходимо выбрать функцию Сброс из меню Запуск или нажать на панели "Отладка" кнопку "Сброс".

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

И помните, что Вы можете всегда получить подробную справку по любой команде, поставив на нее курсор и нажав клавишу F1.


VBA: ОСНОВЫ СИНТАКСИСА

Для полного описания возможностей и составляющих языка Visual Basic for Applications потребовалось бы несколько толстых книг. Поэтому в этом учебнике вы не найдете подробных описаний каждой команды Visual Basic for Applications, рассказа об их формате и требуемых параметрах. Не найдете по очень простой причине — вся эта информация приведена в Справочной системе Редактора VBA, да и встроенные в него средства автоматической подсказки, о которых вы могли прочесть выше, тоже не дадут ошибиться. Если необходимо узнать, какой набор команд позволяет программно реализовать ту или иную встроенную возможность, например, Microsoft Word, то можно воспользоваться средством записи макросов, выполнив необходимые действия во время его работы, а потом почитать в Справочной системе о каждой записанной команде, открыв получившийся макрос в Редакторе VBA.

Однако в Visual Basic for Applications есть некоторые вещи, о которых в Справочной системе упоминается не на первом плане, и человеку, незнакомому с программированием, трудно узнать о них. Поэтому в этой главе будут приведены описания некоторых команд, которые нельзя записать средством записи макросов, а также рассказано о неочевидных возможностях Visual Basic for Applications.

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

Примечание. Очень полезно при разработке программ на Visual Basic for Applications смотреть примеры использования команд, приводимые в справке — в разделах "Example" многих справочных окон (рис. 4.1). Стоит даже копировать оттуда фрагменты кода и модифицировать их под свои нужды.



Рис. 4.1. Фрагмент кода в справке


Если вам никак не удается создать работающий фрагмент кода программы — посмотрите в справке в разделе примеров, не встретится ли вам там то, что вы так долго пытались создать. Все фрагменты кода в справке можно свободно копировать в свои программы. Во всяком случае, в справке все команды написаны грамотно и правильно.


1. События, методы, свойства.

Когда-то давным-давно программы, написанные и работавшие тогда еще под MS-DOS, получали от пользователя данные, обрабатывали их и выдавали затем результат. Почти любая программа предусматривала в своей работе период ввода данных, период обработки, период выдачи результата. Подобные действия были принципом работы Dos-овских программ. И программирование их называлось структурным, — надо было строго и последовательно разрабатывать алгоритм, реализовывать заданный порядок действий программы, в который в процессе работы почти не мог вмешаться пользователь, разве только принудительно остановив программу.

С появлением операционной системы Windows стал широко известным другой принцип программирования и создания алгоритмических языков — принцип объектно-ориентированного языка.

Это значит, что основная направленность разработчика сместилась с действия на объект, — на описание на языке программирования реакций этого объекта на действия пользователя, его свойств и их изменений. И Visual Basic for Applications является типичным представителем объектно-ориентированных языков, как по своему синтаксису, так и по архитектуре программ.

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

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

Почти каждый объект внутри себя имеет подобъекты, которые, в свою очередь, являются полноценными объектами и могут иметь свои подобъекты. Например, у объекта "Документ" есть подобъект "Десятое предложение", у которого есть подобъект "Второе слово", у которого есть подобъект "Третья буква". С помощью объектно-ориентированного языка Visual Basic for Applications можно обратиться к любому объекту Microsoft Office, если знать его иерархию — то есть перечень всех тех объектов, чьим подобъектом он является, и произвести с этим объектом какое-либо действие или, наоборот, узнать какие-либо его характеристики.

Свойство — это любая характеристика объекта. К примеру, у объекта — первой буквы документа есть свойства: выделение жирным, выделение цветом, подчеркивание, выделение курсивом, регистр и много еще других. У объекта — документа есть свойства: наличие автоматической расстановки переносов, наличие автоматической проверки грамматики и др. Большинство свойств объектов Visual Basic for Applications можно задавать программно, однако есть свойства Read-Only — не допускающие изменений. Многие свойства объектов Word также задаются через стандартные диалоговые окна Word — например, "Файл — Параметры страницы" или "Сервис — Параметры", однако их всегда можно задать и программно, а соответствующие диалоговые окна использовать при записи макроса для того, чтобы посмотреть синтаксис команды задания того или иного свойства.

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

With Selection.Find

Text = "Этот текст надо заменить"

Replacement.Text = "Заменить на этот текст"

Forward = True

Wrap = wdFindContinue

Format = False

MatchCase = False

MatchWholeWord = False

MatchWildcards = False

MatchSoundsLike = False

MatchAllWordForms = False

End With

Selection.Find.Execute Replace:=wdReplaceAll

В данном примере вначале объекту Visual Basic for Applications "Find" (т. е. "процессу поиска"), являющемуся подобъектом объекта "Selection" (т. е. выделенный фрагмент текста или, если такового нет, точка ввода текста), задаются необходимые свойства".Text" (текст для замены), ".Forward" (направление поиска), ".Format" (необходимость учитывания формата текста) и другие. Затем выполняется метод".Execute" (т. е. здесь — собственно "выполнить поиск") для объекта "Selection.Find" с параметром "Replace:=wdReplaceAll"(т. е. "Заменить все").

Команда "With… End With" позволяет не писать для каждого свойства или подобъекта полное название соответствующего объекта, что дает возможность экономить место и делать программу лучше и быстрее работающей.

Свойства и методы по-разному отображаются в контекстной подсказке. Так, против названий свойств стоит серый символ указывающей руки, а против названий методов — зеленый значок летящей коробки (см. на рис. 4.2).



Рис. 4.2. Свойства и методы в контекстной подсказке


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

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

В Visual Basic for Applications для каждого события можно написать программу, которая будет срабатывать именно тогда, когда событие произойдет, и выполнять определенные действия, которые должны быть выполнены, когда это событие совершается.

Особое значение понятие событий имеет при написании программы реакций формы на изменения ее компонентов, а также при описании новых классов.


2. Типы данных и объявление переменных.

Переменная — это "данные с именем", некая информация, которая имеет имя и к которой по этому имени можно обращаться для ее считывания или изменения.

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

Разделение переменных по типу данных необходимо для того, чтобы при выполнении программы под каждую переменную иметь возможность отводить нужное количество памяти для размещения содержащейся в этой переменной информации. Если представить себе язык программирования, переменные в котором могут принимать значение лишь какой-либо буквы алфавита или одного из двух вариантов — "Истина" или "Ложь", то для того, чтобы переменная этого языка гарантированно поместилась в памяти, для нее надо выделить один байт столько, сколько занимает буква. А в том случае, если в этом представленном нами языке существует возможность определить тип данных переменной, то переменной, могущей принимать значение лишь "Истина" или "Ложь" и вследствие этого имеющей особый тип данных (обычно он именуется "булевый"), отличающийся от того, который имеют буквенные переменные, может быть выделен лишь один бит памяти — для записи значения "0" или "1", соответственно обозначающего "Ложь" и "Истину". В последнем случае расход памяти в восемь раз ниже.

В Visual Basic for Applications определено большое количество различных типов данных (рис. 4.3). Так, переменная типа Integer — это целое число от — 32 768 до 32 767, а переменная типа String — это строка текста длиной до двух миллионов символов. Все возможные в Visual Basic for Applications типы данных подробно описаны в справке по этому языку. В зависимости от типа данных с переменной можно производить те или иные действия и вычисления, — с числовыми математические, с текстовыми — текстовые (выделение подстроки из строки, получение отдельных символов из строк и др.) и т. д.



Рис. 4.3. Пример справки по типам данных


Для того, чтобы переменной мог быть присвоен тип данных и она могла в дальнейшем использоваться в программе, эта переменная должна быть объявлена, — то есть в программу должно быть включено указание, что такая переменная существует и у нее такой-то тип. В Visual Basic for Applications объявление переменной проводится указанием ее имени и типа в соответствующем разделе модуля, который так и называется — Описания и располагается в самой верхней его части, до начала первой программы (рис. 4.4). Для размещения описания нужно поместить туда строчку вида "Dim х(переменная) As (тип данных)": "Dim а As Integer".

Вместо слова Dim могут также использоваться слова Public и Private, которые тоже служат для объявления переменных. Переменная, объявленная командой Public, может использоваться и программами из других модулей и форм, при этом она своего значения не теряет. Переменная же, объявленная командой Private (или Dim), может использоваться только в программах модуля, в котором она объявлена. При наличии одноименной переменной в программах другого модуля ее значение не будет передаваться в них при их вызове из программы модуля, где она объявлена, — т. е. если вы поместите в программу команду, запускающую макрос из другого модуля, то в этом другом модуле одноименная переменная отнюдь не будет иметь то же значение, что и в исходной программе.



Рис. 4.4. Область описаний


Как Public или Private переменная может быть объявлена только в разделе описаний переменных. С помощью же инструкции (команды, не выполняющей реальных действий) Dim она может быть объявлена и в тексте программы. Однако тогда ее другие модули уже использовать не смогут никак.

В области работы с типами данных Visual Basic for Applications имеет еще одну достаточно уникальную особенность. При написании программ на этом языке можно, как ни странно, даже вообще не объявлять специально переменные! Просто включите их в текст программы по мере надобности, и тогда Visual Basic for Applications автоматически присвоит им специальный тип для таких случаев — "Variant". В переменной, имеющей этот универсальный тип, может содержаться что угодно — хоть число, хоть текст. Однако следует помнить, что объем памяти, отводимый под переменную типа Variant, весьма велик, — значительно больше, чем под любой другой тип данных, поэтому определять все переменные как тип Variant не всегда рационально. Впрочем, учитывая большой объем оперативной памяти на современных компьютерах, потери памяти от использования Variant'а ощутимы крайне редко.

Тип Variant отличается еще и тем, что переменные с таким типом автоматически могут преобразовываться в любой нужный другой тип. Например, если переменная "х" имеет тип Variant и значение 2 (число), то после команды "x=Str(x)", которая преобразует число в строку, она уже будет иметь значение "2", то есть текстовая строка с цифрой "2". Такое преобразование было бы невозможно, если бы переменная "х" была бы объявлена как Integer — целое число.

Если вы не объявляете переменную заранее, а просто упоминаете ее в программе на Visual Basic for Application, то она объявляется "автоматически", и так же "автоматически" ей присваивается тип Variant. Подобная тактика написания программы может показаться неплохой, так как убыстряет этот процесс, однако, к сожалению, необъявленные переменные не могут быть использованы в других модулях или формах — при таком использовании их значения будут потеряны[228].

Можно запретить для себя использование необъявленных переменных, вставив в начало модуля, в верх раздела описаний инструкцию "Option Explicit", и тогда программа остановится и перейдет в режим отладки, если вдруг наткнется на такую переменную.

Стоит быть внимательнее с типами данных, так как в некоторых случаях неправильное их использование может дать ошибку. Например, переменная с типом Integer не может превысить значение 32 767; если же надо использовать большие числа, то следует определить ее тип как Long, а если она может быть еще и дробной, то — Double.

В именах переменных Visual Basic for Applications распознаёт строчные и прописные буквы русского алфавита как разные символы. А вот заглавные и строчные латинские буквы считаются одинаковыми.


3. Процедуры и функции.

В принципе любая программа может быть написана в виде одного длинного блока текста. Однако такой код будет крайне нерациональным. Например, в программе необходимо несколько раз подсчитать сумму всех членов арифметической прогрессии для разных чисел. Можно, конечно, считать результат каждый раз по известной формуле, но это очень усложнит код. А если неизвестно, для какого количества чисел надо считать эту сумму (например, это определяет пользователь), то написание программы становится вообще невозможным! Поэтому в Visual Basic for Applications, как и в других современных языках программирования, есть понятие процедур и функций, иначе называемых подпрограммами.

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

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

В Visual Basic for Applications любая процедура, получающая данные из другой программы, имеет следующий формат:

Sub "Название процедуры"("Получаемая переменная" As "Тип данных получаемой переменной")

"Текст процедуры"

End Sub

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

Вызов процедуры происходит так же, как и вызов любой команды Visual Basic for Applications — путем указания ее названия и передаче ей соответствующих значений переменных:

Sub Main()

Dim a As Integer

a = 1 uvelich a, 3

MsgBox a

End Sub


Sub uvelich(b As Integer, с As Integer)

b = b + с

End Sub

В этом примере из процедуры Main вызывается процедура uvelich, которой передаются два параметра — а (равное 1) и второй — число 3. Процедура uvelich увеличивает первую переданную переменную на значение второго переданного числа, а затем Main отображает результат вычислений. Стоит помнить, что если в заглавии процедуры указываются типы данных переменных, то и в вызывающей процедуре передаваемые значения должны быть определены и иметь тот же тип, иначе Visual Basic for Applications выдаст сообщение об ошибке[229].

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

Если же не нужно, чтобы переменная в процедуре менялась (скажем, процедура использует переменную для каких-то своих нужд, не связанных с исходной программой), то перед именем этой переменной в заголовке процедуры следует поместить инструкцию ByVal. Тогда процедура просто использует переменную так, как в этой процедуре описано, возможно, изменив ее значение, а программа, вызвавшая процедуру, дальше будет работать с прежним значением переменной. К примеру, если бы заголовок процедуры uvelich имел вид Sub uvelich(ByVal b As Integer, с As Integer), то никакого увеличения переменной "а" не произошло бы и программа отобразила бы в качестве результата число 1. Однако в самой процедуре uvelich соответствующая переменная увеличилась бы на 3 и, если бы ее последней командой было бы MsgBox b, то она бы отобразила значение 4.

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

Sub Main()

Dim a As Integer

Dim d As Integer

a = 1

d = uvelich(a, 3)

MsgBox d

End Sub


Function uvelich(ByVal b As Integer, ByVal с As Integer) As Integer

uvelich = b + с

End Function

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

Sub Main()

Dim a As Integer

Dim d As Integer

a = 1

d = uvelich(a, 3)

MsgBox d

MsgBox a

End Sub


Function uvelich(b As Integer, с As Integer) As Integer

uvelich = b + с

a=1555

End Function,

то исходная программа — Main в качестве значения переменной "а" отобразила бы число 1555, а не 1.

Указания типов переменных в заголовке функции или процедуры необязательны — их можно опустить. Однако если типы переменных определены в этом заголовке, то они обязательно должны быть определены точно такими же типами и в вызывающей программе, если только они не определяются в функции или процедуре как Variant. Иными словами, если в функцию или процедуру передается переменная типа Integer, то в вызове функции или процедуры можно использовать только переменные именно этого типа, в противном случае возникнет ошибка. Так, если в заголовке функции указано, что первая переменная, передаваемая ей, имеет тип Integer, то та переменная, которая передается в функцию как первая (в последнем примере — "а"), должна быть определена именно как Integer до вызова функции (что мы и видим в этом примере). Если же в вышеприведенной программе переменная "а" определялась бы как Byte или Long, то возникла бы ошибка.

Перед заголовком функции или процедуры можно поставить инструкции Public или Private (для вышеприведенного примера — "Private Function uvelich(b As Integer, с As Integer) As Integer"). Функция или процедура, объявленная как Public, может вызываться и из других модулей, в то время как функция или процедура, объявленная как Private, доступна только из данного модуля.

По умолчанию все функции и процедуры считаются объявленными как Public (а переменные, как нетрудно заметить — объявленные как Private).

Если в программе есть вложенные процедуры или функции (то есть процедура или функция вызывает другую процедуру или функцию, которая, в свою очередь, вызывает еще одну процедуру или функцию и.т.д.), то их взаимоотношения ("кто кого вызывает?") удобно при отладке отслеживать с помощью окна Стек Вызова (рис. 4.5), в котором видны все произошедшие вызовы.



Рис. 4.5. Окно Стек вызова.


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

Главная процедура — собственно программа — не может иметь параметров (в ее заголовке должны стоять пустые скобки). Только таким процедурам можно назначать кнопки и сочетания клавиш для их вызова на выполнение, и только они будут присутствовать в диалоговом окне "Сервис — Макросы — Макросы". Это и понятно — ведь это окно не предусматривает возможности указывать параметры при запуске макросов, да и передавать параметр в сочетании клавиш весьма затруднительно.

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



Рис. 4.6. Вызов команды Шаг с обходом.


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

Разбивая программу на отдельные процедуры и функции, вы получаете возможность легко использовать повторно одни и те же фрагменты кода, обращаясь к ним из программы по мере надобности.


4. Операторы цикла и перехода.

Если необходимо повторить ту или иную группу операций несколько раз, то используются операторы цикла: Do… Loop, For…Next и While… Wend. Для проведения какой-либо операции или группы операций над однотипными объектами используется оператор For Each…Next.

Если необходимо совершить те или иные действия в зависимости от наличия или отсутствия выполнения какого-либо условия или в зависимости от значения той или иной переменной, используются операторы условия: If… Then…Else и Select Case.

Если необходимо совершить переход к другой части той же программы, то используется оператор GoTo "имя метки". Там, куда должен быть совершен переход, на отдельной строке должна стоять метка с соответствующим именем, а после нее — двоеточие.

Подробное описание функций, особенностей и синтаксиса всех этих операторов можно получить в справочной системе редактора Visual Basic for Applications, поэтому не стоит здесь на них останавливаться.


5. Работа с формами.

Формы — это окна интерфейса программы. С их помощью можно сообщать пользователю необходимую информацию или получать ее от него. Для создания форм используются средства редактора Visual Basic for Applications.

Создав форму (из меню правой кнопки мыши в Менеджере проектов выберите команды "Вставить — UserForm") или дважды щелкнув на имени существующей формы, можно попасть в окно Дизайна форм. На появившейся панели инструментов "Панель управления" (если ее нет, то ее можно вызвать из меню "Вид — Панель элементов") представлены элементы, которые можно использовать в формах программ на Visual Basic for Applications (рис. 4.7). Этот набор на настоящее время идентичен во всех версиях Microsoft Office, так что рассмотрим его подробнее.

Итак, назначение элементов набора таково — если смотреть слева направо и идти сверху вниз.



Рис. 4.7. Панель инструментов с компонентами форм. Пояснение в тексте.


1. Поле отображения текста — отображает текстовую информацию (рис. 4.8)



Рис. 4.8. Поле отображения текста.


2. Поле ввода текста — дает пользователю возможность ввести текстовую информацию (рис. 4.9).



Рис. 4.9. Поле ввода текста.


У Поля ввода текста помимо очевидного отличия — собственно возможности ввода в него текста пользователем — есть еще та особенность, что находящийся в нем текст можно выделить и скопировать, в то время как обычное Поле отображения текста этого не позволяет. Поэтому для размещения на форме доступной для копирования пользователями через буфер обмена информации (например, e-mail — адреса автора, ссылки на его сайт) лучше использовать именно Поле ввода текста, при необходимости запретив его изменения и придав ему вид обычного текста, убрав границы (как это сделать — смотрите ниже).

Текст, отображаемый в полях отображения и ввода текста при запуске формы, можно задать как заранее — с помощью Окна Свойств, так и программно.

3. Несколько видов списков — средства выбора варианта, вроде выпадающего списка шрифтов в Word (рис. 4.10). Значения элементов списков задаются только в программе — при



Рис. 4.10. Выпадающий список.


4. Флажок (рис. 4.11) — элемент, который независимо от других может находиться в трех состояниях: включенном, выключенном (могут быть определены как пользователем — кликом на флажке, так и программистом) и неактивном (определяется программой).



Рис. 4.11. Флажки.


5. Переключатель (рис. 4.12) — элемент, который также может находиться во включенном, выключенном и неактивном состояниях. В отличие от флажка, переключатели должны быть объединены в группы с помощью элемента № 7 — рамки — и, если один из переключателей в группе включен, то остальные включены быть не могут.



Рис. 4.12. Переключатели.


В Microsoft Word имеются диалоговые окна, содержащие как флажки, так и переключатели. Так, почти все вкладки меню "Сервис — Параметры" состоят из флажков, а меню Вставка-Сноска — из переключателей. Так что оба эти элемента управления вы видели неоднократно.

6. Выключатель (рис. 4.13). Это кнопка, которая может находиться в нажатом или отжатом состоянии. Например, в Word так себя ведут кнопки показа скрытых символов или создания списков.



Рис. 4.13. Выключатели.


7. Рамка. Отображает прямоугольник с заголовком. В основном используется для объединения групп переключателей (см. Рис. 4.12).

8. Командная кнопка. Обычная командная кнопка вроде кнопок "Ok" или "Отмена" в любом диалоговом окне (рис. 4.14).



Рис. 4.14. Командные кнопки.


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

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

К сожалению, в настоящее время не сложилась твердая номенклатура этих двух элементов форм Visual Basic for Applications, поэтому в справочной системе, в различной литературе можно встретить разные названия для каждого из них.



Рис. 4.15. Набор страниц.


11. Полоса прокрутки (рис. 4.16). Такая же, как и в окне Word. Может передавать в программу (с помощью свойства Value[230]) число, равное расстоянию от ее начала до бегунка. Расстояние считается на основе задаваемых в Окне Свойств (или в программе — свойства Min и Мах) параметров — величина, заданная в параметре Min, присваивается крайнему верхнему (или левому) положению бегунка, а величина параметра Мах — соответственно крайнему нижнему (или правому). Шаг перемещения бегунка, цвет, ориентацию (вертикальную или горизонтальную) полосы прокрутки можно задавать, так же, как и некоторые другие параметры.



Рис. 4.16. Полоса прокрутки.


12. Счетчик (рис. 4.17). Две нажимающиеся кнопки со стрелками. Может передавать в программу свое значение с помощью свойства Value. Так же, как и Полоса прокрутки, допускает задание своих минимального и максимального значений, а также шага изменения значения и начальной его величины.



Рис. 4.17. Счетчик.


13. Рисунок (рис. 4.18). В этот элемент можно вставить из файла рисунок, который будет храниться в форме (и шаблоне или документе с ней).



Рис. 4.18. Рисунок на форме.


Для вставки самого рисунка нужно после помещения на форму элемента управления Рисунок в Окне свойств выбрать пункт "Picture", нажать на кнопку слева от него и в появившемся окне открытия файла выбрать нужную картинку (рис. 4.19).



Рис. 4.19. Вставка рисунка.


У каждого элемента имеется свое уникальное имя, а также набор свойств. Их можно посмотреть в Окне свойств, выделив элемент и выбрав из контекстного меню правой кнопки мыши пункт "Свойства". Стоит внимательно изучить все возможные свойства для каждого элемента, по возможности осознав их предназначение. При необходимости можно вызвать справку по каждому свойству, поставив на него курсор и нажав F1. Большой набор свойств также имеет сама форма.

С помощью выпадающего меню в Окне свойств можно быстро перейти к свойствам необходимого элемента (рис. 4.20).



Рис. 4.20. Выпадающее меню Окна свойств — навигатор по элементам формы.


Среди наиболее распространенных свойств, имеющихся почти у всех элементов — Caption (т. е. надпись на поверхности или в заголовке, если он есть), Тор и Left — координаты верхнего левого угла элемента, Height и Width — высота и ширина, Enabled — доступность для изменений пользователем, Tablndex — число, показывающее, в какую очередь на данный элемент перейдет фокус (т. е. возможность изменения пользователем содержания или состояния) при переходах между элементами с помощью клавиши табуляции (можно запретить такой переход на какой-либо элемент, указав его свойство TabStop как False). Обратите внимание на свойства Picture, PictureAlignment, PictureSizeMode, PictureTiling собственно формы — с их помощью на поверхность формы можно поместить какой-нибудь фоновый рисунок.

Однако вышеперечисленные "стандартные" элементы управления — отнюдь не все, которые могут присутствовать на форме. Более того — они составляют лишь весьма малую часть всего набора таких элементов. Дело в том, что в окне "Сервис — Дополнительные элементы" ("Tools — Additional Controls", рис. 4.21) перечислены все элементы управления, которые в принципе могут быть использованы в программе на Visual Basic for Applications.

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

Для того, чтобы элемент управления из какой-либо библиотеки мог быть использован при создании формы в программе на Visual Basic for Applications, эту библиотеку необходимо подключить. Делается это простым проставлением отметки против имени нужной библиотеки в окне "Сервис — Дополнительные элементы". При этом на Панели инструментов "Панель управления" (та, которая Toolbox) появляются новые элементы, которые можно располагать на форме.



Рис. 4.21. Подключаемые элементы управления.


Как нетрудно понять из содержимого окна, вышеперечисленные элементы управления относятся к набору Microsoft Forms 2.0, хранятся в библиотеке fm20.dll и присутствуют на любом компьютере с Microsoft Office.

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

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

"Календарь" подключается к Редактору VBA там же, где и все остальные дополнительные элементы управления — в окне "Сервис — Дополнительные элементы".



Рис. 4.22. Элемент управления "Календарь".


С помощью элемента управления "Windows Media Player" можно вставить на форму проигрыватель аудио- и видеофайлов. Имя файла для проигрывания, а также параметры отображения полосы поиска, кнопок управления проигрыванием и показом задаются либо через Окно Свойств, либо программно. Теперь Word можно превратить в настоящий кинозал и даже развлекать пользователя просмотром фильма в то время, пока программа работает (рис. 4.23). Возможности проигрывателя по воспроизведению мультимедийных файлов, встроенного в программу на Visual Basic for Applications, такие же, как и у самого Windows Media Player.



Рис. 4.23. Любимый фильм в среде Word — это не шутка.


Если вы желаете, чтобы во время работы программы играла фоновая музыка, просто расположите "Windows Media Player" за пределами видимой части формы (соответственно задав ему значения отступа сверху или слева — Тор или Left). Только помните, что воспроизводимый файл не сохраняется вместе с шаблоном или документом, содержащим программу, поэтому позаботьтесь о том, чтобы при инсталляции он оказался в известном программе месте (например, в папке автозагружаемых файлов Word или системном каталоге Windows), и чтобы путь к этому файлу в свойстве FileName соответствовал действительности.

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

События форм. Необходимо помнить, что создание элемента — только начало работы над формой. Подавляющее большинство элементов сами по себе элемент никаких действий не выполняют, за исключением тех, которые их определяют. Кнопка — нажимается под мышкой или Enter'ом, список показывает значения, бегунок на полосе прокрутки двигается, во флажке можно поставить и убрать галку, но не более того! (Разве что "Windows Media Player" играет сам по себе.)

Для того, чтобы элемент выполнял какое-нибудь действие при действии с ним, нужно написать для него программу реакции на события.

Событий, могущих произойти с элементом, много. Это и двойной щелчок мыши на нем, это и проводка мыши над ним, это и ввод текста в поле ввода, это и нажатие на вкладке, это и переход к другому элементу, и многое другое.

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

Private Sub CommandButtonl_Click()

End Sub

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

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



Рис. 4.24. Выпадающий список событий.


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

У некоторых событий есть параметры, с которыми информация об его происшествии передается программе. Так, процедура обработки события KeyDown (то есть нажатия какой-либо клавиши тогда, когда активен данный элемент) имеет вид

Private Sub CommandButtonl_KeyDown(ByVal KeyCode As MSForms.Returnlnteger, ByVal Shift As Integer)

End Sub

Переменная KeyCode будет после срабатывания данной процедуры будет иметь значение, равное коду нажатой клавиши, а переменная Shift — 1, если соответствующая клавиша была нажата, и 0, если нет. Эти переменные можно использовать в процедуре обработки события.

Подавляющее большинство свойств (для стандартных элементов управления — все), задаваемых в Окне свойств, можно изменять и из программы. Например, команда TextBox1.Enabled=True даст возможность пользователю ввести текст в поле ввода TextBox1, а команда CheckBox1.Value=False уберет галку из флажка с именем CheckBox1. Эта возможность делает формы Visual Basic for Applications динамическими — то есть содержимое форм может меняться немедленно в ответ на действия пользователя без выгрузки и повторной загрузки формы. Форма может работать как обычное диалоговое окно программы для Windows — например, выбор пользователем значения из списка может каждый раз выводить в форму какой-либо текст, разный для разных значений.

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

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

Для вызова формы из программы следует поместить в ее текст команду ИмяФормы. Show.

Стоит иметь в виду, что после выгрузки формы из памяти (командой Unload Me в одном из обработчиков событий формы) все переменные, описанные в программе реакции формы на события, обнуляются. Поэтому после выгрузки формы получить от нее какие-либо данные уже нельзя. Если в результате работы формы в основную программу должны передаваться какие-либо данные, то нужно в основной программе объявить несколько переменных с помощью инструкции Public, а затем в программе реакции формы на события записать в них всю необходимую информацию, полученную от пользователя, и использовать значения этих переменных в основной программе.

Форму можно убрать с экрана и методом Hide (командой ИмяФормы. Hide или Me.Hide в одном из обработчиков событий формы). При этом значения всех переменных формы сохраняются, и к ним можно обращаться из программы согласно правилам объектно-ориентированного языка. Например, для получения значения окна ввода текста скрытой формы используется примерно такая команда: "a=UserForml.TextBox1.Value".

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

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

Формы, так же как и модули, могут быть сохранены в отдельных файлах путем экспортирования функцией "Экспорт файла" своего контекстного меню правой кнопки мыши в Менеджере проектов или путем перетаскивания ее названия из Менеджера проектов в Explorer. Но, в отличие от модулей, при сохранении форм получается два файла, в одном из которых содержится текст программы реакции формы на события, а в другом — информация о расположении элементов на форме, их свойствах, а также рисунки и фон формы. Поэтому при импортировании формы необходимо, чтобы оба этих файла были в одной папке.

* * *

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


СОЗДАНИЕ ПЕРВОЙ ПРОГРАММЫ

В предыдущих главах рассказывалось об основных средствах Microsoft Office, позволяющих создавать программы, работающие в среде этого пакета, — о Редакторе VBA, его возможностях и компонентах, о языке Visual Basic for Applications и принципах программирования. Здесь же на наглядном примере будет показан процесс создания простой макрокоманды для Microsoft Word и подробно объяснены все шаги этого процесса. Описание каждого более-менее значимого шага снабжено иллюстрацией, так что вы можете изучать эту главу даже в том случае, если под рукой компьютера у вас нет.

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

Напомню, что Microsoft Word в качестве основы для обучения программированию выбран потому, что именно эта программа из всех компонентов Microsoft Office является наиболее частоиспользуемой, и надобность в расширении его возможностей возникает чаще, чем необходимость дополнения остальных программ из пакета. В качестве основной среды разработки выбрана версия Microsoft Office 97, так как, во-первых, программы, написанные в ней, будут работать и в более старших версиях Microsoft Office[231], а, во-вторых, в русской версии Microsoft Office 97 справочная система по Visual Basic for Applications частично русифицирована, что может серьезно помочь в самостоятельном освоении этого языка.

* * *

У программы Microsoft Word есть огромное количество возможностей по работе с текстом. И огромные возможности по замене и поиску, и средства помещения в документ графики, не уступающие многим современным издательским системам, и средства оформления документов красивыми шрифтами и границами… Казалось бы — что еще надо, все необходимые возможности уже учтены создателями Word? Однако иногда перед пользователями встают такие задачи, разрешить которые с помощью стандартных средств Word очень трудно, а то и вовсе невозможно. Но для этого в Word, как, впрочем, и во всех компонентах пакета Microsoft Office, есть очень мощное средство разрешения подобных проблем: встроенный язык программирования — создания макросов.

Вот наглядный пример, когда именно написание макроса — единственный более-менее достойный выход из проблемы.

Все документы на моем компьютере оформлены приблизительно одинаково — для удобства редактирования, переноса текста из одного документа в другой и др.

Можно даже сказать, в чем заключаются эти мои предпочтения — шрифт Times New Roman, 12 пунктов, выделения — жирным и курсивом, выравнивание по ширине, все отступы абзацев равны нулю, а табуляция — 1 см. Именно в таком "формате" я держу все свои документы Word. Кроме того, я очень люблю формат Rtf и стараюсь, по возможности, делать копии своих документов в этом формате. Но вот из Internet'а я скачал 20 файлов с интересующей меня информацией — скажем, рефератов по актуальным вопросам кардиологии. И все они были набраны разными людьми в соответствии с предпочтениями каждого: везде разный шрифт,

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

Можно, конечно, повозиться с каждым документом: открывать, ставить нужный шрифт, отступы, сохранять в формате Word, потом Rtf… Если документов — два, да даже десять, то еще как-то можно справиться, а если их сорок или сто? И вот тут-то придут на помощь макросы.

Но как можно написать программу, да-да, настоящую программу на настоящем языке программирования, ничего не зная о нем, кроме того, что он существует? Это действительно было бы очень трудно сделать на C++ или даже Delphi. Но для написания программ на Visual Basic for Applications не надо особых знаний — они появятся в процессе работы. Важно лишь уметь думать.

Итак, начинаем.

Вначале я определился, что мне надо сделать с каждым документом. Во-первых, обязательно заменить шрифт на Times New Roman, 12 пунктов. Кроме того, необходимо сделать весь текст одного цвета. Во-вторых, убрать все отступы абзацев. В-третьих, заменить все выравнивание по левому краю выравниванием по ширине. Наконец, нужно обработать все документы, предварительно сохранив каждый в формате Rtf.

Я открыл пару документов из общей кучи и включил запись макроса, согласившись на его имя по умолчанию — все равно потом буду его редактировать. После начала записи макроса я стал обрабатывать документ, а Word скрупулезно переводил мои действия на язык Visual Basic for Applications. Выбрал "Правка — Выделить все", выбрал "Формат — Шрифт", поставил шрифт "Times New Roman", 12 пунктов, Черный цвет. Выбрал "Формат — Абзац", обнулил все отступы и поставил одинарный межстрочный интервал. Затем выбрал "Правка-Заменить", и, указав в графе "Формат — Абзац" для заменяемого — выравнивание влево, а для заменяющего — выравнивание по ширине, а также "Везде" в графе "Направление", провел замену во всем тексте (выделенном целиком еще на первом шаге).

После окончания всех этих действий я сохранил документ командой "Файл — Сохранить". Затем я выбрал команду "Файл — Сохранить" в формате Rtf и сохранил документ и в этом формате, после чего закрыл его и выбрал на панели записи макроса кнопку Остановить.

В принципе, назначив записанный макрос какой-нибудь кнопке или сочетанию клавиш, я мог бы на этом остановиться и обработать все документы, открыв их в Word и только нажимая на эту кнопку. Макрос бы просто выполнялся для каждого документа. Но нажимать на кнопку сорок-шестьдесят раз и сидеть около компьютера, ждать, пока все выполнится — не очень приятная перспектива. Хотелось бы, чтобы все было сделано автоматически, а самому пойти выпить кофе или чаю. Поэтому лучше использовать возможности программирования.

Итак, открываем редактор Visual Basic for Applications (рис. 5.1).



Рис. 5.1. Редактор Visual Basic for Applications


В левой части экрана редактора Visual Basic for Applications имеется окно, в котором отображены все открытые в Word в данный момент документы и содержащиеся в них программы — Менеджер проектов. (Если почему-либо он не отображается, из меню "Вид" редактора Visual Basic for Applications выберите пункт Окно проекта или нажмите комбинацию клавиш Ctrl и R.) Все открытые документы представлены в Менеджере проектов как папки в Проводнике Windows (рис. 5.2).



Рис. 5.2. Менеджер проектов


Развернув содержимое папки Normal (то есть макросов в шаблоне Normal.dot), выберем модуль NewMacros. Именно в этот модуль попадают все макросы, записанные пользователем. Поскольку записанный нами макрос — первый, то он сразу и откроется.

Вот его содержимое (рис. 5.3):

Sub Макрос1()

'

' Макрос1 Макрос

' Макрос записан 27.01.00

'

Selection.WholeStory

With Selection.Font

Name = "Times New Roman"

Size = 12

Colorlndex = wdBlack

End With

With Selection.ParagraphFormat

LeftIndent = CentimetersToPoints(0)

Rightlndent = CentimetersToPoints(0)

SpaceBefore = 0. SpaceAfter = 0

LineSpacingRule = wdLineSpaceSingle

FirstLineIndent = CentimetersToPoints(1.27)

End With

Selection.Find.ClearFormatting

Selection.Find.ParagraphFormat.Alignment = wdAlignParagraphLeft

Selection.Find.Replacement.ClearFormatting

Selection. Find.Replacement.ParagraphFormat.Alignment =

wdAlignParagraphJustify

With Selection.Find

Text = ""

Replacement.Text = ""

Forward = True

Wrap = wdFindContinue

Format = True

MatchCase = False

MatchWholeWord = False

MatchWildcards = False

MatchSoundsLike = False

Ma tchAHWordForms = False

End With

Selection.Find.Execute Replace:=wdReplaceAll

ActiveDocument.Save

ActiveDocument.SaveAs FileName:="Доклад!.rtf", FileFormat:=wdFormatRTF, _ LockComments:=False, Password:="", AddToRecentFiles:=True, WritePassword _ ReadOnlyRecommended:=False, EmbedTrueTypeFonts:=False, _

SaveNativePictureFormat:=False, SaveFormsData:=False, SaveAsAOCELetter:= _

False

ActiveWindow.Close

End Sub



Рис. 5.3. Наш записанный макрос.


Разберем все его строки более подробно.

Sub Макрос1()

' Макрос1

'Макрос

' Макрос записан 13.01.02

'

Как нетрудно догадаться, это заголовок макроса. Слово "Sub" означает начало программы. Название программы — в данном случае "Макрос1" — является уникальным именем, по которому эту программу можно запустить из других программ этого модуля.

Знаки ' перед строчкой обозначают комментарии — то есть все, что стоит в той же строке после них, никак не влияет на работу программы. В окне редактора Visual Basic for Applications все комментарии отображаются зеленым цветом.

Selection.WholeStory

Скорее всего, это — переведенная на язык Visual Basic for Applications при записи макроса команда "Выделить все". В самом деле, ведь первое действие, выполненное в процессе записи — именно выделение всего текста. Подтвердить это нетрудно, просто поставив курсор на слово "WholeStory" и нажав кнопку вызова помощи F1. Справка языка Visual Basic for Applications устроена очень удобно — при ее вызове из редактора Visual Basic for Applications она "смотрит", не стоит ли курсор на одном из слов, являющихся командой Visual Basic for Applications, и, если курсор стоит именно на таком слове, то выводится справка, относящаяся к этой самой команде (рис. 5.4).



Рис. 5.4. Вот что показывает справка по слову WholeStory


Немножко непонятный текст, но при помощи словаря удастся перевести, что эта команда расширяет выделение на весь текст.

* * *

НЕБОЛЬШОЕ ОТСТУПЛЕНИЕ.

Конечно, при самом первом знакомстве с редактором Visual Basic for Applications эта информация вряд ли будет очевидной. Но стоит ее привести именно здесь, чтобы строение команд этого языка было более понятным.

Как уже говорилось в предыдущей главе, язык Visual Basic for Applications называется объектно-ориентированнным. Такое название дано этому языку, как, впрочем, и большому количеству других современных языков программирования, из-за особого строения его команд (более подробно синтаксис Visual Basic for Applications был описан выше). Типичная команда Visual Basic имеет такой вид: <Объект>.<Объект, входящий в первый объект>.<…>.<Тот объект, с которым нужно произвести действие>. «Собственно действие>. Иными словами, каждая команда пишется как бы "с конца": вначале определяется то, над чем надо произвести действие — объект, а затем само действие — метод. Разделителями компонентов команды служат знаки "точка". Вот пример такой команды:

Selection.Font.Size = 12

Эта команда устанавливает размер шрифта во всем выделенном тексте в 12 пунктов. У объекта Selection (то есть выделенная в данный момент часть текста) есть подобъект Font — шрифт выделенного текста, а у подобъекта Font — свойство Size. Свойство Size тоже можно считать подобъектом. Знак "=" — это оператор присваивания, в данном случае свойству Size объекта Font объекта Selection присваивается значение 12 — размер шрифта во всем выделенном тексте устанавливается в 12 пунктов. (Если в документе ничего не выделено, то в 12 пунктов устанавливается размер текущего шрифта и следующая набранная буква будет именно такого размера. Если выделен графический объект, то команда будет ошибочной, о чем Visual Basic for Applications выдаст соответствующее сообщение (рис. 5.5).)



Рис. 5.5. Попытка присвоить значение размера шрифта графическому объекту.


Кроме того, с помощью подобной команды можно получить информацию о текущем размере шрифта:

а = Selection.Font.Size

После ее выполнения переменная а будет иметь значение, равное размеру шрифта выделенного текста. Как видите, синтаксис команды подобен ситаксису предыдущей. (Если в документе ничего не выделено, то переменная а будет иметь значение размера шрифта следующего за курсором символа. Если разные части выделенного текста оформлены разными шрифтами, то переменная а будет иметь значение 9999999. Если выделен графический объект, то команда будет ошибочной, о чем Visual Basic for Applications выдаст соответствующее сообщение.)

* * *

With Selection

Font.Name = "Times New Roman"

Size = 12

Colorlndex = wdBlack

End With

Похоже, это что-то, связанное со шрифтом. В самом деле, ведь "Font" по-английски значит "шрифт", a "Selection" — "выделение". По слову "Name" можно заключить, что в этой команде устанавливается имя шрифта — "Times New Roman", а слово "Size", наверное, устанавливает его размер.".Colorlndex = wdBlack" — выглядит как команда, устанавливающая цвет шрифта: есть слово "Color" "цвет" и есть слово "Black" — "черный". Но чтобы не гадать попусту, посмотрим справку Visual Basic for Applications — поставим курсор на слово "Selection" и нажмем F1 (рис. 5.6).



Рис. 5.6. Справка по слову "Selection"


Используя англо-русский словарь, можно узнать, что "Selection" означает выделенный текст или точку ввода текста. Посмотрим справку по слову "Font" (рис. 5.7).



Рис. 5.7. Справка по слову "Font"


Что-то маловато информации. Ну, ясно, что шрифт, а как пишется команда, какие у нее могут быть еще параметры? Нажмем-ка на подчеркнутое слово "Font" в тексте — это выведет информацию об объекте "Font" (рис. 5.8).



Рис. 5.8. Справка об объекте "Font"


Ну, теперь все ясно. Даже примеры приведены, — и очень похожие на наш макрос. Посмотрим тогда ссылку "Properties" вверху окна справки — список свойств шрифта, которые можно задать в программе (рис. 5.9).



Рис. 5.9. Список свойств объекта "Font"


Это, кстати, такой же список, как и тот, что выпадает в качестве контекстной подсказки, если при наборе текста программы вручную поставить после слова "Font" точку. Видно, что там есть все свойства шрифта, задаваемые в макросе: и "Name", и "Size", и "Colorlndex". Можно при желании почитать про каждое свойство подробно, но, наверное, лучше разобраться с командой "With", которая встречается и в нашем макросе, и в справке по слову "Font". Ставим на нее курсор и нажимаем F1 (рис. 5.10).



Рис. 5.10. Справка по слову "With"


В Microsoft Office 97 эта справка будет написана даже на русском языке. Ну и прекрасно — прочтя справку, узнаем, что "Инструкция With позволяет выполнить последовательность инструкций над указанным объектом, не повторяя задание имени объекта". То есть она позволяет сократить обьем кода и облегчить ориентировку программиста в нем — иначе, без этой функции, рассматриваемый фрагмент кода нашего макроса имел бы вид

Selection.Font.Name = "Times New Roman"

Selection.Font.Size = 12

Selection.Font.Colorlndex = wdBlack

что и выглядит некрасиво, и места больше требует. Примем к сведению. Идем дальше:

With Selection.ParagraphFormat

LeftIndent = CentimetersToPoints(0)

Rightlndent = CentimetersToPoints(0)

SpaceBefore = 0. SpaceAfter = 0

LineSpacingRule = wdLineSpaceSingle

FirstLineIndent = CentimetersToPoints(1.27)

End With

Это — команда установки параметров выделенных абзацев: отступов, межстрочного интервала, красной строки. Нетрудно получить эту информацию из справки (рис. 5.11) или просто догадаться, — ведь "Paragraph" означает "абзац".



Рис. 5.11. Справка по слову "ParagraphFormat"


Впрочем, проверим — так ли это. Откроем какой-либо документ и запишем новый макрос — выделив пару абзацев, включим запись макроса и поставим этим двум абзацам отступы сверху, снизу, справа и слева по одному сантиметру, а межстрочный интервал — полуторный. Вот что получилось:

Sub Макрос2()

' Макрос2 Макрос

' Макрос записан 26.01.00

'

With Selection.ParagraphFormat

LeftIndent = CentimetersToPoints(1)

Rightlndent = CentimetersToPoints(1)

SpaceBefore = 1

SpaceAfter = 1

LineSpacingRule = wdLineSpacelpt5

Alignment = wdAlignParagraphJustify

WidowControl = True

KeepWithNext = False

KeepTogether = False

PageBreakBefore = False

NoLineNumber = False

Hyphenation = True

FirstLineIndent = CentimetersToPoints(1.27)

OutlineLevel = wdOutlineLevelBodyText

End With

End Sub

Что-то не то! Код какой-то большой и много новых команд, которых не было записано в первый раз! Какие-то".WidowControl", ".KeepWithNext"… Впрочем, ясно, что это свойства абзаца — наверное, "Не отрывать от следующего", "Не разрывать абзац". Но почему же в первый раз записанный код был гораздо меньше, и все было "по делу"?

Сравним оба случая. В прошлый раз все абзацы в документе были оформлены по-разному, а в этот раз оформление обоих абзацев было одинаковым. Может, в этом дело? И действительно, поэкспериментировав еще (уж не буду здесь приводить все тексты), позаписывав макросы при оформлении разнооформленных абзацев и одинаково оформленных, можно прийти к выводу, что в текст записанного макроса попадают те свойства, которые после установки параметров абзацев через диалоговое окно "Формат — Абзац" оказываются одинаковыми у всех обрабатываемых абзацев! И неважно, были ли эти свойства установлены такими именно сейчас, или когда-то ранее.

* * *

НЕБОЛЬШОЕ ОТСТУПЛЕНИЕ.

Средство записи макросов Visual Basic for Applications отслеживает не столько действия пользователя, сколько изменения параметров текста. Поэтому при задании свойств абзаца с помощью соответствующего диалогового окна "Формат — Абзац" оно скрупулезно записывает в макрос все параметры этого диалогового окна, которые в нем были заданы при нажатии кнопки Ок. Если абзацы имели разное оформление, которое не было изменено в данный момент на единообразное, то те пункты данного диалогового окна, которые остались различными у разных абзацев в выделении, будут иметь неопределенное значение, и средство записи макросов не сможет их поместить в текст записываемого макроса. В самом же диалоговом окне подобные неопределенные опции отображаются галочкой на сером фоне (рис. 5.12), а в полях указания размеров отступов не стоят их значения.



Рис. 5.12. Диалоговое окно установки параметров абзаца с неопределенными опциями.


Если же все выделенные абзацы были оформлены единообразно, то все значения диалогового окна "Формат — Абзац" будут определены, и все они попадут в текст макроса.

Лишние команды задания свойств, оказавшиеся в тексте макроса при его записи, рекомендуется удалить с целью сокращения размера программы и для исключения излишних заданий свойств — программа должна изменять лишь те свойства текста, для изменения которых она создавалась.

Если при вызове диалогового окна параметров текста или шрифта во время записи макроса в документе ничего не было выделено, то будут определены все параметры диалогового окна, и в макрос попадут все свойства, могущие быть указанными в окне. Установленные параметры будут использоваться для вновь набираемого текста.

Параметры таких диалоговых окон, как "Файл — Параметры страницы" или "Файл-Печать" (рис. 5.13) определены полностью всегда, и поэтому при записи макроса в его текст будут записываться все возможные параметры этих диалоговых окон, вне зависимости от того, были ли изменены они все или изменению подверглись лишь некоторые.



Рис. 5.13. Параметры этого окна определены всегда.

* * *

Идем дальше.

Selection.Find.ClearFormatting

Selection.Find.ParagraphFormat.Alignment = wdAlignParagraphLeft

Selection.Find.Replacement.ClearFormatting

Selection.Find.Replacement.ParagraphFormat.Alignment

wdAlignParagraphJustify

With Selection.Find

Text = ""

Replacement.Text = ""

Forward = True

Wrap = wdFindContinue

Format = True

MatchCase = False

MatchWholeWord = False

MatchWildcards = False

MatchSoundsLike = False

MatchAHWordForms = False

End With

Selection.Find.Execute Replace:=wdReplaceAll

Насколько помнится, при записи макроса мы вызывали функцию замены Word для изменения всего выравнивания абзацев по левому краю на выравнивание по ширине. И вот перед нами эта функция, вызов которой записан на языке Visual Basic for Applications. По всей видимости, строчка "Selection.Find.ClearFormatting" означает очищение параметров форматирования в окне замены — эквивалент нажатию кнопки "Снять форматирование", а фразы "Selection.Find.ParagraphFormat.Alignment = wdAlignParagraphLeft" и "Selection.Find.Replacement.ParagraphFormat.Alignment = wdAlignParagraphJustify" — установка параметров того, что надо искать выравнивания "Left" (то есть по левому краю) и того, на что надо заменять — выравнивания "Justify" (по ширине). Нетрудно было догадаться — просто переведя с английского языка значения слов, входящих в команды: "Selection" — выделение, "Find.Replacement" — найти и заменить, "ParagraphFormat" — формат абзаца, "Alignment" — выравнивание, "AlignParagraphJustify" "РавнятьАбзацПоШирине". Что ж, ясно. Оператор "With" нам уже знаком — в следующим за разобранными нами строчками фрагменте речь пойдет об окне "Найти и заменить" (рис. 5.14).



Рис. 5.14. Вызов этой функции на языке Visual Basic for Applications описан в тексте.


Легко сообразить, что все параметры объекта "Selection.Find" (то есть поиска в выделенной части текста или во всем тексте) соответствуют параметрам окна "Найти и заменить": ".MatchWholeWord" — "искать целое слово", ".MatchCase" — "учитывать регистр".".Text" — здесь, наверное, надо указать заменяемый текст, а". Replacement.Text" — здесь то, на что заменить. В нашем случае заменять надо не текст, а форматирование, поэтому эти строчки пусты.

Заметив повторения слов ''''Selection. Find" в первых четырех строчках, можно посчитать, что и их содержимое можно включить в блок оператора "With". Проверим-ка это. Чуть ниже последнего записанного нами макроса напишем строчку: "Sub experiencel()" (имя после "Sub" может быть любым, важно лишь, чтобы оно не совпадало с какой-либо командой Visual Basic for Application). Нажмем Ввод — парой строчек ниже редактор Visual Basic for Applications напишет: "End Sub". С помощью команд "Копировать" и "Вставить" скопируем из нашей программы в текст нового макроса блок "With Selection.Find". А затем переместим все строчки, относящиеся к отражению в макросе работы окна "Найти и заменить" в блок "With Selection.Find", убрав слова "Selection.Find":

Sub experiencel()

With Selection.Find

ClearFormatting

ParagraphFormat.Alignment = wdAlignParagraphLeft

Replacement.ClearFormatting

Replacement.ParagraphFormat.Alignment = wdAlignParagraphJustify.Text = ””

Replacement.Text = ””

Forward = True

Wrap = wdFindContinue

Format = True

MatchCase = False

MatchWholeWord = False

MatchWildcards = False

MatchSoundsLike = False

MatchAHWordForms = False

Execute Replace:=wdReplaceAll

End With

End Sub

Попробуем программу в деле. Откроем еще один документ из общего набора и запустим клавишей F5 новый макрос на выполнение (курсор должен стоять внутри текста запускаемого макроса)…

Все прекрасно! Замена произошла так, как необходимо. Значит, ясно — так сокращать текст программы можно.

Осталось еще несколько интересных строчек, конкретное значение которых может вызвать вопросы — ".Forward = True", ".Wrap = wdFindContinue", ".Execute Replace:=wdReplaceAll". Ну, первая — это направление поиска вперед или назад (в последнем случае там было бы значение "False" — то есть "не вперед"). Но что значит вторая? А запишем-ка для выяснения еще макрос с такой же заменой выравнивания влево на выравнивание по ширине, но с разными параметрами направления поиска. Просто в режиме записи макроса вызовем несколько раз диалог поиска и замены, указывая каждый раз в нем разные параметры.

Вот что получилось:

Параметры поиска ∙ Записанный фрагмент кода

Вперед, с согласием на продолжение поиска

Forward = True

Wrap = wdFindAsk

Назад, с согласием на продолжение поиска

Forward = False

Wrap = wdFindAsk

Вперед, без согласия на продолжение поиска

Forward = True

Wrap = wdFindAsk

Назад, без согласия на продолжение поиска

Forward = False

Wrap = wdFindAsk

Везде

Forward = True

Wrap = wdFindContinue

Видно, что наличие или отсутствие согласия на продолжение поиска, даваемое в выскакивающем запросе, не влияет на записываемый текст. А как же тогда отказаться от этого запроса на продолжение — ведь в готовой программе он явно неуместен? Откроем текст макроса и поставим после команды".Wrap" еще один знак "=" (рис. 5.15). Выпал список возможных продолжений.



Рис. 5.15. Вот так можно определить возможные значения параметра…


Ну вот, все и ясно — так как значения".wdFindAsk" и".wdFindContinue" мы уже перебирали, то для отказа от продолжения замены после достижения конца документа нужно поставить значение параметра".Wrap" как "wdFindStop". То есть вышеприведенная таблица должна иметь вид

Параметры поиска ∙ Необходимый фрагмент кода

Вперед, с согласием на продолжение поиска

Forward = True

Wrap = wdFindAsk

Назад, с согласием на продолжение поиска

Forward = False

Wrap = wdFindAsk

Вперед, без согласия на продолжение поиска

Forward = True

Wrap = wdFindStop

Назад, без согласия на продолжение поиска

Forward = False

Wrap = wdFindStop

Везде

Forward = True

Wrap = wdFindContinue

Осталось разобраться со строчкой".Execute Replace:=wdReplaceAll". По логике вещей, это должна быть команда запуска поиска, тем более что и слово "Execute" означает "Запустить". Посмотрим в справке — по слову "Execute" (рис. 5.16).



Рис. 5.16. Справка по слову Execute.


Так, получаем четыре ссылки: "For information about the Execute method, click one of the following object names: Dialog, Find, KeyBinding, MailMerge". В Microsoft Office 2000/XP это окно Справочной системы VBA несколько красивее, но перечень объектов, к котором может быть применен метод Execute, в нем такой же, разве что отдельно приводятся ссылки на примеры кода. Нас интересует вторая ссылка — "Find", так как мы работаем именно с этим объектом. Открываем (рис. 5.17)…



Рис. 5.17. Справка по команде Execute объекта Find


Так и есть — команда".Execute" запускает команду поиска и замены на выполнение: "Runs the specified find operation. Returns True if the find operation is successful.". Из текста справки также узнаем, что все параметры поиска и замены можно было бы задать и в скобках, а, кроме того, результат выполнения команды можно записать в переменную — успешен ли был поиск или нет (то есть были ли найдены в данном сеансе работы команды "Найти и заменить" искомые элементы), принимающую значения соответственно "True" или "False". Сейчас данная возможность не требуется, однако запомнить ее стоит — мало ли когда пригодится.

Продолжаем изучать записанную макрокоманду.

ActiveDocument.Save

Вопросов не вызывает — это команда сохранения активного документа.

ActiveDocument.SaveAs FileName:="Доклад!.rtf", FileFormat:=wdFormatRTF, LockComments:=False, Password:="", AddToRecentFiles:=True, WritePassword:="", ReadOnlyRecommended:=False, EmbedTrueTypeFonts:=False, SaveNativePictureFormat:=False, SaveFormsData:=False, SaveAsAOCELetter:= False

А вот здесь уже понадобится редактирование. Это команда "Сохранить Как…" — поскольку соответствующая команда Word представляет собой диалоговое окно, то в текст макроса помещаются все возможные параметры, как соответствующие установленным по умолчанию, так и нет: ''''AddToRecentFiles" — добавлять ли ярлык в папку "Recent", ''''EmbedTrueTypeFonts" — внедрять ли шрифты TrueType.

Наиболее интересны элементы команды "FileName:=”Доклад!.rtf"" и "FileFormat:=wdFormatRTF" — имя файла, под которым сохраняется активный документ, и тип сохраняемого файла. Тип нас устраивает — формат Rtf. А вот как быть с именем? Ведь у каждого файла должно быть свое, уникальное имя. А тут получается, что все файлы, обрабатываемые данным макросом, станут сохраняться под одним и тем же именем, что, ясное дело, вызовет их запись друг на друга и тем самым потерю данных во всех них, кроме обработанного последним. Что же делать?

Попробуем для начала просто исключить строчку с указанием имени из текста данной команды. Создадим еще один модуль, скопируем туда всю команду "ActiveDocument.SaveAs" со всеми параметрами и удалим строчку "FileName: = ”Доклад!. rtf"". Запустим программу… ничего не произошло. Но ведь программа что-то делала: и жесткий диск работал, и система была недоступна пару секунд, и сообщений об ошибках не было… Что же все же сработало? А откроем-ка в "Блокноте" или другом редакторе простого текста исходный файл, который обрабатывался и сохранялся после обработки — у меня это был файл "Доклад2.doc" (рис. 5.18), предварительно выгрузив его из Word — чтобы "Блокнот" мог его открыть.



Рис. 5.18. Откроем в "Блокноте" файл, который сохранялся нашей командой.


Так вот в чем дело — файл был сохранен в формате Rtf, но под прежним именем и с расширением".doc"! И исходный файл теперь потерян — на его место записан новый. Нас это совершенно не устраивает — ладно, имя пусть будет то же, а вот расширение должно быть именно".rtf". Тогда и перезаписи исходного файла не произойдет — расширение-то будет другим.

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

Активный документ приобрел имя "Docl.doc" (или "Doc2.doc", "Doc3.doc" — у кого как[232]). Но где же он сохранился? Ищем по F3 в "Проводнике" — так, сохранен он в папке, где произошло последнее ручное сохранение какого-либо файла или в папке для документов Word по умолчанию: "Мои документы" или другая, заданная пользователем, путь к которой можно посмотреть во вкладке "Сервис-Параметры-Расположение" (рис. 5.19).



Рис. 5.19. Здесь можно посмотреть путь к папке для документов Word по умолчанию.


Следовательно, при программном сохранении ранее несохранявшегося документа без задания ему имени и места сохранения[233] происходит сохранение активного документа в папке по умолчанию (или в папке, где был последний раз сохранен вручную какой-нибудь документ) и с именем по умолчанию. Примем к сведению.

Но как же нам быть с нашей программой? Нам ведь надо, чтобы все обрабатываемые файлы сохранялись под своим именем и в формате и с расширением Rtf! А попробуем-ка каким-нибудь способом получить программно имя активного документа. Создадим еще один макрос, и напишем там "ActiveDocument", ставим точку (рис. 5.20) и видим, что среди возможных продолжений команды есть свойство "Name".



Рис. 5.20. А так можно найти нужное продолжение команды…


Похоже, это и есть то, что нам надо. Проверим. Модифицируем экспериментальную процедуру следующим образом:

Sub ехрегience2()

MsgBox ActiveDocument. Name

End Sub

Это позволит нам вызвать окно сообщения с значением функции "ActiveDocument.Name". Можно было бы написать "Debug.Print ActiveDocument.Name", что отобразило бы значение этой функции в специальном Окне отладки (вызывается из меню редактора Visual Basic for Applications "Вид"-"Окно отладки"). Но использовать окно сообщения как-то привычнее. Итак, нажимаем F5… получаем окно с сообщением: "Доклад!.doc".



Рис. 5.21. Результат работы команды "MsgBox ActiveDocument.Name".


Но нам ведь нужно одно только имя, без расширения! Как же его получить? Наверное, проще всего убрать последние четыре символа — ".doc". Но как?

Воспользуемся справкой.

Дальнейшие наши действия и их результат весьма серьезно отличаются в зависимости от той версии Microsoft Office, с которой мы работаем.

1. При работе в Microsoft Office 97 нажмем F1 в Редакторе VBA, в открывшемся окне нажмем кнопку "Разделы" (рис. 5.22), а там — "Предметный указатель" (рис. 5.23 — в нем все разделы справки классифицированы по смыслу, в то время как в разделе "Поиск" просто составлена база данных по всем словам, входящим в справочную систему Visual Basic for Applications).



Рис. 5.22. Именно эту кнопку надо нажать, чтобы в Microsoft Office 97 вывести на экран основное справочное меню.



Рис. 5.23. Предметный указатель


Наберем в строке поиска слово "строка". Из списка разделов справочной системы Visual Basic for Applications выберем то, что нам надо — строчку "крайние левые символы" (ведь нам нужно получить из имени документа с расширением только его имя, то есть левую часть строки без четырех правых символов, то есть крайние слева символы). Получаем справку по функции "Left" (рис. 5.24).



Рис. 5.24. Справка по функции Left в Microsoft Office 97.


Превосходно — функция "Left" является именно той функцией, которая нам требовалась. Но она требует значение количества символов во всей строке — как это узнать? Да так, как описано в данном справочном окне — через функцию "Len". Нажмем ссылку "См. также" и выберем из списка строчку "Функция Len" (рис. 5.25).



Рис. 5.25. Справка по функции Len в Microsoft Office 97.


2. Ну, а если мы используем Microsoft Office 2000 или Microsoft Office ХР, то просто задаем вопрос Помощнику (рис. 5.26) или открываем Справочную систему VBA (рис. 5.27) из меню "Help" Редактора VBA, если Помощник скрыт или не установлен. Вопрос, естественно, формулируется по-английски и может звучать, например, так: "Delete right symbols in string" — "Удалить правые символы из строки".



Рис. 5.26. Вопрос Помощнику…



Рис. 5.27…или Справочной системе.


В обоих случаях нам выдается список ссылок на разделы Справочной системы. Перебрав их все (через окно Справочной системы это делать удобнее, чем с помощью Помощника), определяем, что нужная нам информация содержится в рассказе о функции Left (см. рис. 5.27). В нижней части окна справки по функции Left есть строчка — "То determine the number of characters in string, use the Len function", то есть для определения числа символов в строке (а это нужно, чтобы подсчитать, сколько символов нужно брать слева из исходного имени файла: оно будет равно числу символов в строке минус четыре — длина расширения в три символа и точка) следует использовать функцию Len.

Раз так сказано в Справке по функции Left, то, наверное, рассказ о функции Len и ее синтаксисе находится где-то "рядом". И действительно — открыв ссылку See Also в верхней части окна Справки по функции Left, смотрим на список связанных тем (рис. 5.28)…



Рис. 5.28. Связанные темы.


…и видим, что Справка по функции Len там присутствует. Открываем ее (рис. 5.29)…



Рис. 5.29. Справка по функции Len в Microsoft Office XP


Цель вышеприведенных абзацев, посвященных Справочной системе — не столько проиллюстрировать процесс поиска информации для разработки нашей программы конвертации документов, сколько показать вам основные приемы работы со Справкой VBA, которые вы должны весьма хорошо знать при создании программ на Visual Basic for Applications. В разных версиях Microsoft Office они немного отличаются, однако общие алгоритмы одинаковы — поиск по ключевым словам, переход по ссылкам на связанные рассказы Справки для поиска в них нужной информации.

Найдя нужную нам информацию в Справочной системе (любой версии Microsoft Office — как описано выше), немного подумав и использовав данные о синтаксисе обеих команд в справке, можно написать команду, которая возвращает строку без последних четырех символов:

imyadoc = Left (ActiveDocument. Name, Len (ActiveDocument. Name) — 4)

Можно проверить. Создадим еще один модуль:

Sub experience3()

imyadoc = Left (ActiveDocument. Name, Len (ActiveDocument. Name) — 4)

MsgBox imyadoc

End Sub

и запустим его. В окне сообщения — имя документа без расширения (рис. 5.30).



Рис. 5.30. Результат работы команды "MsgBox Left(ActiveDocument.Name, Len(ActiveDocument.Name) — 4)".


Все так, как нам необходимо.

* * *

НЕБОЛЬШОЕ ОТСТУПЛЕНИЕ.

Вышеизложенный способ получения имени активного документа без расширения — не самый лучший, хотя имеет право на существование. Есть еще один способ узнать только имя документа, унаследованный из предыдущих версий Word, — в макроязыке для Microsoft Word 6.0 и Microsoft Word 95 была специальная команда для получения имени документа, к сожалению, не включенная в Visual Basic for Applications. Однако она может быть использована в Visual Basic for Applications, так как все макросы для Microsoft Word 6.0 и Microsoft Word 95 могут выполняться и в более старших версиях Microsoft Office. При открытии в Microsoft Office 97/2000/ХР шаблонов с макросами, созданных в предыдущих версиях Office, все макросы автоматически конвертируются для выполнения в Visual Basic for Applications с помощью включенной в него версии языка WordBasic, на котором писались макрокоманды для для Microsoft Word 6.0 и Microsoft Word 95.

В для Microsoft Word 6.0 и Microsoft Word 95 была функция "FileNameInfo$(документ, параметр)", с помощью которой можно было получить имя документа без расширения, путь к документу без имени и путь к документу вместе с именем. Для того, чтобы узнать одно имя документа, без расширения и пути, значение параметра должно быть равно 4. (Все это подробно описано в справке по WordBasic для Microsoft Word 6.0 и Microsoft Word 95.) В Visual Basic for Applications эта функция выглядит так:

imyadoc = WordBasic.[FileNameInfo$](ActiveDocument.Name, 4)

Она возвращает полное имя документа без расширения и пути. Данная функция будет просто незаменима при обработке документов с расширениями, состоящими не из трех символов — например, ".html". В то время как в таких случаях с помощью функций "Len", "Mid", "Right" пришлось бы писать большие фрагменты кода для получения имени документа без расширения, эта функция позволит получить его одной строчкой.

Однако при первой работе с Visual Basic for Applications она не будет очевидной, так как узнать о ней, и тем более об ее необходимых параметрах может только тот, кто раньше имел дело с WordBasic. Поэтому в нашей программе будет использоваться предыдущая функция — "imyadoc =

Left (ActiveDocument. Name, Len (ActiveDocument. Name) — 4)".

Вообще говоря, иногда бывает очень полезным воспользоваться старыми командами WordBasic, которые остались в нем от предыдущих версий. К сожалению, в Справочной системе VBA не освещено их применение, однако, если на вашем компьютере установлены сразу несколько версий Word, в том числе Microsoft Word 6.0 или Microsoft Word 95, то вы сможете узнать о таких командах в Справочной системе предыдущей версии этой программы.

* * *

Итак, команда нашей программы "ActiveDocument.SaveAs" должна выглядеть так:

ActiveDocument.SaveAs FileName: = Left (ActiveDocument.Name,

Len(ActiveDocument.Name) — 4), FileFormat:=wdFormatRTF, LockComments:=False, Password:="", AddToRecentFiles:=True, WritePassword:="",

ReadOnlyRecommended:=False, EmbedTrueTypeFonts:=False,

SaveNativePictureFormat:=False, SaveFormsData:=False, SaveAsAOCELetter:= False

Все лишнее можно убрать, хотя это не обязательно:

ActiveDocument.SaveAs FileName: = Left (ActiveDocument.Name,

Len(ActiveDocument.Name) — 4), FileFormat:=wdFormatRTF

He мешало бы еще, чтобы новый документ в формате Rtf сохранялся в той же папке, что и исходный. Для этого добавим к параметру "FileName" информацию о пути к активному документу:

ActiveDocument.SaveAs FileName:=ActiveDocument.Path + "\" +

Left (ActiveDocument. Name, Len (ActiveDocument. Name) — 4),

FileForma t: =wdForma tRTF

Иначе Word будет сохранять документы в той папке, где последний раз был сохранен или открыт како-нибудь документ с помощью диалоговых окон "Сохранить как…" и "Открыть…". А это все же не всегда будет той же самой папкой, где находятся обрабатываемые документы, — к тому же документы для обработки можно открывать в Word и путем перетаскивания иконки файла в окно редактора, а при таком способе открытия папка сохранения документов не меняется.

В Visual Basic for Applications у объекта ActiveDocument есть также параметр FullName, который представляет из себя полный путь к документу, включающий и иерархию папок. Подробнее об этом параметре можно узнать в Справочной системе VBA. Иными словами, последнюю команду можно переписать как

ActiveDocument.SaveAs FileName:= Left(ActiveDocument.FullName,

Len(ActiveDocument.FullName) -4), FileFormat:=wdFormatRTF

Она будет давать точно такой же результат, что и приведенная выше.

И, наконец, последняя строчка:

ActiveWindow.Close

End Sub

Вот и конец программы — закрытие активного окна с документом.

Ну, а теперь надо добиться того, чтобы программа могла обрабатывать не один документ, а сразу множество. Можно пойти двумя путями: либо обрабатывать все нужные документы в одной папке, либо обработать все открытые документы, предварительно открыв нужные. Лично я предпочел второй вариант: ведь тогда можно открыть для обработки все действительно необходимые документы, несмотря на их исходное расположение — пусть даже и не в одной папке[234].

Как это сделать? Заметим, что готовый документ закрывается после обработки, и в окне Word активизируется следующий документ из всех открытых в редакторе. Следовательно, во-первых, надо обеспечить выполнение макроса над всеми документами, то есть его повторение — после окончания работы макроса он должен быть выполнен сначала. Можно считать, что в момент обработки в окне Word будут открыты лишь те документы, которые обработать надо — лишние всегда можно закрыть (а в Microsoft Word 97 ничего не мешает открыть для обработки файлов новое окно Word, если остальные открытые документы так уж необходимо оставить именно открытыми). Для выполнения макроса сначала нужно заставить Visual Basic for Applications перейти в начало программы. Поищем в справке Visual Basic for Applications, в Предметном указателе по слову "переход" — есть ли какая команда для этого (рис. 5.31)? Получаем список — "безусловные", "при ошибке", "условные".



Рис. 5.31. Поиск в предметном указателе по слову "переход" в Microsoft Office 97.


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



Рис. 5.32. Справка по инструкции Goto в Microsoft Office 97.


Из справки и примера узнаем, что инструкция (то есть встроенная функция, которая не возвращает никаких значений) "Goto" указывает на необходимость перехода к строке, на которой находится установленная нами метка.

(К сожалению, из-за того, что в более старших, чем 97-я, версиях Microsoft Office — 2000-й и ХР Справочная система по VBA не русифицирована, провести в ней такой же поиск, как описан выше, не представляется возможным. Однако, введя в окне Справки в качестве ключевого слова фразу "go to" — в переводе "пойти на…", "перейти на…", можно получить довольно большое число разделов Справки, содержащих его (рис. 5.33).



Рис. 5.33. Справка по инструкции Goto в Microsoft OfficeXP.


Выбрав из перечня разделов, содержащих данное ключевое слово, раздел GoTo Statement, можно получить всю ту информацию, которая была приведена на рис. 5.32.)

Итак, поставим метку в начало нашей программы:

Sub Макрос1()

' Макрос1 Макрос

' Макрос записан 27.01.00

'

metka:

Selection.WholeStory

With Selection.Font

Name = "Times New Roman"

……

а в ее конец — инструкцию "Goto":

……

ActiveDocument.SaveAs Filename:= Left (ActiveDocument. FullName,

Len (ActiveDocument. FullName) -4), FileFormat:=*dFormatRTFActiveKindov. Close

Goto metka

End Sub

(Не стоит поддаваться мнению, что "использование оператора Goto — дурной тон". Это не так. Каждый оператор выполняет свою функцию, и если какая-либо проблема может быть лучше всего решена применением именно этого оператора, то его и надо использовать. Дурной тон — делать сложно там, где можно сделать просто.)

Готово. Теперь наша программа обработает все открытые документы. Но… обработать-то обработала, но в конце выдала сообщение об ошибке. Можно, конечно, оставить и так, но программа, заканчивающая свою работу ошибкой, пусть и после выполнения всех необходимых действий, выглядит некрасиво. Поэтому нужно обеспечить остановку выполнения программы после того, как будут обработаны все документы. Итак, алгоритм действий программы должен быть таков:

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

2. Посмотреть, есть ли еще открытые документы.

3. Если есть, то перейти к пункту 1, если нет, то завершить работу.

"Если" — по-английски "If". Поищем по этому слову в Предметном указателе Справочной системы по VBA (из Microsoft Office 97). Получаем строчку:

"Инструкция If", выбрав которую, получаем окно из различных сочетаний слов If, Then, Else и др. (рис. 5.34).



Рис. 5.34. Выберем нужную справку…


Выберем "Инструкция If…Then…Else" — вроде первое слово понятнее. Получаем справку, из которой узнаем синтаксис команды:

If условие Then [инструкции] [Else инструкции_еlsе]

(К сожалению, в Справочной системе по VBA из Microsoft Office 2000/ХР подобный поиск произвести не представляется возможным — на слово "If" ни Предметный указатель, ни Мастер ответов не реагируют. Подобные ситуации встречаются в этой Справочной системе нередко — вот почему для начального обучения программированию на Visual Basic for Applications я рекомендую использовать именно Microsoft Office 97, несмотря на то, что эта версия офисного пакета считается несколько устаревшей.)

Какое же условие должно быть у нас? Наверное, подсчет количества открытых документов — если не 0, то продолжать работу, а если 0, то остановиться. А как можно подсчитать количество открытых документов? Посмотрим, нет ли в Visual Basic for Applications команды для такого подсчета? Напишем в тексте программы: "Documents", поставим точку и просмотрим выпавший список (рис. 5.35).



Рис. 5.35. Как же подсчитать открытые документы?


Есть ли что-нибудь, что может пригодиться?

Так и есть — в списке имеется метод "Count": скорее всего, это функция подсчета. Выберем ее из списка и посмотрим по ней справку и пример — да, эта команда считает открытые документы. То есть условие должно выглядеть как "If Documents. Count > 0 Then…". Ну, а инструкции — переход к метке — нами уже написаны.

Часть команды "Else…" можно опустить, а просто написать нужные инструкции после команды "If…" — ведь все равно к их выполнению программа не перейдет до тех пор, пока останутся открытые документы. А поместить там, наверное, стоит вызов сообщения, желательно со звуковым сигналом, — чтобы можно было поставить документы на обработку и отойти. Используем функцию MsgBox (о ее синтаксисе подробно написано в Справочной системе по VBA, в русской версии Microsoft Office 97 — даже по-русски):

signal = MsgBox ("Обработка закончена", vbln formation, "Обработка текстов")

Ну, вот и все. Итак, наша программа теперь выглядит так:

Sub Макрос1()

'

' Макрос1 Макрос

' Макрос записан 13.01.02 metka:

'

Selection.WholeStory

With Selection.Font

Name = "Times New Roman"

Size = 12

Colorlndex = wdBlack

End With

With Selection.ParagraphFormat

LeftIndent = CentimetersToPoints(0)

Rightlndent = CentimetersToPoints(0)

SpaceBefore = 0. SpaceAfter = 0

LineSpacingRule = wdLineSpaceSingle

FirstLineIndent = CentimetersToPoints(1.27)

End With

Selection.Find.ClearFormatting

Selection.Find.ParagraphFormat.Alignment = wdAlignParagraphLeft

Selection.Find.Replacement.ClearFormatting

Selection. Find.Replacement.ParagraphFormat.Alignment = wdAlignParagraphJustify

With Selection.Find

Text = ""

Replacement.Text = ""

Forward = True

Wrap = wdFindContinue

Format = True

MatchCase = False

MatchWholeWord = False

MatchWildcards = False

MatchSoundsLike = False

MatchAHWordForms = False

End With

Selection.Find.Execute Replace:=wdReplaceAll

ActiveDocument.Save

ActiveDocument.SaveAs FileName:= Left (ActiveDocument.FullName, Len(ActiveDocument.FullName) -4), FileFormat:=wdFormatRTFActiveWindow.Close

ActiveWindow.Close

If Documents.Count > 0 Then GoTo metka

signal = MsgBox ("Обработка закончена", vblnformation, "Обработка текстов")

End Sub

Итак, программа готова. Можно с помощью диалогового окна "Настройка"

назначить ей кнопку, пункт меню или сочетание клавиш, и запускать ее при необходимости.

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

Опять воспользуемся Справкой.

В Предметном указателе Справочной системы по VBA из Microsoft Office 97 зададим слова "dialog boxes", выберем эту же строчку из списка тем (рис. 5.36).



Рис. 5.36. Как же отобразить диалоговые окна? Наверное, поискав в Справке по этим словам.


В появившемся окне выбора выберем второе — "Displaying Built-In Word Dialog-Boxes", так как это, судя по названию, более общая тема, чем список аргументов диалоговых окон (рис. 5.37).



Рис. 5.37. Выбор из двух вариантов — какой нам больше подойдет?


В появившемся окне читаем:

"You can display a built-in dialog box to get user input or to control Word by using Visual Basic. The Show method of the Dialog object displays and executes any action taken in a built-in Word dialog box. To access a particular built-in Word dialog box, you specify a WdWordDialog constant with the Dialogs property. For example, the following macro instruction displays the Open dialog box (wdDialogFileOpen): Dialogs(wdDialogFileOpen).Show."

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

В Microsoft Office 2000/ХР помещение в "Мастер ответов" или "Предметный указатель" Справочной системы VBA слов "dialog boxes" приведет к появлению довольно большого списка разделов, содержащих данные слова (рис. 5.38), так что выбор придется делать непростой. Однако найти наиболее подходящий для нашего случая раздел — "Displaying Built-In Word Dialog-Boxes" — все же можно довольно быстро.



Рис. 5.38. Поиск no словам "dialog boxes" в Справочной системе VBA Microsoft Office XP.


Текст же в разделе "Displaying Built-In Word Dialog-Boxes" практически идентичен тексту такого же раздела из Справочной системы по VBA из Microsoft Office 97.

Итак, нужная нам команда — Dialogs("имя диалога").Show — найдена.

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



Рис. 5.39. Для поиска нужной команды можно перебрать список встроенных диалоговых окон Word.


В качестве метода вывода окна на экран установим".Display" — вывод окна на экран без каких-либо последующих действий: если с помощью команды

Dialogs(wdDialogFileOpen).Show будет выведено окно открытия файла, то при нажатии кнопки "Открыть" в нем выбранный в окне файл будет открыт, а если окно выводилось командой Dialogs(wdDialogFileOpen).Display, то открытия файла не произойдет, но имя выбранного файла можно будет записать в переменную:

With Dialogs(wdDialogFileOpen)

Display

imya=.Name

End With

и впоследствии использовать это имя по своему усмотрению.

При использовании встроенных диалоговых окон Word обязательно использование оператора With, так как, казалось бы, эквивалентный фрагмент кода

Dialogs(wdDialogFileOpen).Display

imya= Dialogs(wdDialogFileOpen).Name

работать не будет.

После перебора остановимся на окне Dialogs(wdDialogCopyFile) — копирование файла. Посмотрев ссылку "Built-in dialog box argument lists" окна "Displaying built-in Word dialog boxes" (в Справочной системе VBA из Microsoft Office 2000/XP этот раздел присутствует в результатах поиска по словам "dialog boxes", рис. 5.40), получаем список всех возможных аргументов диалоговых окон (то есть параметров, значения которых можно получить из окон или задать им).



Рис. 5.40. Microsoft Office XP. Справка по параметрам встроенных диалоговых окон.


Нас интересует параметр "Directory" (папка, куда скопируется файл, указанный в параметре "FileName" при выполнении метода "Show" или "Execute" — при выполнении последнего метода происходит задание параметров диалогового окна или получение из них необходимой информации без отображения собственно диалога). Поэкспериментируем с этим окном — напишем в экспериментальном модуле следующий код:

Sub experience4 ()

With Dialogs(wdDialogCopyFile)

Display

papka =.Directory

End With

MsgBox papka

End Sub

Запустив эту программу несколько раз, получаем, что в переменную "papka" записывается путь и имя папки, но, если в пути или имени были пробелы, то путь окаймляется кавычками: "C: \Program Files\Microsoft Office\Шaблoны\", а если пробелов в пути не было, то кавычки по краям не ставятся. Поэтому возвращаемую переменную нужно обработать — убрать кавычки.

Сделать это можно с помощью уже известных нам команд "Left", "Right", "Mid" и "Len":

If Right (papka, 1) = Chr$ (34) Then papka = Mid (papka, 2, Len (papka) — 2)

"Chr$(34)" — это команда, которая возвращает символ с ASCII-кодом 34: кавычку. (Каждый символ в Word имеет свой номер — ASCII-код, по которому его можно вызвать на экран. Узнать код выделенного символа можно командой "MsgBox Asc(Selection.Text)". Узнать о командах "Chr$" и "Asc" можно, поискав информацию в Справочной системе.)

Кроме того, не мешало бы сделать так, чтобы при запуске программы окно "Копирование файла" по умолчанию стояло бы на директории с активным документом — не всегда же нужно сохранять все обрабатываемые документы в отдельной папке! Нет ничего проще — установим параметр "Directory" как

"ActiveDocument.Path" перед командой".Display":

With Dialogs (wdDialogCopyFHe)

Directory = ActiveDocument.Path

Display

papka =.Directory

End With

If Right (papka, 1) = Chr$ (34) Then papka = Mid (papka, 2, Len (papka) — 2)

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

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



Рис. 5.41. Microsoft Office 97. Справка по методу .Display. Видно, что этот метод возвращает значение — "Return Value", то есть, является функцией.


Добавим в программу условие и команду выхода из программы — он должен произойти, если в диалоговом окне нажата кнопка "Отмена" (тогда функция. Display вернет в программу значение "0"):

With Dialogs(wdDialogCopyFile)

Directory = ActiveDocument.Path

If.Display = 0 Then Exit Sub

papka =.Directory

End With

If Right (papka, 1) = Chr$ (34) Then papka = Mid (papka, 2, Len (papka) — 2)

Теперь при нажатии кнопки "Отмена" в диалоговом окне выбора папки произойдет выход из программы.

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

ActiveDocument.SaveAs FileName:=рарка + Left (ActiveDocument.Name, Len(ActiveDocument.Name) -4), FileFormat:=wdFormatRTF

И вот, наконец, можно привести окончательный вид нашего макроса со всеми внесенными в него доработками:

Sub Макрос1()

'

' Программа для обработки документов

'

With Dialogs(wdDialogCopyFile)

Directory = ActiveDocument.Path

If.Display = 0 Then Exit Sub

papka =.Directory

End With

If Right (papka, 1) = Chr$ (34) Then papka = Mid (papka, 2, Len (papka) — 2)

metka:

Selection.WholeStory

With Selection.Font

Name = "Times New Roman"

Size = 12

Colorlndex = wdBlack

End With

With Selection.ParagraphFormat

LeftIndent = CentimetersToPoints(0)

Rightlndent = CentimetersToPoints(0)

SpaceBefore = 0

SpaceAfter = 0

LineSpacingRule = wdLineSpaceSingle

FirstLineIndent = CentimetersToPoints(1.27)

End With

Selection.Find.ClearFormatting

Selection.Find.ParagraphFormat.Alignment = wdAlignParagraphLeft

Selection.Find.Replacement.ClearFormatting

Selection. Find.Replacement.ParagraphFormat.Alignment = wdAlignParagraphJustify

With Selection.Find

Text = ""

Replacement.Text = ""

Forward = True

Wrap = wdFindContinue

Format = True

MatchCase = False

MatchWholeWord = False

MatchWildcards = False

MatchSoundsLike = False

M tchAllWordForms = False

End With

Selection.Find.Execute Replace:=wdReplaceAll

ActiveDocument.Save

ActiveDocument.SaveAs FileName: =papka + Left(ActiveDocument.Name, Len(ActiveDocument.Name) -4), FileFormat:=wdFormatRTF

ActiveWindow.Close

If Documents.Count > 0 Then GoTo metka signal = MsgBox ("Обработка закончена", vblnformation, "Обработка текстов")

End Sub

* * *

Весь приведенный выше подробный разбор написания первой макрокоманды помещен здесь исключительно для того, чтобы читающий эти строки мог представить себе ход рассуждений и мыслей, необходимый для создания программ, — некоторые приемы анализа программного кода и самостоятельного обучения программированию на Visual Basic for Applications. Ведь статья рассчитана не на профессиональных программистов, которые, без сомнения, знают эти приемы, а скорее на тех, кто ранее вообще не имел представления об этой отрасли человеческой деятельности.

А эти приемы таковы:

1. Для самого первого начала работы, а также для выяснения, какая команда соответствует тому или иному преобразованию текста или другому действию пользователя Office, необходимо широко использовать основное отличие редактора Visual Basic for Applications от сред разработки приложений на других языках программирования — средство записи макросов. Наличие средства записи макросов позволяет быстро и легко создать свою первую программу и начать ее изучать, а также может оказать серьезную помощь, когда необходимо "перевести" на язык Visual Basic for Applications какое-либо действие пользователя Word, Excel или PowerPoint.

2. Для грамотного написания кода, выяснения возможных продолжений каждой команды следует широко использовать контекстную подсказку Visual Basic for Applications, которая появляется при наборе точки или скобки после уже написанной части команды.

3. Справка Visual Basic for Applications — основной источник знаний по этому языку! Она построена по контекстному принципу — при вызове справки клавишей F1 отображается справка по той команде, на которой стоит в это время курсор. Таким образом можно быстро и легко изучить назначение, синтаксис и особенности каждой команды — стоит только набрать ее и вызвать справку. К сожалению, в новых версиях Microsoft Office Справочная система по VBA не переведена на русский язык (а в Microsoft Office 97 перевод затронул отнюдь не весь объем Справки), поэтому англо-русский словарь (или система машинного перевода) может стать вашим спутником на время освоения Visual Basic for Applications. Путешествия по справке и чтение различных ее разделов, даже не относящихся к непосредственно выполняемой задаче, обогатят ваши знания по программированию.

4. Примеры справки Visual Basic for Applications — работа, сделанная за Вас! Копируйте фрагменты кода из примеров себе в программу и модифицируйте их так, как Вам надо.

5. Для тестирования и отладки небольшого фрагмента кода или даже одной команды вынесите ее временно в отдельный модуль — проще будет работать.

В принципе даже этих базовых приемов хватит, чтобы начать полноценно изучать Visual Basic for Applications. Ну, а дальнейшее зависит уже от Вашего разума, логики, сообразительности и наблюдательности.

Бесспорно, "дружественность" Редактора VBA — это не что-то случайно возникшее, а плод многолетней работы программистов Microsoft и множества тестеров и пользователей. Стоит их за это поблагодарить, — освоить без дополнительных руководств какой-либо язык программирования лет 10 назад было крайне и крайне непросто.

Visual Basic for Applications — пожалуй, на настоящее время практически единственный язык, который подавляющее число людей может изучить абсолютно самостоятельно, без каких-либо дополнительных книг или текстов программ. Достаточно лишь иметь "научный взгляд на мир", то есть способность наблюдать, экспериментировать и делать выводы. Даже эта книга имеет цель не научить вас программировать на Visual Basic for Applications, а только помочь вам в этом, чтобы Вы не тратили множество времени на поиск и получение информации о не совсем очевидных вещах. Ведь, согласитесь, совсем неплохо облегчить начало работы и знакомство с возможностями редактора, немного проиллюстрировав процесс программирования.


ДИАЛОГ С ПОЛЬЗОВАТЕЛЕМ

Продолжим изучение программирования на Visual Basic for Applications. Подробные описания теперь уже не нужны — достаточно лишь заострения внимания на некоторых "подводных камнях" или скрытых возможностях.

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

Как и прежде, в качестве основной среды разработки будет использоваться Microsoft Office 97, об отличиях же более старших версий Microsoft Office будет упоминаться тогда, когда это имеет значение.

Для создания формы в Редакторе VBA необходимо из контекстного меню правой кнопки мыши в Менеджере проектов выбрать "Вставить — UserForm" (рис. 6.1).



Рис. 6.1. Окно дизайна форм.


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

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

Основное отличие программного кода, обслуживающего формы, от кода в обычных модулях заключается в принципе программирования. В то время как программа на Visual Basic for Applications вроде той, что была нами совместно написана в предыдущей главе книги, выполняется "последовательно", — то есть все ее команды выполняются одна за другой, и их порядок выполнения изменяется только в зависимости от операторов условного и безусловного перехода "If" и "Goto" (в принципе — в частности могут быть отклонения от данного правила), форма "реагирует на события" — то есть каждому элементу формы может быть поставлена в соответствие определенная отдельная программа, выполняющая нужные команды при совершении с этим элементом каких-либо действий. Большинство программ для Windows, да и сам текстовый редактор Microsoft Word построены именно по такому принципу — они не "работают сами по себе", а ждут от пользователя команд и "реагируют" на них: выполняют те или иные действия. Так и форма: программист должен разработать ее интерфейс — создать форму, расположить на ней элементы, определить их свойства, а затем написать "программы обработки событий", поместив в каждой такой программе код, который должен быть выполнен, когда то или иное событие произойдет, то есть будет нажата какая-нибудь кнопка на форме или на клавиатуре, введен текст в поле ввода текста, выбран тот или иной флажок на форме и др. Программы обработки событий могут изменять и внешний вид самой формы и ее элементов: прятать их или показывать, изменять любые их свойства, так как у каждого элемента формы есть свое уникальное (т. е. принадлежащее только этому элементу и больше никакому другому) имя, по которому к нему можно обращаться.

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

Согласно соответствующим формулам, Q(количество теплоты в джоулях) = U2 (напряжение в вольтах)*t(время в секундах)/R(сопротивление в омах), при этом R = p(удельное сопротивление материала проводника в омах на метр)*l(длина проводника в метрах)/s(площадь поперечного сечения проводника в квадратных сантиметрах). Таким образом, формула для расчета количества теплоты выглядит так (она также известна под именем закона Джоуля-Ленца):

Q = (U2*t*s)/(l*р).

Ее мы и запрограммируем в форме.

Q = U2ts/lp


Рис. 6.2. Закон Джоуля-Ленца.


ЭКСКУРС В ФИЗИКУ

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

Q = I2*R*t = (I2*p*l*t)/s (обозначения такие же: Q — количество теплоты в джоулях, I — сила тока в амперах, t — время в секундах, р — удельное сопротивление материала проводника в омах на метр, l — длина проводника в метрах, s — площадь поперечного сечения проводника в квадратных сантиметрах). Однако в реальности мы значительно чаще имеем дело с электрическими системами, в которых измерению и контролируемому изменению поддается именно напряжение, а не сила тока.

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

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

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

Для помещения на форму элемента управления достаточно перетащить его с "Панели элементов" на форму.

Вот что может у вас получиться — рис. 6.3.



Рис. 6.3. Форма нашей программы.


Поля ввода параметров имеют имена "TextBox1"… "TextBox5" соответственно (такие имена по умолчанию задаются автоматически при создании полей), поле отображения результата имеет имя "TextBox6", кнопки имеют имена "CornmandButton1" и "CommandButton2" сверху вниз соответственно. В элементы "TextBox1"…"TextBox5" пользователь будет вводить текст. Желательно установить свойство Locked элемента "TextBox6" как "True" (рис. 6.4), чтобы не допустить случайного ввода пользователем в него текста — к сбою это не приведет, но вызовет неудобство для пользователя, так как при подсчете результата этот текст придется удалить.



Рис. 6.4. Установка свойства Locked элемента "TextBox6" как "True".


Разработка дизайна программы — ответственный момент, но не менее важным является обдумывание принципов работы программы. Помните, что исправление ошибки на стадии проектировки программы в несколько раз легче ее исправления на стадии реализации, в десятки раз легче, чем на стадии распространения, и в сотни раз легче, чем на стадии внедрения. Можно сделать, например, так: пользователь вводит все значения, нажимает кнопку "Подсчитать" (надо будет добавить на форму…), и ему в окне результата он выдается. Но в этом случае пользователь вынужден выполнять лишнее действие — нажатие на кнопку. Кроме того, так как обязательно надо продумать систему защиты от неправильных действий пользователя (например, нельзя допускать ввод нулевых или нечисловых значений в поля "TextBox4" и "TextBox5"), то при использовании данного способа подсчета придется либо выдавать при неправильном вводе сообщение об этом, либо, что представляется более красивым, ставить в эти поля значения по умолчанию, как только пользователь сделает неправильный ввод и уберет курсор с поля ввода. Но… все же, как неудобно! Нажимать лишний раз кнопку, постоянно следить за тем, стоят ли в полях ввода именно нужные значения, а не значения по умолчанию (ведь можно при вводе и случайно задеть соседнюю клавишу), да и при программировании проблем будет предостаточно, — изволь предусмотреть все случаи, на каждый написать программу обработки именно этого случая… Не слишком ли много проблем? А может быть, надо просто получше подумать о проектировании программы?

Основной принцип такого проектирования — "сделай проще, но без ущерба функциям". Что нам надо? Чтобы был результат — отображался итог вычислений. Когда он может быть посчитан? Да когда определены все значения в полях ввода, и при этом два нижних значения (то есть "TextBox4" и "TextBox5") ненулевые. Так пусть результат в своем окне появляется тогда и только тогда, когда все эти условия выполнены. И пусть программа постоянно отслеживает ввод значений в поля ввода и, как только будут введены все пять значений, и последние два будут ненулевые, а остальные — числовые, отобразит результат. Но есть ли такая возможность у языка Visual Basic for Applications — отслеживать моменты ввода данных в поля ввода текста? А проверим! Откроем окно программного кода формы (из контекстного меню правой кнопки мыши нашей формы в Менеджере проектов выберем "Программа" — рис. 6.5) и из выпадающего списка в левом верхнем углу (рис. 6.6) выберем, например, "TextBox1".



Рис. 6.5. Так можно открыть окно программного кода формы.



Рис. 6.6. Выпадающий список в левом верхнем углу — навигатор по программам элементов формы.


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

Private Sub TextBoxl_Change ()

End Sub

"Change" — это по-английски "изменение". Код, написанный в этой части программы (часть эта называется "обработчик события "Change"), должен выполняться всякий раз при происхождении этого события. Можно предположить, что это событие происходит тогда, когда в поле ввода ввели какой-либо символ или удалили его оттуда. В этом случае это — именно то событие, которое нам надо. Но то ли? Проверим. Напишем-ка здесь строчку:

Private Sub TextBox1_Change ()

TextBox6. Text=TextBox1. Text

End Sub

Пусть для эксперимента при изменении текста в первом поле ввода произойдет изменение текста в поле отображения результата. Проверим, будет ли это работать, — нажмем F5 (запуск программы на выполнение) и введем текст в первое поле ввода.

Прекрасно — в поле отображения результата появляется тот же текст! Значит, событие "Change" — именно то, которое нам надо использовать в нашей программе, чтобы после каждого нового ввода данных пользователем проверять условия возможности отображения результата и отображать его в случае их выполнения. Ну, а если бы оно нам не подошло, то пришлось бы перебирать все остальные события из выпадающего списка вверху справа окна программного кода формы и для каждого проводить такое же исследование: помещать в обработчик этого события команду, выполняющую какое-либо действие и смотреть, будет ли она выполнена при вводе текста в первое поле ввода.

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

Переведем на язык Visual Basic for Applications условие возможности отображения результата. Во-первых, все значения полей ввода должны быть числовыми. В Visual Basic for Applications есть специальная функция для проверки того, является ли та или иная строка записью числа — IsNumeric Можно, например, найти ее описание в разделе "Поиск" Справочной системы по VBA из Microsoft Office 97 по словам "строковое выражение числовое значение" — рис. 6.7.



Рис. 6.7. Справка по функции IsNumeric в Microsoft Office 97.


(В Microsoft Office 2000/ХР информацию об этой функции так просто не получить, однако можно попробовать задать вопрос Мастеру ответов, например, так: "Does the expression a number?" — "Является ли это выражение числом?" В этом случае в перечне результатов поиска будет и справка по функции IsNumeric (рис. 6.8).



Рис. 6.8. Справка по функции IsNumeric в Microsoft Office ХР.


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

Ее (функцию IsNumeric) и используем. Ну, а для проверки отличия от нуля значений в последних двух полях ввода используем функцию "Val", которая переводит строковое выражение в числовое, если это строковое выражение содержит в своем начале цифры (или все состоит из них).

Итак, результат существует, если

IsNumeric (TextBox1. Text) = True And IsNumeric (TextBox2. Text) = True And IsNumeric (TextBox3.Text) = True And IsNumeric (TextBox4.Text) = True And IsNumeric (TextBox5. Text) = True And Not Val (TextBox4. Text) = 0 And Not Val (TextBox5. Text) = 0

В этом случае можно осуществить подсчет по формуле:

rez = ((Val (TextBox1. Text)^2) * Val (TextBox2. Text) * Val (TextBox3. Text))/(Val (TextBox4. Text) * Val (TextBox5. Text))

и отобразить его в поле вывода результата:

TextBox6. Text = Str $ (rez)

Функция Str делает преобразование, обратное тому, что производит Val — конвертирует числовое значение выражения в строковое, что позволяет этому значению в дальнейшем обрабатываться как строке.

(Функции Val и Str нужны "для самого VBA" — они, не производя никакого видимого действия, преобразуют ни что иное, как типы данных обрабатываемых ими переменных, — соответственно из строкового в числовой и из числового в строковый. Подробнее о типах данных — в четвертой главе.)

Теперь можно написать процедуру вычисления результата и вызовы ее из всех обработчиков событий "Change":

Private Sub TextBox1_Change ()

Scet End Sub

Private Sub TextBox2_Change ()

Scet End Sub

Private Sub TextBox3_Change ()

Scet End Sub

Private Sub TextBox4_Change ()

Scet End Sub

Private Sub TextBox5_Change ()

Scet End Sub

Private Sub Scet()

If IsNumeric (TextBox1. Text) = True And IsNumeric (TextBox2. Text) = True And IsNumeric (TextBox3. Text) = True And IsNumeric (TextBox4. Text) = True And IsNumeric (TextBox5. Text) = True And Not Val (TextBox4. Text) = 0 And Not Val (TextBox5. Text) = 0 Then rez = ((Val (TextBox1. Text) ^ 2) * Val (TextBox2. Text) * Val (TextBox3. Text)) / (Val (TextBox4. Text) * Val (TextBox5. Text))

TextBox6. Text = Str$ (rez)

Else

TextBox6. Text = " "

End If End Sub

В принципе программа уже почти закончена, но стоит еще разобраться с командными кнопками. Для кнопки "Отмена" обработчик события "Click" (то есть нажатия на кнопку) прост — выход из программы и выгрузка формы из памяти:

Private Sub CommandButton2_Click ()

Unload Me End Sub

Но у нас есть еще вторая кнопка — "Вставить результат в документ". А пусть она вставит в документ не просто значение результата, а фразу, содержащую как результат, так и введенные параметры! Это можно сделать командой

Selection. Text = "При прохождении тока напряжением в " + TextBox1. Text + " вольт по проводнику длиной " + TextBox4. Text + " метров, сечением " + TextBox3. Text + " кв. мм и удельным сопротивлением " + ТехtBox5. Text + " ом на метр за " + TextBox2. Text + " секунд выделится" + TextBox6. Text + " джоулей теплоты. "

Она сформирует фразу из значений полей ввода и вставит ее в активный документ. Проверим… так, действительно вставляет, но фраза остается выделенной. А значит, что следующая фраза, выведенная с помощью нашей программы, сотрет предыдущую. Надо посмотреть, нет ли в Visual Basic for Applications функции снятия выделения? Посмотрим по выпадающему меню после точки "Selection."… есть команда "Collapse" (то есть "Свернуть") — рис. 6.9.



Рис. 6.9. Список методов объекта Selection.


Из справки по ней (рис. 6.10) узнаем ее синтаксис:

Selection.Collapse Direction:=wdCollapseEnd.



Рис. 6.10. Справка по команде Collapse.


Эта команда убирает выделение и помещает курсор в его конец.

Можно также вставить текст в активный документ "Selection.TypeText Техt="Мой текст" (двоеточие после слова "Text" обязательно). Тогда в специальном снятии выделения со вставленного текста не будет необходимости, — оно будет автоматически сворачиваться к своему концу.

А если вдруг пользователь вызовет программу тогда, когда открытых документов в Word'e нет? Тогда ведь возникнет ошибка программы. Но этого легко избежать — надо просто проверить перед вставкой, есть ли открытые документы и, если нет, создать новый:

If Documents.Count = 0 Then Documents.Add

Осталась еще одна маленькая деталь. Кнопка "Вставить результат в документ" не должна работать, если результат вычислить нельзя (то есть поле "TextBox6" пусто). Как это сделать? Среди всего набора возможных свойств элемента "CommandButton" есть свойство "Enabled" (рис. 6.11) — если его установить как "False" (то есть "ложно"), то кнопка будет отображаться серым цветом и не будет реагировать на события (станет неактивной).



Рис. 6.11. Свойство Enabled элемента CommandButton.


Это свойство можно задать и программно — командой "CommandButton1.Enabled = False". Поставим в процедуру вычисления результата пару команд, активизирующих кнопку, когда результат вычисляется и вставка его в текст возможна, и инактивирующих ее в противном случае, а также зададим с самого начала в форме свойство "Enabled" этой кнопки как "False", — чтобы она была неактивной с самого начала, до того, как в какое-либо окно ввода будут вводиться символы и начнет срабатывать процедура вычисления результата с командами задания состояния кнопки.

Вот готовый код нашей программы:

Private Sub CommandButtonl_Click ()

If Documents.Count = 0 Then Documents.Add

Selection. Text = "При прохождении тока напряжением в " + TextBox1. Text + " вольт по проводнику длиной " + TextBox4. Text + " метров, сечением " + TextBox3. Text + " кв. мм и удельным сопротивлением " + ТехtBox5. Text + " ом на метр за " + TextBox2. Text + " секунд выделится" + TextBox6. Text + " джоулей теплоты. "

Selection.Collapse Direction:=wdCollapseEnd

End Sub

Private Sub CommandButton2_Click ()

Unload Me End Sub

Private Sub TextBox1_Change ()

Scet End Sub

Private Sub TextBox2_Change ()

Scet End Sub

Private Sub TextBox3_Change ()

Scet End Sub

Private Sub TextBox4_Change ()

Scet End Sub

Private Sub TextBox5_Change ()

Scet End Sub

Private Sub Scet()

If IsNumeric (TextBox1. Text) = True And IsNumeric (TextBox2. Text) = True And IsNumeric (TextBox3. Text) = True And IsNumeric (TextBox4. Text) = True And IsNumeric (TextBox5. Text) = True And Not Val (TextBox4. Text) = 0 And Not Val (TextBox5. Text) = 0 Then

rez = ((Val (TextBox1. Text) ^ 2) * Val (TextBox2. Text) * Val (TextBox3. Text)) / (Val (TextBox4. Text) * Val (TextBox5. Text))

TextBox6. Text = Str$ (rez)

CommandButtonl.Enabled = True Else

TextBox6. Text = " "

CommandButton1.Enabled = False

End If

End Sub

Назначить форме кнопку или пункт меню для вызова из Word нельзя, — это возможно только для модулей. Поэтому переименуем для красоты форму в "Teplotok", например (свойство "Name" объекта "UserForm" — можно задать в окне свойств, выделив форму) и напишем модуль, в котором будет всего одна команда — вызов созданной нами формы:

Sub TeploCount()

Teplotok.Show

End Sub

Зададим модулю красивое имя ("Teplo", например, через свойство "Name" объекта "Модуль1" (рис. 6.12), если модуль для программы вызова формы был вставлен с помощью пункта "Вставить — Модуль" контекстного меню правой кнопки мыши в Менеджере проектов) и назначим в Word кнопку для вызова макроса "Normal.Teplo.TeploCount". Вот и все — наша программа готова (рис. 6.13).



Рис. 6.12. Задание модулю нужного имени.



Рис. 6.13. Окно готовой программы.


Теперь ее можно вызывать на выполнение соответствующей кнопкой. При желании можно скопировать форму и модуль в отдельный шаблон и создать в нем панель инструментов с кнопкой вызова макроса, — тогда программу можно будет установить и на другие компьютеры, скопировав шаблон с макросом в папку автозагружаемых файлов Word.


ОКОНЧАТЕЛЬНАЯ ДОРАБОТКА

Когда программа написана и отлажена, необходимо придать ей "товарный вид" — сделать так, чтобы использовать ее было удобно и просто, а установка не требовала от пользователя каких-либо невероятных усилий. Кроме того, весьма желательно максимально сократить размер установочного комплекта, — наверняка большинство пользователей будут загружать программу через Интернет, так что стоит позаботиться об их времени и деньгах.

Ниже будут описаны некоторые действия, которые весьма желательно проделать перед тем, как выставлять свое творение на всеобщее обозрение. Как и прежде, в качестве основной платформы для разработки рассматривается Microsoft Word, поэтому все нижеизложенное относится к программам, разработанными именно для этого текстового редактора, если не указано иное.

Для начала надо решить, в каком формате программу стоит оформить — как простой шаблон Word, на основе которого можно создавать документы, как шаблон Word, загружаемый автоматически при запуске Word'а или как простой документ.

1. Если программа предназначена для одномоментных нечасто используемых расчетов или действий и не работает с текстом документа, то ее проще всего поместить в документ Word — с расширением".doc". При необходимости его можно будет открыть и выполнить программу. Например, очень хорошо в качестве отдельного документа сделать инсталлятор программы.

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

3. Если же программа выполняет какие-нибудь серьезные операции с текстом, постоянно требуется пользователю или работает с многими документами сразу, то тогда ей прямая дорога в папку автозагружаемых файлов Word. Формат файла, помещаемого в эту папку — шаблон документа (и только он).

Потом необходимо создать документ с программой. Лучше всего поступить так — создать пустой документ необходимого формата — шаблон или простой файл Word, а затем с помощью диалогового окна Word "Организатор" ("Сервис — Макрос

— Макросы — Организатор" или "Сервис — Шаблоны и надстройки — Организатор") скопировать в него все готовые компоненты программы из шаблона или документа, где велась разработка (обычно это Normal.dot), и сохранить под каким-нибудь красивым именем. В этом случае в полученном файле будут присутствовать только компоненты программы, что послужит к уменьшению его размера.

Если разработка программы велась в каком-либо отдельном шаблоне или документе, то можно просто убрать из файла, содержащего ее, лишние модули (которые могли там оказаться, например, в процессе экспериментирования с командами Visual Basic for Applications), почистить компоненты самой программы — удалить закомментированные ненужные команды, излишние комментарии.

Ну и, наконец, следует сделать способ вызова программы. Без этого даже с очень хорошо написанной программой сможет работать лишь ее создатель, да и то не всегда. К тому же красивая обложка всегда радует глаз. Можно с помощью диалогового окна "Сервис — Настройка — Команды — Макросы" назначить макросу пункт меню или кнопку на стандартной панели путем простого перетаскивания. Можно там же назначить ему комбинацию клавиш для вызова. А можно, что считается лучшим вариантом, создать новую панель инструментов и уже на ней поместить кнопки для вызова макросов. Надо только сохранить все изменения именно в документе или шаблоне с макросами, а не в своем Normal.dot или где-нибудь еще.

В окне "Сервис — Настройка — Команды — Макросы" (рис. 7.1) название каждого макроса отображается так: сначала пишется имя проекта, затем — имя его модуля (можно изменить в окне свойств, выделив мышью название модуля), а затем — собственно имя макроса (то, что стоит после команды начала программы Sub).



Рис. 7.1. Список макросов, которым можно назначить кнопки.


Название проекта можно задать с помощью команды "Свойства" (в англоязычных версиях — Project Properties) контекстного меню этого названия (рис. 7.2), а также через Окно свойств (рис. 7.3), предварительно выделив прежнее название проекта.



Рис. 7.2. Изменение имени проекта через пункт меню "Свойства проекта".



Рис. 7.3. Изменение имени проекта через Окно свойств.


По умолчанию каждому новому проекту дается название TemplateProject (если этот проект содержится в шаблоне) или просто Project (если этот проект содержится в документе Word). Проект, содержащийся в шаблоне Normal.dot, по умолчанию так и называется — Normal.

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

Имя проекта может содержать как русские, так и английские символы, но не должно иметь пробелов — при попытке задания проекту имени с пробелами будет выдано предупреждение (рис. 7.4).



Рис. 7.4. Пробелы в имени проекта недопустимы — иначе будет ошибка.


Назначить кнопку или сочетание клавиш для вызова формы невозможно. Необходимо вставить команду вызова формы ("ИмяФормы. Show") в текст программы в модуле, и уже затем назначить кнопку или сочетание клавиш для вызова именно этой программы.

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

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

Впрочем, всплывающие подсказки кнопок можно задать самостоятельно с помощью команды "CommandBars("Имя панели").Controls("Номер иконки на панели").TooltipText = "Текст подсказки"". К сожалению, через диалоговое окно настройки панелей и кнопок сделать это не удастся, поэтому для ввода этой команды придется использовать отдельный модуль или Окно отладки.

Вам может не понравиться весьма ограниченный выбор значков для кнопок, предлагаемый Word'ом. Этот набор, вызываемый из меню "Выбрать значок для кнопки" в режиме настройки панелей, действительно, маловат. Но никто не мешает с помощью других команд того же меню скопировать значок с любой другой кнопки на любой другой панели или создать его самому во встроенном редакторе изображений на кнопках (рис. 7.5).



Рис. 7.5. Редактор кнопок. Не забывайте про него!


Кроме того, красивые значки можно извлечь из "недр" Office, — а он содержит в себе около двух тысяч разнообразных значков. Для этого достаточно ввести в Окне отладки команды

Set dd = ActiveDocument.CommandBars.Add("Panel")

CommandBars("Panel").Controls.Add(Type:=msoControlButton, ID:=797).Faceld = x

где x — любое число от 1 до 3000. Тогда на указанной в команде панели — с именем "Panel" — будет создана кнопка со значком, который можно скопировать на свою кнопку. Не для всех кодов существуют значки, поэтому иногда созданная таким образом кнопка будет пустой, — попробуйте еще раз с другим х[235]. Параметр Id, упоминаемый в команде, задает то действие, которое должно быть выполнено при нажатии на создаваемую кнопку, в данном случае — открытие диалогового окна "Настройка".

Весьма желательно для программного добавления своих кнопок использовать создаваемые отдельно панели инструментов, так как работать со стандартными, исходно входящими в состав Word'а панелями иногда не удается, в частности, из-за того, что в локализованных версиях Microsoft Office, в том числе и в русской, отображаемые и истинные их имена не совпадают[236].

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

Довольно много полезных приемов работы с панелями инструментов, кнопками на них — создание, копирование, удаление — реализованы в наборе макросов "Saveln" (есть на прилагаемом к книге компакт-диске, а также доступен через Сеть с адреса http://antorlov.chat.ru/savein.htm).

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

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

Не стоит забывать и об информативном руководстве для пользователя, особенно если программа будет распространяться через Интернет. Лучше всего такое руководство оформить в отдельном текстовом файле или, если оно имеет большой объем, в виде набора связанных html-документов.

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

Создание инсталлятора для программы — отдельная большая тема, выходящая за рамки данной книги. Для начала можно посоветовать обходиться вообще без него (просто указывая в документации к программе, что файл с ней, например, нужно скопировать в папку автозагружаемых файлов Word) или использовать уже готовые инсталляторы, — например, из разработок "Untaco", "ВерсткаТекстаКнижкой", про которые рассказывается в 9-й главе, модифицируя их под свои нужды.


НЕМНОГО О ПАНЕЛЯХ, ШАБЛОНАХ И МАКРОСАХ

Панель инструментов Microsoft Word 97/2000/ХР, то есть ее название, имена, рисунки, всплывающие подсказки кнопок, расположенных на ней, информация о связи этих кнопок с командами и макросами может храниться либо в шаблоне Microsoft Word 97/2000/ХР (с расширением. dot), либо в документе Word (с расширением. doc). При этом имеет место быть следующее:

1. Если панель инструментов сохранена в шаблоне Normal.dot, то она доступна всегда, когда открыт Word.

2. Если панель инструментов сохранена в шаблоне, который загружен как глобальный — то есть помещен в папку автозагружаемых файлов Word, то она также доступна всегда, когда открыт Word, но ее можно убрать, выгрузив шаблон с помощью диалогового окна "Сервис — Шаблоны и надстройки" (или удалив шаблон из папки автозагружаемых файлов). Местонахождение папки автозагружаемых файлов можно посмотреть в окне "Сервис — Параметры — Расположение" (рис. 7.6). Для Word97 это обычно папка..\Microsoft Office\Office\Startup, а для Word2000/XP по умолчанию назначается папка C: \Windows\Application Data\Microsoft\Word\Startup, однако эти пути всегда можно поменять на более удобные.



Рис. 7.6. В этом окне можно посмотреть расположение папки автозагружаемых файлов.


3. Если панель инструментов сохранена в шаблоне, на котором основаны документы, например, в одном из шаблонов, находящихся в папке шаблонов пользователя Word (посмотреть можно там же, для Word97 по умолчанию назначается папка..\Microsoft Office\Offiсе\Шаблоны, а для Word2000 — С: \Windows\Application Data\Microsof\Шаблоны) и ее подпапках, то она доступна тогда, когда этот шаблон присутствует на компьютере и активен документ, созданный на его основе. (Если документ просто открыт в Word, но неактивен, то панель инструментов все равно не видна.)

4. Если панель инструментов сохранена в каком-либо документе, то она доступна тогда, когда активен этот документ.

Панели инструментов можно копировать из одного шаблона или документа в другой с помощью диалогового окна "Организатор" (рис. 7.7).



Рис. 7.7. Диалоговое окно "Организатор". С его помощью можно копировать панели инструментов из одного шаблона в другой.


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

С макросами, которым назначены кнопки на панелях, дело обстоит так.

Каждой кнопке панели инструментов, вызывающей макрос, ставится в соответствие имя вызываемого ею макроса, которое состоит из имени модуля, содержащего этот макрос, и имени самого этого макроса в модуле. Узнать имена модуля и макроса в модуле можно в редакторе VBA (рис. 7.8).



Рис. 7.8. Выделено название макроса DocsMerger в модуле UniterDocs.


При изменении хотя бы одного компонента имени кнопка становится неработоспособной. Всплывающая подсказка на кнопке, возникающая по умолчанию, совпадает с именем макроса в модуле, причем в случае, если имя макроса было составлено из двух-трех слов, начинающихся с большой буквы, например, "UniterDocs", то в подсказке эти слова разделяются пробелом (рис. 7.9).



Рис. 7.9. Всплывающая подсказка на кнопке вызова макроса. Обратите внимание на возникшие в ней пробелы.


Несмотря на то, что при создании кнопки путем перетаскивания пиктограммы, изображающей макрос, на какую-нибудь панель инструментов, в тексте, сопровождающем эту пиктограмму, указывается, в каком проекте макрос находится, этот параметр Word'ом не учитывается. Поэтому имеет место быть следующее, — если в глобально загруженном шаблоне (то есть помещенном в папку автозагружаемых файлов Word) есть макрос с таким же названием и именем, что и в Normal.dot, то при нажатии кнопки, вызывающей этот макрос (расположенной на любой панели), выполняется макрос из Normal.dot, а не из глобального шаблона.

Если при запуске Word в папке Шаблоны не оказывается шаблона Normal.dot, то он создается самим Word'ом на основании стандартов по умолчанию. В него помещается изначальный набор панелей инструментов.

Поиск модуля и имени макроса при нажатии кнопки (при этом не имеет значения, где панель сохранена) идет в следующем порядке: "Активный документ" — "Шаблон, на котором основан документ" — "Normal.dot" — "Шаблон, загруженный глобально через папку автозагружаемых файлов Word или окно "Шаблоны и надстройки".

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


А КАК В EXCEL?

В Microsoft Excel макросы могут храниться в книгах Excel, содержась как в отдельных модулях, так и в программной части листов книг и книги в целом.

Для вызова макроса можно использовать сочетание клавиш, пункт меню или кнопку на панели инструментов.

Создать панель инструментов можно в диалоговом окне "Сервис — Настройка — Панели инструментов". Для создания кнопки на панели инструментов, вызывающей макрос, следует открыть окно "Сервис — Настройка — Команды — Макросы" (рис. 7.10), и, перетащив иконку "Настраиваемая кнопка" на какую-либо панель инструментов, выбрать из ее контекстного меню пункт "Назначить макрос" (рис. 7.11), а в появившемся окне (рис. 7.12) выбрать тот макрос, который следует кнопке назначить.



Рис. 7.10. Excel ХР. Окно средств настройки интерфейса



Рис. 7.11. Нажмите здесь, чтобы назначить кнопке макрос.



Рис. 7.12. …и этот макрос выберите…



Рис. 7.13. А так можно назначить макросу пункт меню.


Панели инструментов могут храниться как в книгах, так и в файле настроек Excel с расширением. xlb. В зависимости от версии Microsoft Office этот файл находится либо в системном каталоге, либо в специальной папке в разделе пользовательских настроек (например, в Windows2000 это папка D: \Documents and Settings\Администратор\Application Data\Microsoft\Excel), имя же этого файла соответствует имени пользователя Windows в сочетании с версией Excel'а.

Создать панель инструментов можно только в файле настроек Excel — с помощью диалогового окна "Сервис — Настройка — Панели инструментов". Однако если необходимо, чтобы панель инструментов хранилась в книге Excel, ее следует туда скопировать с помощью диалогового окна "Вложить" (открывается при нажатии кнопки "Вложить" в диалоговом окне "Сервис — Настройка — Панели инструментов"), см. рис. 7.14.



Рис. 7.14. Окно копирования панелей инструментов в книги.


При работе с панелями инструментов в Excel имеет быть следующее.

1. Скопированная в книгу панель инструментов изменяться не может. Все изменения, вносимые в отображаемую на экране панель инструментов, делаются в той панели, которая хранится в файле настроек Excel. Чтобы эти изменения были перенесены в панель инструментов, находящуюся в книге, необходимо ее заново туда скопировать с помощью диалогового окна "Сервис — Настройка — Панели инструментов — Вложить", предварительно удалив старые.

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

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

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

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

Если вы переместили в другую папку файл с макросами, вызываемыми кнопками на скопированной в файл настроек Excel панели инструментов, то просто удалите эту панель из файла настроек Excel с помощью диалогового окна "Сервис — Настройка — Панели инструментов", а затем откройте и закройте книгу с макросами, находящуюся уже на новом месте. Excel заново скопирует панель инструментов в свой файл настроек и укажет в параметрах кнопок уже новый путь к файлу с макросами[237].

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

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

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

В Excel можно также создавать особые формы файлов, содержащих программный код — надстройки. Но рассказ о них выходит за рамки нашей книги.


ЦИФРОВАЯ ПОДПИСЬ

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

Однако при постоянной работе с файлами, содержащими программы на Visual Basic for Applications, постоянно появляющееся диалоговое окно с предупреждением изрядно надоедает. Возникает желание, чтобы документы, созданные каким-то одним человеком (или группой лиц), открывались без запроса о запуске в них макросов, а при открытии всех остальных диалоговое окно по-прежнему отображалось. И как раз вот для таких случаев и был создан механизм цифровой подписи.

Цифровая подпись — это небольшой набор данных (около килобайта), который можно прикрепить к проекту на Visual Basic for Applications для того, чтобы пользователи этого проекта могли запускать макросы из него без появления утомительного диалога о необходимости запуска макросов при открытии файла с проектом. Иными словами, цифровая подпись является механизмом снятия защиты от вирусов в макросах только при работе с тем документом, который эту подпись имеет.

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

Возможность добавлять цифровую подпись (и, соответственно, использовать ее для запрета появления диалога о запуске макросов при работе с каким-либо файлом с программами на Visual Basic for Applications) появилась в Microsoft Office начиная с 2000-й его версии.

После того, как вы завершили работу над своей программой на Visual Basic for Applications и оформили ее в виде отдельного проекта (для Word — шаблона или документа, для Excel — книги и т. д.), вы можете добавить к нему цифровую подпись. Чтобы это сделать, необходимо в каталоге, куда установлен Office, запустить файл Selfsert.exe (рис. 7.15).



Рис. 7.15. Вот этот файл генерирует электронную подпись.


(Этот файл копируется на компьютер только в том случае, если при установке Microsoft Office был выбран также и пункт "Цифровая подпись для проектов VBA". Если этого сделано не было, то для использования программы Selfsert, возможно, потребуется снова запустить программу установки Microsoft Office в режиме добавления и удаления компонентов пакета.)

Программа пригласит ввести имя (рис. 7.16). Именно это имя потом будет отображаться при установке проекта с цифровой подписью на компьютер другого пользователя.



Рис. 7.16. Генерация цифровой подписи.


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



Рис. 7.17. Файлы сертификатов.


Сразу с момента создания новый сертификат с цифровой подписью можно использовать. Например, чтобы подписать им новый проект на Visual Basic for Applications, необходимо выделить какой-либо компонент подписываемого проекта (например, его название), а затем выбрать из пункта меню "Tools" Редактора VBA пункт "Digital Signature" (рис. 7.18) и в появившемся диалоговом окне "Цифровая подпись" для выбора сертификата следует нажать одноименную кнопку.



Рис. 7.18. Прикрепление электронной подписи.


В открывшемся диалоговом окне (рис. 7.19) можно выбрать прикрепляемый сертификат. Вы можете создать множество сертификатов с разными именами, и тогда в данном окне выбор будет больше, чем на рисунке.



Рис. 7.19. Выбор сертификата для прикрепления.


О том, какой сертификат прикреплен к тому или иному файлу (и прикреплен ли вообще), вы можете узнать в диалоговом окне "Цифровая подпись", вызываемом пунктом меню "Tools — Digital Signature", — том же самом, что используется для прикрепления сертификата (рис. 7.18).

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

* * *

Когда пользователь откроет файл, подписанный сертификатом, ему будет выдано сообщение об этом (рис. 7.20).



Рис. 7.20. Запрос при открытии файла с макросами и сертификатом.


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

Посмотреть список цифровых подписей, файлы с которыми признаны достойными открытия без запросов, можно в диалоговом окне "Сервис — Макросы Безопасность", на его вкладке "Надежные источники" (рис. 7.21). Все установленные сертификаты (т. е. те, в при открытии документов с которыми был отмечен пункт "Всегда доверять макросам из этого источника"), будут там перечислены. При необходимости можно удалить ненужные.



Рис. 7.21. Список установленных сертификатов.


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

Цифровую подпись нельзя применять для аутентификации проектов на Visual Basic for Applications по имени или еще каким-либо данным ее создателя, то есть для стопроцентного уверения пользователя, что автор макросов в открываемом им файле именно тот, чье имя высвечивается в диалоговом окне подтверждения разрешения на использование макросов, — в программу Selfsert можно ввести любое имя, в том числе и используемое каким-либо другим автором VBA-программ, и доказать, что новый сертификат был создан не реальным владельцем этого имени, будет нельзя. Для того, чтобы это сделать все-таки было можно, необходимо получить сертификат в компании Verisign, которая как раз и занимается созданием сертификатов, уникальных для каждого ее клиента, или другой ей подобной (адреса приводятся в Справочной системе Microsoft Office в разделе "Цифровые подписи"). Кроме того, не поддающиеся подделке сертификаты можно создавать с помощью программы Microsoft Certificate Server).

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

Для установки сертификата в диалоговом окне запроса о необходимости разрешения использования макросов следует нажать кнопку "Настройка" (см. рис. 7.20), а в открывшемся окне (рис. 7.22) — кнопку "Просмотр сертификата".



Рис. 7.22. Ручная установка сертификата. Очередной шаг.


В окне информации о сертификате, которое откроется после нажатия этой кнопки, следует нажать следующую кнопку — "Установить сертификат". Запустится мастер импорта сертификатов (рис. 7.23).



Рис. 7.23. Мастер импорта сертификатов.


Для прохождения мастера достаточно во всех его диалоговых окнах нажимать кнопку "Далее…" или "Готово". Появление сообщения с запросом (рис. 7.24) является окончанием процесса.



Рис. 7.24. Ручная установка сертификата. Последний запрос.


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

* * *

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

Для добавления электронной подписи, например, к файлу Word следует открыть вкладку "Безопасность" диалогового окна "Сервис — Параметры" и нажать кнопку

"Цифровые подписи". Добавление цифровой подписи к документу осуществляется (как это ни странно!) кнопкой "Добавить" в открывающемся по нажатию предыдущей кнопки окне (рис. 7.25).



Рис. 7.25. Подписывание файла Word.


Используйте цифровую подпись, если вы желаете гарантировать неизменность передаваемых вами другим пользователям файлов, но не стремитесь запретить их им редактировать.


ПОЛЕЗНЫЕ СОВЕТЫ

В этой главе вы найдете набор советов по программированию на VBA, которые могут помочь вам в решении тех или иных задач. Кроме того, в конце главы есть несколько заметок на различные темы, связанные с программированием на Visual Basic for Applications.

* * *

Настройки программы можно сохранять в системном реестре Windows. Для этого служит команда "SaveSetting", с помощью которой можно поместить в системный реестр строку или число. Она имеет формат "SaveSetting "Имя приложения","Имя раздела", "Ключ", "Значение"". Имя приложения, имя раздела и ключ — указатели места, в котором сохраняется значение. Получить значения из реестра можно командой "GetSetting" с синтаксисом "GetSetting "Имя приложения","Имя раздела", "Ключ", "То значение, которое следует вернуть, если такого ключа, как указанный в предыдущем параметре, в реестре нет"", а удалить — командой "DeleteSetting "Имя приложения","Имя раздела", "Ключ"". Например:

SaveSetting "Макросы", "Макрос1", "Имя папки", "C: \MyPapka"

papka = GetSetting "Макросы", "Макрос1", "Имя папки", "C: \Docs"

* * *

Записать список всех установленных в системе шрифтов в массив можно таким способом:

ReDim shrifti(FontNames.Count) As String

For r = 1 To FontNames.Count shrifti(r) = FontNames(r)

Next r

WordBasic.SortArray shrifti()

(В массив "shrifti()" размером в количество шрифтов в системе помещается список имен всех установленных в системе шрифтов. Команда "WordBasic.SortArray" сортирует его по алфавиту.)

* * *

Условие "If Selection. Type = wdSelectionIP Then…" выполнится, только если в документе не выделен фрагмент текста.

* * *

Если вы решили хранить какую-нибудь информацию, нужную при работе программы, в отдельном файле, не стоит экспериментировать с командами чтения и открытия файла типа "open", "write" и др. Просто открывайте файл в Word как текстовый с помощью команды "Documents. Open…" и пишите в него обычными средствами записи текста: "Selection.Text = "Мой текст"".

* * *

Посмотрите повнимательнее свойства, объекты и методы таких объектов, как "Application" и "System" (для этого достаточно набрать название объекта и поставить после него точку, — список возможных продолжений отобразится сам — рис. 8.1). Среди них можно найти немало весьма интересных и полезных, вроде средства задания и получения значений ширины и высоты окна Word, информации о языке данной версии Office, метод чтения данных из произвольного места реестра и многое другое.



Рис. 8.1. Свойства и методы объекта System — склад весьма интересных вещей….


Вот некоторые полезные свойства объекта Application.

Application.CapsLock — показывает, горит ли на клавиатуре индикатор CapsLock.

Application.NumLock — показывает, горит ли на клавиатуре индикатор NumLock.

Application.Caption — сообщает заголовок окон запущенной программы (для Word, например, это — "Microsoft Word"). Этот заголовок можно поменять: так, команда "Application.Caption = "Мой Word"" заменит традиционный заголовок окна Word'а на тот текст, что указан в скобках.

Application.DisplaystatusBar — сообщает, отображается ли статусная строка. С помощью этого свойства можно и убрать ее, и снова восстановить — командами Application.DisplayStatusBar=False и Application.DisplaystatusBar=True соответственно.

Application.EnableCancelKey — в случае установки в True запущенный макрос нельзя будет прервать нажатием Ctrl+Break.

Application.Height и Application.Widht — возвращают соответственно высоту и ширину окна приложения. С помощью этих свойств можно и задать размеры окна приложения, скажем, расширить окно Word до нужной ширины.

Application.РаthSeparator — возвращает символ, служащий разделителем имен папок в полном пути к файлу. В MS-DOS и Windows это "\", а в операционных системах, применяемых на компьютерах Macintosh — ":". Использование данного свойства может пригодиться при разработке мультиплатформенных программ — работающих как в Microsoft Office for Windows, так и в Microsoft Office for Macintosh.

Application.Version — сообщает версию приложения. Например, такая команда, будучи вызванной в Microsoft Word 97, вернет "8.0" или "8.0а", в Microsoft Word 2000 — "9.0", в Microsoft Word ХР — "10.0".

А вот некоторые интересные методы этого объекта:

a=Application.CleanString (строковая переменная) — очищает строку, находящуюся в строковой переменной, от неотображаемых специальных символов;

Application.OnTime — позволяет запустить тот или иной макрос в назначенное время или спустя некоторый срок после выполнения данной команды. О параметрах использования рассказано в Справочной системе VBA, там же приведены и примеры.

* * *

С помощью фрагмента кода

Set MyData = New DataObject

MyData.SetText "Мой текст"

MyData.PutlnClipboard

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

* * *

С помощью команды "Options.DefaultFilePath("константа названия папки")" можно получить пути и имена папок, перечисленных в диалоговом окне Word "Сервис — Параметры — Расположение". Все константы перечислены в справке VBA по слову "DefaultFilePath" (рис. 8.2), а об их значении можно легко догадаться, переведя название константы с английского языка.



Рис. 8.2. Пути и папки. Справка.

* * *

Если у одного из элементов формы установить свойство Cancel в True, то нажатие кнопки Esc будет эквивалентно клику мыши на этом элементе.

* * *

Если вы пишете инсталлятор для ваших программ, который помещает шаблоны с макросами в папку автозагружаемых файлов Word, то совсем необязательно требовать перезагрузки редактора, чтобы макросы из помещенного в эту папку шаблона стали доступны. VBA позволяет активизировать такие шаблоны без перезагрузки Microsoft Word — для этого существует специальная команда Addins.Add("полное имя шаблона, включая путь к нему и расширение").Installed = True

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

Предотвратить подобную ситуацию можно, например, с помощью следующей конструкции, — разместите ее после команды копирования шаблона "FileCopy":

а="Имя шаблона в папке автозагрузки с полным указанием пути"

On Error Resume Next

Do

If Addins(a).Installed Then Exit Do

Addins(a).Installed = True

Loop[238]

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

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

* * *

Для удаления шаблона без выгрузки Word можно использовать такой же код:

а="Имя шаблона в папке автозагрузки с указанием пути"

On Error Resume Next

Do

If Not Addins(a).Installed Then Exit Do

Addins(a).Installed = False

Loop

Addins (a).Delete

Kill (a)

Команда "Kill" выполняет удаление файла.

* * *

Команда "On Error Resume Next", встречающаяся в обоих вышеприведенных фрагментах кода — это обработчик ошибок. В случае возникновения ошибки в коде после него (скажем, связанной с обращением к несуществующему объекту) он продолжит выполнение программы с команды, следующей за вызвавшей ошибку. Обработчик ошибок может также иметь вид "On Error GoTo метка", и тогда при ошибке в коде после него произойдет переход к указанной в обработчике метке и выполнение программы продолжится именно с нее.

* * *

Если вы, работая в Word 97, часто сохраняете документы в формате HTML, и вам мешает постоянно появляющийся диалог о выборе кодировки файла (рис. 8.3), то отключите его, установив в системном реестре строковый параметр "HKEY_LOCAL_MACHINE\Software\Microsoft\Shared Tools\ Text Converters\Export\HTML\Options\Show EncodingDialog" как "No" (рис. 8.4). Установить этот параметр реестра можно и программно с помощью команды "System.PrivateProfileString("", "HKEY_LOCAL_MACHINE\Software\Microsoft\Shared Tools\Text Converters\Export\HTML\Options", "ShowEncodingDialog") = "No""



Рис. 8.3. Надоевший диалог в Microsoft Word 97…



Рис. 8.4убирается здесь…

* * *

Если Вы закрыли исходный код Вашей программы на VBA от просмотра паролем, а потом благополучно его забыли — не огорчайтесь: в Интернете, по адресу www.passwords.ru есть программа AVPR, позволяющая восстановить забытый Вами пароль. Ее английская версия требует оплаты и регистрации, а русская бесплатная (есть на прилагаемом к книге компакт-диске). К сожалению, бесплатная версия работает только с файлами, созданными в Word и Excel из Microsoft Office 97.

* * *

Чтобы ускорить работу программы, работающей с текстом, поставьте в ее начале команду "Application.ScreenUpdating = False", а в ее конец — команду "Application.ScreenUpdating = True", если только в процессе работы программы не требуется визуальный контроль происходящих изменений. Эта команда позволяет системе не тратить время и силы на постоянное обновление экрана и отображение изменений. Для того, чтобы все же обновить экран после отключения обновления экрана, используйте команду "Application.ScreenRefresh".

* * *

Для получения от пользователя определенных данных, кроме создания форм, можно использовать встроенные диалоги VBA — диалоговое окно "Открытие файла", "Свойства документа" и др. Они вызываются командой Dialogs("Название диалога").Show (показывает диалог и выполняет соответствующие ему действия), Dialogs("Название диалога").Display (только показывает диалог и позволяет записать в переменные введенные изменения, но не выполняет никаких действий и ничего не изменяет: очень полезно для использования встроенных диалоговых окон в своих целях), Dialogs("Название диалога").Execute (ничего не отображает на экране, но применяет все те изменения, которые были сделаны ранее с помощью команды With Dialogs ("Название диалога")… End With). Для вывода списка возможных диалогов наберите "Dialogs(", и Вам будет выдан их список. К сожалению, описания конкретных диалогов нет в справке — придется просто попробовать отобразить каждый, хотя список возможных параметров каждого диалога в справке есть.

В Microsoft Excel набора встроенных диалогов нет, однако отобразить на экране окна открытия и сохранения файлов все же можно. Для этого служат команды "Application.GetOpenFilename" и "Application.GetSaveAsFilename". В результате выполнения команды "file = Application.GetOpenFilename" будет отображено окно открытия файла, а после выбора имя файла поместится в переменную (Здесь — "file"). Команда же "rez = Application.GetSaveAsFilename" отобразит окно сохранения файла, в переменную же (здесь — rez) будет помещено True — если сохранение успешно, и False — если нет. Обе команды допускают указание параметров (например, меняющих заголовки окна и других).

* * *

Помимо привычных кнопок и выпадающих меню в Word существует еще несколько типов элементов вызова команд и программ — поля ввода и выпадающие меню выбора. К примеру, элемент "Выпадающее меню с полем ввода" используется для указания масштаба просмотра документа на панели "Стандартная" или для ввода вопроса к справочной системе в OfficeXP (рис. 8.5).



Рис. 8.5. Выпадающее меню с полем ввода.


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

CommandBars(х).Controls.Add Туре:=у

где "х" — номер панели (можно узнать, просто перебрав их все с помощью команды "MsgBox CommandBars(номер).Name" и выяснив, какой номер имеет панель инструментов с нужным названием), а "у" — одна из констант: "msoControlEdit", "msoControlDropdown", "msoControlComboBox", создающие соответственно поле ввода текста, выпадающее меню и выпадающее меню с возможностью ввода текста.

Управлять созданными полями, добавляя, к примеру, в них текст, можно стандартными командами работы с панелями инструментов. Так, чтобы поместить какой-либо текст в поле ввода, следует использовать команду

CommandBars(х).Controls(у).Text = "текст в поле ввода"

где "х" — номер панели, "у" — номер по счету слева направо данного поля среди кнопок этой панели. Таким образом можно использовать эти элементы для отображения нужной пользователю информации. Точно так же — командой "a=CommandBars(х).Controls(у).Text" можно считать информацию из данного поля и использовать ее в работе программы. Следует лишь внимательно следить за соответствием номеров кнопок их реальному расположению, — при изменении порядка кнопок программа может работать неверно. Назначить макрос кнопке, меню или полю ввода можно командой "CommandBars(х). Controls(у).OnAction = "Имя модуля. Имя программы"".

* * *

Если у вас на компьютере установлено несколько версий Microsoft Office, то вы наверняка сталкивались с одной весьма неприятной ситуацией. Все компоненты Microsoft Office, начиная с 2000-й версии, при каждом своем запуске сканируют системный реестр и перепрограммируют открытие файлов, которые должны ими открываться —.doc, xls — "на себя", заставляя их открываться именно в новой версии, а не в старой. Помимо того, что это занимает немало времени, подобная ситуация мешает использовать на компьютере сразу две версии Office, например, для того, чтобы, работая в старой, постепенно осваивая новую или, используя новую версию, не отказываться от возможностей, входящих только в предыдущую.

Для того, чтобы "отучить" Word2002 (из OfficeXP) перерегистрировать расширения файлов при каждом запуске, создайте в системном реестре, в разделе HKEY_CURRENT_USER\Software\Microsoft\0ffice\10.0\word\0ptions параметр NoRereg, имеющий формат Dword и равный 1, а чтобы сделать то же с Word2000, отредактируйте так же содержимое раздела HKEY_CURRENT_USER\Software\ Microsoft\Office\9.0\word\Options.


PROGRESSBAR В ВАШИХ ПРОГРАММАХ

Во многих программах для Windows используется такой элемент, как ProgressBar — индикатор, показывающий, на сколько продвинулся тот или иной процесс. В частности, он есть практически во всех программах-инсталляторах. К сожалению, в VBA этот элемент отсутствует, но его можно сделать самостоятельно!

Выглядеть он будет, например, так, как на рис. 8.6.



Рис. 8.6. ProgressBar в программе на VBA


А делается он следующим образом (предполагается, что у нас есть часть программы, в которой выполняется длинный и долгий цикл: то есть известное нам количество множество однотипных операций, и которую надо снабдить ProgressBar'ом):

1. Создаем небольшую форму и помещаем на нее: надпись с пояснительным текстом (например, "Label1") и две другие надписи, (скажем, "Label2" и "Label3"), низкие и широкие, которые расположим одну над другой (рис. 8.7).



Рис. 8.7. А вот как он сделан


К примеру, их координаты и размеры:

Label2: Тор — 45, Left — 15, Height — 15, Width — 250

Labe13: Top — 45, Left — 15, Height — 15, Width — 0

Зададим в качестве фонового цвета для "Label2" — серый, а для "Label3" — зеленый (свойство "BackColor", вкладка "Палитра" — рис. 8.8).



Рис. 8.8. Выбор фонового цвета для ProgressBar'а — здесь.


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

Private Sub UserForm_Activate()

— остальной текст программы, которая должна выполняться во время отображения ProgressBar ' а…

Unload Me

End Sub

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

3. Идея такова. Ширину третьей надписи "Label3" можно изменять программно. Поэтому для отображения ProgressBar'а надо вставить в код строки, изменяющие ширину этой надписи. К примеру, цикл в программе выполняется п раз. Тогда ширина надписи "Label3" будет определяться командой в теле цикла по формуле "Label3.Width = (scet / п) * 250", где "scet" — это счетчик цикла, а 250 — ширина надписи Label2.

После каждой такой команды надо вставлять инструкцию "Me.Repaint", чтобы перерисовать форму с учетом новых параметров третьей надписи, автоматической перерисовки до полного отображения формы (которое произойдет, когда кончится обработка события "UserForm_Activate()" и форма не будет выгружена) не происходит. Если форма с ProgressBar'ом должна долго находится на экране без изменений, то рекомендуется почаще использовать команду "Me.Repaint", так как без перерисовки внешний вид формы может быть легко испорчен окнами других приложений, когда пользователь решит воспользоваться ими во время работы макроса.

Итак, код для формы с ProgressBar' ом должен иметь такой вид ("п" количество необходимых выполнений цикла):

Private Sub UserForm_Activate()

Me.Repaint For t=1 to n

…. необходимые команды программы в цикле….

Label3.Width = ((t / n) * 250)

Me.Repaint Next t

Unload Me

End Sub

Разумеется, в нем возможны изменения и улучшения. Можно несколько раз использовать ProgressBar в одной форме, каждый раз обнуляя ширину третьей надписи. Можно поместить на одну форму несколько ProgressBar'ов, где один, например, показывает выполнение всего задания, а другой — его текущей части.


ХРАНЕНИЕ СКРЫТОЙ ИНФОРМАЦИИ В ДОКУМЕНТЕ

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

Можно, конечно, использовать Свойства документа (объект

"Dialogs (wdDialogFileSurnmarylnfo).Comments"), но лучше сделать такую запись с помощью добавления специальной переменной прямо в документ Word:

ActiveDocument.Variables.Add Name:="xl", Value:="Текст"

ActiveDocument.Variables.Add Name:="x2", Value:=12

Прочитать эти переменные можно будет с помощью похожей функции:

y1 = ActiveDocument.Variables("x1").Value

y2 = ActiveDocument.Variables("x2").Value

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

For Each per In ActiveDocument.Variables

Debug.Print per.Name + " " + per.Value

Next per

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


ЧТО ТАКОЕ API?

Для того, чтобы облегчить труд своих коллег и обеспечить всем программам для Windows универсальный интерфейс, программисты Microsoft создали такую вещь, как API — "Application Programming Interface".

Это — набор функций и процедур, которые могут наиболее часто использоваться программами: отображение дерева каталогов, поиск файлов, отображение стандартного окна с кнопками закрытия, минимизации и развертывания на весь экран и многих других. В итоге разработчик, создающий программу для Windows, не должен продумывать и разрабатывать специальные подпрограммы для отображения окна программы, окна для выбора папки и остальных подобных элементарных операций, — ему достаточно просто вызвать из библиотек kernel32.dll или user32.dll, содержащих функции и процедуры API, нужную ему функцию, а она уже все сделает за него сама. Таких функций и процедур много — порядка 600.

В операционной системе MS-DOS такого понятия, как API, не было, — тот, кто брался писать программу для этой операционной системы, обязан был сам, от начала до конца, продумать и реализовать способы выдачи на экран изображения, получения данных от пользователя, путешествия по файловой системе, рисования графики, если таковая возможность была необходимой[239]. Это делало процесс разработки программ с удобным для пользователя интерфейсом весьма трудоемким процессом, зачастую затраты времени и сил на создание приемлемого графического интерфейса программы превосходили затраты на реализацию собственного алгоритма программы, ради которого она и создавалась. Недаром были очень распространены так называемые "консольные" приложения, то есть программы, работающие только из командной строки, без интерфейса, — ввод данных происходил в той же командной строке или производился из указанного в ней файла, а вывод результатов шел в простом текстовом режиме.

С появлением операционной системы Windows каторжный труд программистов по разработке внешнего вида программы и удобных способов ввода и вывода информации резко облегчился, — уже в Windows 3.0 использовались функции API. Теперь программист, если он, например, желал создать окно ввода текста или полосу прокрутки, должен был всего лишь написать вызов функции отображения такого окна с необходимыми ему параметрами, так же, как и любой другой функции языка, на котором он писал свою программу, а не вводить огромные объемы кода ради создания программы, заново рисующей такое окно или полосу (сознавая при этом, что при разработке следующей программы, в которой тоже будут использоваться такие объекты, ему придется вновь разрабатывать такой код или пытаться частично использовать старый, приспосабливая его к нуждам этой новой программы). Поэтому появление API совершило революционный прорыв в технологии программирования, позволяя создавать нужные программы с привычным удобным интерфейсом гораздо быстрее, не заботясь о таких рутинных деталях, как программирование стандартных объектов интерфейса для ввода и вывода информации.

В языке Visual Basic for Applications (VBA) многие функции и процедуры API вызываются сами при выполнении программы интерпретатором, так что использовать их для отображения окон ввода и вывода текста, рисования на экране геометрических фигур и других простых действий совершенно нет необходимости, — их VBA вызывает по мере надобности, а программе на нем достаточно использовать соответствующие функции этого языка. Однако иногда возникает необходимость в некоторых действиях, для которых либо нет аналогов во встроенных функциях VBA, либо они работают нерационально или слишком медленно. Например, окно выбора папки с изображением дерева каталогов (рис. 5.1) или программа поиска файлов (аналог на функциях VBA — объект "Application.FileSearch" — работает слишком медленно при больших количествах файлов). Для таких случаев в VBA предусмотрена возможность вызова функций API.

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

В подавляющем большинстве случаев при программировании для Office можно обойтись без использования API, но иногда только вызов API-функции может привести к достижению нужного результата. Скажем, вам надо обеспечить вызов разных макросов при простом нажатии мышью кнопки на какой-либо панели инструментов Word и в случае одновременного нажатия этой кнопки и клавиши Shift или Control. Вот фрагмент кода, делающего это:

Declare Function GetAsyncKeyState Lib "user32.dll" (ByVal kState As Long) As Integer

Sub Program()

GetAsyncKeyState (vbKeyShift Or vbKeyControl)

If GetAsyncKeyState(vbKeyShift) Then

Call macrol: Exit Sub

Elself GetAsyncKeyState(vbKeyControl) Then

Call macro2: Exit Sub

End If

Call macro 3

End Sub

Первая строчка — это как бы "резервирование" функции API для использования в программе на VBA. Видно, что вызывается функция GetAsyncKeyState из библиотеки (файла, содержащего программы, предназначенные только для использования другими программами) user32.dll, причем в эту функцию передается номер клавиши, а возвращает она целое число (а именно — 0, если клавиша с соответствующим номером не нажата, и -32767 или 1, если нажата). Любую функцию или процедуру, вызываемую из библиотек, не относящихся к VBA, необходимо так резервировать с помощью команды Declare.

Фраза vbKeyShift в команде — это заменитель кода клавиши Shift (его значение — 16), a vbKeyControl, как нетрудно понять — заменитель кода клавиши Control. Структура инструкций "If… Then", думается, ясна[240], а если нет посмотрите в справке VBA. Команда Call перед именем макроса, как вы помните, означает его запуск.

В Интернете есть русские сайты, посвященные API[241]. Посетите их, чтобы узнать больше об этом наборе функций.



Рис. 8.9. Это окно вызывается функцией API.


Но помните, что программы, использующие функции API, в принципе не смогут быть мультиплатформенными, — об использовании их в Microsoft Office for Macintosh придется забыть.


НЕМНОГО О ПАРОЛИРОВАНИИ И ШИФРОВАНИИ

Защита доступа с помощью пароля — самый распространенный способ хранения всяческих секретов на компьютере. Однако о принципах такой защиты большинству пользователей известно плохо. В чем же ее основы? И как можно преодолеть такую защиту?

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

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

Иными словами, это некое подобие функции ИЛИ[242], которая в отличие от настоящей ИЛИ возвращает 0, если на входы было подано сразу две единицы.

А теперь — приглядитесь повнимательнее и обратите внимание на интереснейшую вещь: если на вход функции XOR подать значение 1 входа и результат, то получится значение 2-го входа! И то же самое — со значением 2 входа и результатом: получается значение 1-го входа. Следовательно, зная итог функции XOR и значение на любом из входов, можно получить значение на другом входе, то есть функция XOR обратима.

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

11010101010110101001101010111110101010111110101010001…

Представляем так же пароль:

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

11010101010110101001101010111110101010111110101010001…

10010101010011100101010100111001010101001110010101010…

И теперь — шифруем: применяем к этим двум последовательностям функцию XOR:

01000000000101001100111110000111111111110000111111011…

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

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

Функция XOR, разумеется, присутствует и в VBA. Вот пример кода, реализующего возможности шифрования с ее помощью.

Sub encrypt()

Dim а, b, с, d As String

Исходный текст для шифрования — запрашивается от пользователя, к примеру:

а = "secret text from kgb agent from newyork rezidentura…"

Пароль: может запрашиваться от пользователя: b = "password"

Итог шифрования: с = ""

Узнаем длины каждой из строк — пароля и исходного текста:

lentext = Len(а)

lenpass = Len(b)

Собственно шифрование:

For cn = 1 То lentext

В этой строке попробуйте разобраться самостоятельно. Здесь выполняется функция Хог с каждым символом исходной строки и соответствующим символом пароля, как бы "повторенным" на всю длину исходного текста. Mid берет из середины строки символ, Asc — превращает его в ASCII-код, Str — превращает число в строку, Trim — удаляет пробелы:

d = Trim(Str(Asc(Mid(a, cn, 1)) Xor Asc(Mid(b, ((cn — 1) Mod lenpass) + 1, 1))))

А теперь сделаем так, чтобы каждый символ занимал ровно три позиции, вне зависимости от величины его ASCII-кода. А иначе как потом при расшифровке разбивать строку на символы?

Select Case Val(d)

Case 0 To 9

d = "00" + d

Case 10 To 99

d = "0" + d

End Select

с = с + d

Ну вот и все, и так — с каждым символом из исходной строки:

Next cn

Теперь в переменной с — шифрованная строка, каждой исходной букве соответствует 3 символа. Ее можно записать, например, в документ:

Selection.TypeText Text:=c

End Sub

А теперь — программа расшифровки данных. Точно так же разберем ее по строкам.

Sub decrypt()

Dim а, b, с, d As String

Строка для расшифровки:

с = "003004016001018027082016021025007083017029029009"

Пароль:

b = "password"

Итог расшифровывания: а = ""

Узнаем длины каждой из строк:

lentext = Len(с)

lenpass = Len(b)

Собственно расшифровывание (попробуйте разобраться самостоятельно в структуре команды — это не так сложно):

For cn = 1 То lentext Step 3

а = а + Chr(Val(Mid(с, cn, 3)) Xor Asc(Mid(b, (Int(cn / 3) Mod lenpass) + 1, 1)))

Next cn

В итоге в переменной а — расшифрованная строка, ее можно записать в любое место — в документ, к примеру:

Selection.TypeText Text:=a

End Sub

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


ОТКРЫТЫЙ И ЗАКРЫТЫЙ КОДЫ

Наверняка все слышали такие фразы: "Шифрование с открытым ключом", "Шифрование с закрытым ключом", "Публичный ключ". О том, что они означают, можно писать большие книги, однако стоит вкратце описать ситуацию для полноты изложения.

При шифровании с закрытым ключом для кодирования и расшифровки используется одна и та же последовательность символов в качестве пароля — ключа. Пример — тот, что описан выше. При шифровании же с открытым ключом используются две последовательности символов, причем зашифрованное с помощью первой последовательности можно расшифровать только с помощью второй, и наоборот. Обе последовательности связаны между собой по определенному закону, при этом из второй последовательности можно получить первую, но из первой вторую не узнаешь, — обратное преобразование невозможно.

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

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

Именно на таком принципе работает механизм шифрования PGP.


ОТВЕТЫ НА ВОПРОСЫ

Эта книга написана по мотивам цикла статей "Начала программирования на VBA", публиковавшегося в журнале "Мир ПК" в 2000–2001 годы. После публикации статей цикла мне пришло немало писем с различными вопросами о программировании. Ниже представлены ответы на наиболее интересные из них.

1.

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

Нет. Microsoft Word делать это не позволяет.

Впрочем, можно пойти на хитрость. Создайте документ Doc1.doc и вставьте в него рисунок. Затем сохраните документ с рисунком, задав ему пароли на открытие и на изменения. Создайте документ Doc2.doc. В том месте, где должен быть рисунок, вызовите окно Вставка-Обьект-Создание из файла и укажите в пути файл doc1.doc, отметив предварительно пункт "Связь с файлом". Введите пароль на открытие — и рисунок в Вашем документе. Сохраните его.

Теперь при открытии файла doc2.doc рисунок будет виден, но при попытке изменить его будет запрашиваться пароль на открытие файла doc1.doc. Проблема остается в том, что оба файла — и с рисунком, и с текстом — должны присутствовать, причем в тех местах, где они были изначально. То есть вся эта конструкция труднопереносима.


2.

"Возможно ли в "Word, проводить сравнение двух документов по словам."

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


3.

"Как можно узнать количество страниц в Word2000 из макроса?"

С помощью команды

р = ActiveDocument.ComputeStatistics(wdStatisticPages)

где в переменную р запишется количество страниц в активном документе.


4.

"Сделал документацию на свою VBA-программу в "Word. 97 в doc-файле. Включил в нее screenshot 'ы, на которые наложил автофигуры "Word — выноски, стрелки, скобки, надписи и проч., что разъясняло бы назначение частей рисунков. Теперь хочется поставлять документацию в формате HTML, но. при конвертации "Word начисто игнорирует свои же автофигуры, оставляя в итоговых gif-файлах чистый рисунок. Как цивилизовано выйти из ситуации?"

Да, автофигуры Word97 при конвертации в HTML игнорируются. Для реализации желаемой Вами задачи выделите все автофигуры рисунка вместе с самим рисунком (инструментом "Выделение объектов" панели "Рисование"), сгруппируйте их, вырежьте в Буфер обмена, а затем вставьте то, что в буфере, на то место, где был исходный рисунок, с помощью команды "Правка"-"Специальная вставка", используя в качестве формата вставляемого изображения "Точечный рисунок" или "Метафайл Windows", т. е. что угодно, кроме "рисунка MS Office". После этого у Вас в документе появится рисунок с всеми вставленными автофигурами, который, однако, спокойно конвертируется в GIF-формат при конвертации всего документа в HTML. Так следует поступить со всеми рисунками в документе. В Word2000 и Word2002 такой проблемы нет — там автофигуры сохраняются в самой генерируемой web-странице, но при просмотре ее в старых браузерах могут быть не видны.


5.

"Можно ли "Word 2000 убрать автоматический запуск панели "Буфер обмена"?"

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

Макрос для полного скрытия панели:

Sub clipboard_hide()

CommandBars("Clipboard").Enabled = False

End Sub

Макрос для показа панели:

Sub clipboard_show()

CommandBars("Clipboard").Enabled = True

CommandBars("Clipboard").Visible = True

End Sub

К счастью, в Word ХР эта рекомендация уже неактуальна — там Область задач с вкладкой "Буфер обмена" вызывается только тогда, когда дважды нажата комбинация клавиш Ctrl+C.


6.

"Как определить с помощью макроса в документе "Word, текущий номер страницы, где произошло при поиске вхождение заданной подстроки."

Существуют функции Selection.Information(wdActiveEndPageNumber), которая возвращает номер страницы по счету, на которой располагается конец выделения, и функция Selection.Information(wdActiveEndAdjustedPageNumber), которая возвращает присвоенный номер страницы, на которой располагается выделенный фрагмент. Вторую функцию следует использовать тогда, когда необходимо получить тот номер страницы, который указан на ней непосредственно (т. е. с учетом ручных установок нумерации), а первую — если номер необходим абсолютный. Описание обеих команд можно получить в Справке VBA по слову Information.

При работе подпрограммы поиска каждое вхождение выделяется. Вот, к примеру, фрагмент кода макроса, который отображает в диалоговом окне номера страниц, на которых найден текст "text".

Selection.HomeKey Unit:=wdStory

Dim a As String

a = ""

Selection.Find.ClearFormatting

Selection.Find.Replacement.ClearFormatting

With Selection.Find

Text = "text"

Forward = True

Wrap = wdFindStop

End With

While Selection.Find.Execute = True

a = a + " " + Str(Selection.Information(wdActiveEndPageNumber))

Wend

MsgBox a


7.

"Открыт документ Word, хочу запустить в нем макрос, который в свою очередь запускает макрос Excel, обрабатывающий Excel-таблицу. После этого через Clipboard из Excel макрос пересылает в Word-документ заданную прямоугольную область таблицы. Макрос Word обрабатывает эту область и начинает в требуемой последовательности копировать в Word-документ через Clipboard фрагменты Excel-таблицы. По окончании копирования Word закрывает все ненужные макросы, включая макрос Excel. Как все это сделать, чтобы работало?"

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

Так, чтобы можно было из Word'oвoro макроса работать с Excel'ем, следует создать объект Excel.Sheet (здесь "es" — простое наименование переменной, у вас может быть любым).

Dim es As Object

Set es = CreateObject("Excel.Sheet")

Если надо сразу открыть какой-либо файл Excel'а, то можно использовать команду GetObject:

Set es= GetObject("Путь к файлу Excel'a")

При желании можно сделать созданный объект Excel видимым:

es.Application.Visible = True

Теперь можно этому объекту es (т. е. просто запущенному Excel'у) посылать команды такие же, как и в макросах Excel'a (предваряя текстом "es.Application." те из команд, которые не требуют прямого указания объекта, — так как надо дать понять программе, что работа идет именно с Excel'ем). Так, чтобы открыть файл Excel'а, можно также дать команду

es.Application.Workbooks.Open FileName:="Путь к файлу Excel'a"

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

es.Cells(1, 1).Value = "Это столбец А, строка 1"

В принципе я бы вам посоветовал поместить тот макрос, который Вы планировали для Excel'a, именно в исходный Word'oBbrii, переписав его команды в соответствии с принципом связывания (т. е. управления одним приложением из другого — так, как описано выше).

Закрыть Excel можно командой

es.Application.Quit

Set es= Nothing

Если работать с таблицей из Word почему-либо нельзя, и требуется именно вызвать Excel'евский макрос, то для вызова макроса следует использовать команду

es.Application.Run "имя макроса"

Также можно автоматически запустить какой-либо макрос при открытии файла Excel:

es.Application.Workbooks.Open FileName:="Путь к файлу Excel'а!имя макроса" (например, es.Application.Workbooks.Open FileName:="c: \bookl.xls!macrl", точно так же, разделяя имя файла и имя макроса восклицательным знаком — и в команде Shel1)

В общем, есть простор для творчества. Про работу из Word'а с Excel'ем и т. д. почитайте разделы Справки VBA (для Microsoft Office 97 — по-русски): "Работа с приложениями", "Функция CreateObject", "Функция GetObject", "Программирование объектов".


8.

"Можно ли в "Word, при помощи гиперссылки вызвать команду меню, в частности команду "Найти"?"

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

Конструктора", добавить элемент "Надпись", в меню правой кнопки мыши выбрать "Свойства", в разделе Caption поместить текст ссылки, оформить шрифт и цвет текста в соответствующем разделе Свойств, затем из меню правой кнопки мыши выбрать "Исходный текст", а в появившийся макрос вписать команду

Private Sub Label1_С1ick()

On Error Resume Next

Dialogs(wdDialogEditFind).Show

End Sub

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

"Я сделал так, как Вы сказали, но при вводе в появляющееся окно поиска фрагмента, которого в тексте нет, не отображается сообщение о безрезультатности поиска — как при использовании непосредственно команды "Найти". Можно ли сделать так, чтобы вызываемое окно работало точь-в-точь так же, как и обычное?"

К сожалению, с командой Dialogs… ничего сделать нельзя — так уж будет себя вести это диалоговое окно.

Однако можно использовать "финт ушами". В VBA есть функция SendKeys, которая передает активному окну нажатия клавиш — как если бы они были нажаты на клавиатуре. (Подробнее — смотрите в Справочной системе VBA.) Поэтому можно ее использовать:

Private Sub

Label1_Сlick()

SendKeys "^f"

End Sub

предполагая, что комбинация клавиш Ctrl+f вызывает окно "Найти", как, впрочем, устанавливается по умолчанию. Список кодов функциональных клавиш — в Справке.

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


ОТЛИЧИЯ НОВЫХ ВЕРСИЙ OFFICE

Отличия VBA в новых версиях Office в основном заключаются в добавлении новых функций, событий, процедур и объектов. Например, в Office 2000 появились события объекта Application, позволяющие перехватить почти любое происходящее в документе событие. Так, событие "DocumentBeforeClose" выполняется перед закрытием документа, "DocumentBeforePrint" — перед его печатью, "WindowBeforeRightClick" — сразу после клика правой кнопкой мыши в окне программы, "WindowSelectionChange" — при изменении выделения, смещении точки ввода (за исключением простого ввода текста).

В Office2000 изменилась система защиты от вирусов в макросах. Так, в Word2000 для того, чтобы иметь возможность запускать макросы, необходимо, чтобы в диалоговом окне "Сервис — Макросы — Безопасность" был установлен "Средний" или "Низкий" уровень защиты от макросов (лучше "Средний" — тогда при открытии документов с макросами пользователю будет выдан запрос о необходимости разрешения исполнения макросов).

Также в Word2000 для того, чтобы пользователь имел возможность запускать макросы из шаблонов, установленных в папку автозагружаемых файлов Word, необходимо на вкладке "Надежные источники" диалогового окна "Сервис-Макросы-Безопасность" установить отметку в пункте "Доверять всем установленным надстройкам и шаблонам". Обо всем этом следует упомянуть в документации к разрабатываемой вами программе.

То же самое верно и для Office ХР, однако отличия есть и здесь.

Во-первых, по умолчанию компоненты Office ХР, отвечающие за запуск макросов, на жесткий диск не ставятся — таким образом, похоже, Microsoft пытается защитить наиболее неразумных пользователей от макровирусов. По большому счету, подобные ее действия обычно приносят больше вреда, чем пользы, для авторов же программ на VBA из этого следует, что в справочных файлах к своим программам им следует упоминать о необходимости доустановки компонентов Office перед началом использования макросов.

Во-вторых, для того, чтобы иметь возможность программно копировать модули и формы макросы между документами и шаблонами, необходимо, чтобы в диалоговом окне "Сервис — Макросы — Безопасность", на вкладке "Надежные источники" имелась отметка в пункте "Доверять доступ к Visual Basic Project". Об этом тоже следует упомянуть в справке к программе.

Из появившихся новых событий в Office ХР можно отметить возможность отслеживать изменение размеров окна приложения (обработчиком события WindowSize).

В OfficeXP скопировать файл из одной папки в другую или удалить его посредством программного кода можно только при отключенной Службе индексирования (ссылка "Параметры поиска" на панели "Обычный поиск", рис. 8.10). К сожалению, по умолчанию эта Служба включена, а программно ее отключить невозможно. Поэтому, несмотря на декларируемую "совместимость сверху вниз" версий Office, автору программ на VBA настоятельно рекомендуется тестировать свои программы во всех версиях Office и отлаживать их при необходимости.



Рис. 8.10. Если в OfficeXP вы хотите копировать и удалять файлы с помощью VBA — выключите здесь "Службу индексирования".


Более подробно о новшествах в Visual Basic for Applications в новых версиях Microsoft Office читайте в разделах их Справочных систем, которые так и называются — "Whats New for Office Developers" и, для Word, "Whats New for Word Developers".


НАПУТСТВИЕ

Создавая программы для Microsoft Office, вы сможете на опыте получить представление практически обо всех современных принципах программирования: как структурных — основанных на последовательном выполнении всех команд программы, так и "событийных", согласно которым программа должна реагировать соответствующим образом на различные действия пользователя. В современном программировании используются оба этих принципа: интерфейс программ построен по принципу реакции на события, а функции, выполняемые программой — по принципу независимой работы. Например, графический редактор Paint, да и тот же текстовый процессор Word в большей своей части являются приложениями, управляемыми событиями — действиями пользователя; а, скажем, программы дефрагментации или проверки диска работают почти независимо от пользователя, он только должен задать им начальные параметры. В Visual Basic for Applications можно писать как программы, управляемые событиями (посредством разработки форм), так и работающие последовательно и независимо (используя только модули), а также, разумеется, и приложения, сочетающие в себе оба этих принципа.

Visual Basic for Applications может служить не только полноценной средой разработки приложений, работающих в Microsoft Office, но и как бы "учебным центром" по освоению принципов и различных приемов современного программирования. Работа с системным реестром, с файловой системой и даже со встроенными в Windows функциями программирования API, — все это вы сможете изучить на опыте, используя Visual Basic for Applications, причем сделать это Вам будет значительно легче, чем если бы вы сразу начали учиться программировать на Delphi или Visual Basic for Windows. Средство записи макросов, возможность легкого анализа уже написанных программ (так как фактически любая программа на Visual Basic for Applications распространяется вместе со своим исходным текстом), русский интерфейс редактора, большая и четко написанная справка, обилие примеров, — все это очень помогает в освоении этого языка и делает возможным его самостоятельное изучение — даже без использования дополнительной литературы. Другие языки программирования так освоить практически невозможно. Кроме того, редактор Visual Basic for Applications обладает большими возможностями по коррекции ошибок, и поэтому программа на этом языке вряд ли вызовет ошибку системы и необходимость перезагрузки, если только не увлекаться вызовом функций API.

Если Вы научитесь программировать на Visual Basic for Applications, поймете принципы разработки алгоритмов и основные приемы программирования, освоите среду написания программ — редактор Visual Basic for Applications, то для Вас практически не составит труда начать создавать программы на Visual Basic for Windows. У этого языка абсолютно такой же синтаксис, такая же среда разработки с контекстной справкой и пошаговыми подсказками, на первый взгляд он отличается от Visual Basic for Applications разве что набором доступных встроенных процедур и функций и отсутствием возможности записи макросов. Безусловно, есть и более глубокие различия, но при создании не очень сложных программ они не будут иметь большого значения. Вы сможете легко освоить средство разработки программ Delphi, однако логика языка Pascal, лежащего в основе Delphi, несколько отличается от логики Visual Basic. Однако и среда разработки, и общие принципы программирования в Delphi те же. Несколько труднее будет освоить C++ и его производные из-за серьезно отличающегося синтаксиса и высокой сложности этого языка, но это не всегда необходимо, — подавляющее большинство проектов программ можно реализовать на Visual Basic или Delphi.

* * *

Среди тех, кто занимается программированием уже много лет и достиг в этом деле определенных высот, весьма распространено мнение, что Visual Basic for Applications, да и просто Visual Basic — языки, на которых нельзя создать быстро и хорошо работающие программы. В определенной степени это соответствует действительности: программы на Visual Basic обычно работают несколько медленнее и занимают больше места, чем аналогичные им программы на C++, на Visual Basic весьма проблематично решение некоторых программистских задач и приемов. Поэтому профессиональные программисты часто считают, что Visual Basic — язык для дилетантов в программировании, а любой уважающий себя специалист в области информационных технологий обязан знать и использовать такие языки, как C++ или ассемблер. Но не следует забывать, что изначальное предназначение компьютерных технологий — помощь человеку в обработке и создании информации, а отнюдь не "служение самим себе", своему дальнейшему развитию. Поэтому основная функция большинства компьютерных программ получение нужного результата, обработка вводимой информации, например, анализ электрокардиограммы или расчет траектории космической ракеты, а быстродействие, малый размер, да и удобство интерфейса — всего лишь их хорошие свойства, которые могут серьезно облегчить работу с программой.

Бесспорно, в настоящее время крупные программные комплексы делаются не в одиночку. Специалисты в какой-либо области пишут подробное техническое задание, а программисты его реализовывают. Однако в любой области человеческой деятельности есть множество задач, для решения которых привлекать сторонние коллективы слишком затратно. И вот тут-то и приходят на помощь легкие в освоении, но богатые возможностями языки программирования — Visual Basic, VBA, Delphi. Поэтому практически любой специалист своего дела может в наши дни использовать в своей работе новейшие достижения информационных технологий — создать нужную ему программу, разработав ее алгоритм на основе своего опыта.

На вопрос: "Какой язык программирования лучше всего?" стоит отвечать так:

"Тот, на котором ты можешь лучше всего писать программы и реализовывать свои проекты." Проще всего освоить Visual Basic и Delphi. И поэтому не стоит так уж стремиться обязательно знать ассемблер, выучить все функции API и жалеть, что не можешь вводить программы сразу в машинных кодах, — лучше повнимательнее изучить более простой язык даже вроде того же Visual Basic for Applications для того, чтобы уметь использовать все его возможности для воплощения своих пожеланий в жизнь. Ну, а если кто желает посвятить свою жизнь информационным технологиям, создавать новые языки общения с компьютером, то тому знание Visual Basic никогда не помешает, а остальные знания, как говорится, дело наживное, — надо лишь начать учиться и освоить общие принципы.

Не стоит думать, что "программирование мне никогда не понадобится" современные компьютерные технологии развиваются с огромной быстротой, и скоро практически любая область человеческой деятельности будет компьютеризирована. А чтобы получить в своей работе наилучший результат, нужно уметь приспособить орудие труда — компьютер — под свои нужды, то есть — программировать.

* * *

И, наконец, стоит сказать об использовании программирования на Visual Basic for Applications в процессе обучения в школе, институте, да и в самостоятельном образовании. Даже если человек не желает посвятить свою жизнь информационным технологиям, умение программировать ему всегда пригодится, так как использование возможностей компьютеров сейчас возможно практически в любой области человеческой деятельности. Но главное — это то, что обучение искусству составления программ на собственном опыте, путем самостоятельного исследования возможностей языка и среды разработки является одним из наилучших способов научиться так называемому "научному мышлению", тому подходу к различным явлениям окружающего мира, на котором стоит вся современная наука. Самостоятельно обучаясь использованию Visual Basic for Applications, можно как бы на маленькой модели испробовать почти все исследовательские приемы, которые используются современной наукой, — и наблюдение, и анализ результатов, и эксперимент… Например, вынесение из записанного макроса неизвестной команды в отдельную процедуру для выяснения ее функции, — чем не эксперимент в контролируемых условиях? Или изменение параметров команды с целью узнать, к чему это приведет, — разве не так действуют исследователи, изменяя начальные условия эксперимента?

Так что изучение Visual Basic for Applications может стать целым "научным исследованием", в течение которого можно будет отработать основные приемы современного научного подхода.

* * *

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

Удачи!

Орлов Антон Александрович,

2002 г.

Адрес сайта: http://antorlov.chat.ru или http://www.newtech.ru/~orlov

Загрузка...