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

Сегодня, в последний рабочий день недели, практически весь день провозился над передачей данных из Delphi в Word. Так как подозрение есть, что работа продолжится то решил кое-какие моменты по работе с Microsoft Word в Delphi запечатлеть и у себя в блоге. Написать такую мини-шпаргалку (тем более, что по Excel уже кое что есть).

Для начала, немного общих моментов по работе с MS Office в Delphi. И первое, что мы сделаем — это создадим объект Word.Application. Создается этот объект абсолютно также, как и объект Excel.Application:

uses ComObj;
var Word: variant;
[...]
procedure CreateWord(const Visible: boolean);
begin
  Word:=CreateOleObject('Word.Application');
  Word.Visible:=Visible;
end;

Всё достаточно просто. Далее мы можем работать с объектом следующим образом:

  1. Создавать документ Word с нуля
  2. Открыть уже существующий документ и изменить в нем текст для получения необходимой формы документа.

Рассмотрим оба варианта, т.к. оба они имеют как свои плюсы, так и недостатки.

1. Создание документа Microsoft Word в Delphi с нуля.

Чтобы создать новый документ необходимо выполнить метод Add у коллекции Documents, т.е.:

[...]
Word.Documents.Add
[...]

и после этой операции уже начинать работать с документам обращаясь к нему по индексу или имени в коллекции. Также, можно создать новый документ по шаблону (*.dot). Для этого необходимо выполнить тот же метод Add, но с одним входным параметром — путем к файлу-шаблону:

[...]
Word.Documents.Add(TamplatePath:string);
[...]

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

[...]
var List: TStringList;
    i: integer;
begin
  List:=TStringList.Create;
  for i:=1 to Word.Documents.Count do
    List.Add(Word.Documents.Item(i).Name);
end;
[...]

Обратите внимание, что нумерация начинается с 1, а не с нуля. Чтобы активировать любой документ из коллекции для работы, необходимо выполнить метод Activate:

Word.Documents.Item(index).Activate

где index — номер документа в коллекции.

Теперь можно приступать к записи и чтению документа. Для работы с текстов в документе Word, как и в Excel для работы с ячейками таблицы, определен объект Range. Именно методы этого объекта и дают нам возможность работы с текстом. Для начала рассмотрим работу двух основных методов: InsertBefore и InsertAfter.

Как следует из название — первый метод вставляет текст в начало содержимого Range, а второй — в конец. При этом сам объект Range может содержать как весть документ (Document) так и какую-либо его часть. Например, в следующем листинге я вставлю строку в начало документа и затем методом InsertAfter буду добавлять несколько строк текста в конец документа:

[...]
Word.ActiveDocument.Range.InsertBefore('Hello World');
Word.ActiveDocument.Range.InsertAfter('текст после Hello World');
Word.ActiveDocument.Range.InsertAfter('окончание строки в документа');
[...]

При выполнении этих трех операции Range содержал весь документ.

Если работать со всем документом неудобно, а необходимо, например выделить фрагмент с 50 по 100 символ и работать с ним, то можно воспользоваться функцией Range, которая вернет нам необходимый объект Range:

var MyRange: variant;
begin
  MyRange:=WordActiveDocument.Range(50,100);
  MyRange.InsertBefore('Привет');//всё, что было после 50-го символа сдвинулось вправо
end;

Это что касается записи текста. Решение обратной задачи — чтения текста из документа ещё проще. Достаточно воспользоваться свойством Text у объекта Range:

[...]
ShowMessage(Word.ActiveDocument.Range.Text) //весь текст в документе
[...]

Также для чтения документа можно воспользоваться коллекцией документа Words (слова). За слово принимается непрерывный набор символов — цифр и букв, который оканчивается пробелом.

Перечисляются слова документа точно также как и при работе с коллекцией документов, т.е. первое слово имеет индекс 1 последнее — Word.Count.

[...]
  ShowMessage(Word.ActiveDocument.Words.Item(Word.ActiveDocument.Words.Count).Text)
[...]

В данном случае я вывел на экран последнее слово в документе.

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

2. Работа с документами Word в Delphi. Открытие готового документа и замена текста.

Чтобы открыть заранее заготовленный документ Word в Delphi достаточно воспользоваться методом Open у коллекции Documents, например так:

var FilePath: string;
[...]
  Word.Documents.Open(FilePath)
[...]

