Delphi замена в колонтитулах word

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 минуты

Цитата
Сообщение от Пытливый
Посмотреть сообщение

Вы лучше код покажите, как вы ищете в колонтитулах.

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var
  Shape, Find: olevariant;
  i: integer;
begin
  for i:=1 to WordApp1.ActiveDocument.Shapes.Count do begin {поиск и замена в надписях}
    Shape:=WordApp1.ActiveDocument.Shapes.Item(i);
    if Shape.Type= 17 then begin
      Find:=Shape.TextFrame.TextRange.Find;
        Find.ClearFormatting;
        Find.Replacement.ClearFormatting;
        Find.Text:='что ищем';
        Find.Replacement.Text:='на что заменяем';
        Find.Forward:=True;
        Find.Wrap:=wdFindContinue;
        Find.Format:=False;
        Find.MatchCase:=False;
        Find.MatchWholeWord:=False;
        Find.MatchWildcards:=False;
        Find.MatchAllWordForms:=False;
        Find.Execute(Replace:=wdReplaceAll);
    end;
  end;
end;



0



DenNik

Житель Земли

2999 / 2998 / 391

Регистрация: 26.07.2011

Сообщений: 11,459

Записей в блоге: 1

24.07.2019, 10:26

4

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

Изменение текста в колонтитулах в таблице WORD

ну и сам макрос

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
Sub Ìàêðîñ3()
'
' Ìàêðîñ3 Ìàêðîñ
'
'
    Selection.Find.ClearFormatting
    Selection.Find.Replacement.ClearFormatting
    With Selection.Find
        .Text = "#SURNAME"
        .Replacement.Text = "Èâàíîâ"
        .Forward = True
        .Wrap = wdFindContinue
        .Format = False
        .MatchCase = False
        .MatchWholeWord = False
        .MatchWildcards = False
        .MatchSoundsLike = False
        .MatchAllWordForms = False
    End With
    Selection.Find.Execute Replace:=wdReplaceAll
    With Selection.Find
        .Text = "#NAME"
        .Replacement.Text = "Âàñèëèé"
        .Forward = True
        .Wrap = wdFindContinue
        .Format = False
        .MatchCase = False
        .MatchWholeWord = False
        .MatchWildcards = False
        .MatchSoundsLike = False
        .MatchAllWordForms = False
    End With
    Selection.Find.Execute Replace:=wdReplaceAll
    With Selection.Find
        .Text = "#PATR"
        .Replacement.Text = "Ïåòðîâè÷"
        .Forward = True
        .Wrap = wdFindContinue
        .Format = False
        .MatchCase = False
        .MatchWholeWord = False
        .MatchWildcards = False
        .MatchSoundsLike = False
        .MatchAllWordForms = False
    End With
    Selection.Find.Execute Replace:=wdReplaceAll
End Sub

все, что начинается на .Match, наверное можно выкинуть, т.к. это значения по умолчанию



0



0 / 0 / 0

Регистрация: 21.03.2018

Сообщений: 33

24.07.2019, 11:10

 [ТС]

5

Цитата
Сообщение от DenNik
Посмотреть сообщение

alse
* * End With
* * Selection.Find.Execute Replace:=wdReplaceAll
End Sub

Вы ошибаетесь, привожу пример файла на котором это не сработало.
Нужно заменить №16 и 12.038. Ваш макрос не решает этой проблемы.
Версия Word 2016



0



DenNik

Житель Земли

2999 / 2998 / 391

Регистрация: 26.07.2011

Сообщений: 11,459

Записей в блоге: 1

24.07.2019, 11:34

6

Цитата
Сообщение от Kompish
Посмотреть сообщение

Ваш макрос не решает этой проблемы.

это не мой макрос. Это записанный Вордом макрос. и в приведенном тобой документе все прекрасно меняет. Две замены

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Sub Макрос3()
'
' 
'
    Selection.Find.ClearFormatting
    Selection.Find.Replacement.ClearFormatting
    With Selection.Find
        .Text = "№16"
        .Replacement.Text = "Hello"
        .Forward = True
        .Wrap = wdFindContinue
        .Format = False
        .MatchCase = False
        .MatchWholeWord = False
        .MatchWildcards = False
        .MatchSoundsLike = False
        .MatchAllWordForms = False
    End With
    Selection.Find.Execute Replace:=wdReplaceAll
End Sub

Добавлено через 2 минуты
все также неясна конечная цель

Добавлено через 25 секунд
Ворд 2010



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

Цитата
Сообщение от Kompish
Посмотреть сообщение

если ставил область поиска ‘надпись в колонтитула’

возможно, как раз дело в версии, т.к. указанной опции в 2010 нет. но тем не менее, ищет по всему документу, невзирая на место расположения текста

Миниатюры

Изменение текста в колонтитулах в таблице WORD
 



0



