Delphi выделить текст в word

Если «до конца» = «До самого конца»:

Procedure SelectFromPositionToEnd(startPosition: integer);
begin
  W.Selection.Start := startPosition;
  W.Selection.End   := W.ActiveDocument.Characters.Count; // последний символ в документе
end;

Если «до конца» = «До конца предложения»:

Procedure SelectFromPositionToEdnOfSentence(startPosition: integer);
const
  WdSentence = 3; //значение для перехода к следующему предложению
begin
  w.Selection.Start := startPosition; //поставили сюда курсор
  w.Selection.Move(WdSentence, 1);    //передвинули до следующего предложения
  w.Selection.Start := startPosition; //растянули выделение до начального символа
end;

Если «до конца» = «До конца строки», то тоже что и во втором случае, только заменить первый параметр в Move
с

WdSentence

на

Wdline = 5 //значение для перехода к следующей линии (строке)

Mawrat

13094 / 5875 / 1706

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

Сообщений: 8,808

01.09.2013, 05:11

6

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

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

Тогда понадобится не запускать новый экземпляр MS Word, а подключиться к уже запущенному экземпляру. В этом случае надо заменить вызов CreateOleObject() на GetActiveOleObject().
Полностью код будет выглядеть так:

Delphi
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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
uses
  ComObj;
 
{Пояснение по поиску.
Объект wdFind связан с диапазоном wdRng. При каждом вызове wdFind.Execute
поиск продолжается в том диапазоне, который определял wdRng до первого
вызова wdFind.Execute. Т. е., поиск выполняется в одном и том же диапазоне.
Но сам объект wdRng изменяется при каждом обнаружении искомого текста - он
становится равным диапазону, который охватывает этот найденный текст.}
 
{Функция ищет заданный текст aSearchText в документе MS Word aWdDoc и возвращает
ссылку на диапазон, который охватывает найденный текст.}
function FindInDoc(const aWdDoc : Variant; const aSearchText : String) : Variant;
const
  wdFindStop = 0; //Завершить поиск при достижении границы диапазона.
var
  wdRng, wdFind : Variant;
begin
  VarClear(Result);
  //Диапазон, охватывающий всё содержимое документа.
  wdRng := aWdDoc.Content;
 
  //Настройка поиска.
  wdFind := wdRng.Find;
  //wdFind.ClearFormatting;
  wdFind.Text := aSearchText;
  //True - поиск вести от начала - к концу диапазона.
  wdFind.Forward := True;
  //wdFindStop - завершить поиск при достижении границы диапазона.
  //wdFind.Wrap := wdFindStop;
 
  //Поиск текста.
  if wdFind.Execute then Result := wdRng;
end;
 
//Поиск заданного текста в документе MS Word.
procedure TForm1.Button1Click(Sender: TObject);
var
  wdApp, wdDocs, wdDoc, wdRng : Variant;
  SearchText : string;
begin
  //Искомый текст.
  SearchText := Edit1.Text;
  if SearchText = '' then begin
    MessageBox(0, 'Искомый текст не задан. Действие отменено.'
      ,'Искомый текст не задан', MB_OK + MB_ICONEXCLAMATION + MB_APPLMODAL);
    Exit;
  end;
  
  //Запуск MS Word и подключение к его корневому объекту.
  try
    wdApp := GetActiveOleObject('Word.Application');
  except
    MessageBox(0, 'Нет запущенных экземпляров MS Word. Действие отменено.',
      'Отмена', MB_OK + MB_ICONWARNING + MB_APPLMODAL);
    Exit;
  end;
 
  //Подключаемся к коллекции документов.
  wdDocs := wdApp.Documents;
  //Проверяем - есть ли хотя бы один открытый документ.
  if wdDocs.Count = 0 then begin
    MessageBox(0, 'Нет ни одного открытого документа. Действие отменено.'
      ,'Отмена', MB_OK + MB_ICONWARNING + MB_APPLMODAL);
    Exit;
  end;
  //Делаем видимым окно MS Word.
  wdApp.Visible := True;
  //Подключаемся к первому документу в коллекции.
  wdDoc := wdDocs.Item(1);
  //Поиск заданного текста.
  wdRng := FindInDoc(wdDoc, SearchText);
  if VarIsClear(wdRng) then begin
    ShowMessage('Текст НЕ найден.');
    Exit;
  end;
 
  ShowMessage('Текст найден.');
 
  //Выделяем найденный текст.
  wdRng.Select;
  //Прокручиваем содержимое документа (в первом окне) таким образом, чтобы стал
  //видимым участок с найденным текстом.
  wdDoc.Windows.Item(1).ScrollIntoView(wdRng);
 
  //Можно выполнить какие-нибудь действия с найденным текстом.
  //Например, пометим найденный текст жирным красным шрифтом.
  //wdRng.Font.Bold := True;
  //wdRng.Font.Color := RGB(255, 100, 100);
end;
 
end.

Здесь происходит попытка подключения к уже запущенному экземпляру MS Word. Затем, выполняется подключение к первому из уже открытых документов. Если все эти шаги успешны, то выполняется поиск текста.

Ещё можно сделать так. Подключаемся к запущенному экземпляру MS Word. Потом, среди открытых документов ищем тот, чьё имя файла совпадает с заданным и выполняем поиск в этом документе. Имя файла пускай будет выбираться через OpenDialog.

Delphi
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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
implementation
 
{$R *.dfm}
 
uses
  ComObj;
 
{Пояснение по поиску.
Объект wdFind связан с диапазоном wdRng. При каждом вызове wdFind.Execute
поиск продолжается в том диапазоне, который определял wdRng до первого
вызова wdFind.Execute. Т. е., поиск выполняется в одном и том же диапазоне.
Но сам объект wdRng изменяется при каждом обнаружении искомого текста - он
становится равным диапазону, который охватывает этот найденный текст.}
 