Метод Open можно вызывать с несколькими аргументами:

  • FileName: string — путь и имя файла;
  • ConfirmConversions: boolean — False — не открывать диалоговое окно «Преобразование файла» при открытии файла, формат которого не соответствует формату Word (doc или docx)
  • ReadOnly:boolean — True — открыть документ в режиме «Только для чтения»
  • AddToRecentFiles: boolean — True, чтобы добавить документ в список недавно открытых документов.
  • PasswordDocument: string — пароль для открытия документа
  • PasswordTemplate: string — пароль для открытия шаблона
  • Revert : boolean — True, чтобы вернуться к сохраненному документу, если этот документ открывается повторно.
  • WritePasswordDocument: string — пароль для сохранения измененного документа в файле
  • WritePasswordTemplate:string — пароль для сохранения изменений в шаблоне
  • Format:integer — формат открываемого документа.

Обязательным параметром метода Open является только FileName, остальные — могут отсутствовать. Если же Вам необходимо воспользоваться несколькими параметрами, то их необходимо явно указывать при вызове метода, например:

[...]
  Word.Documents.Open(FileName:=FilePath, ReadOnly:=true)
[...]

В этом случае документ открывается в режиме «Только для чтения». При таком способе вызова (с явным указанием аргументов) положение аргументов может быть произвольным.

Что касается последнего аргумента — Format, то он может принимать  целочисленные значения (применительно к версиям Microsoft Word 2007 и выше) от 0 до 13. При этом, для того, чтобы открыть «родные» вордовские документы (doc) достаточно использовать значения 0 или 6.

Теперь, когда документ открыт его необходимо преобразовать. Обычно я делаю следующим образом: в тех местах документа, в которые необходимо вставить текст я расставляю либо закладки, либо простые строки текста, например, обрамленные символом $ или #. И затем просто выполняю поиск и замену подстрок следующим образом:

function FindAndReplace(const FindText,ReplaceText:string):boolean;
  const wdReplaceAll = 2;
begin
  Word.Selection.Find.MatchSoundsLike := False;
  Word.Selection.Find.MatchAllWordForms := False;
  Word.Selection.Find.MatchWholeWord := False;
  Word.Selection.Find.Format := False;
  Word.Selection.Find.Forward := True;
  Word.Selection.Find.ClearFormatting;
  Word.Selection.Find.Text:=FindText;
  Word.Selection.Find.Replacement.Text:=ReplaceText;
  FindAndReplace:=Word.Selection.Find.Execute(Replace:=wdReplaceAll);
end;

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

Вот, наверное, самые-самые простые методы работы с Word в Delphi. Кстати, пишу пост и, думаю, что у кого-то из читателей может возникнуть вопрос: причём тут Delphi в Internet и Word в Delphi? :) Честно говоря, приведенный выше фрагменты кода можно использовать для нужд в Internet с натяжкой, например, при автосоставлении небольших отчётов по чему-либо. А вообще, в недалеком будущем, есть в планах поразбираться с Тезаурусом Word и попробовать составить небольшой синонимайзер для собственных нужд — он-то и пригодится нам в Internet :)

3.5 10 голоса
Рейтинг статьи
уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.
Подписаться
Уведомить о
66 Комментарий
Межтекстовые Отзывы
Посмотреть все комментарии
Алексей
Алексей
27/02/2010 23:50

Спасибо, попробую сегодня. А для чего тебе вообще из программы в Word пересылку делать? Отчеты что ли там формируют? Просто для этого вроде более удобные способы есть. Хотя заказчикам все подряд нужно. :-)

DimaBy
DimaBy
28/02/2010 00:51

А не проще ли использовать юниты с ранним связываеним.
Например word2000.pas,wordxp.pas  и т.п.
Все продукты офиса имеют обратную совместимость, т.е. word2000.pas отлично отработает на msword2007.
У них есть только 1 недостаток — почему-то параметры нужно передавать через var, а это затрудняет использование констант, зато в результате мы сразу можем пользоваться всеми прелестями синтаксис-помощника

JayDi
28/02/2010 21:47

Еще можно было бы упомянуть о такой маленькой хитрости, как макросы. Когда мы не знаем нужных нам команд для работы с Excel или Word — открываем документ, делаем запись макроса и смотрим его исходники. Код на Visual Basic практически не будет отличаться от того, который нам нужен в Delphi.

irwin
irwin
01/03/2010 15:33

Интересует формирование отчётов не через OLE в ворд, а через создание  XML документа, который ворд откроет.

Гимаев Наиль
Гимаев Наиль
02/03/2010 21:58

