I would like to search in a word header and footer for specific words, and then replace them with words from my database.
Currently i can search and replace words anywhere in the word document except for the header and footer.
Can anybody help me with this?
Code for normal search(that works):
Procedure FindAndReplace(Find,Replace:String);
Begin
//Initialize parameters
WrdApp.Selection.Find.ClearFormatting;
WrdApp.Selection.Find.Text := Find;
WrdApp.Selection.Find.Replacement.Text := Replace;
WrdApp.Selection.Find.Forward := True;
WrdApp.Selection.Find.Wrap := wdFindContinue;
WrdApp.Selection.Find.Format := False;
WrdApp.Selection.Find.MatchCase := False;
WrdApp.Selection.Find.MatchWholeWord := wrfMatchCase in Flags;
WrdApp.Selection.Find.MatchWildcards :=wrfMatchWildcards in Flags;
WrdApp.Selection.Find.MatchSoundsLike := False;
WrdApp.Selection.Find.MatchAllWordForms := False;
{ Perform the search}
if wrfReplaceAll in Flags then
WrdApp.Selection.Find.Execute(Replace := wdReplaceAll)
else
WrdApp.Selection.Find.Execute(Replace := wdReplaceOne);
End;
Code for header and footer search(doesnt work):
WrdApp.Selection.Find.ClearFormatting;
WrdApp.Selection.Find.Text := 'Class';
WrdApp.Selection.Find.Replacement.Text := grade;
WrdApp.Selection.Find.Forward := True;
WrdApp.Selection.Find.Wrap := wdFindContinue;
WrdApp.Selection.Find.Format := False;
WrdApp.Selection.Find.MatchCase := False;
WrdApp.Selection.Find.MatchWholeWord := wrfMatchCase in Flags;
WrdApp.Selection.Find.MatchWildcards :=wrfMatchWildcards in Flags;
WrdApp.Selection.Find.MatchSoundsLike := False;
WrdApp.Selection.Find.MatchAllWordForms := False;
{ Perform the search}
if wrfReplaceAll in Flags then
WrdApp.ActiveDocument.Sections.Item(1).Headers.Item(wdHeaderFooterPrimary).Range.Find.Execute(Replace := wdReplaceAll)
else
WrdApp.ActiveDocument.Sections.Item(1).Headers.Item(wdHeaderFooterPrimary).Range.Find.Execute(Replace := wdReplaceOne);
0 / 0 / 0 Регистрация: 21.03.2018 Сообщений: 33 |
|
1 |
|
RAD XE3+ 23.07.2019, 17:42. Показов 3735. Ответов 19
В общем знаю тема баян, но рыл форум и ничего не помогает ни макросы ни код на delphi. Есть колонтитул в нем таблица, в этой таблице значение которое нужно изменить. В основном документе все хорошо текст меняется. Даже если сделать активным окно колонтитулов, замена текста не происходить. Пытался использовать макросы для замены автофигур и надписей все равно не помогает. В общем надеюсь на вашу помощь, потому что сам уж точно не разберусь, если кому нужно могу дать ссылку на пример файла с колонтитулом.
0 |
3392 / 2043 / 654 Регистрация: 29.05.2013 Сообщений: 8,778 |
|
23.07.2019, 18:23 |
2 |
Вы лучше код покажите, как вы ищете в колонтитулах.
0 |
Kompish 0 / 0 / 0 Регистрация: 21.03.2018 Сообщений: 33 |
||||
23.07.2019, 18:39 [ТС] |
3 |
|||
… Добавлено через 4 минуты
Вы лучше код покажите, как вы ищете в колонтитулах.
0 |
DenNik Житель Земли 2999 / 2998 / 391 Регистрация: 26.07.2011 Сообщений: 11,459 Записей в блоге: 1 |
||||
24.07.2019, 10:26 |
4 |
|||
я провел эксперимент, и ответственно заявляю — ворду по барабану, где находится искомый текст. хоть в таблице, хоть в колонтитуле, хоть в надписи. ну и сам макрос
все, что начинается на .Match, наверное можно выкинуть, т.к. это значения по умолчанию
0 |
0 / 0 / 0 Регистрация: 21.03.2018 Сообщений: 33 |
|
24.07.2019, 11:10 [ТС] |
5 |
alse Вы ошибаетесь, привожу пример файла на котором это не сработало.
0 |
DenNik Житель Земли 2999 / 2998 / 391 Регистрация: 26.07.2011 Сообщений: 11,459 Записей в блоге: 1 |
||||
24.07.2019, 11:34 |
6 |
|||
Ваш макрос не решает этой проблемы. это не мой макрос. Это записанный Вордом макрос. и в приведенном тобой документе все прекрасно меняет. Две замены
Добавлено через 2 минуты Добавлено через 25 секунд
0 |
0 / 0 / 0 Регистрация: 21.03.2018 Сообщений: 33 |
|
24.07.2019, 11:49 [ТС] |
7 |
В таблицах тоже изменился текст, где написано документ 16?можно скрин?Может дело в версии ворда? Потому что когда я пытался заменить текст с помощью поиска в ворде он не за менял его, но если ставил область поиска ‘надпись в колонтитула’, то он менял.
0 |
Житель Земли 2999 / 2998 / 391 Регистрация: 26.07.2011 Сообщений: 11,459 Записей в блоге: 1 |
|
24.07.2019, 11:59 |
8 |
если ставил область поиска ‘надпись в колонтитула’ возможно, как раз дело в версии, т.к. указанной опции в 2010 нет. но тем не менее, ищет по всему документу, невзирая на место расположения текста Миниатюры
0 |
0 / 0 / 0 Регистрация: 21.03.2018 Сообщений: 33 |
|
25.07.2019, 18:03 [ТС] |
9 |
Применил макрос, ничего не вышло. Миниатюры
0 |
0 / 0 / 0 Регистрация: 21.03.2018 Сообщений: 33 |
|
25.07.2019, 22:03 [ТС] |
10 |
Ребят тема все также актуальна, есть колонтитул в который добавлена надпись, именно в надписях меняться ничего не хочет, проверьте сами, найдется герой решивший эту проблему?
0 |
D1973 Модератор 8379 / 5580 / 2275 Регистрация: 21.01.2014 Сообщений: 23,954 Записей в блоге: 3 |
||||
26.07.2019, 04:57 |
11 |
|||
есть колонтитул в который добавлена надпись Именно надпись или таки таблица? В таблице все прекрасно меняется при использовании механизма закладок… Добавлено через 7 минут
Миниатюры
0 |
Житель Земли 2999 / 2998 / 391 Регистрация: 26.07.2011 Сообщений: 11,459 Записей в блоге: 1 |
|
26.07.2019, 09:12 |
12 |
Применил макрос, ничего не вышло. опять макрос! открой Ворд и средствами ворда (Ctrl + H) попробуй заменить текст во всем документе. если работает, значит ошибка в коде (о чем косвенно свидетельствует эксперимент D1973)
0 |
Kompish 0 / 0 / 0 Регистрация: 21.03.2018 Сообщений: 33 |
||||||||
27.07.2019, 12:32 [ТС] |
13 |
|||||||
Именно надпись или таки таблица? В таблице все прекрасно меняется при использовании механизма закладок… Добавлено через 7 минут
Создал новый документ, повторил ничего не вышло Миниатюры
0 |
Kompish 0 / 0 / 0 Регистрация: 21.03.2018 Сообщений: 33 |
||||
27.07.2019, 12:37 [ТС] |
14 |
|||
опять макрос! открой Ворд и средствами ворда (Ctrl + H) попробуй заменить текст во всем документе. если работает, значит ошибка в коде (о чем косвенно свидетельствует эксперимент D1973)
Попробуйте пожалуйста применить данный код у себя, если выйдет то скорее проблема с вордом.
0 |
Модератор 8379 / 5580 / 2275 Регистрация: 21.01.2014 Сообщений: 23,954 Записей в блоге: 3 |
|
27.07.2019, 14:55 |
15 |
Создал новый документ, повторил ничего не вышло Зачем было цитировать мой пост, если Вы не повторили, а сделали по своему!
0 |
Kompish 0 / 0 / 0 Регистрация: 21.03.2018 Сообщений: 33 |
||||
27.07.2019, 16:25 [ТС] |
16 |
|||
Сделал как вы сказали, но опять же закладки не видны, пишет что не существует запрашиваемый номер семейства.
0 |
Модератор 8379 / 5580 / 2275 Регистрация: 21.01.2014 Сообщений: 23,954 Записей в блоге: 3 |
|
27.07.2019, 17:46 |
17 |
закладки не видны А Вы их
0 |
0 / 0 / 0 Регистрация: 21.03.2018 Сообщений: 33 |
|
27.07.2019, 17:53 [ТС] |
18 |
Да создал, говорю же те что в основном документе изменились, в колонтитулах и надписях не находит, пока они не активны. Добавлено через 3 минуты
0 |
0 / 0 / 0 Регистрация: 21.03.2018 Сообщений: 33 |
|
27.07.2019, 20:33 [ТС] |
19 |
возможно, как раз дело в версии, т.к. указанной опции в 2010 нет. но тем не менее, ищет по всему документу, невзирая на место расположения текста И да вот тот фрагмент где осуществляется выбор поиска, надпись в колонтитуле, вот где мне нужно осуществить поиск Миниатюры
0 |
Kompish 0 / 0 / 0 Регистрация: 21.03.2018 Сообщений: 33 |
||||
27.07.2019, 23:50 [ТС] |
20 |
|||
Всем большое спасибо, разобрался. Отдельно спасибо за идею D1973, нужно было слегка изменить код.
0 |
Поиск и замена текста в колонтитулах word
, Поиск и замена текста в колонтитулах с таблицей
- Подписаться на тему
- Сообщить другу
- Скачать/распечатать тему
|
|
Стоит задача найти и заменить текст в колонтитулах документа word, в колонтитулах находятся таблицы, в которых также необходимо осуществить поиски замену. Накидал такой код:
function SeekInsertInColon(SText, IText : string):boolean; var colon, colon1, colon2: olevariant; i, b: integer; begin for i:=1 to WordApp1.ActiveDocument.Sections.Count do begin colon2:=WordApp1.ActiveDocument.Sections.Item(i).Range; for b := 1 to WordApp1.ActiveDocument.Sections.item(i).Range.Tables.Count do begin {поиск и замена в колонтитулах} colon1:=colon2.Tables.item(b).range; colon:=Colon1.{Footers.}Range.Find; colon.ClearFormatting; colon.Replacement.ClearFormatting; colon.Text:=SText; colon.Replacement.Text:=IText; colon.Forward:=True; colon.Wrap:=wdFindContinue; colon.Format:=False; colon.MatchCase:=False; colon.MatchWholeWord:=False; colon.MatchWildcards:=False; colon.MatchAllWordForms:=False; colon.Execute(Replace:=wdReplaceAll); end; end; end; естественно ничего не работает, помогите найти ошибку. |
volvo877 |
|
Вот так — отработало:
function SeekInsertInColon(SText, IText : string):boolean; procedure DoReplace(Rng : OleVariant); var Finder : OleVariant; begin Finder := Rng.Find; Finder.ClearFormatting; Finder.Replacement.ClearFormatting; Finder.Text:=SText; Finder.Replacement.Text:=IText; Finder.Forward:=True; Finder.Wrap:=wdFindContinue; Finder.Format:=False; Finder.MatchCase:=False; Finder.MatchWholeWord:=False; Finder.MatchWildcards:=False; Finder.MatchAllWordForms:=False; Finder.Execute(Replace:=wdReplaceAll); end; var hdr, ftr: OleVariant; i: Integer; begin hdr := WordApp1.ActiveDocument.Sections.Item(1).Headers.Item(1).Range; DoReplace(hdr); for i := 1 to hdr.Tables.Count do begin DoReplace(hdr.Tables.Item(i).Range); end; ftr := WordApp1.ActiveDocument.Sections.Item(1).Footers.Item(1).Range; DoReplace(ftr); for i := 1 to ftr.Tables.Count do begin DoReplace(ftr.Tables.Item(i).Range); end; end;
|
0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
0 пользователей:
- Предыдущая тема
- Delphi: Система, Windows API
- Следующая тема
[ Script execution time: 0,0209 ] [ 18 queries used ] [ Generated: 13.04.23, 22:37 GMT ]
Господа, уже кричу о помощи!
Никак не получается замена текста в нижнем колонтитуле документа Ворд. Испробовала все что можно. Представлю три варианта:
1)
//Колонитул — активизация
if(WordApp->ActiveWindow->View->SplitSpecial != wdPaneNone)
WordApp->ActiveWindow->Panes->Item(2)->Close();
if ((WordApp->ActiveWindow->ActivePane->View->Type == wdNormalView)
|| (WordApp->ActiveWindow->ActivePane->View->Type == wdOutlineView))
{
WordApp->ActiveWindow->ActivePane->View->Type = wdPrintView;
}
WordApp->ActiveWindow->ActivePane->View->SeekView = wdSeekCurrentPageHeader;
if (WordApp->Selection->HeaderFooter->IsHeader == true)
WordApp->ActiveWindow->ActivePane->View->SeekView = wdSeekCurrentPageFooter;
else
WordApp->ActiveWindow->ActivePane->View->SeekView = wdSeekCurrentPageHeader;
//Поиск и замена текста
OleVariant oldStr, newStr;
oldStr=AnsiString(«Dez-nomer»);
newStr=AnsiString(«ххххх»);
OleVariant EmptyPar=False;
OleVariant Yes=True;
OleVariant Replace = wdReplaceAll;
WordApp->Selection->Find->Execute( oldStr, EmptyPar,
EmptyPar, EmptyPar, EmptyPar, EmptyPar,
Yes, wdFindContinue, EmptyPar, EmptyPar, wdReplaceAll, EmptyPar,
EmptyPar, EmptyPar, newStr, Yes);
Этот код активизирует нижний колонтитул, а поиск и замена не выполняется. Хотя функция Execute() прекрасно работает вне колонтитула.
2) На форумах наткнулась на такое предложение:
WordApp->ActiveDocument->Sections->Item(1)-> Footers->Item(wdHeaderFooterFirstPage)->Range->Find->Execute(oldStr,
EmptyParam,EmptyParam,EmptyParam,EmptyParam,
EmptyParam,EmptyParam,EmptyParam,EmptyParam,
newStr,Yes);
Поиск должен осуществляться сразу в колонтитуле без его активизации. Реакция такая же.
3) Наполовину работает такой код. После активизации колонтитула начинает выполняться код:
OleVariant ReplaceWith=False;
WordApp->Selection->Find->ClearFormatting();
WordApp->Selection->Find->Replacement->ClearFormatting();
WordApp->Selection->Find->Execute(oldStr);
WordApp->Selection->Find->get_Replacement()->set_Text(StringToOleStr(ModulePipes->ADODocum->Fields->Fields[2]->AsString));
WordApp->Selection->Find->Replacement->set_Text(Un);
WordApp->Selection->Find->set_MatchCase(false);
WordApp->Selection->Find->set_MatchWholeWord(false);
WordApp->Selection->Find->set_MatchWildcards(false);
WordApp->Selection->Find->set_MatchSoundsLike(false);
WordApp->Selection->Find->set_MatchAllWordForms(false);
WordApp->Selection->Find->set_Forward(true);
WordApp->Selection->Find->set_Wrap(wdFindContinue);
WordApp->Selection->Find->set_Format(false);
WordApp->Selection->Find->Execute(ReplaceWith);
WordApp->Selection->Find->Execute(Replace);
WordApp->Selection->Find->set_MatchKashida(false);
WordApp->Selection->Find->set_MatchDiacritics(false);
WordApp->Selection->Find->set_MatchAlefHamza(false);
WordApp->Selection->Find->set_MatchControl(false);
Здесь происходит поиск текста и его выделение. Замены почему-то не происходит. Аналогичный код я встретила в Интернете на языке VBA. Участник форума тоже взывал о помощи. Так же, как и я, бился с этим вопросом ни один день. Но ответа не добился.
Может быть кто-нибудь знает работающий код? Еще раз акцентирую внимание: обычная функция Execute() с заданными параметрами прекрасно находит и заменяет текст во всем документе, кроме колонтитула. С ним есть какая-то закавыка, но как ее узнать…
И еще. Если участники форума не могут помочь, есть ли инстанция в интернете, куда можно обратиться, где обязательно помогут
Попросили меня доработать старый модуль, который генерирует клиентам компании письма в формате MS Word. Пользователи создают шаблоны, в которых расставляют названия полей, заключенные в служебные символы (например, #CONTRACT_NUM#, #FIO#, #ADDRESS#…). Программа по заданным критериям выбирает информацию о клиентах из базы и генерирует письма, находя в тексте шаблонов названия полей и заменяя их фактическими значениями.
Если опустить все детали и различную логику, то упрощенно это выглядит так:
Var
MSWord: OleVariant;
i: Integer;
q: TSDQuery;
…
begin
…
MSWord := CreateOleObject(‘Word.Application’);
MSWord.Documents.Add(‘какой то шаблон.dot’);
For i := 0 to q.FieldCount-1 do
MSWord.Selection.Find.Execute(FindText := ‘#’ + q.Fields[i].FieldName + ‘#’, ReplaceWith := q.Fields[i].AsString);
…
MSWord.ActiveDocument.SaveAs(‘письмо любимому клиенту.doc’);
…
Первое, с чем я столкнулся, это то, что длина значения параметра ReplaceWith не должна превышать 255 символов. Но это я обошел легко, заменив «поиск и замену текста» на «поиск и вывод текста»:
If MSWord.Selection.Find.Execute(FindText := ‘#’ + q.Fields[i].FieldName + ‘#’) then
MSWord.Selection.TypeText(q.Fields[i].AsString);
Вторая задачка оказалась сложнее. Внизу листа в фиксированное место необходимо было вывести фамилию и адрес получателя. Сначала я думал поместить его в нижний колонтитул, но оказалось, что письмо может быть на двух листах. Тогда ничего не оставалось, как использовать объект «заметка». Вставил «заметку». Красота! Документ генерируется, текст сдвигается, заметка остается на месте… Но радость была недолгой, т.к. поля #FIO# и #ADDRESS#, помещенные в заметку, так и остались незамененными
Оказалось, что MSWord.Selection.Find.Execute ищет текст только в основной части документа, а в документе, состоящем из разных структурных элементов (заметок, колонтитулов, сносок и т.д.), поиск необходимо производить отдельно в каждом из этих элементов. Все эти структурные элементы документа являются элементами коллекции StoryRanges. Т.к. дело было к ночи, а модуль должен был быть готов к утру, я не стал разбираться, как работать со StoryRanges через OLE из Delphi, и просто добавил в тестовый шаблон письма макрос на VBA, в котором перебираются все структурные элементы активного документа, в которых ведется поиск:
Sub ReplaceText(sFindText As String, sReplaceText As String)
Dim rngStory As Range
For Each rngStory In ActiveDocument.StoryRanges
With rngStory.Find
.Text = sFindText
.Replacement.Text = sReplaceText
.Wrap = wdFindContinue
.Execute Replace:=wdReplaceAll
End With
Next rngStory
End Sub
А в программе я только написал вызов макроса:
MSWord.Application.Run(‘ReplaceText’, ‘#FIO#’, ‘Иванов Иван Иванович’);
Работает как часы
P.S. После окончания генерации документа, если MS Word вам больше не нужен, то не забывайте закрывать его и высвобождать память
MSWord.Quit;
MSWord := UnAssigned;
P.P.S. Для подобной задачи генерации писем в формат MS Word больше подходит не поиск и замена текста, использование полей с переменными (DocVariable) и закладок (Bookmark). А как это сделать, я расскажу в следующий раз.
Я успешно выполнил поиск замены в заголовке и нижнем колонтитуле doc docx, используя: этот вопрос. Я использую Delphi для управления Word через OLE Automation.
Теперь проблема в том, что это работает только для первой страницы, если один устанавливает «другой заголовок для первой страницы», или не работает вообще, если один устанавливает «разные на чет / нечет».
Этот документ объясняет это немного подробнее.
ОБНОВИТЬ:
В упомянутом выше документе объясняется, что MS Word управляет верхним и нижним колонтитулами как первой / нечетной / четной страницей. Но также можно выбрать ни один вариант, и в этом случае все верхний и нижний колонтитулы будут одинаковыми.
В случае, если выполняется поиск и замена с использованием кода, который я привел выше, он работает только в том случае, если не выбраны дополнительные параметры, поэтому в случае, если один из них — поиск и замена в документе, где все верхние и нижние колонтитулы одинаковы.
Если случайно этот код используется против документа, в котором выбран «другой заголовок для первой страницы», поиск и замена будут выполняться только в верхнем и нижнем колонтитулах первой страницы.
Хотя это вообще не сработает, если выбран только один вариант — «разные верхний и нижний колонтитулы на нечетных и четных страницах» (а не «разные на первой странице»).
Итак, я спрашивал, решал ли уже эту проблему во всех случаях. Я имею в виду, что было бы полезно найти этот ответ также для других пользователей, которым необходимо выполнять поиск и замену в верхнем и нижнем колонтитулах в документах MS Word, используя автоматизацию Delphi и OLE.
Это не сработает, потому что вы настраиваете объект «Найти» в выделении, а затем используете объект «Найти» в диапазоне заголовка. Это разные вещи.
Если вы измените эти строки
WrdApp.ActiveDocument.Sections.Item(1).Headers.Item(wdHeaderFooterPrimary).Range.Find.Execute(Replace := wdReplaceAll);
что-то вроде следующего (вам нужно получить правильный синтаксис Delphi)
WrdApp.ActiveDocument.Sections.Item(1).Headers.Item(wdHeaderFooterPrimary).Range.Select;
WrdApp.Selection.Find.Execute(Replace := wdReplaceAll);
Вы должны увидеть улучшение, но я думаю, (а) это предпочтительнее, если вы можете избежать использования объекта Selection, и (б) если вам нужно иметь дело с более общей ситуацией с различными верхними и нижними колонтитулами, все может стать немного сложнее, Поэтому я хотел бы предложить вам перейти к
«Использование макроса для замены текста там, где он появляется в документе» на веб-сайте Word MVP и изучения кода, который у них есть. Перевод с VBA->Delphi должен быть довольно простым.