скрыть

скрыть

  Форум  

Delphi FAQ - Часто задаваемые вопросы

| Базы данных | Графика и Игры | Интернет и Сети | Компоненты и Классы | Мультимедиа |
| ОС и Железо | Программа и Интерфейс | Рабочий стол | Синтаксис | Технологии | Файловая система |



Google  
 

Delphi и OLE Automation с Word



In the beginning was the Word, and the Word was 1.0...

Автоматизация позволяет одному приложению управлять другим приложением. Управляемое приложение называется сервером автоматизации (в нашем случае Word). Приложение, управляющее сервером называется диспетчером автоматизации.

Есть два пути для получения доступа к серверам автоматизации:

Позднее связывание (Интерфейс IDispatch)

При использовании данного метода имена функций и типы параметров решаются во время выполнения программы, все параметры определены вариантным типом.

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

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

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

Раннее связывание (Использование библиотеки типов/интерфейсов)

При использовании данного метода имена функций и типы параметров полностью решаются во время компиляции.

Библиотека типов должна импортироваться в Delphi. Библиотека типов является языковым нейтральным описанием всех объектов и функций, поддерживаемых сервером. (Это подобно файлу заголовка языка C).

При вызове функции должны обязательно присутствовать все параметры, даже те, которые в документации указаны как дополнительные (необязательные). Это позволяет обнаружить и исправить множество ошибок еще до запуска программы.

Скорость выполнения значительно быстрее, чем при использовании позднего связывания.

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

Подготовка библиотеки типов.

Модуль Pascal должен быть создан на основе файла библиотеки типов.

  • Выберите пункт меню Project|Import Type Library
  • Нажмите кнопку Add и выберите следующий файл
  • c:\program files\microsoft office\office\msword8.olb
  • Нажмите OK.

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

Наиболее простой путь заключается в следующем: удалите модуль excel_tlb из проекта и только после этого добавьте его в список используемых модулей.

Документация

Справочный файл c:\program files\microsoft office\office\vbawrd8.hlp содержит информацию о доступных объектах Word.

"Записыватель" макросов позволяет быстро создавать VBA-код. После этого он довольно может легко быть портирован в Delphi.

Пример автоматизации

Следующий пример использует класс-оболочку Delphi, инкапсулирующий прямые вызовы объектов Word. Вот преимущество этого метода:

  • Обеспечение скрытия параметров. Возможность использования для многих методов параметров по умолчанию. Многие методы Word также работают с вариантными параметрами. Это означает невозможность использования констант - скрытие параметров решает данную проблему.
  • Обеспечение проверки типа. Многие методы определены с параметрами OLEVariant, обеспечивая внешнюю совместимость.
  • Следующий класс-оболочка демонстрирует ключевые методы автоматизации Word. Полностью класс приведен в Приложении 1.

unit doc;
interface
uses

  windows, sysutils, Word_TLB;
type

  TWinWord = class
  private
    App: _Application;
  public
    constructor Create;
    destructor Destroy; override;
    procedure NewDoc(Template: string);
    procedure GotoBookmark(Bookmark: string);
    procedure InsertText(Text: string);
    procedure SaveAs(Filename: string);
  end;

  //------------------------------------------------------------------

implementation

//------------------------------------------------------------------

constructor TWinWord.Create;
begin

  App := CoApplication.Create;
end;

//------------------------------------------------------------------

destructor TWinWord.Destroy;
var
  SaveChanges: OLEVariant;
  OriginalFormat: OLEVariant;
  RouteDocument: OLEVariant;
begin

  SaveChanges := wdDoNotSaveChanges;
  OriginalFormat := unAssigned;
  RouteDocument := unAssigned;
  app.Quit(SaveChanges, OriginalFormat, RouteDocument);
  inherited destroy;
end;

//------------------------------------------------------------------

procedure TWinWord.GotoBookmark(Bookmark: string);
var

  What: OLEVariant;
  Which: OLEVariant;
  Count: OLEVariant;
  Name: OLEVariant;
begin

  What := wdGoToBookmark;
  Which := unAssigned;
  Count := unAssigned;
  Name := Bookmark;
  App.Selection.GoTo_(What, Which, Count, Name);
end;

//------------------------------------------------------------------

procedure TWinWord.InsertText(Text: string);
begin

  App.Selection.TypeText(Text);
end;

//------------------------------------------------------------------

procedure TWinWord.NewDoc(Template: string);
var

  DocTemplate: OleVariant;
  NewTemplate: OleVariant;
begin

  DocTemplate := Template;
  NewTemplate := False;
  App.Documents.Add(DocTemplate, NewTemplate);
end;

//------------------------------------------------------------------

