Подписка

добавить на Яндекс

Наши проекты

Delphi+Google

Google API

Google API в Delphi - проект с открытым исходным кодом.

Chrono

Chrono

Хронометр - программа для ведения списка задач.

ODFProc

ODFProc

ODFProc - работа с документами OpenOffice в Lazarus и FreePascal.

Поддержка блога

А тут я коплю на лицензию Delphi XE на iPad =).
Сумма пожертвования не фиксирована.

Публикации

Год назад

Случайный пост

Последние

Сообщения форума

Комментарии

Социальные сети

Google

Facebook

Twitter

Опрос

Вы сейчас или в ближайшем обозримом будущем планируете разрабатывать кроссплатформенное приложение с использованием Firemonkey?



Loading ... Loading ...

Блоги и сообщества

Статьи по Delphi DelphiFeeds.ru - Все Delphi-блоги Рунета Сообщество умных людей VR-Online.RU Бесплатный журнал для программистов и всех, кто интересуется IT Статьи и уроки по Delphi Новостной блог о высоких технологиях
Система Orphus
Опубликовал Vlad 27 февраля 2010 в 22:08.
Категории: Моя работа, Основы Delphi.


Сегодня, в последний рабочий день недели, практически весь день провозился над передачей данных из 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 :)

----------------------
Надоели волосы, торчащие из всех частей тела? Не проблема - лазерная эпиляция поможет Вам навсегда избавится от волосяного покрова в любом месте тела :)
----------------------
Понравилась статья? Тогда:
Делись! Загружай! Плюсуй!
   Отправить PDF на   
Читай ещё статьи на WebDelphi.ru

Комментарии (44)

