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

Рекомендации

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

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 и др. Просто командой Documents.Open откройте файл в Word как текстовый и запишите в него обычными средствами: Selection.Text = «Мой текст».

  • С помощью фрагмента программы

Set MyData = New DataObject
MyData.SetText "Мой текст"
MyData.PutInClipboard

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

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

Рис. 1. Интересные свойства объекта System

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

  • Если вы часто сохраняете документы в формате HTML и вам мешает постоянно появляющееся диалоговое окно с выбором кодировки файла, то отключите его, установив в Системном реестре как No строковый параметр HKEY_LOCAL_MACHINESOFTWARE MicrosoftShared ToolsText ConvertersExportHTML OptionsShowEncodingDialog (см. рис. 2).

Рис. 2. Параметр Системного реестра, который в случае сохранения документа в формате HTML требует выведения на экран окна с выбором кодировки файла

Отключить вывод окна можно и программно, применив команду System.PrivateProfileString(«», «HKEY_LOCAL_MACHINESOFTWAREMicrosoft Shared ToolsText ConvertersExportHTMLOptions», «ShowEncodingDialog») = «No»

  • С помощью команды Options.DefaultFilePath(«константа названия папки») можно получить пути и имена папок, перечисленных в диалоговом окне Word «Сервис?Параметры?Расположение». Все константы приведены в справочной системе Visual Basic for Applications по слову DefaultFilePath, а об их значении легко догадаться, переведя с английского названия (см. рис. 3).

Рис. 3. Справка по слову DefaultFilePath

  • Если вы пишете инсталлятор для программ, помещающий шаблоны с макросами в папку автозагружаемых файлов Word, то можно сделать доступными макросы из помещенного в эту папку шаблона без перезагрузки редактора. Местонахождение папки автозагружаемых файлов можно посмотреть в окне «Сервис?Параметры?Расположение». Для Word 97 это обычно папка …Microsoft OfficeOfficeStartup, а для Word 2000 по умолчанию назначается каталог C:WindowsApplication DataMicrosoftWordStartup. Активизировать такие шаблоны без перезагрузки Microsoft Word позволяет VBA — для этого существует специальная команда AddIns.Add(«полное имя шаблона, включая путь к нему и расширение»).Installed = True. Эта команда эквивалентна подключению шаблона с макросами вручную через меню Word «Сервис?Шаблоны и надстройки» (см. рис. 4).

Рис. 4. Окно «Шаблоны и надстройки»

Если же команда будет выполнена сразу после программного копирования шаблона в папку автозагружаемых файлов, то может появиться ошибка — при подобном копировании Word должен зарегистрировать полученный шаблон как доступный для подключения (после регистрации он появится в диалоговом окне «Сервис?Шаблоны и надстройки», но не будет отмечен в качестве загруженного). На такой процесс уходит несколько секунд, и если в это же время вызвать команду на подключение шаблона, то Word может выдать сообщение, что искомого шаблона в папке автозагрузки нет, и это приведет к ошибке. Предотвратить подобную ситуацию можно, например поместив после команды копирования шаблона FileCopy следующей конструкции:

a="Имя шаблона в папке автозагрузки
 с полным указанием пути"
On Error Resume Next
Do
If AddIns(a).Installed Then Exit Do
AddIns(a).Installed = True
Loop

В цикле Do…Loop команда повторяется до тех пор, пока шаблон не подключится, при этом для предотвращения возникновения ошибки программы используется команда On Error Resume Next.

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

a="Имя шаблона в папке автозагрузки
 с полным указанием пути"
On Error Resume Next
Do
If Not AddIns(a).Installed Then Exit Do
AddIns(a).Installed = False
Loop
AddIns (a).Delete
Kill (a)

По команде Kill файл удаляется.

Примечание. При программировании в среде Office XP могут возникнуть проблемы с копированием и удалением файлов средствами VBA, что связано с наличием в этом пакете программы Microsoft Indexing Service, по мысли своих создателей улучшающей возможности поиска файлов. По умолчанию эта служба включена, отключить ее можно по адресу «Файл?Найти?Ссылка «Параметры поиска» на панели «Обычный поиск». Кроме того, если в диалоговом окне Word 2002 «Сервис?Макросы?Безопасность?Надежные источники» выключена опция «Доверять доступ к Visual Basic Project», то программно копировать макросы между документами и шаблонами будет невозможно.

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

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

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

