Сегодня, в последний рабочий день недели, практически весь день провозился над передачей данных из 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;
Всё достаточно просто. Далее мы можем работать с объектом следующим образом:
- Создавать документ Word с нуля
- Открыть уже существующий документ и изменить в нем текст для получения необходимой формы документа.
Рассмотрим оба варианта, т.к. оба они имеют как свои плюсы, так и недостатки.
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 :)
Спасибо, попробую сегодня. А для чего тебе вообще из программы в Word пересылку делать? Отчеты что ли там формируют? Просто для этого вроде более удобные способы есть. Хотя заказчикам все подряд нужно. :-)
А не проще ли использовать юниты с ранним связываеним.
Например word2000.pas,wordxp.pas и т.п.
Все продукты офиса имеют обратную совместимость, т.е. word2000.pas отлично отработает на msword2007.
У них есть только 1 недостаток — почему-то параметры нужно передавать через var, а это затрудняет использование констант, зато в результате мы сразу можем пользоваться всеми прелестями синтаксис-помощника
DimaBy, Низнаю, может и проще, но мне превычнее работать сразу с OLE-объектом…да и интереснее :)
Алексей, там не столько отчёт, сколько пояснительная записка формируется по расчётам. Мог бы и FastReport использовать или чего-нибудь наподобие, но с Вордом как-то «роднее» :)
Еще можно было бы упомянуть о такой маленькой хитрости, как макросы. Когда мы не знаем нужных нам команд для работы с Excel или Word — открываем документ, делаем запись макроса и смотрим его исходники. Код на Visual Basic практически не будет отличаться от того, который нам нужен в Delphi.
Да как бы тут и макросов не надо особо — есть msdn и справка по объектной модели. Я обычно этими истониками и пользуюсь при разработках программ. Пробовал как-то с макросами возиться — не понравилось :)
Интересует формирование отчётов не через OLE в ворд, а через создание XML документа, который ворд откроет.
Меня тоже интересует :) Попробую чего-нибудь написать по тому поводу
Использовать в серьезных проектах привязку к Word не правильно. Как системный администратор я перевел целое предприятие на лицензионный софт. Word был куплен только для секретаря. У остальных, в том числе и у бухгалтерии, был поставлен OpenOffice.org, на всякий случай. Когда выяснилось, что одна из бухгалтерских программ требует для своей печати Microsoft Office, то пришлось воспользоваться менее качественной, но более самостоятельной программой. К первоначальному варианту мы вернулись лишь тогда, когда программа научилась печатать генерируя PDF-файлы. Если задача нашей программы лишь красиво напечатать, то пусть генерирует PDF. А если нужна возможность редактирования, то пусть работает через OpenOffice. Благо, что библиотека для этого имеется http://yuri.elmeh.ru, а… Подробнее »
Согласен с вами, Наиль. И всегда стараюсь как раз минимизировать лишние затраты при разработке программ. Убедить человека можно, особенно, когда в руках есть «убеждалка» в виде прайс-листа :) Но могу если сам по себе заказчик программы никак не зависит от закупки софта — убедить практически нереально. Простой пример — университет. В универе все закупки софа проходят централизовано, и отдельно взятой кафедре по барабану сколько чего стоит — она просто регулярно отчисляет в фонд универа фиксированный процент с дохода и всегда имеет свежий софт и никому не важно надо кафедре этот софт или нет — всучили балванку и иди устанавливай. Кафедре… Подробнее »
Очень интересный подход, а я в дельфи так и не смог этого сделать
Здравствуйте. Подскажите, пожалуйста, как подавить диалоговое окно на сохранение документа? Пол дня уже не могу сделать.
Про которое окно идет речь? Если про то, что выскакивает, когда Вы пытаетесь закрыть Ворд из своей программы, то при создании объекта надо написать так:
var Word: OLEVariant
begin
[...]//создаем объект
Word.DisplayAlerts:=wdAlertsNone
end;
DisplayAlerts может принимать одно из следующих значений:
wdAlertsAll -1
wdAlertsMessageBox -2
wdAlertsNone 0
Подскажите, как вставить таблицу в Word программно, не нарисовать таблицу, а именно вставить. Я выделяю весь текст и мне нужно на него «надеть» таблицу. Через меню управления в Worde, это делается так: Таблица — Вставить — Таблица, а как это сделать программно? Заранее спасибо.
Вот привожу листинг из макроса, для вставки таблицы, то ничего не понятно.
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
Спасибо, через компоннеты не помогло, а тут все так просто)
Подскажите пожалуйста кто нить, как можно установить курсор в Ворде в заданную позицию? Т.е. я вставляю из шаблона в новый документ небольшую табличку и рядом(именно рядом) мне надо вставить еще одну, но после первой вставки курсор встает вниз таблицы и, соответсвенно, следующая табличка помещается ниже :(…Всем заранее спасибо
А как программно закрыть новую копию Word’а, запущенного таким образом?
srg91,
[code]Word.Quit;
UnAssigned(Word)[/code]
Спасибо
Подскажите, как можно открыть DOC-файл в Delphi приложении?
Компонент нужен какой-то для этого?
Я использую RxRichEdit для открытия RTF-файлов с картинками, но ссылки почему-то из http://www.webdelphi.ru превращаются в <http://www.webdelphi.ru>, с е-мейлами еще хуже… :(
В Delphi-приложении вроде бы никак. Или я просто не встречал программ, способных такое сделать.
Понял, спасибо.
Еще вопрос есть.
RichEdit и RxRichEdit как-то странно ссылки в тексте отображают.
В открываемом RTF ссылки нормальные:
например:
http://www.webdelphi.ru
delphi@yandex.ru
а когда открываю RTF в своей программке, ссылки имеют такой вид:
<http://www.webdelphi.ru>
delphi@yandex.ru <mailto:delphi@yandex.ru>
Почему так? И можно ли привести их в нормальный вид?
Подскажите пожалуйтса.
У меня в программе нужно открыть Word на определенной закладке.
Когда работал в Delphi 7 я это сделал с помощью Ole,
Перешел на 2010 и не могу это сделать. И вообще нет компонентов с Word.
Подскажите плиз!
Как это нет компонентов с Word? Есть. Просто их надо импортировать через «Components — Import Component — Type Library».
to Vlad
слушай подсади нубу как в ворде через делфи вставить ТАБ
такая команда не работает, а точнее компилятор не пропускает, команду взял из макроса:
[code]
var
word_stud:Variant;
word_stud.Selection.TypeText Text:=vbTab;
[/code]
За ранее спасибо!
подскажите пожалуйста:
мне необходимо записать из поля edit информацию в word при том, чтобы word он не открывался.
спасибо
Word.Visible = false
где Word — объект MS Word
можно просто не показывать видимость документа:
w.visible:=false;
Подскажите как вообще мне вставить в документ word значение из программы, вот так пишет «Ошибка на сервере»
MSWord.Selection.TypeText(znach1,’Текст’);
MSWord.Selection.TypeText(‘Текст’);
а вот так все нормально записывает…
В один документ надо вставить с определенной позиции весь текст другого документа. Как это сделать? Пишет слишком длинная строка.
НЕ подскажете можно ли из дельфи вставить и редактировать формулы в Word Т.е. работа с редактором формул. Или это не реально?
Через OLE-контейнеры вроде бы можно было, но сам никогда над такими вещами не работал
Понятно. Спасибо за отклик. Придется тогда шаблон использовать. А хотелось конечно все программно сделать
Подскажите, как можно создать базу данных, состоящую из документов word в delphi?
Ну видимо можно, если только все документы будут хранится в blob’ах…только зачем?
преподаватель задал вот такую задачку)
Помогите, не могу создать путь чтобы открыть документ
Word.Documents.Open(D:\??? ??? ??????\?????? ??? ???????????.docx:=FilePath, ReadOnly:=true) Что тут не так?????????
Серега, всё не так. Во-первых почему первый параметр задом наперед стоит? Во-вторых, почему в пути к файлу кодировка сбита?
нахожу в документе нужное слово с помощью метода FIND объекта SELECTION. Как теперь перед найденным словом перевести каретку (аналогично нажатию клавиши ENTER)?
И ещё, как после нахождения искомого слова выделить следующий за ним фрагмент текста?
Заранее благодраю!
Антон, каретка всегда и везде переводится одинаково — двумя символами — #10#13. Для выделения следующего слова смотрите методы и свойства объекта Words…по-моему так называлась коллекция, содержащая слова документа.
Спасибо!! Однако в инете никак не могу найти как работать с коллекцией Words (свойства, методы). Смотрел в книге Василия Корнякова «Программирование приложений под Office…», но там тоже ни слухом ни духом. А между тем, вопрос выделения текста за найденным куском по методу Find остается открытым. В принципе, если знать координаты положения курсора, то можно использовать свойства W.Selection.Start и W.Selection.Start. Возможно есть более простой способ, не знаю… А возникла такая задача при написании проги, которая сканирует документ в поисках флага ‘[#’, а затем считывает временный номер, стоящий сразу за ним. Я пока у истоков автоматизации процессов обработки документов, так сказать ещё… Подробнее »
Антон, может покажется странным, но САМЫЙ стоящий источник по данной теме — это MSDN.com.. Ну нет ничего более побробного, кроме MSDN — это ИХ разработка, ИХ документация, ИХ пордукт. А Корняков просто показал КАК использовать правильно справку MSDN и с какой стороны её надо читать. Ну, а чтобы не теряться в догадках «а как сделать….?» первое, что необходимо для нормальной работы — это 1 раз сесть и уделить время на изучение вопроса использования OLE и понять, что такое раннее связывание, что такое позднее связывание, чем они отличаются. Поймете — напишите любую программу для автоматизации, не поймете — никакой эксперт вам… Подробнее »
Спасибо! Я только только начал заниматься вопросами автоматизации обработки документов и сразу же встретился с массой трудностей. В инете ничего конкретного. Я был бы вам признателен, если бы вы подсказали мне какой-нибудь ресурс или ссылку на источник, где более или менее освещен данный вопрос (к слову, известная многим книга В.Корнякова мне не очень помогла).
Добрый день!
Почему то не получилось открыть документ методом Word.Documents.Open(FilePath)
всё перепробовах в чём проблема может быть? (пишет invalid varian operation)
У меня word 2010
Спасибо за код. Полезный. Позволяет лучше структурировать текст программы. Только у меня он заработал в несколько ином виде принимать 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]
как записать на дельфи содержимое оле контейнера, (а там формулы) в таблицу программно
[…] Работа с Word в Delphi […]
Здравствуйте!
В 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 и т.д.? Наличие русской док-ии принципиально.
Благодарю!
>>В Delphi XE3, приходится вызывать CoInitialize перед CreateOleObject, иначе пишет что не было вызова CoInitialize, почему так? Для главного потока приложения Delphi, по идее, неявно сама вызывает CoInitialize при подключенных модулях…ComObj или ActiveX по-моему. Ваш код точно вызывается из главного потока? Если что, про CoInitialize можно прочитать немного тут >>Мне выдает, что документ заблокирован мною же. MS Word закрыт, открываемый документ тоже закрыт. Как лечить? Открыть диспетчер задач и убить процесс word.exe — видимо где-то он у вас не убивается в программе. То чно не видно окно Word’а еще не гарантирует того, что процесс не запущен. >>wWord.Documents.Open(FileName:=filepath,ReadOnly:=False); У метода Open… Подробнее »
код точно вызывается из главного потока? Код вызывается из, мною созданного, потока TThread. Но смысл понял. Сейчас, я это решаю просто CoInitialize(0); Как я понял из ссылок, в мой ситуации ещё и CoUninitialize; надо вызывать в деструкторе потока. У метода Open есть ещё много каких параметров, я решил использовать только два из всех возможных — отсюда и вот такая форма записи. Я имел ввиду немного другое, обязательно ли писать так: wWord.Documents.Open(FileName:=filepath,ReadOnly:=False); Или можно так? wWord.Documents.Open(filepath,False); В книге — все по-русски и доступным языком, в блоге — тоже по-русски :), но только для решения конкретных задач автоматизации Excel. Извините, описался. Я… Подробнее »
так
wWord.Documents.Open(filepath,False);
можно вызывать метод только в том случае, если вы используете все параметры метода.
Конечно. Это встроенная справка Word, раздел для разработчиков
var Word: OleVariant;
[..]
Word.Quit;
Word:=UnAssigned;
У меня все получилось!
а как изменить word на excell? пожалуйста помогите,
Спасибо большое! Очень помогло! Проверил по макросам то же самое. Так что макросы как и в Excel очень полезны.
Добрый день, помогите пожалуйста… вот тут написано как искать текстт в шаблоне и потом его менять…. нельзя ли по подробнее, как менять текст
Так в последнем куске когда расписано как ищется и меняется текст в документе…или я не правильно понимаю вопрос?
Простите, у меня вопрос очень близок к вашей теме, но немного в другом ракурсе. Не могли бы вы описать как вводить текст в ворде а он автоматически будет отображаться в поле edit в Delphi. Заранее спасибо☺️
Первое, что приходит в голову — это создание отдельного потока, который будет читать содержимое открытого файла Word и выводить текст в Edit
А как вставить один документ (целиком с текстом, картинками, форматированием) в другой. Точнее как вставить я понял — ReplaceText. Но вот как взять ВЕСЬ документ не понял. Н
Нужно открыть один документ, где в месте вставки другого документа будет какая-то уникальная строка
Затем открыть второй документ
Затем выделить весь документ. Как?
Затем скопировать выделение в буфер обмена. Как?
Затем вставить из буфера. Как? (я так понимаю ReplaceText — это только текст — string)
И в конце сохранить все под каким-то именем. Как?
Не слишком много вопросов? :)
Функция по замене текста работает хорошо, но есть проблема. Если текст длиннее 255 символов, то пишет ошибку «Слишком длинный строковый параметр».
Можно ли как то сделать заменяемую строку длиннее 255 символов, чтоб все работало?
Спасибо.
Пытаюсь в открытом документе Word добавить нумерованные списки. Как подойти к вопросу, даже не знаю как подойти к вопросу, макрос записывал, но для меня сложновато…
Покажите, что вам макрос там насочинял.
Вот текст макроса: [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… Подробнее »
Прошу прощения за глупый вопрос, но как именно вызывать эту функцию в коде? В том смысле, что мне к примеру надо заменить строки в нескольких местах, то есть вызывать надо несколько раз. Сначала, не заметив, что это НЕ процедура, думал просто отдельным оператором несколько раз, но потом заметил function, и не могу сообразить как вызывать, ведь вызов должен быть после оператора присвоения.
Так и вызывайте несколько раз в коде. Результат функции — boolean. Если замена текста прошла успешно, то функция вернет True, иначе False. Если вам не важно заменится текст или нет, то вызывайте так:
begin
//тут какой-то код
FindAndReplace('Текст','Заменяющий текст');
//снова кокой-то ваш код
FindAndReplace('Текст2','Заменяющий текст2');
end;
Или так, есди дальнейшая работа зависит от того, заменится ли текст или нет:
begin
//тут какой-то код
if FindAndReplace('Текст','Заменяющий текст') then
FindAndReplace('Текст2','Заменяющий текст2')
else
ShowMessage('Не удалось заменить строку "Текст"')
end;