Обмен данными с Microsoft Word в системе автоматизации

В настоящем разделе будут рассмотрены несколько примеров управления объектами Microsoft Word из процедур VBA: открытие и печать документа, слияние документов для почтовых рассылок и заполнение полей в документе Word данными из БД Microsoft Access.

Иерархия объектов VBA приложения Microsoft Word

Так же как и при использовании объектной модели Microsoft Excel, познакомимся сначала с некоторыми объектами объектной модели Microsoft Word.

Открытие документа Word

Для того чтобы открыть документ Word, можно использовать любой из перечисленных ранее способов создания экземпляров класса объекта автоматизации. Ниже приводятся примеры процедур VBA для открытия документа. В первой используется функция CreateObject (), а во второй — GetObject(). Для проверки кода этих процедур вы можете, так же как и при работе с объектами приложения Excel, использовать окно отладки.

Sub OpenDocument()

Dim wda As Word.Application

Set wda = CreateObject("Word.Application")

With wda

.Visible = True

.Documents.Open "C:\Doc\Letter.doc"

End With

'операции над документом wda.Quit Wda.Nothing

End Sub

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

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

wda.ActiveDocuments.Close False

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

В следующей процедуре для открытия документа используется функция Getobject (). То есть сначала делается попытка проверить, не запущен ли уже Word. Если он еще не запущен, будет сгенерирована ошибка (код ошибки: 429). Программа перехватит эту ошибку и использует функцию CreateObject(), чтобы запустить Word. Если Word уже запущен, то новый документ будет открыт в этом же экземпляре приложения. Затем документ выводится на печать, после чего закрывается либо документ, либо приложение в зависимости от значения флага (modeFlag). Значение флага показывает, запускался ли экземпляр Word, или документ был добавлен к другим открытым документам:

Sub OpenPrintDocument() Dim wda As Word.Application

Dim modeFlag As Boolean

On Error GoTo ErrStartWord

modeFlag = True 'устанавливаем флаг операции

Set wda = GetObjectf, "Word.Application")

With wda

.Visible = True

.Documents.Open "C:\Doc\Letter.doc"

.ActiveDocument.Printout

Do While .backgroundPrintingStatus <> 0

DoEvents "ждем, пока документ напечатается

Loop

If modeFlag Then

.ActiveDocument.Close 'закрываем только документ

Else

.Quit 'закрываем все приложение

End If

End With

Set wda = Nothing Exit Sub

ErrStartWord:

If Err.Number = 429 Then ' Word не запущен

Set wda = CreateObject("Word.Application")

modeFlag = False 'сбрасываем флаг

Resume Next 'возвращаемся к оператору, следующему за

'тем, который вызвал ошибку Else

'выдаем диалоговое окно с сообщением и номером ошибки

MsgBox Err.Description & " " & Err.Number, vblnformation

Exit Sub ' выходим из процедуры

End If

End Sub

Вывод данных из таблицы Access в документ Word

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

В качестве примера рассмотрим документ Word, который находится в файле Contract.doc на компакт-диске. Документ представляет собой текст договора и содержит несколько полей формы, которые должны быть заполнены данными из таблицы Access. (Подробно о полях формы можно пропитать, например, в кн.: Ф. Новиков, А. Яценко. Microsoft Office 2000 в целом. "БХВ—Санкт-Петербург", 1999.) Откройте этот файл, запустив Word. На рис. 15.32 показаны начало документа и поля, которые должны быть заполнены. Кроме того, представлена стандартная панель инструментов Формы (forms), с помощью которой эти поля были созданы.

Замечание

Чтобы вывести на экран эту панель инструментов, щелкните правой кнопкой мыши в области панелей инструментов и выберите из списка элемент Формы (forms).

Чтобы вставить такое поле в документ, нужно:

  1. Установить курсор (точку ввода) в то место, где должно начинаться поле, и нажать кнопку Текстовое поле (Text form Field). Поле будет вставлено в документ в точке ввода.
  2. Дважды щелкнуть на этом поле. Откроется диалоговое окно Параметры текстового поля (Text form Field Options), в котором требуется заполнить, по крайней мере, одно поле: Закладка (Bookmark).
  3. Ввести имя закладки и нажать кнопку ОК.

Рис. 15.32. Документ Word, содержащий поля для вставки

Рассмотрим программу, которая открывает файл Contract.doc и автоматически заполняет поля договора. Такая программа может быть связана, например, с кнопкой в форме "Заказы клиентов" (Customer Orders) и обрабатывает нажатие данной кнопки. При нажатии на кнопку должен сформироваться договор с тем клиентом, который отображается в текущей записи формы. Для простоты будем считать, что номер договора будет равен номеру текущего заказа (выделенного в подчиненной форме).