{Функция ищет заданный текст aSearchText в документе MS Word aWdDoc и возвращает
ссылку на диапазон, который охватывает найденный текст.}
function FindInDoc(const aWdDoc : Variant; const aSearchText : String) : Variant;
const
  wdFindStop = 0; //Завершить поиск при достижении границы диапазона.
var
  wdRng, wdFind : Variant;
begin
  VarClear(Result);
  //Диапазон, охватывающий всё содержимое документа.
  wdRng := aWdDoc.Content;
 
  //Настройка поиска.
  wdFind := wdRng.Find;
  //wdFind.ClearFormatting;
  wdFind.Text := aSearchText;
  //True - поиск вести от начала - к концу диапазона.
  wdFind.Forward := True;
  //wdFindStop - завершить поиск при достижении границы диапазона.
  //wdFind.Wrap := wdFindStop;
 
  //Поиск текста.
  if wdFind.Execute then Result := wdRng;
end;
 
//Поиск заданного текста в документе MS Word.
procedure TForm1.Button1Click(Sender: TObject);
var
  wdApp, wdDocs, wdDoc, wdRng : Variant;
  SearchText : string;
  i : Integer;
  Od : TOpenDialog;
begin
  //Искомый текст.
  SearchText := Edit1.Text;
  if SearchText = '' then begin
    MessageBox(0, 'Искомый текст не задан. Действие отменено.'
      ,'Искомый текст не задан', MB_OK + MB_ICONEXCLAMATION + MB_APPLMODAL);
    Exit;
  end;
  //Выбор имени файла.
  Od := OpenDialog1; //OpenDialog1 уже должен быть на форме.
  if Od.InitialDir = '' then
    Od.InitialDir := ExtractFilePath( ParamStr(0) );
  if not Od.Execute then Exit;
  if not FileExists(Od.FileName) then begin
    MessageBox(0, 'Файл с заданным именем не найден. Действие отменено.'
      ,'Файл не найден', MB_OK + MB_ICONEXCLAMATION + MB_APPLMODAL);
    Exit;
  end;
 
  //Попытка подключиться к уже запущенному экземпляру MS Word.
  try
    wdApp := GetActiveOleObject('Word.Application');
  except
    MessageBox(0, 'Нет запущенных экземпляров MS Word. Действие отменено.',
      'Отмена', MB_OK + MB_ICONWARNING + MB_APPLMODAL);
    Exit;
  end;
 
  //Подключаемся к коллекции документов.
  wdDocs := wdApp.Documents;
  //Ищем документ по имени файла.
  VarClear(wdDoc);
  for i := 1 to wdDocs.Count do
    if wdDocs.Item(i).FullName = Od.FileName then begin
      wdDoc := wdDocs.Item(i);
      Break;
    end;
  if VarIsClear(wdDoc) then begin
    MessageBox(0, 'Документ не является открытым в настоящее время. Действие отменено.'
      ,'Отмена', MB_OK + MB_ICONWARNING + MB_APPLMODAL);
    Exit;
  end;
 
  //Делаем видимым окно MS Word.
  wdApp.Visible := True;
  //Поиск заданного текста.
  wdRng := FindInDoc(wdDoc, SearchText);
  if VarIsClear(wdRng) then begin
    ShowMessage('Текст НЕ найден.');
    Exit;
  end;
 
  ShowMessage('Текст найден.');
 
  //Выделяем найденный текст.
  wdRng.Select;
  //Прокручиваем содержимое документа (в первом окне) таким образом, чтобы стал
  //видимым участок с найденным текстом.
  wdDoc.Windows.Item(1).ScrollIntoView(wdRng);
 
  //Можно выполнить какие-нибудь действия с найденным текстом.
  //Например, пометим найденный текст жирным красным шрифтом.
  //wdRng.Font.Bold := True;
  //wdRng.Font.Color := RGB(255, 100, 100);
end;
 
end.