procedure TWinWord.SaveAs(Filename: string);
begin

  OLEVariant(App).ActiveDocument.SaveAs(FileName);
end;

//------------------------------------------------------------------

end.

Чтобы создать класс:

Добавьте модуль библиотеки типов в список используемых модулей.


uses
  windows, sysutils, Word_TLB;

Создадим определение класса:


TWinWord = class

Private
App : _Application;
public
procedure NewDoc(Template : String);
procedure GotoBookmark(Bookmark : String);
procedure InsertText(Text : String);
procedure SaveAs(Filename : string);
constructor Create;
destructor Destroy; override;
end;

Переменная App является ссылкой на приложение Word. Это допускает вызов методов Word с применением технологии раннего связывания.

Опубликованные (public) процедуры - процедуры, которые могут быть использованы при работе с классом.

Создадим конструктор.


constructor TWinWord.Create;
begin
  App := CoApplication.Create;
end;

Он вызывается при создании класса TWinWord. CoApplication.create создает новый экземпляр Word и возвращает ссылку на интерфейс Application. Это позволяет вызывать методы объекта app.

Реализация дектруктора


destructor TWinWord.Destroy;
var

SaveChanges : OLEVariant;
OriginalFormat : OLEVariant;
RouteDocument : OLEVariant;
begin

SaveChanges := wdDoNotSaveChanges;
OriginalFormat := unAssigned;
RouteDocument := unAssigned;
app.Quit(SaveChanges, OriginalFormat, RouteDocument);
inherited destroy;
end;

Деструктор должен вызываться В ОБЯЗАТЕЛЬНОМ ПОРЯДКЕ. Метод Quit объекта приложения закрывает Word и распределяет всю связанную с ним память. Так как параметры метода Quit определены как вариантный тип OLEVariant, вся свазанная с ними память распределяется именно для этого типа переменных.

Реализуем метод NewDoc. Этот метод создаст новый текстовый документ на основе заданного шаблона.


procedure TWinWord.NewDoc(Template : String);
var

DocTemplate : OleVariant;
NewTemplate : OleVariant;
begin

DocTemplate := Template;
NewTemplate := False;
App.Documents.Add(DocTemplate, NewTemplate);
end;

Данный метод осуществляет более строгую проверку типов, чем это осуществляет сам Word. Параметр Template должен содержать строку с именем шаблона. Метод Word Add в качестве параметров может содержать значения любого типа. Лучшая пример этого - метод MoveRight, реализация которого показана в Приложении 1.

Ниже показана реализация метода SaveAs. Данный метод позволит сохранить в файле текущий документ.


procedure TWinWord.SaveAs(Filename : string);
begin
  OLEVariant(App).ActiveDocument.SaveAs(FileName);
end;

проверяются только во время прогона. Изменение имени метода в этом случае не вызовет ошибку во время компиляции. В нашем случае технология позднего связывания более эффективна, так как метод SaveAs требует 12 параметров, но только параметр FileName является обязательным. Так как данный вызов можно считать единичным, его выполнение не может особо сказаться на скорости выполнения программы.

Следующий код демонстрирует использование данного класса для создания, редактирования, печати и сохранения документа, созданного на основе шаблона:


Word := TWinWord.create;
try

Word.visible := true;
Word.NewDoc('c:\delphi\word\sample\Demo');
Word.GotoBookmark('From');
Word.InsertText('Иван Иваныч');
Word.GotoBookmark('Dept');
Word.InsertText('Разработка');
Word.GotoBookmark('Phone');
Word.InsertText('111111');
Word.GotoBookmark('Now');
Word.InsertText(FormatDateTime('d-mmm-yyyy', now));
//SF элементы
Word.GotoBookmark('Items');
Word.InsertText('112021');
Word.MoveRight(1);
Word.InsertText('PVCS');
Word.MoveRight(1);
Word.InsertText('1');
Word.MoveRight(1);
Word.InsertText('£ 305.99');
Word.MoveRight(1);
Word.InsertText('£ 305.99');
Word.MoveRight(1);
Word.UpdateFields;
Word.RunMacro('Demo');
Word.Print;
Word.SaveAs(filename);
finally

Word.Free;
end;