Private Sub CreateContract_Click()

Dim wda As Word.Application

Dim wdd As Word.Document

Dim intPrint As Integer On Error GoTo ErrStartWord

Set wdd = GetObject("C:\Doc\Contract.doc")

Set wda = wdd.Parent

wda.Visible = True

wdd.Bookmarks("ContractNumber").Select

wda.Selection.TypeText

Text:=[Подчиненная форма заказов 1].form![КодЗаказа]

wdd.Bookmarks("ContractDate").Select With wda

.Selection.TypeText Text:=Date

.Selection.GoTo Name:="CustemerName"

.Selection.TypeText Text:=[Название]

.Selection.GoTo Name:="CustomerAddress"

.Selection.TypeText Text:=[Страна]

' заполнение остальных полей

intPrint = MsgBox("Печатать договор?", vbYesNo + vbQuestion)

If intPrint = vbYes Then

wdd.Printout

Do While .backgroundPrintingStatus <> 0

DoEvents

Loop

End If

.ActiveDocument.Close False If .Windows.Count = 0 Then

.Quit

End If

End With

Set wdd = Nothing Set wda = Nothing

Exit Sub

ErrStartWord:

MsgBox Err.Description & " " & Err.Number, vblnformation

Exit Sub

End Sub

В данной программе с помощью функции Getobject() создается объект Document. Если при этом Word не запущен, то одновременно создается скрытый экземпляр объекта Application Word. Если Word уже запущен, то новый документ добавляется к уже открытым документам.

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

Во втором случае к объекту Selection (вспомните, что он может означать не только выделенную область, но и точку ввода) применяется метод Goto, которому в качестве значения аргумента Name передается имя нужной закладки.

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

Потом документ закрывается и далее проверяется, открыты ли еще какие-либо документы (используется свойство Count семейства windows). Если других открытых документов нет, то приложение тоже закрывается. В конце процедуры освобождаются обе объектные переменные.

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

Слияние документов для почтовых рассылок

Следующий пример связан с эффектным решением еще одной типовой задачи — созданием серийных документов. Это могут быть письма с одинаковым содержанием, но адресованные разным лицам, или типовые бланки, которые должны оформляться в большом количестве. Задача сводится к тому, что должны существовать шаблон такого документа и некоторая база данных. Требуется создать необходимое количество экземпляров такого документа, вставив в каждый экземпляр существующие данные. Если источником данных является таблица Access или запрос, задача решается просто — достаточно выделить эту таблицу (запрос) в списке в окне базы данных и выполнить команду меню Сервис, Связи с Office, Слияние с MS Word (Tools, Office Links, Merge it With MS Word). Однако может оказаться, что данные для вставки в бланк или письмо определяются достаточно сложно, например представляют собой набор записей — Recordset. Тогда можно создать все бланки программно.

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

Рис. 15.33. Шаблон документа для слияния с данными из Access

Шаблон документа должен быть приготовлен заранее. Рассмотрим, как это можно сделать.

  1. Создайте красивый бланк, пользуясь средством Microsoft Clip Gallery или любой другой библиотекой картинок, рамочек и т. д. (Можно использовать шаблон, присутствующий на компакт-диске, — файл Приглашение.dot). Это будет основной документ для слияния.
  2. Теперь нужно установить связь с источником данных. В программе мы будем использовать в качестве источника данных временную таблицу Access, т. е. таблицу, которая существует только при работе процедуры VBA. Однако для установления связи нужно создать такую таблицу в базе данных. Создайте новую таблицу и определите следующие поля таблицы: "Фамилия", "Имя", "Обращение", "Должность". Назовите ее "СписокПриглашенных".
  3. Откройте файл Приглашение-dot и выполните команду меню Сервис, Письма и рассылки, Мастер слияния (Tools, Letters and Mailing, Mail Merge Wizard). Будет запущен Мастер слияния, который в новой версии Microsoft Word реализован в виде панели задач, расположенной слева на экране (рис. 15.34)

Рис. 15.34. Панель Мастера слияния

  1. Далее следуйте указаниям мастера. На первом шаге выберите тип документа — Письма (Letter) и нажмите кнопку Далее (Next), чтобы перейти к следующему шагу.
  2. На втором шаге выберите переключатель Текущий документ (Use The current document).
  3. На третьем шаге нужно указать источник данных. Оставьте значение поля Выбор получателей (Select Recipient) по умолчанию — Использование списка (Use an existing List) и нажмите на ссылку Обзор (Browse). Появится стандартное диалоговое окно для выбора файла.
  4. Найдите в этом окне файл "Борей.MDB" и нажмите кнопку Открыть (Open). Появится диалоговое окно со списком таблиц.
  5. Выберите в нем таблицу "СписокПриглашенных". Появится диалоговое окно, в котором будет отображено содержимое исходной таблицы (рис. 15.35). Закройте это окно.

