Связь Access с другими приложениями

Источник: infocity

Объектная модель MSWord. Основные понятия.
 

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

Структура Word рассматривается в основном структура word97(8), но будут ссылки и на 9 версию.

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

Для получения "структурного дерева" приложения Word нажмите F1 в окне редактора кода VBA Word и в сведениях о программировании найдите пункт Microsoft Word Objects(Объекты Word). Там вы обнаружите более 35 коллекций и объектов. Обращаю ваше внимание только на объекты ,необходимые для понимания прочитанного материала в дальнейшем.

Объектная модель Word представляет собой иерархию объектов, подчиненных одному объекту application. Большинство объектов используют только библиотеку Word, однако, некоторые ссылаются и на другие библиотеки (например, объект assistant - помощник ссылается на библиотеку объектов office)

табличка объектов первого уровня иерархии объектной модели Word.(элементы с пометкой "2000" доступны соответственно только в версиях Word начиная с 9)

Объект (семейство)
Комментарии

Application

Ссылается на активное приложение Word. Используется для управления приложением. Этот объект может быть использован другим приложением с помощью метода automation технологии ActiveX

Addin (addins)

Семейство объектов addin - набор всех доступных надстроек Word. Просмотреть надстройки и шаблоны можно в диалоговом окне, выбрав в меню Word пункт сервисшаблоны и надстройки.

Browser

Средство передвижения курсора по объектам документа (задействуется при активации в нижнем правом углу окна Word в полосе вертикальной прокрутки одной из трех кнопок навигации или нажатии комбинации клавиш "ctrl+alt+home" )

Dafaultweboptions 2000

Активизируется при работе с Web-документами.

Dialog(dialogs)

Набор встроенных диалоговых окон (например "Открытие файла")

Document(documents)

Семейство объектов document- набор всех открытых документов

Emailoptions 2000

Через этот объект приложение Word имеет доступ ко всем глобальным параметрам, используемым при правке в Word сообщений электронной почты

Filecionverter(Filecionverters)

Набор всех установленных конверторов, которые используются при открытии/сохранении документа

Language(Languages)

Набор языков используемых при проверке орфографии

Options

Через этот объект производится доступ к параметрам приложения и документов Word. Многие параметры доступны в диалоговом окне Word в меню сервиспараметры

Selection

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

System

Через этот объект производится доступ к некоторым параметрам операционной системы, производится доступ к реестру, файлам *.ini и др.

Template(Templates)

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

Window(Windows)

Все окна приложения Word

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

Хочется еще отметить, что объект Selection вынесен в верхушку иерархии Word и обращается к выделенной области или месту вставки активного  документа приложения. Т.е. надо быть аккуратным, при обращении к свойствам этого объекта, пока открыты несколько документов Word, и не забывать, что Selection принадлежит объекту Application. И он единственный.

Семейство Documents предназначено для управления документами Word. Это наиболее употребляемый объект и поэтому приведу описание основных объектов и семейств подчиненных этому объекту.

Табличка объектов, подчиненных объекту Document .

Объекты
Комментарии

Bookmark(Bookmarks)

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

Characters[ range ]

Важный элемент семейства range. Каждый элемент соответствует одному символу документа, диапазона или области выделения. Свойство count элемента Characters даст количество символов документа. ВНИМАНИЕ! Нет элемента Character.

Email 2000

Объект - сообщение электронной почты. У каждого документа - только 1 такой объект. Доступен только в режимах правки документа как электронного сообщения.

Fields(field)

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

Pagesetup

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

Paragraph(Paragraphs)

Коллекция абзацев документа, диапазона или области выделения.

Range

Наверное, самый важный элемент документа по работе с его содержимым. Представляет собой строго определенный диапазон, однозначно определен начальным и конечным символом диапазона. Используется для идентификации текста в документе. От области выделения не зависят. В отличие от выделенной области можно работать с несколькими диапазонами одновременно. Доступны только во время выполнения процедуры VBA . Любая манипуляция с диапазоном (диапазонами) вне области выделения не затрагивает области выделения и никак ее не меняет.

Section(sections)

Набор разделов документа, диапазона или области выделения