0 / 0 / 0

Регистрация: 21.03.2018

Сообщений: 33

25.07.2019, 18:03

 [ТС]

9

Применил макрос, ничего не вышло.

Миниатюры

Изменение текста в колонтитулах в таблице WORD
 



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

Цитата
Сообщение от Kompish
Посмотреть сообщение

есть колонтитул в который добавлена надпись

Именно надпись или таки таблица? В таблице все прекрасно меняется при использовании механизма закладок…

Добавлено через 7 минут
Да, собственно, и в надписи — тоже… Офис, если что, как раз 2016

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
procedure TForm1.Button1Click(Sender: TObject);
var W, WD: OLEVariant;
    f, nf: String;
begin
  f := 'C:TMPdoc1.docx';
  nf := 'c:TMPnew_doc1.docx';
  try
    W := CreateOleObject('Word.Application');
  except
    ShowMessage('Не удалось запустить MS Word. Действие отменено.');
    Exit;
  end;
  WD := W.Documents.Open(f);
  WD.Bookmarks.Item('z1').Range.Text := Edit1.Text;
  WD.Bookmarks.Item('z2').Range.Text := DateToStr(DateTimePicker1.Date);
  WD.Bookmarks.Item('z3').Range.Text := Edit2.Text;
  W.DisplayAlerts := False;
  WD.SaveAs(nf);
  W.DisplayAlerts := True;
  WD.Close;
  W.Quit;
end;

Миниатюры

Изменение текста в колонтитулах в таблице WORD
 



0



Житель Земли

2999 / 2998 / 391

Регистрация: 26.07.2011

Сообщений: 11,459

Записей в блоге: 1

26.07.2019, 09:12

12

Цитата
Сообщение от Kompish
Посмотреть сообщение

Применил макрос, ничего не вышло.

опять макрос! открой Ворд и средствами ворда (Ctrl + H) попробуй заменить текст во всем документе. если работает, значит ошибка в коде (о чем косвенно свидетельствует эксперимент D1973)



0



Kompish

0 / 0 / 0

Регистрация: 21.03.2018

Сообщений: 33

27.07.2019, 12:32

 [ТС]

13

Цитата
Сообщение от D1973
Посмотреть сообщение

Именно надпись или таки таблица? В таблице все прекрасно меняется при использовании механизма закладок…

Добавлено через 7 минут
Да, собственно, и в надписи — тоже… Офис, если что, как раз 2016

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
procedure TForm1.Button1Click(Sender: TObject);
var W, WD: OLEVariant;
    f, nf: String;
begin
  f := 'C:TMPdoc1.docx';
  nf := 'c:TMPnew_doc1.docx';
  try
    W := CreateOleObject('Word.Application');
  except
    ShowMessage('Не удалось запустить MS Word. Действие отменено.');
    Exit;
  end;
  WD := W.Documents.Open(f);
  WD.Bookmarks.Item('z1').Range.Text := Edit1.Text;
  WD.Bookmarks.Item('z2').Range.Text := DateToStr(DateTimePicker1.Date);
  WD.Bookmarks.Item('z3').Range.Text := Edit2.Text;
  W.DisplayAlerts := False;
  WD.SaveAs(nf);
  W.DisplayAlerts := True;
  WD.Close;
  W.Quit;
end;
Delphi
1
2
3
4
5
6
7
8
9
10
11
procedure TForm2.Button1Click(Sender: TObject);
var Word: OLEVariant;
     const wdReplaceAll = 2;
begin
Word:=CreateOleObject('Word.Application');
Word.Documents.Open('C:abcdocl.docx');
Word.Visible := True;
Word.selection.find.Text :='№16';
Word.selection.find.replacement.Text := '№4327';
Word.Selection.find.execute(Replace := wdReplaceAll);
end;

Создал новый документ, повторил ничего не вышло
В основном документе надпись изменилась, а надпись которая лежит в колонтитуле -нет.
Да, с помощью CTRL+H, все заменятся, но с макросами и кодом это не работает.

Миниатюры

Изменение текста в колонтитулах в таблице WORD
 



0



Kompish

0 / 0 / 0

Регистрация: 21.03.2018

Сообщений: 33

27.07.2019, 12:37

 [ТС]

14

Цитата
Сообщение от DenNik
Посмотреть сообщение

опять макрос! открой Ворд и средствами ворда (Ctrl + H) попробуй заменить текст во всем документе. если работает, значит ошибка в коде (о чем косвенно свидетельствует эксперимент D1973)

Delphi
1
2
3
4
5
6
7
8
9
10
11
procedure TForm2.Button1Click(Sender: TObject);
var Word: OLEVariant;
     const wdReplaceAll = 2;