Рис. 15.35. Диалоговое окно с содержимым таблицы "СписокПриглашенных"

  1. Теперь на экране отображается панель инструментов Слияние (Mail Merge). Установите курсор в левый верхний угол документа и нажмите кнопку Добавить поля слияния (Insert Merge Fields). Появляется одноименное диалоговое окно со списком всех полей в источнике данных. Выберите в списке поле "Обращение" и нажмите кнопку Вставить (Insert). Аналогично вставьте остальные поля (см. рис. 15.34). Поля слияния являются одним из видов полей Word и выглядят в основном документе как заключенные в угловые кавычки названия соответствующих полей источника данных.
  2. Сохраните документ в виде шаблона (файл с расширением dot) и закройте.

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

Private Sub MergeDocument_Click()

Dim wda As Word.Application

Dim rst As Recordset, rstNew As Recordset

Dim db As Database

Dim tdf As TableDef

Dim i As Integer

Set db = CurrentDb()

' Создаем новую таблицу

Set tdf = db.CreateTableDef("СписокПриглашенных")

With tdf

' Создаем поля таблицы и добавляем их в семейство Fields

.Fields.Append .CreateField("Фамилия", dbText)

.Fields.Append . CreateFieldC'HMH", dbText)

.Fields.Append .CreateField("Обращение", dbText)

.FieIds.Append .CreateField("Должность", dbText)

' Добавляем таблицу в семейство TableDefs

db.TableDefs.Append tdf End With

' копируем записи из формы в созданную таблицу

Set rst = Me.RecordsetClone rst.MoveFirst

Set rstNew = db.OpenRecordset("СписокПриглашенных")

Do While Not rst.EOF

rstNew.AddNew

for i = 0 To rst.Fields.Count - 1

rstNew.Fields(i) = rst.Fields(i)

Next i

rstNew.Update

rst.MoveNext Loop

' создаем объект Application Word

On Error GoTo err_StartWord

Set wda = GetObject(, "Word.Application")

wda.Visible = True

' открываем документ на основе шаблона - он добавляется в семейство

Documents wda.Documents.Add "C: \Doc\nj»iMiaEieHHe.dot"

' выполняем слияние основного документа и данных из источника

With wda.ActiveDocument.MailMerge

.Destination = wdSendToNewDocument

.Execute End With

' печатаем приглашения wda.ActiveDocument.Printout

Do While wda.backgroundPrintingStatus <> 0

DoEvents Loop

' сохраняем получившийся документ

wda.ActiveDocument.SaveAs "C:\Doc\MailMergeDoc.doc"

' закрываем окно с новым документом

wda.ActiveWindow.Close False

' закрываем, не сохраняя, окно с первоначальным документом

wda.Documents (1).Close False

' если нет больше открытых документов, то закрываем Word If

wda.Documents.Count = 0 Then

wda.Quit End If

' Удаляем временную таблицу

db.TableDefs.Delete "СписокПриглашенных"

db.Close

Set wda = Nothing

Set rst = Nothing

Set rstNew = Nothing

Exit Sub

err_StartWord:

If Err = 429 Then ' Word не запущен

Set wdd = CreateObject("Word.Application")

Resume Next Else

MsgBox Err.Description & " " & Err.Number, vblnformation

Exit Sub End If

End Sub

Сначала создается таблица "СписокПриглашенных" с той же структурой, которая была создана вручную. Затем все данные, отображаемые в форме, записываются в эту таблицу. Все операции с данными выполняются с использованием объектов DАО. Объект Application Word создается с помощью функции GetObject() или CreateObject () в зависимости от того, запущен ли уже Word. Для создания нового документа на основе шаблона используется метод Add семейства Documents. При слиянии основного документа с записями в таблице создается новый документ. Для этого устанавливается значение свойства Destination объекта MailMerge равным константе wdSendToNewDocument. Этот документ уже не содержит поля слияния, а является просто текстовым документом, который можно сохранить в виде файла, задав его имя. Перед сохранением в файле документ выводится на печать. После этого нужно аккуратно закрыть сначала новый документ, потом основной документ, к которому присоединен источник данных, и потом, если нужно, сам Word.