Sentences[ range ]

Важный элемент семейства range. Каждый элемент соответствует одному предложению документа, диапазона или области выделения. Свойство count элемента Sentencesдаст количество предложений документа. ВНИМАНИЕ! Нет элемента Sentence.

Style(Styles)

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

Subdocument(subdocuments)

Коллекция подчиненных документов документа или диапазона

Table(tables)

Коллекция таблиц документа, диапазона или области выделения

Variable(variables)

Семейство объектов - переменных документа. Variableсодержит определенный код, и в обычном режиме не доступна конечному пользователю. Используя определенный тип поля(fields) можно выводить содержимое Variableв определенное место документа. Чаще всего используется в VBA .

Weboptions 2000

Через этот объект производится доступ к параметрам документа при сохранении или открытии WEB-документа.

Words[ range ]

Важный элемент семейства range. Каждый элемент соответствует одному слову документа, диапазона или области выделения. Свойство count элемента Wordsдаст количество словдокумента. ВНИМАНИЕ! Нет элемента Word.

В этой табличке были выделены те элементы объекта document, что принадлежат семейству range (диапазон).
Именно через этот элемент происходит доступ к любому месту/символу/вставке/и т.д. Как вы успели, наверное, заметить, любой символ документа принадлежит к семейству range. Причем один символ еще принадлежит к подразделу characters, группа символов ограниченных пробелами (точнее заканчивающиеся пробелами или знаками препинания) - к подразделу words, набор символов ограниченных точками с пробелом (переводами каретки, и т.п.) - к Sentences. На мой взгляд - замечательная задумка. Само собой, что там, где есть что-то хорошее - там есть и плохое.
Плюсы, наверное, очевидны:

* Быстрый доступ к любому элементу - слову, предложению, и т.п.
* Проверка слов (символов, предложений) происходит автоматически при добавлении чего-либо в семейство.
* Удобная навигация перехода - посимвольно, пословно, по предложениям.
* Поиск по семейству проще.
* Статистика автоматическая - выделил - получил отчет о наличии чего-либо.

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

* Большой текст - много элементов семейства - документ сильнее загружает машину при работе с ним.
* Известно, что, например, работа с массивом происходит быстрее.
* Ввиду заложенных особенностей каждого элемента семейства range не всегда корректно работает поэлементная статистика, для предотвращения чего навешивается проверка ошибок статистики и проч.

Нет, конечно же, Range работает правильно. Именно так, как и должно быть по правилам элементов семейств. Но не всегда так, как хочется. Например: Данилов М.Е. - Это 6 слов (точка - самостоятельное слово, пробел к словам не относится, далее следует место вставки т.е. курсор - это тоже слово), и одно предложение. Но проверка насильно мне указывает, что я забыл пробел после первой точки. Ставим пробел - получили 6 слов, и 2 предложения. Именно этот момент чаще всего вынуждает при авто переносе текста из какого-нибудь другого приложения office использовать другие механизмы передачи данных (поля, закладки, переменные). Но если вы точно знаете, сколько слов и предложений будет (было), то раскидать по местам нужные нам данные не составит очень уж большого труда.

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

Задача.
* Открываем новый документ на основе шаблона normal.
* Проверим, нет ли там чего ненужного (слов, и т.п.).
* Создаем и вставляем текст.
* Находим 10 Слово.
* Меняем его на него же, но с заглавной буквы.
* Находим слово аксессс и меняем его на Access
* Находим символ [@], причем не позднее 3-го предложения, меняем его на [№].
* Ищем "господа" и добавляем ", а также дяденьки и тетеньки".
Все действия производим, используя механизмы Word.

 

Public Sub text_in_word()

Dim word_obj As Object ' не стоит забывать что так тоже можно обьявлять переменную.

Dim const_input_txt As String ' Это тот кусок текста, что нам надо перенести в ворд

Dim Full_name_new_doc As String 'ПОЛНОЕ имя нашего документа будет лежать здесь

Dim Name_new_doc As String 'имя нашего документа будет лежать здесь

Dim i As Integer 'пригодится, мало ли чего..... :)

