Будь умным!


У вас вопросы?
У нас ответы:) SamZan.net

о Редакторе VB его возможностях и компонентах о языке Visul Bsic for pplictions и принципах программирования

Работа добавлена на сайт samzan.net:


Создание первой программы

*       *       *

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

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

Напомню, что Microsoft Word в качестве основы для обучения программированию выбран потому, что именно эта программа из всех компонентов Microsoft Office является наиболее частоиспользуемой, и надобность в расширении его возможностей возникает чаще, чем необходимость дополнения остальных программ из пакета. В качестве основной среды разработки выбрана версия Microsoft Office 97, так как, во-первых, программы, написанные в ней, будут работать и в более старших версиях Microsoft Office1, а, во-вторых, в русской версии 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… Если документов - два, да даже десять, то еще как-то можно справиться, а если их сорок или сто? И вот тут-то придут на помощь макросы.

Но как можно написать программу, да-да, настоящую программу на настоящем языке программирования, ничего не зная о нем, кроме того, что он существует? Это действительно было бы очень трудно сделать на С++ или даже 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).

05_01.bmp

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

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

05_02.bmp

Рис. 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

.ColorIndex = wdBlack

End With

With Selection.ParagraphFormat

.LeftIndent = CentimetersToPoints(0)

.RightIndent = 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

.MatchAllWordForms = False

End With

Selection.Find.Execute Replace:=wdReplaceAll

ActiveDocument.Save

ActiveDocument.SaveAs FileName:="Доклад1.rtf", FileFormat:=wdFormatRTF, _

LockComments:=False, Password:="", AddToRecentFiles:=True, WritePassword _

:="", ReadOnlyRecommended:=False, EmbedTrueTypeFonts:=False, _

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

False

ActiveWindow.Close

End Sub

05_03.bmp

Рис. 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).

05_04.bmp

Рис. 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).)

05_05.bmp

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

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

а = Selection.Font.Size

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

* * *

With Selection.Font

.Name = "Times New Roman"

.Size = 12

.ColorIndex = wdBlack

End With

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

05_06.bmp

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

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

05_07.bmp

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

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

05_08.bmp

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

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

05_09.bmp

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

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

05_10.bmp

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

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

Selection.Font.Name = "Times New Roman"

Selection.Font.Size = 12

Selection.Font.ColorIndex = wdBlack

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

Идем дальше:

With Selection.ParagraphFormat

.LeftIndent = CentimetersToPoints(0)

.RightIndent = CentimetersToPoints(0)

.SpaceBefore = 0

.SpaceAfter = 0

.LineSpacingRule = wdLineSpaceSingle

.FirstLineIndent = CentimetersToPoints(1.27)

End With

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

05_11.bmp

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

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

Sub Макрос2()

'

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

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

'

With Selection.ParagraphFormat

.LeftIndent = CentimetersToPoints(1)

.RightIndent = CentimetersToPoints(1)

.SpaceBefore = 1

.SpaceAfter = 1

.LineSpacingRule = wdLineSpace1pt5

.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 отслеживает не столько действия пользователя, сколько изменения параметров текста. Поэтому при задании свойств абзаца с помощью соответствующего диалогового окна “Формат - Абзац” оно скрупулезно записывает в макрос все параметры этого диалогового окна, которые в нем были заданы при нажатии кнопки Ok. Если абзацы имели разное оформление, которое не было изменено в данный момент на единообразное, то те пункты данного диалогового окна, которые остались различными у разных абзацев в выделении, будут иметь неопределенное значение, и средство записи макросов не сможет их поместить в текст записываемого макроса. В самом же диалоговом окне подобные неопределенные опции отображаются галочкой на сером фоне (рис. 5.12), а в полях указания размеров отступов не стоят их значения.

05_12.bmp

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

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

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

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

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

05_13.bmp

Рис. 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

.MatchAllWordForms = 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).

05_14.bmp

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

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

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

Sub experience1()

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

.MatchAllWordForms = 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). Выпал список возможных продолжений.

05_15.bmp

Рис. 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).

05_16.bmp

Рис. 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)...

05_17.bmp

Рис. 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:="Доклад1.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:="Доклад1.rtf"” и “FileFormat:=wdFormatRTF” - имя файла, под которым сохраняется активный документ, и тип сохраняемого файла. Тип нас устраивает - формат Rtf. А вот как быть с именем? Ведь у каждого файла должно быть свое, уникальное имя. А тут получается, что все файлы, обрабатываемые данным макросом, станут сохраняться под одним и тем же именем, что, ясное дело, вызовет их запись друг на друга и  тем самым потерю данных во всех них, кроме обработанного последним. Что же делать?

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

05_18.bmp

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

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

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

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

05_19.bmp

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

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

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

05_20.bmp

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

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

Sub experience2()

MsgBox ActiveDocument.Name

End Sub

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