Рис.5. Сайт Passwords.ru

  • На сайте Microsoft (www.microsoft.ru/offext) есть «Библиотека расширений для Microsoft Office», где можно найти огромное число макросов и шаблонов. Изучение их текста помогает освоить Visual Basic for Applications, узнать много новых приемов и команд. Можно даже послать на конкурс свою программу-макрос, а если она будет признана достойной, то и выиграть приз!

Рис.6. Программа Advanced Password Recovery

  • Если исходный текст программы на Visual Basic for Applications закрыт от просмотра паролем, а вы его забыли, то не огорчайтесь: в Internet по адресу www.passwords.ru есть программа Advanced VBA Password Recovery, позволяющая восстановить забытый пароль. Ее английская версия требует оплаты и регистрации, а русская — бесплатна (см. рис. 5, 6, 7).

Рис.7. Страница программы Advanced Password Recovery

ProgressBar в наших программах

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

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

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

  • Создаем небольшую форму и помещаем на нее надпись с пояснительным текстом (в частности, Label1) и две другие (скажем, Label2 и Label3), низкие и широкие, располагая их одну над другой (см. рис. 9).

Рис. 9. А вот как сделан ProgressBar

Зададим этим формам, к примеру, следующие координаты и размеры:

Label2: Top — 45, Left — 15, Height — 15, Width — 250

Label3: Top — 45, Left — 15, Height — 15, Width — 0

Для Label2 укажем в качестве фонового цвета серый, а для Label3 — зеленый (свойство BackColor, закладка «Палитра») (см. рис. 10).

Рис. 10. Задание фонового цвета для надписи

  • Чтобы форма появилась на экране, но могла быть программно модифицируема во время своего отображения, помещаем в нее следующий текст:

Private Sub UserForm_Activate()

…остальной текст программы, которая должна выполняться во время отображения ProgressBar?а…

Unload Me
End Sub

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

  • Ширину любой надписи можно изменять программно. Поэтому для отображения ProgressBar вставим в текст строки, изменяющие ширину надписи Label3. Например, некий цикл, который нужно снабдить ProgressBar, в программе выполняется n раз. Тогда ширина надписи Label3 будет определяться командой в теле этого цикла по формуле: Label3.Width = (scet / n)*250, где scet — счетчик цикла, а 250 — ширина надписи Label2. После каждой такой команды следует вставлять инструкцию Me.Repaint, чтобы перерисовать форму с учетом новых параметров третьей надписи, поскольку автоматической перерисовки до полного отображения формы не происходит — это совершится тогда, когда закончится обработка события UserForm_Activate() и форма будет выгружена. Если форма с ProgressBar должна долго находиться на экране без изменений, то рекомендуется почаще использовать команду Me.Repaint, так как без перерисовки внешний вид формы может быть испорчен окнами других приложений.

Итак, текст для формы с ProgressBar должен иметь следующий вид:

Private Sub UserForm_Activate()
Me.Repaint
For t=1 to n ?n - количество
 необходимых выполнений команд цикла
… … … … нужные команды программы
 в цикле ... ... ... ...
Label3.Width = ((t / n) * 250)
Me.Repaint
Next t
Unload Me
End Sub

В то место основной программы, в котором должен находиться цикл с ProgressBar, следует поместить команду вызова этой формы (здесь: UserForm.Show), не забыв объявить передаваемые в цикл и из цикла переменные основной программы как Public. Цикл как бы «выносится за пределы» основной программы и помещается в обработчик события UserForm_Activate.

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

Хранение в документе скрытой информации

Иногда в документ нужно записать какую-нибудь информацию «для внутреннего пользования», в частности такую, которая позволила бы при следующей обработке документа программой использовать определенные предыдущие данные. Можно, конечно, взять Свойства документа (объект Dialogs(wdDialogFileSummaryInfo).Comments), однако лучше сделать такую запись с помощью свойства Variable:

ActiveDocument.Variables.Add Name:="x1",
 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

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

Успехов вам в освоении искусства программирования!

Антон Александрович Орлов, antorlov@inbox.ru, http://antorlov.chat.ru