Обмен
данными с 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).
Чтобы вставить
такое поле в документ, нужно:
Рис. 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
Шаблон документа
должен быть приготовлен заранее. Рассмотрим, как это можно сделать.
Рис. 15.34.
Панель Мастера слияния
Рис. 15.35.
Диалоговое окно с содержимым таблицы "СписокПриглашенных"
Рассмотрим
теперь программу, которая будет выполнять слияние документа 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.