Использовать в серьезных проектах привязку к Word не правильно. Как системный администратор я перевел целое предприятие на лицензионный софт. Word был куплен только для секретаря. У остальных, в том числе и у бухгалтерии, был поставлен OpenOffice.org, на всякий случай. Когда выяснилось, что одна из бухгалтерских программ требует для своей печати Microsoft Office, то пришлось воспользоваться менее качественной, но более самостоятельной программой. К первоначальному варианту мы вернулись лишь тогда, когда программа научилась печатать генерируя PDF-файлы. Если задача нашей программы лишь красиво напечатать, то пусть генерирует PDF. А если нужна возможность редактирования, то пусть работает через OpenOffice. Благо, что библиотека для этого имеется http://yuri.elmeh.ru, а… Подробнее »

Заводской раб
Заводской раб
04/03/2010 18:27

Очень интересный подход, а я в дельфи так и не смог этого сделать

Михаил
Михаил
12/05/2010 10:11

Здравствуйте. Подскажите, пожалуйста, как подавить диалоговое окно на сохранение документа? Пол дня уже не могу сделать.

Dream
Dream
12/05/2010 20:20

Подскажите, как вставить таблицу в Word программно, не нарисовать таблицу, а именно вставить. Я выделяю весь текст и мне нужно на него «надеть» таблицу. Через меню управления в Worde, это делается так: Таблица — Вставить — Таблица, а как это сделать программно? Заранее спасибо.

Dream
Dream
12/05/2010 20:22

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

Selection.WholeStory
Selection.ConvertToTable Separator:=wdSeparateByParagraphs, NumColumns:=1, _
NumRows:=8, AutoFitBehavior:=wdAutoFitFixed
With Selection.Tables(1)
If .Style «Сетка таблицы» Then
.Style = «Сетка таблицы»
End If
.ApplyStyleHeadingRows = True
.ApplyStyleLastRow = True
.ApplyStyleFirstColumn = True
.ApplyStyleLastColumn = True
End With
End Sub

Сергей
Сергей
03/08/2010 17:21

Спасибо, через компоннеты не помогло, а тут все так просто)

Василий
Василий
12/08/2010 12:03

Подскажите пожалуйста кто нить, как можно установить курсор в Ворде в заданную позицию? Т.е. я вставляю из шаблона в новый документ небольшую табличку и рядом(именно рядом) мне надо вставить еще одну, но после первой вставки курсор встает вниз таблицы и, соответсвенно, следующая табличка помещается ниже :(…Всем заранее спасибо

srg91
srg91
30/08/2010 12:27

А как программно закрыть новую копию Word’а, запущенного таким образом?

srg91
srg91
30/08/2010 15:15

Спасибо

V2010
V2010
18/10/2010 22:06

Подскажите, как можно открыть DOC-файл в Delphi приложении?
Компонент нужен какой-то для этого?
Я использую RxRichEdit для открытия RTF-файлов с картинками, но ссылки почему-то из http://www.webdelphi.ru превращаются в <http://www.webdelphi.ru&gt;, с е-мейлами еще хуже… :(

V2010
V2010
19/10/2010 10:21

Понял, спасибо.
Еще вопрос есть.
RichEdit и RxRichEdit как-то странно ссылки в тексте отображают.
В открываемом RTF ссылки нормальные:
например:

http://www.webdelphi.ru
delphi@yandex.ru

а когда открываю RTF в своей программке, ссылки имеют такой вид:

<http://www.webdelphi.ru&gt;
delphi@yandex.ru <mailto:delphi@yandex.ru>

Почему так? И можно ли привести их в нормальный вид?

Alexander
Alexander
28/10/2010 12:49

Подскажите пожалуйтса.
У меня в программе нужно открыть Word на определенной закладке.
Когда работал в Delphi 7 я это сделал с помощью Ole,
Перешел на 2010 и не могу это сделать. И вообще нет компонентов с Word.
Подскажите плиз!

Сашка_Белый
Сашка_Белый
19/11/2010 00:22

to Vlad
слушай подсади нубу как в ворде через делфи вставить ТАБ
такая команда не работает, а точнее компилятор не пропускает, команду взял из макроса:

[code]
var
word_stud:Variant;
word_stud.Selection.TypeText Text:=vbTab;
[/code]
За ранее спасибо!


Ух_ты
Ух_ты
11/03/2011 05:58

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

dinaflox
dinaflox
15/03/2011 16:35

можно просто не показывать видимость документа:
w.visible:=false;

Илья
Илья
28/05/2011 15:18

Подскажите как вообще мне вставить в документ word значение из программы, вот так пишет «Ошибка на сервере»
MSWord.Selection.TypeText(znach1,’Текст’);

MSWord.Selection.TypeText(‘Текст’);
а вот так все нормально записывает…

Максим
Максим
16/06/2011 20:55

В один документ надо вставить с определенной позиции весь текст другого документа. Как это сделать? Пишет слишком длинная строка.

Просто
Просто
05/09/2011 18:56

НЕ подскажете можно ли из дельфи вставить и редактировать формулы в  Word Т.е. работа с редактором формул. Или это не реально?

Просто
Просто
16/09/2011 15:29

Понятно. Спасибо за отклик. Придется тогда шаблон использовать. А хотелось конечно все программно сделать

Алексей
Алексей
18/09/2011 23:45

Подскажите, как можно создать базу данных, состоящую из документов word в delphi?

Алексей
Алексей
20/09/2011 02:04

преподаватель задал вот такую задачку)