Dim range_word As Word.Range 'а вот это стадия раннего связывания. .
' Ниже будет понятно зачем оно нам надо (не связывание а переменная)
Dim range_character As Word.Range 'Ниже будет понятно зачем оно нам надо

Dim range_sentences As Word.Range 'Ниже будет понятно зачем оно нам надо

'' ----------стандартный модуль открытия объекта --------

Err.Clear 'очистка ошибок

On Error Resume Next

Set word_obj = GetObject(, "word.Application")'Проверили, вдруг ворд уже открыт

If Err = 429 Then ' ну коли закрыт - откроем

Set word_obj = CreateObject("word.Application") 'так или иначе, объект мы получили

ElseIf Err <> 0 Then

MsgBox "error" & Err ' если какая то еще ошибка - например пользователь не имеет доступа

End If ' к ворд - пишем какая ошибка

If Err <> 429 And Err <> 0 Then Exit Sub Else Err.Clear ' и выйдем, если ошиблись

On Error GoTo 0 ' при этом еще происходит очистка ошибки аналогично Err.Clear

'' ----------Ваяем далее --------

''-----------Проверка свободного файла -----------------

On Error Resume Next

If Dir("c:text_in.doc", vbNormal) <> "" Then Kill "c:text_in.doc" 'Этот файл будет шаблоном

'для последующего переноса данных. Если он уже есть тогда его удалим.

If Err = 75 Then

MsgBox "А кто то с этим файлом работает...." 'если файл занят другими пользователями

Exit Sub ' остановим процедуру

ElseIf Err <> 0 Then

MsgBox Err ' при условии что призошла ошибка файловой системы

Exit Sub ' тоже остановим процедуру

End If

On Error GoTo 0

''------------------- место для файла есть, объект создали --------

''----- Откроем новый файл, с шаблоном Normal ---------

With word_obj 'Что бы не писать далее много раз имя переменной.

'И работать будет немного быстрее

.Visible = True 'а то не видно, чего там происходит :)

.Documents.Add Template:="normal.dot", NewTemplate:=False, _

DocumentType:=wdNewBlankDocument, Visible:=True

' добавили ЧИСТЫЙ НОВЫЙ документ, шаблон у него будет normal, он станет активным при открытии

' и будет именно документом, а не шаблоном

Full_name_new_doc = .ActiveDocument.FullName ' получили ПОЛНОЕ имя нашего нового документа

Name_new_doc = .ActiveDocument.Name ' получили имя нашего нового документа

const_input_txt = "Уважаемые дамы и господа! Оповещаем Вас, что надо обработать " & _

"все нижеперечисленные заказы и развезти их по адресам:" & vbCrLf & " Заказ#234/исп " & _

vbCrLf & "тот кто не имеет аксесс к необходимым документам, тот будет отстранен до выяснения " & _

"причин присутствия наличия отсутствия!"
'Тут я использовал vbcrlf,как перенос строки, для получения

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

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

If .ActiveDocument.FullName <> Full_name_new_doc Then .Documents(Name_new_doc).Activate

If .ActiveDocument.Words.Count > 1 Then ' дело в том что в чистом документе есть 1 "слово"

'Это место вставки.

For i = .ActiveDocument.Words.Count To 2 Step -1 'Задом наперед для того что бы не возиться с

' do while - end

.ActiveDocument.Words(i).Delete 'убираем все слова поочередно, начиная с последнего

'я, конечно же, понимаю, что в НОВОМ документе нет ничего. Этот кусок нужен тем, кто работает

' с существующими документами.

Next

End If

.Selection.Text = const_input_txt ' Использовали объект selection для вставки текста.

'т.к. именно наш документ сейчас активен - то все нормально.Но все же я проверил какой документ активен.

'ввиду того, что никаких выделеных областей в новом документе нет, а есть только область вставки

'(палочка-курсор), то вставится именно в это место.

If .ActiveDocument.Words.Count > 10 Then
'Мы то знаем что слов вставили более 10 шт. Но мало ли чего.

.ActiveDocument.Words(10).Case = wdTitleWord 'Удобный метод range, по смене регистра

For Each range_word In .ActiveDocument.Words 'Поиск во всем диапазоне слов