1



    msm.ru

    Нравится ресурс?

    Помоги проекту!

    !
    user posted image

    Пожалуйста, выделяйте текст программы тегом [сode=pas] … [/сode]. Для этого используйте кнопку [code=pas] в форме ответа или комбобокс, если нужно вставить код на языке, отличном от Дельфи/Паскаля.

    Соблюдайте общие правила форума

    Следующие вопросы задаются очень часто, подробно разобраны в FAQ и, поэтому, будут безжалостно удаляться:
    1. Преобразовать переменную типа String в тип PChar (PAnsiChar)
    2. Как «свернуть» программу в трей.
    3. Как «скрыться» от Ctrl + Alt + Del (заблокировать их и т.п.)
    4. Как запустить программу/файл? (и дождаться ее завершения)
    5. Как перехватить API-функции, поставить hook? (перехват сообщений от мыши, клавиатуры — внедрение в удаленное адресное прстранство)
    … (продолжение следует) …


    Внимание:
    Попытки открытия обсуждений реализации вредоносного ПО, включая различные интерпретации спам-ботов, наказывается предупреждением на 30 дней.
    Повторная попытка — 60 дней. Последующие попытки — бан.
    Мат в разделе — бан на три месяца…


    Полезные ссылки:
    user posted image MSDN Library user posted image FAQ раздела user posted image Поиск по разделу user posted image Как правильно задавать вопросы


    Выразить свое отношение к модераторам раздела можно здесь: user posted image Rouse_, user posted image Krid

    >
    Delphi и Word
    , Не могу выделить текст

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



    Сообщ.
    #1

    ,
    07.09.05, 10:23

      Народ!!!
      Пишу на Delphi программу которая по шаблону будит генерить страници в Word’е.
      Вроде все получаеться, мне осталось скопировать страницу и размножить ее(програмно естественно).
      Но я не могу выделить весь текст,что бы его потом скопировать.
      Сам вопрос: как выделить весь текст?


      Modest Wizard



      Сообщ.
      #2

      ,
      07.09.05, 10:33

        ExpandedWrap disabled

          Var Word:Variant;

          begin

              Word:=CreateOleObject(‘Word.Application’);

              Word.Documents.Open(‘c:myfile.doc’,emptyparam,emptyparam,emptyparam,emptyparam,emptyparam,emptyparam,emptyparam,emptyparam,emptyparam,1251);

              Word.Selection.WholeStory;

              Word.Visible:=true;

          end;

        Guru

        Rouse_



        Сообщ.
        #3

        ,
        07.09.05, 10:35

          Moderator

          *******

          Рейтинг (т): 320

          ExpandedWrap disabled

            unit Unit1;

            interface

            uses

              Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

              Dialogs, ComObj, StdCtrls;

            type

              TForm1 = class(TForm)

                Button1: TButton;

                procedure Button1Click(Sender: TObject);

                procedure FormDestroy(Sender: TObject);

              private

                { Private declarations }

              public

                { Public declarations }

              end;

            var

              Form1: TForm1;

              W: Variant;

            implementation

            {$R *.dfm}

            procedure TForm1.Button1Click(Sender: TObject);

            begin

              W := CreateOleObject(‘Word.Application’);

              W.Documents.Open(FileName := ‘c:tmp.doc’, ReadOnly:=False);

              W.Visible := True;

              W.ActiveDocument.Range(Start := 10, End := 40).Select;

            end;

            procedure TForm1.FormDestroy(Sender: TObject);

            begin

              W.Quit(SaveChanges:=True);

            end;

            end.


          Kryak



          Сообщ.
          #4

          ,
          07.09.05, 11:00

            Посибки :)


            Shaden

              


            Сообщ.
            #5

            ,
            14.09.05, 03:44

              Junior

              *

              Рейтинг (т): 0

              Извините, а как скопировать, допустим, с третьей по шестую строку текста, содержащего 10 строк и вставить скопированный текст после десятой строки?
              Спасибо заранее.

              Сообщение отредактировано: Shaden — 14.09.05, 03:45

              Master

              Krid



              Сообщ.
              #6

              ,
              23.09.05, 16:23

                Moderator

                ******

                Рейтинг (т): 237

                Цитата Shaden @ 14.09.05, 03:44

                Извините, а как скопировать, допустим, с третьей по шестую строку текста, содержащего 10 строк и вставить скопированный текст после десятой строки?

                ExpandedWrap disabled

                  const

                   wdGoToLine=3;

                   wdGoToAbsolute=1;

                   wdLine = 5;

                   wdExtend=1;

                   wdGoToLast=-1;

                  var

                   W,Sel: Variant;

                  procedure TForm1.Button1Click(Sender: TObject);

                  begin

                    W := CreateOleObject(‘Word.Application’);

                    W.Documents.Open(FileName := ‘c:tmp.doc’, ReadOnly:=False);

                    W.Visible := True;

                    Sel:=W.Selection;

                    Sel.GoTo(What:=wdGoToLine, Which:=wdGoToAbsolute, Count:=3);

                    Sel.MoveDown(Unit:=wdLine, Count:=3, Extend:=wdExtend);

                    Sel.Copy;

                    Sel.GoTo(What:=wdGoToLine, Which:=wdGoToLast);

                    Sel.EndKey( Unit:=wdLine);

                    Sel.TypeParagraph;

                    Sel.Paste;

                    Sel:=Unassigned;

                  end;


                yurant



                Сообщ.
                #7

                ,
                11.11.05, 09:36

                  Junior

                  *

                  Рейтинг (т): 0

                  А можно ли выделить весь текст БЕЗ открытия
                  Ворда и отобразить все это, скажем, в Мемо?


                  vet



                  Сообщ.
                  #8

                  ,
                  11.11.05, 15:03

                    Full Member

                    ***

                    Рейтинг (т): 16

                    Открывать-то придется, но если его не делать видимым, то никто ничего и не узнает :)

                    ExpandedWrap disabled

                      var

                       Word: variant;

                      begin

                       Word := CreateOleObject(‘Word.Application’);

                       Word.Documents.Open(‘C:666.doc’);

                       Word.Selection.WholeStory;

                       Word.Selection.Copy;

                       Memo.PasteFromClipboard;

                       Word.Quit;

                       Word := Unassigned;

                      end;

                    Вообще-то узнает, так как будет задержка на открытие документа


                    dron-s



                    Сообщ.
                    #9

                    ,
                    30.11.05, 05:10

                      yurant
                      можно так

                      ExpandedWrap disabled

                        var

                          word:variant;

                        begin

                         Word := CreateOleObject(‘Word.Application’);

                         Word.Documents.Open(‘C:333.doc’);

                         RichEdit1.Text := word.ActiveDocument.Range.Text;

                         word.Quit;

                      это без буфера обмена…


                      valyan



                      Сообщ.
                      #10

                      ,
                      20.07.10, 16:02

                        Full Member

                        ***

                        Рейтинг (т): нет

                        Здравствуйте. Вопрос таков — в документе порядка 100 страниц, на каждой странице есть информация о человеке, эта информация — переменная величина (для каждого человека), так вот как выделить эти строки (информацию о человеке)


                        VahaC



                        Сообщ.
                        #11

                        ,
                        20.07.10, 16:13

                          Имхо лучше всего делать вот так:

                          Берем весь текст из ворда и пихаем его к примеру в RichEdit

                          Цитата dron-s @ 30.11.05, 05:10

                          yurant
                          можно так

                          ExpandedWrap disabled

                            var

                              word:variant;

                            begin

                             Word := CreateOleObject(‘Word.Application’);

                             Word.Documents.Open(‘C:333.doc’);

                             RichEdit1.Text := word.ActiveDocument.Range.Text;

                             word.Quit;

                          а потом парсим текст в этом RichEdit`е с помощью Pos, PosEx и иже с ними

                          Сообщения были разделены в тему «Вставка текста в середину страницы. Word»


                          evg_reg35



                          Сообщ.
                          #12

                          ,
                          05.11.10, 17:37

                            Добрый вечер. Подскажите пожалуйста. Для удобства решил написать программу, но не получается.
                            Идея в следующем. Открыт какойто текст в Word. При прочтении текста появляется необходимость у некоторых слов изменить заливку (именно заливку, а не цвет букв). Хочется чтобы было так: читаю книгу в WORD, выделяю мышкой текст в Wordе (удерживая определенную клавишу), отпускаю мышку и заливка текста меняется.
                            Нашел в иннете что заливка текста меняется функцией WordTextBox.Fill, но чтото не работает, может нужно подключить какойто модуль в раздел uses
                            Ну хотябы пока научится по нажатию кнопки менять заливку выделенного слова в книге?

                            0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)

                            0 пользователей:

                            • Предыдущая тема
                            • Delphi: Система, Windows API
                            • Следующая тема

                            Рейтинг@Mail.ru

                            [ Script execution time: 0,0376 ]   [ 16 queries used ]   [ Generated: 13.04.23, 22:37 GMT ]  

                            Если «до конца» = «До самого конца»:

                            Procedure SelectFromPositionToEnd(startPosition: integer);
                            begin
                              W.Selection.Start := startPosition;
                              W.Selection.End   := W.ActiveDocument.Characters.Count; // последний символ в документе
                            end;
                            

                            Если «до конца» = «До конца предложения»:

                            Procedure SelectFromPositionToEdnOfSentence(startPosition: integer);
                            const
                              WdSentence = 3; //значение для перехода к следующему предложению
                            begin
                              w.Selection.Start := startPosition; //поставили сюда курсор
                              w.Selection.Move(WdSentence, 1);    //передвинули до следующего предложения
                              w.Selection.Start := startPosition; //растянули выделение до начального символа
                            end;
                            

                            Если «до конца» = «До конца строки», то тоже что и во втором случае, только заменить первый параметр в Move
                            с

                            WdSentence
                            

                            на

                            Wdline = 5 //значение для перехода к следующей линии (строке)
                            

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

                            Текст

                            Сначала о самом простом
                            — добавлении в документ Word нужной строки текста. Поместим на форму компоненты
                            WordDocument, WordApplicationи WordParagraphFormat с
                            палитры Servers. Нас интересуют в первую очередь свойство Range
                            компонента WordDocument и свойство Selection компонента
                            WordApplication
                            . Классики утверждают, что они являются ссылкой на объекты
                            Range
                            и Selection. Range представляет из себя, проще говоря,
                            кусок текста, это может быть как весь текст документа, так и любая его часть.
                            Его пределы задаются двумя (или меньше) параметрами типа OleVariant.
                            Например:

                            var range1, range2, range3, a, b : OleVariant;
                            ...
                            range1:=WordDocument1.Range;
                            a:=5;
                            b:=15;
                            range2:=WordDocument1.Range(a,b);
                            range3:=WordDocument1.Range(a);
                            

                            Первый наш объект включает в себя весь текст документа, у второго мы ограничили
                            пределы 5-м и 15-м символами, третий представляет из себя весь последующий текст
                            документа, начиная с 5-го символа. Объект имеет несколько полезных методов,
                            например, с его помощью можем добавить текст в документ:

                            range2.InsertAfter('MS Word');
                            

                            Это
                            мы вставили текст после выделенного Range. Точно также можем вставить
                            текст и перед ним, для этого служит метод InsertBefore(). Текст,
                            заключенный в объекте Range, можем получить так:
                            WordDocument1.Range(a,b).Text; Кроме
                            того, с помощью Range можем изменить шрифт в пределах объекта. Пример:

                            a:=5;
                            b:=15;
                            WordDocument1.Range(a,b).Font.Bold:=1;
                            WordDocument1.Range(a,b).Font.Size:=14;
                            WordDocument1.Range(a,b).Font.Color:=clRed;
                            

                            Если
                            хотим отменить выделение жирным шрифтом, присваиваем 0. Аналогично можно сделать
                            шрифт курсивом, подчеркнутым — наберите WordDocument1.Range.Font., и
                            среда сама подскажет, какие могут быть варианты. Методы Select, Cut, Copy и
                            Paste работают как в обычном тексте. С помощью Paste можем на место выбранного
                            Range вставить не только строки, но и рисунок, находящийся в буфере
                            обмена.

                            WordDocument1.Range(a,b).Select;
                            WordDocument1.Range(a,b).Cut;
                            WordDocument1.Range(a,b).Copy;
                            WordDocument1.Range(a,b).Paste;
                            

                            С
                            помощью Range можем найти в документе нужную строку. Пусть в тексте содержится
                            слово «picture». Например, нам на его место надо будет вставить рисунок.

                            var a, b, vstart, vend: OleVariant;
                             j, ilengy: Integer;
                            ...
                            ilengy:=Length(WordDocument1.Range.Text);
                            for j:=0 to ilengy-8 do begin
                             a:=j;
                             b:=j+7;
                             if WordDocument1.Range(a,b).Text='picture' then begin
                             vstart:=j;
                             vend:=j+7;
                             end;
                            end;
                            WordDocument1.Range(vstart,vend).Select;
                            

                            Такая
                            процедура находит и выделяет нужный кусок текста.Теперь про Selection, представляющий из себя выделенный фрагмент
                            документа. Если выделения нет, это текущая позиция курсора в документе. С его
                            помощью можем вставить что-либо на место выделенного фрагмента, сделать
                            выравнивание, изменить шрифт. Он также имеет методы InsertAfter() и
                            InsertBefore()
                            :

                            WordApplication1.Selection.InsertAfter("text1");
                            WordApplication1.Selection.InsertBefore("text2");

                            Форматирование выделенного текста происходит аналогично Range, например:

                            WordApplication1.Selection.Font.Bold:=1;
                            WordApplication1.Selection.Font.Size:=16;
                            WordApplication1.Selection.Font.Color:=clGreen;
                            

                            Для
                            выравнивания проще воспользоваться компонентом WordParagraphFormat.
                            Сначала только нужно «подключить» его к выделенному фрагменту текста:

                            WordParagraphFormat1.ConnectTo(WordApplication1.Selection.ParagraphFormat);
                            WordParagraphFormat1.Alignment:=wdAlignParagraphCenter;
                            

                            Значения его свойства Alignment может принимать значения
                            wdAlignParagraphCenter, wdAlignParagraphLeft, wdAlignParagraphRight
                            , смысл
                            которых очевиден. Имеются и методы Cut, Copy и Paste, которые в пояснениях вряд
                            ли нуждаются:

                            WordApplication1.Selection.Cut;
                            WordApplication1.Selection.Copy;
                            WordApplication1.Selection.Paste;
                            

                            Убираем выделение с помощью метода Collapse.
                            При этом необходимо указать, в какую сторону сместится курсор, будет ли он до
                            ранее выделенного фрагмента или после:

                            var vcol: OleVariant;
                            ...
                            vcol:=wdCollapseStart;
                            WordApplication1.Selection.Collapse(vcol);
                            

                            При
                            этом выделение пропадет, а курсор займет позицию перед фрагментом текста. Если
                            присвоить переменной значение wdCollapseEnd, то курсор переместится назад. Можно
                            просто поставить в скобках «пустышку»:

                            WordApplication1.Selection.Collapse(EmptyParam);
                            

                            Тогда
                            свертывание выделения производится по умолчанию, к началу выделенного текста.
                            РисункиЛогично было бы предположить, что рисунки документа будут представлять из себя
                            коллекцию, аналогичную таблицам, и мы, обратившись к конкретной картинке, сможем
                            менять ее свойства — обтекание, размер и т.д. Однако ничего подобного в WordDocument не обнаруживается. Потому возможности управления встраиваемыми в
                            документ изображениями сильно ограничены. Простейший метод вставить в документ рисунок — по упомянутым причинам он же и
                            единственный — скопировать его в Word из буфера обмена. Предположим, рисунок у
                            нас находится в компоненте DBImage. Сначала нужно загнать его в буфер обмена:

                            Clipboard.Assign(DBImage1.Picture);
                            

                            Теперь для его вставки следует воспользоваться методом Paste объектов Range или
                            Selection: WordApplication1.Selection.Paste или WordDocument1.Range(a,b).Paste.
                            Оставить для рисунка достаточное количество пустых строк и попасть в нужное
                            место — это уже наша забота. Если он попадет посреди текста, вид будет довольно
                            противный — при такой вставке обтекание текстом рисунка происходит как-то
                            странно. Можно приготовить для отчета шаблон, где заменяем рисунком какое-либо
                            ключевое слово. О том, как найти в документе нужный текст, см. выше.
                            А
                            теперь о несколько ином способе вставки рисунка, который устраняет проблемы с
                            обтеканием и дает нам возможность перемещать его по документу, масштабировать и
                            задавать отступы между рисунком и текстом. Способ, собственно, тот же — копируем
                            из буфера обмена, но не прямо в документ, а в «рамку» — текстовую вставку. В ней
                            может находиться не только текст, но и картинка, чем и воспользуемся.
                            «Рамки» образуют коллекцию Frames, нумеруются целым индексом, пробегающим
                            значения от 1 до WordDocument1.Frames.Count. Добавим в документ рамку,
                            изменим ее размер и вставим рисунок:

                            Clipboard.Assign(DBImage1.Picture);
                            vstart:=1;
                            vend:=2;
                            WordDocument1.Frames.Add(WordDocument1.Range(vstart,vend));
                            i:=1;
                            WordDocument1.Frames.Item(i).Height:=DBImage1.Height;
                            WordDocument1.Frames.Item(i).Width:=DBImage1.Width;
                            WordDocument1.Frames.Item(i).Select;
                            WordApplication1.Selection.Paste;
                            

                            Здесь
                            для простоты предполагается, что размер DBImage равен размеру самой
                            картинки, а также что до этого рамок у нас в документе не было. Обратить
                            внимание следует на несколько моментов. Размер рамки надо задавать до того, как
                            копировать в нее рисунок. Иначе она будет иметь размер по умолчанию, под который
                            замасштабируется и наша картинка. При попытке изменить размер рамки задним
                            числом размер картинки уже не изменится. Кроме того, параметр Range при
                            добавлении рамки часто никакой роли не играет. Рамка изначально все равно
                            появится в левом верхнем углу документа, а указанный кусок текста при этом не
                            пострадает. Но это только в том случае, если он не выделен. Если в документе
                            есть выделение, рамка появится вместо выделенного фрагмента. Таким образом можем
                            ее вставить в нужное место взамен какого-то ключевого слова.
                            При желании можем ее подвигать в документе и «вручную». Для этого служат
                            свойства горизонтального и вертикального позиционирования, которые задают ее
                            отступ от левого верхнего «угла» документа:

                            i:=1;
                            WordDocument1.Frames.Item(i).VerticalPosition:=30;
                            WordDocument1.Frames.Item(i).HorizontalPosition:=50;
                            Отступ между краями рамки и текстом задается следующим образом:
                            WordDocument1.Frames.Item(i).HorizontalDistanceFromText:=10;
                            WordDocument1.Frames.Item(i).VerticalDistanceFromText:=10;
                            

                            А
                            теперь о масштабировании. Для этого достаточно длину и ширину рамки умножить на
                            одно и то же число. Например:

                            WordDocument1.Frames.Item(i).Height:=DBImage1.Height*1.5;
                            WordDocument1.Frames.Item(i).Width:=DBImage1.Width*1.5;
                            

                            При
                            этом наша картинка в полтора раза пропорционально растянется. Точно также можно
                            и уменьшить, но делить, как и множить, следует на одно число. Растягивать длину
                            и ширину по-разному у меня лично не получалось. Задавать размер опять-таки надо
                            еще до вставки рисунка. Ну и, наконец, удаление рамки:

                            WordDocument1.Frames.Item(i).Delete;
                            

                            Списки Списки в документе образуют коллекцию Lists, к отдельному списку
                            обращаемся WordDocument1.Lists.Item(i), где i целое число от 1 до
                            WordDocument1.Lists.Count
                            … на этом все. Нет методов, позволяющих не то
                            что создать новый список, а даже добавить пункт к уже существующему. Ничего
                            страшного, настоящие герои всегда идут в обход:)) Сейчас мы все же проделаем и
                            то, и другое. Все что нам понадобится — свойство Range отдельного списка, то
                            есть его текст без разделения на пункты, а также возможность его выделить:

                            WordDocument1.Lists.Item(i).Range.Select;
                            

                            Для
                            этого в любом случае потребуется заготовка. Неважно, вставлена она в общий
                            шаблонный документ или хранится в отдельном файле. Заготовку делаем так:
                            выбираем в меню Формат/Список, и сохраняем, если это отдельный шаблон списка. У
                            нас появляется пустой список без текста с одним маркером. Далее вспоминаем, как
                            мы делали списки вручную — писали текст, нажимали «Enter», появлялся новый
                            элемент списка. Теперь то же самое, только программно. Предположим, у нас уже
                            открыт документ с заготовкой, и мы хотим внести в список пункты «Item 1» и «Item
                            2»:

                            var i: Integer;
                             vcol: OleVariant;
                            ...
                            i:=1;
                            vcol:=wdCollapseEnd;
                            WordDocument1.Lists.Item(i).Range.Select;
                            WordApplication1.Selection.Collapse(vcol);
                            WordApplication1.Selection.InsertAfter('Item 1');
                            WordDocument1.Lists.Item(i).Range.Select;
                            WordApplication1.Selection.Collapse(vcol);
                            WordApplication1.Selection.InsertAfter(#13);
                            WordDocument1.Lists.Item(i).Range.Select;
                            WordApplication1.Selection.Collapse(vcol);
                            WordApplication1.Selection.InsertAfter('Item 2');
                            WordDocument1.Lists.Items(i).Range.Select;
                            WordApplication1.Selection.Copy;
                            

                            То
                            есть мы вставляем в документ текст первого пункта списка, он попадает на свое
                            место. Потом посылаем в Word символ перехода строки, он честно переходит и тем
                            самым сам создает нам второй пункт списка, куда и вставляем нужную строку. Ну и
                            так далее, нужное количество раз. Последние две строки нужны, если список
                            заготовлен в отдельном файле — после их выполнения список оказывается в буфере
                            обмена. Здесь выгода в том, что можем иметь заготовки списков разных стилей и по
                            ходу дела выбирать, какой список создать. Затем открываем документ, где должен
                            быть список, выделяем с помощью Range нужный кусок, копируем из буфера обмена
                            через WordDocument1.Range(a,b).Paste. Чтобы не испортить файл с заготовкой,
                            можем сразу после открытия пересохранить его под другим именем, а можем просто
                            выйти из него без сохранения изменений

                            var vsave: OleVariant;
                            ...
                            vsave:=wdDoNotSaveChanges;
                            WordDocument1.Close(vsave);
                            

                            Константа сохранения изменений может принимать значения

                            Символьное
                            обозначение


                            Шестнадцатеричное

                             

                            wdSaveChanges

                            $FFFFFFFF

                            wdDoNotSaveChanges

                            $00000000

                            wdPromptToSaveChanges

                            $FFFFFFFE

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

                            var i,j: Integer;
                            ...
                            i:=1;
                            j:=1;
                            WordDocument1.Lists.Item(i).ListParagraphs.Item(j).Range.Text:='Item 1';

                            Так что можно с помощью переходов строки создать нужное количество элементов, а затем их заполнить:

                            WordDocument1.Lists.Item(i).Range.Select;
                            WordApplication1.Selection.Collapse(vcol);
                            WordApplication1.Selection.InsertAfter(#13);
                            j:=1;
                            WordDocument1.Lists.Item(i).ListParagraphs.Item(j).Range.Text:='Item 1';
                            j:=2;
                            WordDocument1.Lists.Item(i).ListParagraphs.Item(j).Range.Text:='Item 2';
                            

                            Это
                            было в предположении, что у нас один элемент списка в заготовке уже есть. Ну
                            вот, в общем-то, и все про текст, списки и картинкиСтатистика документовВ
                            данном небольшом материале рассматривается вопрос подсчета статистики файлов
                            *.doc и *.rtf. Такой вопрос у меня возник, когда пришлось сделать небольшую базу
                            данных по учету документов, куда надо было заносить и статистику документа —
                            число знаков, слов и т.п. Открывать каждый раз Word, считать статистику и
                            забивать ее в форму ввода было лень, так что пришла в голову мысль это дело
                            автоматизировать. Информации по данному вопросу найти так и не удалось, так что
                            основным источником знаний служили заголовочный файл Word2000.pas и
                            справка по Visual Basic for Applications. Ну и, конечно, множество разных
                            экспериментов. Сразу
                            оговорюсь, что я не профессиональный программист, так что в тонкости интерфейсов
                            вникать не будем — сам в них не особо разбираюсь. Потому, не мудрствуя лукаво,
                            просто поместим на форме компоненты WordApplication и WordDocument
                            с палитры Servers. Для работы используются свойства и методы этих
                            компонентов. Встроенная статистика Word подсчитывает статистику обычного текста, обычных и
                            концевых сносок. Для подсчета статистики используется метод компонента
                            WordDocument ComputeStatistic()
                            . Он имеет один параметр, характеризующий,
                            что именно считать, представляющий из себя шестнадцатеричную константу.
                            Константы описаны в заголовочном файле Word2000.pas, он лежит обычно в
                            /Delphi/Ocx/Servers
                            .


                            Шестнадцатеричная

                            Символьное обозначение

                            Смысл

                            $00000000

                            wdStatisticWords

                            Количество слов

                            $00000001

                            wdStatisticLines

                            Количество строк

                            $00000002

                            wdStatisticPages

                            Количество страниц

                            $00000003

                            wdStatisticCharacters

                            Знаки без пробелов

                            $00000004

                            wdStatisticParagraphs

                            Количество разделов

                            $00000005

                            wdStatisticCharactersWithSpaces

                            Знаки с пробелами

                            Это было основное, что
                            надо знать. Ну а теперь по порядку. Поместив на форму упомянутые компоненты, видим, что свойств и методов у них
                            совсем мало. В первую очередь следует определиться с методом ConnectKind
                            компонента WordApplication. Оно может принимать различные значения, но мы
                            оставим присваемое по умолчанию значение ckRunningOrNew. Это означает, что
                            соединение происходит с уже работающим сервером, при его отсутствии запускается
                            новый. Как правило, это вполне устраивает. Первым делом откроем документ. Предварительно надо объявить переменную FileName,
                            она будет типа OleVariant, которой присвоим строку с именем файла.

                            WordApplication1.Connect;
                            WordApplication1.Documents.Open(FileName,
                            EmptyParam,EmptyParam,EmptyParam,
                            EmptyParam,EmptyParam,EmptyParam,
                            EmptyParam,EmptyParam,EmptyParam,
                            EmptyParam,EmptyParam);
                            WordDocument1.ConnectTo(WordApplication1.ActiveDocument);
                            

                            Обратите внимание на количество параметров-«пустышек».
                            Их число больше того, которое обычно
                            приводится в книжках. Ну, в моих, во всяком случае. Объясняется это тем, что
                            «книжные» функции предназначены для MS Word 97, а такая запись для работы с Word
                            2000 и Word XP.
                            «Plain Text»
                            Объявив нужное количество переменных типа LongInt (в очень большом файле или при
                            суммировании по нескольким документам в принципе может оказаться больше знаков,
                            чем пределы обычного целого типа), можем уже и приступать к подсчету. Например,
                            посчитаем число слов, знаков с пробелами и без пробелов обычного текста, а также
                            количество страниц в документе. Результаты сохраним соответственно в «длинных»
                            переменных

                            WCount:=WordDocument1.ComputeStatistics($00000000);
                            CCount:=WordDocument1.ComputeStatistics($00000003);
                            SCount:=WordDocument1.ComputeStatistics($00000005);
                            PCount:=WordDocument1.ComputeStatistics($00000002);
                            

                            Открыв нужный документ в Word’е и вызвав диалог подсчета статистики, нетрудно
                            увидеть, что значения переменных равны параметрам вордовской статистики со
                            сброшенным флажком «Учитывать все сноски».
                            Сноски
                            Сноски в документах могут быть обычные и концевые. То есть если первые
                            располагаются внизу данной страницы, то концевые — строго в конце документа.
                            Кроме того, они могут отличаться и нумерацией — автоматической или заданной
                            пользователем. Начнем с обычных сносок как с самого простого. В терминологии
                            объектной модели Word — Footnotes. Сначала надо вычислить количество самих
                            сносок:

                            ifcount:=WordDocument1.DefaultInterface.Footnotes.Count;
                            

                            Подсчет статистики текста в сноске производится так:

                            FWCount:=WordDocument1.DefaultInterface.Footnotes.Item(ifoot).Range.ComputeStatistics($00000000);
                            

                            Здесь
                            ifoot — целое число, «нумерующее» сноску. Для того, чтобы учесть сами номера
                            сносок, сделаем так:

                            FWCount:=FWCount+WordDocument1.DefaultInterface.Footnotes.Item(ifoot).Reference.ComputeStatistics($00000000);
                            

                            Это
                            мы посчитали для примера количество слов в сноске с номером ifoot и ее метке —
                            при пользовательской нумерации в качестве «номера» может быть целое предложение.
                            Далее начинаем перебирать их одну за другой. При этом следует учесть, что кроме
                            статистики сносок необходимо получить и статистику их «номеров». То есть:

                            for ifoot:=1 to ifcount do begin
                             FWCount:=FWCount+WordDocument1.DefaultInterface.Footnotes.Item(ifoot).Range.ComputeStatistics($00000000);
                             FCCount:=FCCount+WordDocument1.DefaultInterface.Footnotes.Item(ifoot).Range.ComputeStatistics($00000003);
                             FSCount:=FSCount+WordDocument1.DefaultInterface.Footnotes.Item(ifoot).Range.ComputeStatistics($00000005);
                             FCCount:=FCCount+WordDocument1.DefaultInterface.Footnotes.Item(ifoot).Reference.ComputeStatistics($00000003);
                             FSCount:=FSCount+WordDocument1.DefaultInterface.Footnotes.Item(ifoot).Reference.ComputeStatistics($00000005)+1;
                             if WordDocument1.DefaultInterface.Footnotes.Item(ifoot).Reference.Text<>IntToStr(ifoot)
                             then begin
                             FWCount:=FWCount+
                             WordDocument1.DefaultInterface.Footnotes.Item(ifoot).Reference.ComputeStatistics($00000000);
                             end;
                            end;
                            

                            Прибавление единицы появляется оттого, что сумма статистики сносок и номеров не
                            совпадает с тем, что выдает встроенная статистика Word. Между номером сноски и
                            текстом сноски Word ставит пробел, который почему-то не учитывается. Условный
                            оператор определяет, как пронумерована данная сноска — по умолчанию или нет. В
                            последнем случае следует проверить количество слов в обозначении сноски. Такая
                            схема дает результат, совпадающий со показаниями встроенной статистики. Кроме
                            того, цикл у нас идет от 1 — так начинается нумерация сносок в MS Word, да и
                            практически всех остальных объектов тоже.Теперь перейдем к концевым сноскам. Теоретически все то же самое, только вместо
                            слова «Footnotes» пишем «Endnotes». И тут наталкиваемся на сюрприз — почему-то
                            оно считает неточно. Я в данном случае поступил так: сохраняю документ под
                            другим именем, переконвертирую концевые сноски в обычные и далее все, как
                            сказано выше. Сохранение документа:

                            WordDocument1.SaveAs(FileName, FileFormat),
                            

                            где в скобках стоят два параметра типа OleVariant — имя файла и шестнадцатеричная
                            константа, задающая формат файла. Некоторые константы:


                            Шестнадцатеричная


                            Символьное
                            обозначение


                            Смысл

                            $00000000

                            wdFormatDocument

                            Документ Word

                            $00000004

                            wdFormatDOSText

                            Простой текст

                            $00000006

                            wdFormatRTF

                            Файл RTF

                            Полный список констант
                            формата можно найти все в том же файле Word2000.pas. И еще один интересный
                            момент — если просто поставить в скобки обе константы, работать не будет.
                            Следует предварительно объявить две переменных, присвоить им соответствующие
                            значения и только потом сохранять. Ну, а
                            теперь, собственно, можем вернуться к сноскам. Конвертирование концевых сносок в
                            обычные происходит так:

                            WordDocument1.DefaultInterface.Endnotes.Convert;
                            

                            Теперь мы имеем документ, в котором содержатся только обычные сноски. С ними
                            никаких проблем не возникает, пример, как с ними работать, см. выше. Если
                            интересует статистика отдельно разных типов сносок, считаем предварительно
                            статистику обычных сносок, сохраняем ее в «буферных» переменных и считаем еще
                            раз после конвертирования. Разница даст статистику концевых сносок по
                            отдельности. Сложив статистику сносок и простого текста, получаем статистику
                            документа с учетом сносок так, как ее дает сам Word.
                            Дополнительно…
                            Тут
                            по традиции несколько покритикуем Microsoft. Как оказалось, Word показывает не
                            все, что содержится в документе. Не принимаются в расчет колонтитулы. А ведь в
                            них может содержаться изрядный кусок текста, особенно в справках, бланках и т.п.
                            Оказывается, Word их на самом деле считает, но нам не показывает. Вот и
                            посмотрим, как же его можно заставить это сделать. Колонтитулы в документе тесно связаны с несколько загадочной штукой под
                            названием «разделы» — Sections. Каждый раздел может иметь верхние и нижние
                            колонтитулы. Потому первым делом определяем количество абзацев.

                            isectct:=WordDocument1.DefaultInterface.Sections.Count;
                            

                            Здесь
                            у нас целые переменные isectct, icofct, icohct обозначают
                            соответственно количество разделов как таковых, количество нижних и верхних
                            колонтитулов данного раздела. Переменная isec служит «номером» раздела,
                            переменные icof, icoh «нумеруют» соответственно нижние и верхние
                            колонтитулы в пределах данного раздела. Количество колонтитулов в разделе
                            определяем так:

                            icofct:=WordDocument1.DefaultInterface.Sections.Item(isec).Footers.Count;
                            icohct:=WordDocument1.DefaultInterface.Sections.Item(isec).Headers.Count;
                            

                            Теперь уже можем «достать» текст из колонтитула:

                            CBWCount:=
                            WordDocument1.DefaultInterface.Sections.Item(isec).Footers.Item(icof).Range.ComputeStatistics($00000000);
                            

                            В
                            данном случае мы для примера посчитали число слов, содержащихся в нижнем
                            колонтитуле под номером icof, принадлежащем разделу под номером isec.
                            Теперь можем написать «двойной» цикл для подсчета статистики верхних и нижних
                            колонтитулов.

                            I have difficulties understanding the Selection in Word Automation.
                            To make it short, I want to have a table somewhere in my generated Word document, and I need to make alignments to the text inside a particular cell. How do I achieve that?

                            I use the ComObj approach:

                              var
                               MsWord: Variant;
                              ...
                              try
                                MsWord := GetActiveOleObject('Word.Application');
                              except
                                try
                                  MsWord := CreateOleObject('Word.Application');
                                  MsWord.Visible := True;
                                except
                                  Exception.Create('Error');
                                end;
                              end;
                            

                            How do I tell Word where is the text (cell) to be able later to align it?
                            I use this code to add text to a cell:

                            Function AddTextToTableCell(Table:integer;Row, Column:integer;text:string):boolean;
                            begin
                              AddTextToTableCell:=true;
                              try
                                MsWord.ActiveDocument.Tables.Item(Table).Columns.Item(Column).Cells.Item(Row).Range.Text:=text;
                              except
                                AddTextToTableCell:=false;
                              end;
                            End;
                            

                            Can I somehow modify this to set the alignment of the text inside the cell? Let’s say I want to center-align the cell located at: row:1 and column:3. My cell has multiple (variable) lines of text. I want to center it horizontally and vertically.

                            I searched other code of automation on Google and this line should do the trick, except it does not in delphi…(seems like VB equivalent works with it):

                            MSWORD.ActiveDocument.Tables.Item(Table).Cell(Row,Column).Range.Paragraphs.Alignment := wdAlignParagraphCenter;
                            

                            If I use

                            MSWORD.ActiveDocument.Tables.Item(Table).Range.ParagraphFormat.Alignment := wdAlignParagraphCenter
                            

                            then all the cells in the table are aligned to horiz-center. I only want one particular cell and I want it to be centered vertically too

                            Please help.

                            Thank you

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