Серега
Серега
27/10/2011 01:57

Помогите, не могу создать путь чтобы открыть документ

Серега
Серега
27/10/2011 01:59

Word.Documents.Open(D:\??? ??? ??????\?????? ??? ???????????.docx:=FilePath, ReadOnly:=true) Что тут не так?????????

Антон
Антон
24/11/2011 23:21

нахожу в документе нужное слово с помощью метода FIND объекта SELECTION.  Как теперь   перед найденным словом перевести каретку (аналогично нажатию клавиши ENTER)?
И ещё, как после нахождения искомого слова выделить следующий за ним фрагмент текста?
Заранее благодраю!

Антон
Антон
26/11/2011 00:43

Спасибо!! Однако в инете никак не могу найти как работать с коллекцией Words (свойства, методы). Смотрел  в книге Василия Корнякова «Программирование приложений под Office…», но там тоже ни слухом ни духом. А между тем, вопрос выделения текста за найденным куском по методу Find остается открытым. В принципе, если знать координаты положения курсора, то можно использовать свойства W.Selection.Start и  W.Selection.Start. Возможно есть более простой способ, не знаю… А возникла такая задача при написании проги, которая сканирует документ в поисках флага ‘[#’, а затем считывает временный номер, стоящий сразу за ним. Я пока у истоков автоматизации процессов обработки документов, так сказать ещё… Подробнее »

Антон
Антон
26/11/2011 23:14

Спасибо! Я только только начал заниматься вопросами автоматизации обработки документов и сразу же встретился с массой трудностей. В инете ничего конкретного. Я был бы вам признателен, если бы вы подсказали мне какой-нибудь ресурс или ссылку на источник, где более или менее освещен данный вопрос (к слову, известная многим книга В.Корнякова мне не очень помогла).

Игорь
11/03/2012 10:50

Добрый день!
Почему то не получилось открыть документ методом  Word.Documents.Open(FilePath)
всё перепробовах в чём проблема может быть? (пишет invalid varian operation)
У меня word 2010

Сергей
Сергей
11/03/2012 14:23

Спасибо за код. Полезный. Позволяет лучше структурировать текст программы. Только у меня он заработал в несколько ином виде принимать Word.Selection.Find.Execute(Replace:=wdReplaceAll);, а именно скобку не захотел):
 [code]function FindAndReplace(const FindText,ReplaceText:string):boolean;
var
  wdReplaceAll : OleVariant;
begin
  wdReplaceAll := 2;
  WDApp.Selection.Find.MatchSoundsLike := False;
  WDApp.Selection.Find.MatchAllWordForms := False;
  WDApp.Selection.Find.MatchWholeWord := False;
  WDApp.Selection.Find.Format := False;
  WDApp.Selection.Find.Forward := True;
  WDApp.Selection.Find.ClearFormatting;
  WDApp.Selection.Find.Text:=FindText;
  WDApp.Selection.Find.Replacement.Text:=ReplaceText;
  FindAndReplace:=WDApp.Selection.Find.Execute(EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, wdReplaceAll, EmptyParam, EmptyParam, EmptyParam, EmptyParam);
end;[/code]

aito
aito
27/03/2012 10:36

как записать на дельфи содержимое оле контейнера, (а там формулы) в таблицу программно

trackback
Итоги 2012 года на WebDelphi.ru | Delphi в Internet
28/12/2012 16:04

[…] Работа с Word в Delphi […]

Александр
25/03/2013 16:33

Здравствуйте!