begin
Word:=CreateOleObject('Word.Application');
Word.Documents.Open('C:abcdocl.docx');
Word.Visible := True;
Word.selection.find.Text :='№16';
Word.selection.find.replacement.Text := '№4327';
Word.Selection.find.execute(Replace := wdReplaceAll);
end;

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



0



Модератор

8379 / 5580 / 2275

Регистрация: 21.01.2014

Сообщений: 23,954

Записей в блоге: 3

27.07.2019, 14:55

15

Цитата
Сообщение от Kompish
Посмотреть сообщение

Создал новый документ, повторил ничего не вышло

Зачем было цитировать мой пост, если Вы не повторили, а сделали по своему!
Я еще раз повторюсь: делайте при помощи закладок — это работает начиная с Word 6 и до сих пор… Ну а если нет — ну дело-то хозяйское…



0



Kompish

0 / 0 / 0

Регистрация: 21.03.2018

Сообщений: 33

27.07.2019, 16:25

 [ТС]

16

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
procedure TForm1.replaceNumSchool();
begin
Word.selection.find.Text :='№16';
Word.selection.find.replacement.Text := Edit1.Text;
Word.Selection.find.execute(Replace := wdReplaceAll);
Word.selection.Bookmarks.Item('z1').Range.Text := Edit1.Text;
Word.ActiveDocument.ActiveWindow.View.SeekView := wdSeekCurrentPageHeader;
Word.selection.Bookmarks.Item('z2').Range.Text := Edit1.Text;
Word.selection.Bookmarks.Item('z3').Range.Text := Edit1.Text;
Word.selection.start := 0;
Word.selection.end := 0;
end;

Сделал как вы сказали, но опять же закладки не видны, пишет что не существует запрашиваемый номер семейства.
Причем в основном документе все заменилось, с колонтитулом также не найдено, но я сделал его активным и теперь закладку находит, но в надписи которая находится в колонтитуле не видна. Так же решил поставить закладку в надпись в основном документе, все также не работает. Нужно как то сделать надпись активной



0



Модератор

8379 / 5580 / 2275

Регистрация: 21.01.2014

Сообщений: 23,954

Записей в блоге: 3

27.07.2019, 17:46

17

Цитата
Сообщение от Kompish
Посмотреть сообщение

закладки не видны

А Вы их реально в документе создали??? Прежде, чем к ним кодом обращаться?



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

Цитата
Сообщение от DenNik
Посмотреть сообщение

возможно, как раз дело в версии, т.к. указанной опции в 2010 нет. но тем не менее, ищет по всему документу, невзирая на место расположения текста

И да вот тот фрагмент где осуществляется выбор поиска, надпись в колонтитуле, вот где мне нужно осуществить поиск

Миниатюры

Изменение текста в колонтитулах в таблице WORD
 



0



Kompish

0 / 0 / 0

Регистрация: 21.03.2018

Сообщений: 33

27.07.2019, 23:50

 [ТС]

20

Всем большое спасибо, разобрался. Отдельно спасибо за идею D1973, нужно было слегка изменить код.
Действительно нужно было поставить закладки. Код для замены ниже.Тему можно закрыть.

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
procedure TForm1.replaceNumSchool();
var
 BookmarkName, Doc, R: OleVariant;
begin
Doc := Word.ActiveDocument;
 BookmarkName := 'z2';
  if Doc.Bookmarks.Exists(BookmarkName) then
   begin
     R := Doc.Bookmarks.Item(BookmarkName).Range;
     R.InsertAfter(Edit1.Text);
  end;
end;



0



>
Поиск и замена текста в колонтитулах word
, Поиск и замена текста в колонтитулах с таблицей

  • Подписаться на тему
  • Сообщить другу
  • Скачать/распечатать тему



Сообщ.
#1

,
25.04.11, 19:52

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

    ExpandedWrap disabled

      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;

    естественно ничего не работает, помогите найти ошибку.
    заранее огромное спасибо!

    Guru

    volvo877



    Сообщ.
    #2

    ,
    27.04.11, 07:18

      Вот так — отработало:

      ExpandedWrap disabled

        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;


      БылоПрикреплённый файлwrd_before.png (5,1 Кбайт, скачиваний: 1084)


      СталоПрикреплённый файлwrd_after.png (5,46 Кбайт, скачиваний: 1103)

      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() с заданными параметрами прекрасно находит и заменяет текст во всем документе, кроме колонтитула. С ним есть какая-то закавыка, но как ее узнать…
      И еще. Если участники форума не могут помочь, есть ли инстанция в интернете, куда можно обратиться, где обязательно помогут
      :x

         Попросили меня доработать старый модуль, который генерирует клиентам компании письма в формате 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 должен быть довольно простым.

      Понравилась статья? Поделить с друзьями:
    • Delphi если файл excel не открыт
    • Delphi если excel открыт то закрыть
    • Delphi если excel не установлен
    • Delphi добавить строку в excel
    • Delphi фильтр как в excel