Итог

  • Всегда используйте раннее связывание.
  • Если позднее связывание необходимо для вызовов некоторых функций, используйте где возможно раннее связывание и преобразование типа объектной переменной к типу OLEVariant для вызовов, требующим позднее связывание.
  • Не включайте модуль библиотеки типов в ваш проект. Добавьте его только в список используемых модулей.
  • Создавайте код автоматизации в отдельном модуле. Инкапсулируйте вызовы в классе-оболочке.
  • Используйте "записыватель" макросов Word для создания прототипа кода автоматизации.
  • Используйте файл электронной справки vbawrd8.hlp для получения информации об объектах Word.
  • Используйте модуль Word_tlb.pas для проверки необходимых Delphi типов и количества параметров. Для проверки правильности кода перекомпилируйте проект, нажав клавиши <CTRL><F9>.
  • Загружайте и используйте шаблоны Word, содержащие предварительное форматирование текста. Этот способ существенно быстрее и не требует большого времени для создания сложноформатированных документов. Шаблоны ДОЛЖНЫ сохраняться приложением в своей рабочей директории. Это поможет избежать проблем, связанных с конфликтом имен.
  • Используйте закладки (Bookmarks) для определения области ввода текста приложением Delphi.
  • Удостоверьтесь в том, что ваш код содержит команду закрытия приложения Word (app.quit). Не вызывая app.quit, можно быстро исчерпать системные ресурсы, особенно при работе с большим количеством документов Word. Обратите на это особое внимание.
  • Наличие множества незакрытых документов Word легко проверить в Windows NT, используя Менеджер Задач (нажмите CTL+ALT+Del для его открытия).

Приложение A – Полный исходный код сласса TWinWord

Полный исходный код класса tWinWord приведен ниже. Он включает реализацию всех методов:


unit doc;
interface
uses

  Word_TLB, windows, sysutils;
type
  TWinWord = class

  private
    App: _Application;
    function fGetVisible: boolean;
    procedure fSetVisible(visible: boolean);
  public
    procedure NewDoc(Template: string);
    procedure GotoBookmark(Bookmark: string);
    procedure InsertText(Text: string);
    procedure MoveRight(Count: integer);
    procedure Print;
    procedure UpdateFields;
    procedure SaveAs(Filename: string);
    procedure RunMacro(MacroName: string);
    constructor Create;
    destructor Destroy; override;
    property visible: boolean
      read fGetVisible
      write fSetVisible;
  end;

implementation

//------------------------------------------------------------------

constructor TWinWord.Create;
begin

  App := CoApplication.Create;
end;

//------------------------------------------------------------------

destructor TWinWord.Destroy;
var
  SaveChanges: OLEVariant;
  OriginalFormat: OLEVariant;
  RouteDocument: OLEVariant;
begin

  SaveChanges := wdDoNotSaveChanges;
  OriginalFormat := unAssigned;
  RouteDocument := unAssigned;
  app.Quit(SaveChanges, OriginalFormat, RouteDocument);
  inherited destroy;
end;

//------------------------------------------------------------------

function TWinWord.fGetVisible: boolean;
begin

  result := App.Visible;
end;

//------------------------------------------------------------------

procedure TWinWord.fSetVisible(Visible: boolean);
begin

  App.visible := Visible;
end;

//------------------------------------------------------------------

procedure TWinWord.GotoBookmark(Bookmark: string);
var

  What: OLEVariant;
  Which: OLEVariant;
  Count: OLEVariant;
  Name: OLEVariant;
begin

  What := wdGoToBookmark;
  Which := unAssigned;
  Count := unAssigned;
  Name := Bookmark;
  App.Selection.GoTo_(What, Which, Count, Name);
end;

//------------------------------------------------------------------

procedure TWinWord.InsertText(Text: string);
begin

  App.Selection.TypeText(Text);
end;

//------------------------------------------------------------------

procedure TWinWord.NewDoc(Template: string);
var

  DocTemplate: OleVariant;
  NewTemplate: OleVariant;
begin

  DocTemplate := Template;
  NewTemplate := False;
  App.Documents.Add(DocTemplate, NewTemplate);
end;

//------------------------------------------------------------------

procedure TWinWord.MoveRight(Count: integer);
var

  MoveUnit: OleVariant;
  vCount: OleVariant;
  Extended: OleVariant;
begin

  MoveUnit := wdCell;
  vCount := Count;
  Extended := unassigned;
  app.selection.MoveRight(MoveUnit, vCount, Extended);
end;

//------------------------------------------------------------------

procedure TWinWord.Print;
begin

  OLEVariant(app).Printout;
end;

//------------------------------------------------------------------

procedure TWinWord.UpdateFields;
begin

  App.ActiveDocument.Fields.Update;
end;

//------------------------------------------------------------------

procedure TWinWord.SaveAs(Filename: string);
begin

  OLEVariant(App).ActiveDocument.SaveAs(FileName);
end;

//------------------------------------------------------------------

procedure TWinWord.RunMacro(MacroName: string);
begin

  App.Run(MacroName);
end;

//------------------------------------------------------------------

end.







Copyright © 2004-2016 "Delphi Sources". Delphi World FAQ


|  Светодиодная лента светодиодные ленты http://www.sitmarket.net/.  |

Группа ВКонтакте   Ссылка на Twitter   Группа на Facebook