WP_Cloudy
  • Алексей пишет:

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

  • DimaBy пишет:

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

  • Vlad пишет:

    DimaBy, Низнаю, может и проще, но мне превычнее работать сразу с OLE-объектом…да и интереснее :)
    Алексей, там не столько отчёт, сколько пояснительная записка формируется по расчётам. Мог бы и FastReport использовать или чего-нибудь наподобие, но с Вордом как-то «роднее» :)

  • JayDi пишет:

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

  • Vlad пишет:

    Да как бы тут и макросов не надо особо — есть msdn и справка по объектной модели. Я обычно этими истониками и пользуюсь при разработках программ. Пробовал как-то с макросами возиться — не понравилось :)

  • irwin пишет:

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

  • Vlad пишет:

    Меня тоже интересует :) Попробую чего-нибудь написать по тому поводу

  • Гимаев Наиль пишет:

    Использовать в серьезных проектах привязку к Word не правильно.
    Как системный администратор я перевел целое предприятие на лицензионный софт. Word был куплен только для секретаря. У остальных, в том числе и у бухгалтерии, был поставлен OpenOffice.org, на всякий случай. Когда выяснилось, что одна из бухгалтерских программ требует для своей печати Microsoft Office, то пришлось воспользоваться менее качественной, но более самостоятельной программой. К первоначальному варианту мы вернулись лишь тогда, когда программа научилась печатать генерируя PDF-файлы.
    Если задача нашей программы лишь красиво напечатать, то пусть генерирует PDF.
    А если нужна возможность редактирования, то пусть работает через OpenOffice. Благо, что библиотека для этого имеется http://yuri.elmeh.ru, а чего не хватает можно найти на форуме http://www.sql.ru/forum/actualthread.aspx?bid=20&tid=405083&pg=20 Правда, такой подход многим не нравиться, но убедить людей пользоваться OppenOffice не так уж и сложно, даже в дополнение к Word.
    Другими словами, серьёзная программа может быть привязана лишь к тем программам, установка которых не вызовет финансовых затрат и других проблем мирового значения.

  • Vlad пишет:

    Согласен с вами, Наиль. И всегда стараюсь как раз минимизировать лишние затраты при разработке программ. Убедить человека можно, особенно, когда в руках есть «убеждалка» в виде прайс-листа :) Но могу если сам по себе заказчик программы никак не зависит от закупки софта — убедить практически нереально. Простой пример — университет. В универе все закупки софа проходят централизовано, и отдельно взятой кафедре по барабану сколько чего стоит — она просто регулярно отчисляет в фонд универа фиксированный процент с дохода и всегда имеет свежий софт и никому не важно надо кафедре этот софт или нет — всучили балванку и иди устанавливай. Кафедре требуется нестандартная программка, например, генерирующая списки студентов по определенным признакам (не обязательно половым) и должна формировать документ, скажем для секретаря кафедры, учебных мастеров и т.д., чтоб они его дальше перерабатывали, вносили чего-нибудь и т.д.. Как думаете какое первое требование в этом случае? отчет в файле Word/Excel. И только заикнись по Оо — задушат :).

    З.Ы. За ссылку на библиотеку — спасибо огроменное, т.к. параллельно как раз в Лазарусе пытаюсь подружиться с оО — может часть библиотеки и пригодиться как раз

  • Заводской раб пишет:

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

  • Михаил пишет:

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

  • Vlad пишет:

    Про которое окно идет речь? Если про то, что выскакивает, когда Вы пытаетесь закрыть Ворд из своей программы, то при создании объекта надо написать так:
    var Word: OLEVariant
    begin
    [...]//создаем объект
    Word.DisplayAlerts:=wdAlertsNone
    end;

    DisplayAlerts может принимать одно из следующих значений:
    wdAlertsAll -1
    wdAlertsMessageBox -2
    wdAlertsNone 0

  • Dream пишет:

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

  • Dream пишет:

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

    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

  • Сергей пишет:

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

  • Василий пишет:

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

  • srg91 пишет:

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

  • Vlad пишет:

    srg91,

    Word.Quit;
    UnAssigned(Word)
  • srg91 пишет:

    Спасибо

  • V2010 пишет:

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

  • Vlad пишет:

    В Delphi-приложении вроде бы никак. Или я просто не встречал программ, способных такое сделать.

  • V2010 пишет:

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

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

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

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

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

  • Alexander пишет:

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

  • Vlad пишет:

    Как это нет компонентов с Word? Есть. Просто их надо импортировать через «Components — Import Component — Type Library».

  • Сашка_Белый пишет:

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


    var
    word_stud:Variant;<cite></cite>
    <cite>word_stud.Selection.TypeText Text:=vbTab;</cite>

    За ранее спасибо!


  • Ух_ты пишет:

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

  • dinaflox пишет:

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

  • Vlad пишет:

    Word.Visible = false
    где Word — объект MS Word

  • Илья пишет:

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

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

  • Максим пишет:

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

  • Просто пишет:

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

  • Vlad пишет:

    Через OLE-контейнеры вроде бы можно было, но сам никогда над такими вещами не работал

  • Просто пишет:

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

  • Алексей пишет:

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

  • Vlad пишет:

    Ну видимо можно, если только все документы будут хранится в blob’ах…только зачем?

  • Алексей пишет:

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

  • Серега пишет:

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

  • Серега пишет:

    Word.Documents.Open(D:\Âñå äëÿ Äèïëîì\äàííûå äëÿ ñïðàâî÷íèêà.docx:=FilePath, ReadOnly:=true) Что тут не так?????????

  • Vlad пишет:

    Серега, всё не так. Во-первых почему первый параметр задом наперед стоит? Во-вторых, почему в пути к файлу кодировка сбита?

  • Антон пишет:

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

  • Vlad пишет:

    Антон, каретка всегда и везде переводится одинаково — двумя символами — #10#13. Для выделения следующего слова смотрите методы и свойства объекта Words…по-моему так называлась коллекция, содержащая слова документа.

  • Антон пишет:

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

  • Антон пишет:

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

  • Vlad пишет:

    Антон, может покажется странным, но САМЫЙ стоящий источник по данной теме — это MSDN.com.. Ну нет ничего более побробного, кроме MSDN — это ИХ разработка, ИХ документация, ИХ пордукт. А Корняков просто показал КАК использовать правильно справку MSDN и с какой стороны её надо читать. Ну, а чтобы не теряться в догадках «а как сделать….?» первое, что необходимо для нормальной работы — это 1 раз сесть и уделить время на изучение вопроса использования OLE и понять, что такое раннее связывание, что такое позднее связывание, чем они отличаются. Поймете — напишите любую программу для автоматизации, не поймете — никакой эксперт вам не поможет =) Вы поймите, что нельзя написать что-либо стОящее, не поняв основы работы. Понятно, что может у вас время поджимает, заказчик торопит, но забейте вы на спешку 1 (один) раз и почитайте того же Корнякова С НАЧАЛА и до конца он ведь довольно толково расписывает там что такое контроллер автоматизации, какие принципы разработки применять и т.д.

Ваш ответ

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

Пожалуйста, заключайте исходный код в тэги [code][/code].
Если код большой, то воспользуйтесь Вставкой кода на отдельной странице и оставьте в комментарии ссылку на исходник

   


у нас бак хром, лопата для снега