05_21.bmp

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

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

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

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

05_22.bmp

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

05_23.bmp

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

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

05_24.bmp

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

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

05_25.bmp

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

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

05_26.bmp

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

05_27.bmp

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

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

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

05_28.bmp

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

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

05_29.bmp

Рис. 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).

05_30.bmp

Рис. 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/XP шаблонов с макросами, созданных в предыдущих версиях 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

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

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

Иначе 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

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

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

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

05_31.bmp

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

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

05_32.bmp

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

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

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

05_33.bmp

Рис. 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:=wdFormatRTFActiveWindow.Close

Goto metka

End Sub

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

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

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

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

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

"Если" - по-английски "If". Поищем по этому слову в Предметном указателе Справочной системы по VBA (из Microsoft Office 97). Получаем строчку: "Инструкция If", выбрав которую, получаем окно из различных сочетаний слов If, Then, Else и др. (рис. 5.34).

05_34.bmp

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

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

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

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

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

05_35.bmp

Рис. 5.35. Как же подсчитать открытые документы? Есть ли что-нибудь, что может пригодиться?

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

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

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

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

Sub Макрос1()

'

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

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

'

metka:

Selection.WholeStory

With Selection.Font

.Name = "Times New Roman"

.Size = 12

.ColorIndex = wdBlack

End With

With Selection.ParagraphFormat

.LeftIndent = CentimetersToPoints(0)

.RightIndent = 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

.MatchAllWordForms = 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("Обработка закончена", vbInformation, "Обработка текстов")

End Sub

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

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

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

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

05_36.bmp

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

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

05_37.bmp

Рис. 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/XP помещение в "Мастер ответов" или "Предметный указатель" Справочной системы VBA слов "dialog boxes" приведет к появлению довольно большого списка разделов, содержащих данные слова (рис. 5.38), так что выбор придется делать непростой. Однако найти наиболее подходящий для нашего случая раздел - "Displaying Built-In Word Dialog-Boxes" - все же можно довольно быстро.

05_38.bmp

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

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

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

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

05_39.bmp

Рис. 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), получаем список всех возможных аргументов диалоговых окон (то есть параметров, значения которых можно получить из окон или задать им).

05_40.bmp

Рис. 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\Шаблоны\", а если пробелов в пути не было, то кавычки по краям не ставятся. Поэтому возвращаемую переменную нужно обработать - убрать кавычки.

Сделать это можно с помощью уже известных нам команд "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(wdDialogCopyFile)

.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).

05_41.bmp

Рис. 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:=papka + 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

.ColorIndex = wdBlack

End With

With Selection.ParagraphFormat

.LeftIndent = CentimetersToPoints(0)

.RightIndent = 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

.MatchAllWordForms = 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("Обработка закончена", vbInformation, "Обработка текстов")

End Sub

*       *       *

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

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

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

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

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

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

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

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

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

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

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

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

3 Место сохранения можно задать, включив в имя документа в пункте “FileName” полный путь к его новому местоположению.

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




1. Практическая энциклопедия бухгалтера1
2. Зависть - ключ к просветлению
3. 19057
4. Организация компьютерного центра Ультра Стар
5. Коммуникации- общая характеристика и разновидности
6. 2 Ма~саты- Биологиялы~ молекулаларды~ электронды~ ~~рылысын сол молекуларды~ электронды~ к~шуін ж
7. Красные и белые
8. ЮРИДИЧЕСКАЯ АКАДЕМИЯ РОССИЙСКИЙ УНИВЕРСИТЕТ ИННОВАЦИЙ Согласовано
9. реферат на здобуття наукового ступеня кандидата бiологiчних наук Київ ~ 1999 Дисе
10. Тема лекции- Репрезентативная теория измерения и ее шкалы ШКАЛА НАИМЕНОВАНИЙ Первая шкала ~ шкала н
11. Методика преподавания анализа музыкальных форм (Рондо)
12. Церковь и мир - Основы социальной концепции Русской Православной Церкви.html
13. Вариант 1 ЗАВДАННЯ 1 Прочитай текст
14. ЛЕКЦИИ ПО ОБЩЕЙ И НЕОРГАНИЧЕСКОЙ ХИМИИ Учебное пособие Томск Сибирский г
15. Рекомендовано на методичній нараді кафедра факультетської педіатрії Завідувач кафедри д
16. ді есептегенде оны~ ~~рамына ~анша сома кіреді 20 000 А~ша ~сынысын арттыру ~ай кезде жиынты~ ~німді ~сіре
17. Витамин D3 влияет на регулирование обмена кальция и фосфора в механизме кишечной абсорбации кальция
18. Тема- Стилістичні можливості повнозначних частин мови дієслова та прислівника
19. Функции и принципы налогообложения Этапы формирования налоговой системы в РФ
20. Сути санкхьи йоги и веданты Глава 6