В Delphi XE3, приходится вызывать CoInitialize перед CreateOleObject, иначе пишет что не было вызова CoInitialize, почему так?

Далее при открытии документа:
[…]
wWord.Documents.Open(FileName:=’F:\Doc1.docx’,ReadOnly:=False);
[…]

Мне выдает, что документ заблокирован мною же. MS Word закрыт, открываемый документ тоже закрыт. Как лечить?

Далее, вы привели пример указания параметров:
[…]
wWord.Documents.Open(FileName:=filepath,ReadOnly:=False);
[…]
FileName:= , ReadOnly:= — Обязательно, или это как пример «что куда»?

Далее, Где можно можно почитать методах объектов OLE для Word , Excel и т.д.? Наличие русской док-ии принципиально.

Благодарю!

Александр
25/03/2013 23:09

код точно вызывается из главного потока? Код вызывается из, мною созданного, потока TThread. Но смысл понял. Сейчас, я это решаю просто CoInitialize(0); Как я понял из ссылок, в мой ситуации ещё и CoUninitialize; надо вызывать в деструкторе потока. У метода Open есть ещё много каких параметров, я решил использовать только два из всех возможных — отсюда и вот такая форма записи. Я имел ввиду немного другое, обязательно ли писать так: wWord.Documents.Open(FileName:=filepath,ReadOnly:=False); Или можно так? wWord.Documents.Open(filepath,False); В книге — все по-русски и доступным языком, в блоге — тоже по-русски :), но только для решения конкретных задач автоматизации Excel. Извините, описался. Я… Подробнее »

Andrey
Andrey
02/05/2013 22:35

У меня все получилось!

AZiza
AZiza
27/11/2013 13:02

а как изменить word на excell? пожалуйста помогите,

Denis
Denis
18/12/2014 20:25

Спасибо большое! Очень помогло! Проверил по макросам то же самое. Так что макросы как и в Excel очень полезны.

Igor
Igor
06/08/2015 18:20

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

Olga
Olga
06/11/2015 14:28

Простите, у меня вопрос очень близок к вашей теме, но немного в другом ракурсе. Не могли бы вы описать как вводить текст в ворде а он автоматически будет отображаться в поле edit в Delphi. Заранее спасибо☺️

vadi61
vadi61
07/11/2015 04:01

А как вставить один документ (целиком с текстом, картинками, форматированием) в другой. Точнее как вставить я понял — ReplaceText. Но вот как взять ВЕСЬ документ не понял. Н
Нужно открыть один документ, где в месте вставки другого документа будет какая-то уникальная строка
Затем открыть второй документ
Затем выделить весь документ. Как?
Затем скопировать выделение в буфер обмена. Как?
Затем вставить из буфера. Как? (я так понимаю ReplaceText — это только текст — string)
И в конце сохранить все под каким-то именем. Как?
Не слишком много вопросов? :)

Игорь
Игорь
28/06/2016 21:27

Функция по замене текста работает хорошо, но есть проблема. Если текст длиннее 255 символов, то пишет ошибку «Слишком длинный строковый параметр».
Можно ли как то сделать заменяемую строку длиннее 255 символов, чтоб все работало?
Спасибо.

Алимбек Хидзев
31/08/2016 01:53

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

Алимбек Хидзев
01/09/2016 13:20
Ответить на  Vlad

Вот текст макроса: [code] Sub Макрос1() ' ' Макрос1 Макрос ' ' With ListGalleries(wdNumberGallery).ListTemplates(1).ListLevels(1) .NumberFormat = "%1." .TrailingCharacter = wdTrailingTab .NumberStyle = wdListNumberStyleArabic .NumberPosition = CentimetersToPoints(0.63) .Alignment = wdListLevelAlignLeft .TextPosition = CentimetersToPoints(1.27) .TabPosition = wdUndefined .ResetOnHigher = 0 .StartAt = 1 With .Font .Bold = wdUndefined .Italic = wdUndefined .StrikeThrough = wdUndefined .Subscript = wdUndefined .Superscript = wdUndefined .Shadow = wdUndefined .Outline = wdUndefined .Emboss = wdUndefined .Engrave = wdUndefined .AllCaps = wdUndefined .Hidden = wdUndefined .Underline = wdUndefined .Color = wdUndefined .Size = wdUndefined .Animation = wdUndefined .DoubleStrikeThrough = wdUndefined .Name = "" End With .LinkedStyle = "" End… Подробнее »

Virus
Virus
30/10/2016 23:48

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