If range_word.Text = "аксессc " Then range_word.Text = "Access "
' слово должно оканчиваться пробелом
' или знаком препинания или спец сиволом

Next

End If

Set range_sentences = .ActiveDocument.Range(Start:=.ActiveDocument.Sentences(1).Start, End:=.ActiveDocument.Sentences(3).End)
' сделали конецом диапазона третье предложение ' сделали началом диапазона первое предложение

range_sentences.Select

For Each range_character In range_sentences.Characters
' только для 3х предложений

If range_character.Text Like "@" Then range_character.Text = "№"
' like тоже можно использовать

Next
' последнее, это добавление новых элементов в коллекцию.
' много вариантов. Например использовать метод replace
' можно использовать метод find, а потом selection и вставить текст
' ну раз уж мы используем коллекции. У words нет явного метода add. Думаю это сделано для
' избежания неразберихи, при введении этого метода явно.
' а вот метод insertafter (before) как пить дать то что надо!

For Each range_word In .ActiveDocument.Words

If range_word.Text = "господа" Then range_word.InsertAfter ", а также дяденьки и тетеньки"

Next
' ну вроде все что обещался - сделал. Причем только методы ворд использовал.

Full_name_new_doc = "c:text_in.doc"
'Задали имя для записи документа

.ActiveDocument.saveas filename:=Full_name_new_doc, fileformat:=wdFormatDocument
'вообще
'SaveAs имеет много параметров, так что я часть их просто не использовал

.ActiveDocument.Close
'Закрыл именно этот документ

If .Documents.Count = 0 Then .Application.Quit SaveChanges:=wdDoNotSaveChanges
'А вот тут как раз проверили, если нет более документов - можем вообще закрыть приложение.

End With

Set word_obj = Nothing
'очистили память

End Sub


 


 

Модуль запускается из Access и создает документ на диске С в корневом каталоге. Этот пример при пристальном осмотре должен научить использовать основные элементы семейства range объекта document приложения Word. В принципе, все вышеперечисленные механизмы позволят быстро ориентироваться в теле любого документа. Одно большое НО. Для передачи данных из другого приложения и создания шаблона надо выстроить четкий алгоритм расстановки данных.

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

Что касается остальных, не менее важных элементов Document, то оставим их на следующий раз.

Напоследок маленький, но забавный и не особо нужный в работе пример. Кувыркатель индикатора клавиатуры (язык при этом меняется только в Word) при запуске модуля из Access. Не знаю, то, что в других приложениях office язык остается тем же, хотя индикатор сменился, правильно это или нет. Вам судить. Но, как факт, такое возможно:

 

Public Sub shifted_lang()

Dim word_obj As Word.Application
'Требует раннего связывания

Err.Clear 'очистка ошибок

On Error Resume Next

Set word_obj = GetObject(, "word.Application")
'Проверили, вдруг ворд уже открыт

If Err = 429 Then ' ну коли закрыт - откроем

Set word_obj = CreateObject("word.Application")
'так или иначе, объект мы получили

ElseIf Err <> 0 Then

MsgBox "error" & Err
' если какая то еще ошибка - например пользователь не имеет доступа

End If ' к ворд - пишем какая ошибка

If Err <> 429 And Err <> 0 Then Exit Sub Else Err.Clear
' и выйдем, если ошиблись

On Error GoTo 0 ' при этом еще происходит очистка ошибки аналогично Err.Clear

If word_obj.Keyboard = 68748313 Then word_obj.Keyboard (1033) Else word_obj.Keyboard (1049)

'если английский - переключили на русский и наоборот.

If word_obj.Documents.Count = 0 Then word_obj.Application.Quit SaveChanges:=wdDoNotSaveChanges

'Проверили, если нет более документов - можем вообще закрыть приложение.

Set word_obj = Nothing 'очистили память

End Sub


 


 

Этот момент показывает наличие некоторых удобных, но недоступных Access, механизмов Word. Так что ждем. Вдруг и у Access такое будет возможно. Без WinApi.

Подведем итог всего, что тут написано.

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


Страница сайта http://test.interface.ru
Оригинал находится по адресу http://test.interface.ru/home.asp?artId=10341