Delphi шаблон для word

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
114
115
116
117
118
unit Unit1;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;
 
type
  TForm1 = class(TForm)
    Button1: TButton;
    OpenDialog1: TOpenDialog;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    Edit1: TEdit;
    Edit2: TEdit;
    Edit3: TEdit;
    Edit4: TEdit;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
 
var
  Form1: TForm1;
 
implementation
 
{$R *.dfm}
 
uses
  ComObj;
 
//Функция записывает новый текст для закладки с именем aBmName.
//Функция возвращает значение True, если закладка найдена и её текст изменён
//и False - если закладка не найдена.
//Переустановка текста закладки выплоняется так:
//- Получаем ссылку на объект-диапазон, который содержит текст закладки.
//- Удаляем закладку.
//- Устанавливаем новый текст для объекта-диапазона.
//- Создаём новую закладку с диапазоном, который содержит новый текст.
function SetBmText(var aBms : Variant; const aBmName, aText : String) : Boolean;
var
  Bm, Rng : Variant;
begin
  //Проверяем - существует ли закладка с заданным именем.
  Result := aBms.Exists(aBmName);
  //Если закладка не найдена - выходим.
  if not Result then Exit;
 
  //Ссылка на закладку.
  Bm := aBms.Item(aBmName);
  //Ссылка на диапазон, связанный с закладкой.
  Rng := Bm.Range;
  //Удаление закладки.
  Bm.Delete;
  //Заменяем текст в диапазоне.
  Rng.Text := aText;
  //Добавляем новую закладку с таким же именем.
  aBms.Add(aBmName, Rng);
end;
 
procedure TForm1.Button1Click(Sender: TObject);
var
  wdApp, wdDocs, wdDoc, wdBms : Variant;
  Od : TOpenDialog;
begin
  Od := OpenDialog1;
 
  if Od.InitialDir = '' then
    Od.InitialDir := ExtractFilePath( Application.ExeName )
  ;
  Od.Title := 'Выберите шаблон, на основе которого будет создан новый документ';
  if not Od.Execute then Exit;
  if not FileExists(Od.FileName) then begin
    MessageDlg(
      'Файл с заданным именем не найден. Действие отменено.'
      ,mtWarning, [mbOK], 0
    );
    Exit;
  end;
  try
    wdApp := CreateOleObject('Word.Application');
  except
    ShowMessage('Не удалось запустить MS Word. Действие отменено.');
    Exit;
  end;
 
  //Делаем видимым окно MS Word.
  wdApp.Visible := True;
  //Ссылка на коллекцию документов.
  wdDocs := wdApp.Documents;
  //Попытка открыть выбранный файл.
  wdDoc := wdDocs.Open(FileName:=Od.FileName);
  //Подключаемся к коллекции закладок.
  wdBms := wdDoc.Bookmarks;
  //Ищем закладки с нужными именами и изменяем их текст, в соответствие
  //с данными, введёнными на форме.
  SetBmText(wdBms, 'N_DOC', Edit1.Text);
  SetBmText(wdBms, 'DATE_CREATE', Edit2.Text);
  SetBmText(wdBms, 'N_TAB', Edit3.Text);
  SetBmText(wdBms, 'FIO', Edit4.Text);
 
  //Сохранять документ следует под другим именем, чтобы не перезаписать шаблон.
  //wdApp.DisplayAlerts := False; //Отключаем режим показа предупреждений.
  //wdDoc.SaveAs(FileName:=...);
  //wdApp.DisplayAlerts := True; //Включаем режим показа предупреждений.
  //Закрываем документ.
  //wdDoc.Close;
  //Закрываем MS Word.
  //wdApp.Quit;
end;
 
end.

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

Сегодня, в последний рабочий день недели, практически весь день провозился над передачей данных из Delphi в Word. Так как подозрение есть, что работа продолжится то решил кое-какие моменты по работе с Microsoft Word в Delphi запечатлеть и у себя в блоге. Написать такую мини-шпаргалку (тем более, что по Excel уже кое что есть).

Для начала, немного общих моментов по работе с MS Office в Delphi. И первое, что мы сделаем — это создадим объект Word.Application. Создается этот объект абсолютно также, как и объект Excel.Application:

uses ComObj;
var Word: variant;
[...]
procedure CreateWord(const Visible: boolean);
begin
  Word:=CreateOleObject('Word.Application');
  Word.Visible:=Visible;
end;

Всё достаточно просто. Далее мы можем работать с объектом следующим образом:

  1. Создавать документ Word с нуля
  2. Открыть уже существующий документ и изменить в нем текст для получения необходимой формы документа.

Рассмотрим оба варианта, т.к. оба они имеют как свои плюсы, так и недостатки.

Чтобы создать новый документ необходимо выполнить метод Add у коллекции Documents, т.е.:

[...]
Word.Documents.Add
[...]

и после этой операции уже начинать работать с документам обращаясь к нему по индексу или имени в коллекции. Также, можно создать новый документ по шаблону (*.dot). Для этого необходимо выполнить тот же метод Add, но с одним входным параметром — путем к файлу-шаблону:

[...]
Word.Documents.Add(TamplatePath:string);
[...]

Чтобы получить список всех открытых в данный момент документов Word можно воспользоваться следующим листингом:

[...]
var List: TStringList;
    i: integer;
begin
  List:=TStringList.Create;
  for i:=1 to Word.Documents.Count do
    List.Add(Word.Documents.Item(i).Name);
end;
[...]

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

Word.Documents.Item(index).Activate

где index — номер документа в коллекции.

Теперь можно приступать к записи и чтению документа. Для работы с текстов в документе Word, как и в Excel для работы с ячейками таблицы, определен объект Range. Именно методы этого объекта и дают нам возможность работы с текстом. Для начала рассмотрим работу двух основных методов: InsertBefore и InsertAfter.

Как следует из название — первый метод вставляет текст в начало содержимого Range, а второй — в конец. При этом сам объект Range может содержать как весть документ (Document) так и какую-либо его часть. Например, в следующем листинге я вставлю строку в начало документа и затем методом InsertAfter буду добавлять несколько строк текста в конец документа:

[...]
Word.ActiveDocument.Range.InsertBefore('Hello World');
Word.ActiveDocument.Range.InsertAfter('текст после Hello World');
Word.ActiveDocument.Range.InsertAfter('окончание строки в документа');
[...]

При выполнении этих трех операции Range содержал весь документ.

Если работать со всем документом неудобно, а необходимо, например выделить фрагмент с 50 по 100 символ и работать с ним, то можно воспользоваться функцией Range, которая вернет нам необходимый объект Range:

var MyRange: variant;
begin
  MyRange:=WordActiveDocument.Range(50,100);
  MyRange.InsertBefore('Привет');//всё, что было после 50-го символа сдвинулось вправо
end;

Это что касается записи текста. Решение обратной задачи — чтения текста из документа ещё проще. Достаточно воспользоваться свойством Text у объекта Range:

[...]
ShowMessage(Word.ActiveDocument.Range.Text) //весь текст в документе
[...]

Также для чтения документа можно воспользоваться коллекцией документа Words (слова). За слово принимается непрерывный набор символов — цифр и букв, который оканчивается пробелом.

Перечисляются слова документа точно также как и при работе с коллекцией документов, т.е. первое слово имеет индекс 1 последнее — Word.Count.

[...]
  ShowMessage(Word.ActiveDocument.Words.Item(Word.ActiveDocument.Words.Count).Text)
[...]

В данном случае я вывел на экран последнее слово в документе.

Очевидно, что приведенный выше способ работы с документам хорош в случае, когда требуется создать относительно простой документ Word и не требуется лишний раз рассчитывать фрагменты текста, правильно вставлять таблицы и т.д. Если же необходимо работать с документами, которые имеют сложное содержание, например текст в перемежку с рисунками, таблицами, а сам текст выводится различными шрифтами, то, на мой взгляд наиболее удобно использовать второй способ работы с Word в Delphi — просто заменить текст в уже заранее заготовленном документа.

2. Работа с документами Word в Delphi. Открытие готового документа и замена текста.

Чтобы открыть заранее заготовленный документ Word в Delphi достаточно воспользоваться методом Open у коллекции Documents, например так:

var FilePath: string;
[...]
  Word.Documents.Open(FilePath)
[...]

Метод Open можно вызывать с несколькими аргументами:

  • FileName: string — путь и имя файла;
  • ConfirmConversions: boolean — False — не открывать диалоговое окно «Преобразование файла» при открытии файла, формат которого не соответствует формату Word (doc или docx)
  • ReadOnly:boolean — True — открыть документ в режиме «Только для чтения»
  • AddToRecentFiles: boolean — True, чтобы добавить документ в список недавно открытых документов.
  • PasswordDocument: string — пароль для открытия документа
  • PasswordTemplate: string — пароль для открытия шаблона
  • Revert : boolean — True, чтобы вернуться к сохраненному документу, если этот документ открывается повторно.
  • WritePasswordDocument: string — пароль для сохранения измененного документа в файле
  • WritePasswordTemplate:string — пароль для сохранения изменений в шаблоне
  • Format:integer — формат открываемого документа.

Обязательным параметром метода Open является только FileName, остальные — могут отсутствовать. Если же Вам необходимо воспользоваться несколькими параметрами, то их необходимо явно указывать при вызове метода, например:

[...]
  Word.Documents.Open(FileName:=FilePath, ReadOnly:=true)
[...]

В этом случае документ открывается в режиме «Только для чтения». При таком способе вызова (с явным указанием аргументов) положение аргументов может быть произвольным.

Что касается последнего аргумента — Format, то он может принимать  целочисленные значения (применительно к версиям Microsoft Word 2007 и выше) от 0 до 13. При этом, для того, чтобы открыть «родные» вордовские документы (doc) достаточно использовать значения 0 или 6.

Теперь, когда документ открыт его необходимо преобразовать. Обычно я делаю следующим образом: в тех местах документа, в которые необходимо вставить текст я расставляю либо закладки, либо простые строки текста, например, обрамленные символом $ или #. И затем просто выполняю поиск и замену подстрок следующим образом:

function FindAndReplace(const FindText,ReplaceText:string):boolean;
  const wdReplaceAll = 2;
begin
  Word.Selection.Find.MatchSoundsLike := False;
  Word.Selection.Find.MatchAllWordForms := False;
  Word.Selection.Find.MatchWholeWord := False;
  Word.Selection.Find.Format := False;
  Word.Selection.Find.Forward := True;
  Word.Selection.Find.ClearFormatting;
  Word.Selection.Find.Text:=FindText;
  Word.Selection.Find.Replacement.Text:=ReplaceText;
  FindAndReplace:=Word.Selection.Find.Execute(Replace:=wdReplaceAll);
end;

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

Вот, наверное, самые-самые простые методы работы с Word в Delphi. Кстати, пишу пост и, думаю, что у кого-то из читателей может возникнуть вопрос: причём тут Delphi в Internet и Word в Delphi? :) Честно говоря, приведенный выше фрагменты кода можно использовать для нужд в Internet с натяжкой, например, при автосоставлении небольших отчётов по чему-либо. А вообще, в недалеком будущем, есть в планах поразбираться с Тезаурусом Word и попробовать составить небольшой синонимайзер для собственных нужд — он-то и пригодится нам в Internet :)

3.1
8
голоса

Рейтинг статьи

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

Собранные версии компонента с примерами использования

Архив на Яндекс.Диск

Файлы в архиве

Файлы для Delphi 7

  • ОписаниеРазработки.txt — этот файл.
  • WordReport70.zip — исполняемые файлы и ресурсы компонента.
  • WR_ExampleD7.zip — пример применения компонента.
  • WordReport70src.zip — исходные коды компонента.

Файлы для Delphi XE3

  • ОписаниеРазработки.txt — этот файл.
  • WordReport170.zip — исполняемые файлы и ресурсы компонента.
  • WordReport170src.zip — исходные коды компонента.
  • WR_ExampleDXE3.zip — пример применения компонента.

Назначение

Компонент предназначен для автоматизации создания отчетов через MS Word.
Как исходный шаблон, так и готовый отчет представляют собой обычные документы Word, что обеспечивает пользователю самыме богатые возможности редактирования, предпросмотр и печать без каких-либо дополнительных средств.

Программные требования

  • Borland Delphi или Embarcadero RAD Studio XE3.
  • Microsoft Word 2000 и выше.

Установка

  1. Извлечь файлы из WordReport(Version).zip в директорию с установленной Delphi (например, WordReport70.zip в «C:Program Files (x86)BorlandDelphi7»).
  2. Запустить Delphi.
  3. Выбрать пункт меню Component >> Install Packages…
  4. Нажать кнопку Add… и выбрать файл WordReport(Version).bpl в DelphiBin (например, WordReport70.bpl в «C:Program Files (x86)BorlandDelphi7BinWordReport70.bpl»)
  5. Компонент готов к работе. Его можно найти на вкладке WordReport.

Инструкция

Правила создания шаблонов

Шаблон в нашем случае — это документ MS Word (именно документ — т.е. файл *.doc, а не *.dot !), составленный по определенным правилам.

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

  • Каждая секция должна быть отмечена закладкой с именем DataN, где N — целое число от 1 до 8.
    Повторяться будет ТОЛЬКО то, что в диапазоне закладки, поэтому закладкой лучше отмечать всю строку документа целиком. Если секция используется
    для повторения строки таблицы, то отмечать закладкой следует также всю строку документа, в которой находится эта строка таблицы.

  • Существует три категории переменных шаблона:

  1. переменные вне секций

    Синтаксис объявления: #(ИмяСвободнойПеременной)
    Способ определения значения: напрямую, методом SetValue

  2. переменные секций

    Синтаксис объявления: #(ИмяСекции(ИмяСчетчика).ИмяПеременной)
    Способ определения значения: из текущей записи привязанного поля набора данных.

  3. счетчики записей секций

    Синтаксис объявления: #(ИмяСчетчика)
    Объявление действительно только внутри секции.
    Заменяется на текущий номер записи привязанного набора данных при отсутствии групп секций
    или на номер записи в неразвывной последовательности при группировке секций.

  • ИмяСвободнойПеременной — ненулевая последовательность латинских букв, цифр и точек (только букв, цифр и точек, никаких других знаков!). Регистр букв не важен.

  • ИмяПеременной — ненулевая последовательность латинских букв и цифр. Регистр букв не важен.

  • ИмяСчетчика — ненулевая последовательность латинских букв и цифр. Регистр букв не важен.

  • ИмяСекции — ненулевая последовательность латинских букв и цифр. Регистр букв не важен.

  • Максимальное количество переменных в секции — 16.

  • Максимальное количество секций в документе — 8.

  • Максимальное количество переменных вне секций — 2^31 — 1, то есть верхняя граница 32-битного целого типа.

Описание функционала компонента

Свойства времени разработки

Имя документа, содержащего шаблон

TemplateDocFileName: string

Имя документа, в котором следует сохранить готовый отчет

ResultDocFileName: string

Показать MS Word c готовым отчетом при вызове Quit

ShowResult: boolean

Свойства времени выполнения

Массив секций документа.
Доступ по имени секции.
Если секция не найдена — возвращает nil.

Bands[Name:string]: TDataBand

Количество секций документа.

BandCount: integer

Методы

Существует ли в шаблоне секция с именем BandName.

function BandExists(BandName: string): boolean;

Сохранить документ в файле FileName.

procedure SaveToFile(FileName: string);

Выйти. Завершает процесс MS Word или показывает готовый документ.

procedure Quit;

Сформировать отчет. Выполняет все операции для формирования одного отчета, сохраняет и закрывает полученный документ.
Однако, сам Word остается запущенным для формирования следующих отчетов.

procedure Build;

Установить значение свободной переменной.

procedure SetValue(VariableName:string; Value:Variant);

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

procedure JoinBands(BandKeyField:string; BandName1:string; KeyValue1:integer; BandName2:string; KeyValue2:integer);

События

Событие наступает после прочтения структуры документа-шаблона,
т.е. тогда, когда имена всех секций (bands) и переменных уже определены, но
этим переменным еще не установлены значения или поля набора данных (НД).

OnReadMaket:TNotifyEvent;

Объект секции документа (TDataBand)

Свойства времени выполнения

Имя секции документа.

Name: string

Имя поля для переменной VarName.

Field[VarName:string]: string

Формат вывода переменной.

Format[VarName:string]: string

Методы

Подключить набор данных к секции.
Параметром служит указатель на TDataset, т.е. вызов производится так:
AssignDataSet(@IBQuery1) или AssignDataSet(@ADOTable1).

procedure AssignDataSet(aDataSet: PDataSet);

Установить переменной VariableName из секции поле FieldName набора данных, подключенного к этой секции.
Если поле содержит действительные числа, то лучше использовать маску формата для их отображения,
например %10.2f (полный список форматов см. в описании функции SysUtils.Format).
Во всех других случаях значение параметра формат можно оставить пустой строкой, т.к. это ни на что не повлияет

procedure SetField(VariableName,FieldName,Format:string);

Обработка события OnReadMaket

Так как каждый шаблон уникален и содержит свой неповторимый набор секций и переменных, то и связывание этих секций и переменных со своими
значениями также процесс уникальный, а потому не может быть до конца автоматизирован внутри самого компонента. Эту задачу предстоит решить пользователю компонента.

Специально для этой цели и было создано данное событие.
В обработчике этого события НЕОБХОДИМО произвести связывание:

  • имен переменных с их значениями (TWordReport.SetValue),
  • секций с их заполненными наборами данных (TDataBand.AssignDataset),
  • переменных в секции с их полями (TDataBand.SetField),
  • а также, если это нужно — формирование групп секций (TWordReport.JoinBands)

Подробнее об этом в примере приложения.

Иные версии Delphi

Если нужен компонент для другой версии Delphi — используйте исходные коды, чтобы собрать пакет на своей Delphi, а затем скопируйте его:

  1. 32-битную release версию bpl — в поддиректорию bin
  2. 64-битную release bpl — в bin64
  3. 32-битную release версию dcu вместе с файлами WordReport.dcr и wrtprogress.dfm в libwin32release.
  4. 64-битную release версию dcu вместе с файлами WordReport.dcr и wrtprogress.dfm в libwin64release.
  5. Отладочные DCU, если они нужны, копируются в libwin32debug и libwin64debug уже без файлов ресурсов.

>
Заполнение и печать шаблона MS Word
, Как это делается?

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



Сообщ.
#1

,
14.04.04, 19:00

    Необходимо программно вставить данные из программы в шаблон документа MS Word и распечатать результат, при этом шаблон оставить прежним. Как это сделать, используя компоненты WordApplication и WordDocument?

    Пример: есть шаблон pattern.doc, содержащий текст:
    Фамилия:
    Имя:

    Нужно программно заполнить этот шаблон:
    Фамилия: Иванов
    Имя: Иван

    И распечатать. После чего закрыть файл шаблона без изменений.

    Открывать и писать в документы я научился. Печатать тоже, наверное, смогу. А как писать текст в ОПРЕДЕЛЕННЫЕ места документа? Самое первое что напрашивается, это сделать метки в шаблоне и осуществлять замену. Но метода вроде Replace ни где не нашел.

    Буду очень благодарен за советы и примеры.


    zx



    Сообщ.
    #2

    ,
    15.04.04, 06:25

      НА места куда надо вписать данные ставь таблички пустые, потом такой код

      fil: OleVariant;

      wordApplication1.Connect;
      fil:=’c:Shablon_sotr.doc’;
      //WordApplication1.Documents.Add(EmptyParam,EmptyParam);
      WordApplication1.Documents.Open(fil,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam);
      WordDocument1.ConnectTo(WordApplication1.ActiveDocument);
      WordApplication1.Options.CheckSpellingAsYouType:=false;
      WordApplication1.Options.CheckGrammarAsYouType:=false;

      WordDocument1.Tables.Item(1).Range.Text:= ‘текст’;
      WordDocument1.Tables.Item(2).Range.Text:= ‘текст’;
      WordDocument1.Tables.Item(3).Range.Text:= ‘текст’;
      WordDocument1.Tables.Item(4).Range.Text:= ‘текст’;

      только кто нить знает как потом закрыть всё это корректно, без вопросов и без провисания сервака в памяти?


      zx



      Сообщ.
      #3

      ,
      15.04.04, 06:25

        Для печати
        WordDocument1.PrintOut;


        AlexAnt



        Сообщ.
        #4

        ,
        15.04.04, 07:21

          Спасибо!

          А что если уже в самом шаблоне есть таблицы? У меня именно такая ситуация. Причем заносить данные нужно не просто в пустые ячейки, а в ячейки содержащие уж какой-то текст. Поэтому я сразу пытался избежать обращения к таблицам, шаблон большой и посчитать где какая таблица — практически невыполнимая задача для меня.


          AlexAnt



          Сообщ.
          #5

          ,
          15.04.04, 08:48

            Аналогичную задачу в Perl я всегда решал расстановкой меток в шаблоне, с последующей их заменой. Например:

            Фамилия: %surname%
            Имя: %name%

            Затем используется простое регулярное выражение s/%surname%/Name/g, которое заменяет все метки %surname% на значение переменной Name. И т.д.

            Неужели ничего подобного нет в сервере MS Word? Я имею ввиду не регулярные выражения естественно, а замену текста на текст. Можете есть еще какие-то объекты, которые можно заменять на текст?


            zx



            Сообщ.
            #6

            ,
            15.04.04, 08:56

              Попробуй сделать так, на месте где тебе надо установить переменную, делаешь метку, например %name%, тоесть простой текст.
              Потом выполняешь команду поиска и замены. Заменяешь на то что тебе надо.
              Посмотри на www.delphikingdom.ru, есть 2 статейки по word+delphi.


              AlexAnt



              Сообщ.
              #7

              ,
              15.04.04, 09:38

                В том-то и дело, что я ни где не могу найти инфу о том, как делать замену! :) Куча доков и книг по работе с Word из Delphi и ни где нет и слова о замене! :)

                Сейчас поищу на дельфикингдум…


                ych_boriss



                Сообщ.
                #8

                ,
                15.04.04, 09:45

                  Senior Member

                  ****

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

                  ExpandedWrap disabled

                    text := AnsiReplaceText(text, ‘%surname%’, surname); // or

                    text := StringReplace(text, ‘%surname%’, surname, [rfReplaceAll]); // or

                    // …

                    // or написать свою замену

                  Сообщение отредактировано: ych_boriss — 15.04.04, 09:46


                  Song



                  Сообщ.
                  #9

                  ,
                  15.04.04, 10:03

                    ych_boriss, тут разговор о замене средствами VBS.


                    AlexAnt



                    Сообщ.
                    #10

                    ,
                    15.04.04, 10:52

                      Всем кому интересно, приведенный ниже кусок открывает доковский файл FileName, находит первый текст %name% и заменяет его на ‘Вася’, распечатывает и закрывает файл без сохранения (распечатку еще не проверял):

                      procedure TForm1.APrintExecute(Sender: TObject);
                      var
                      FileName, wdDoNotSaveChanges: OleVariant;
                      FindText, ReplaceText, OleFalse, OleTrue, Unknow: OleVariant;
                      begin
                      FileName := Directory + PatternFile;
                      try
                      WordApplication1.Connect;
                      WordApplication1.Visible := True;
                      try
                      WordApplication1.Documents.Add(FileName, EmptyParam,
                      EmptyParam, EmptyParam);

                      FindText := ‘%name%’;
                      ReplaceText := ‘Вася’;
                      OleFalse := False;
                      OleTrue := True;
                      Unknow := wdFindContinue;

                      WordApplication1.Selection.Find.Execute(FindText, OleFalse, OleFalse,
                      OleFalse, OleFalse, OleFalse, OleTrue, Unknow, OleFalse, ReplaceText,
                      OleTrue, EmptyParam, EmptyParam, EmptyParam, EmptyParam);

                      WordApplication1.PrintOut;
                      WordApplication1.Quit(wdDoNotSaveChanges);
                      WordApplication1.Disconnect;
                      except
                      ShowMessage(‘Не могу найти файл шаблона: ‘ + PatternFile)
                      end;
                      except
                      ShowMessage(‘Не могу подключиться к серверу MS Word.’)
                      end;
                      end;

                      Wizard

                      Bas



                      Сообщ.
                      #11

                      ,
                      15.04.04, 10:57

                        ExpandedWrap disabled

                            oldStr,newStr,replace:OleVariant;

                            replace:=1;  oldStr:=’@1′;  newStr:=DateTimeToStr(Now);

                          //Находим в документе метки и производим их замены

                            WordDocument1.Range.Find.Execute(oldStr,EmptyParam,EmptyParam,

                           EmptyParam,EmptyParam,EmptyParam,EmptyParam,

                                          EmptyParam,EmptyParam,newStr,replace);


                        TarZan



                        Сообщ.
                        #13

                        ,
                        05.05.04, 14:48

                          Морока с этими док’ами…
                          Я для себя когда-то делал так.
                          Шаблон сохранял в RTF и ставил че-то типа @001 в качестве метки.
                          Во время формирования нового документа делал так: копировал посимвольно файл и если встречал «@» то читал следующие 3 символа, проганял полученное значение по кейсу и на выходе получал некоторую строку, которую и влепливал вместо @001 в новый файл.
                          ПРЕИМУЩЕСТВА:
                          RTF — кроссплатформенный формат
                          не могут жить вирусы
                          открывается Word’ом по умолчанию (в TOLEcontainer закинуть имя файла и сказать DoVerb(0))
                          может открываться другим текстовым редактором
                          Исходный макет никогда не затрется
                          …короче, решайте сами…

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

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

                          • Предыдущая тема
                          • Delphi: Общие вопросы
                          • Следующая тема

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

                          Шаблоны и отчёты MS Word
                          Многие популярные информационно-правовые системы содержат шаблоны различных документов в формате Word. Используя их и информацию данной статьи, вы можете легко и быстро создавать отчеты, если пишете свои программы на Delphi. Если пишете на другом языке, это не помеха, описанный подход справедлив к различным языкам.
                          Когда мы формируем сложный документ по шаблону, и когда в этом шаблоне есть таблицы, количество строк которых в выходном документе может быть произвольным и зависеть от объема информации, то нам недостаточно просто функций создания таблиц и записи в ячейки определенной информации. Для создания такого документа необходимо, как минимум, еще несколько функций работы с таблицами, в перечень которых входит перемещение по таблицам, добавление строк (столбцов) в конец или в середину таблицы. Также необходимо определять размер (количество строк, столбцов) и номер текущего столбца и строки. Чтобы понимать, о чем речь, необходимо просмотреть части 1-3 данной статьи, опубликованных в предыдущих номерах.
                          Для того, чтобы применить свои знания к конкретной задаче, сделаем ее постановку. Например, в нашем документе есть таблица, которая представляет собой шаблон и заполняется из массива информации, который имеет произвольную длину. Таким документом может быть счет-фактура, заголовок которой представляет собой сложную таблицу, средняя часть представляет таблицу переменной длины, а нижняя также представляет сложную таблицу. Для заполнения такого шаблона можно использовать способ, описанный во второй части данной статьи. Этот способ основан на поиске в шаблоне переменных (неповторяющиеся строковые значения длиной 3-5 символов) и подстановке вместо них реальных значений на этапе формирования документа. Поэтому для добавления информации в такую таблицу придется осуществить поиск и позиционирование в строку (по переменной), в которую и перед которой необходимо вставлять строки, и запомнить, в какие колонки какую записывать информацию, но для начала необходимо определить, находится курсор в таблице или нет.
                          Для этого используем свойство Information объекта Selection, в качестве параметра которого будет константа wdWithInTable. В этом случае этот метод возвращает TRUE, если курсор в таблице, или FALSE, если нет. Для использования в нашем приложении создадим функцию GetSelectionTable.

                          Function GetSelectionTable:boolean;
                           const wdWithInTable=12;
                          begin
                           GetSelectionTable:=true;
                           try
                           GetSelectionTable:=W.Selection.Information(wdWithInTable);
                           except
                           GetSelectionTable:=false;
                           end;
                          End;

                          Если в нашем документе может быть более одной таблицы, то, скорее всего, необходима возможность перехода и позиционирование курсора на следующей или предыдущей таблице. Объект Selection дает нам эту возможность через методы GoTo и GoTo, в этом случае в качестве их параметров должна использоваться константа wdGoToTable.

                          Function GoToTable (table_:integer):boolean;
                           const wdGoToTable=2;
                          begin
                           GoToTable:=true;
                           try
                           W.Selection.GoTo (wdGoToTable);
                           except
                           GoToTable:=false;
                           end;
                          End;
                          Function GoToTable (table_:integer):boolean;
                           const wdGoToTable=2;
                          begin
                           GoToTable:=true;
                           try
                           W.Selection.GoTo(wdGoToTable);
                           except
                           GoToTable:=false;
                           end;
                          End;

                          Когда мы позиционируемся на таблице, можем определить количество столбцов и строк в ней. Для этого также используем свойство Information объекта Selection, но в качестве аргументов используем константы wdMaximum Number Of Columns и wdMaximum NumberOfRows.

                          Function GetColumnsRowsTable(table_:integer;

                           var Columns,Rows:integer):boolean;

                           const

                           wdMaximumNumberOfColumns=18;

                           wdMaximumNumberOfRows=15;

                          begin

                           GetColumnsRowsTable:=true;

                           try

                           Columns:=W.Selection.Information (wdMaximumNumberOfColumns);

                           Rows:=W.Selection.Information (wdMaximumNumberOfRows);

                           except

                           GetColumnsRowsTable:=false;

                           end;

                          End;

                          Кроме размера таблицы, нам может быть необходим номер колонки и строки, на которой позиционирован курсор. Для этого так же используем свойство Information объекта Selection, но в качестве аргументов используем константы wdStartOfRangeColumnNumber, wdStartOfRangeRowNumber. Для реализации этого в Delphi создадим функцию GetColumnRowTable.

                          Function GetColumnRowTable(table_:integer;

                           var Column,Row:integer):boolean;

                           const

                           wdStartOfRangeColumnNumber=16;

                           wdStartOfRangeRowNumber=13;

                          begin

                           GetColumnRowTable:=true;

                           try

                           Column:=W.Selection.Information (wdStartOfRangeColumnNumber);

                           Row:=W.Selection.Information (wdStartOfRangeRowNumber);

                           except

                           GetColumnRowTable:=false;

                           end;

                          End;

                          После того, как мы нашли таблицу в шаблоне документа и позиционировались на определенной ячейке, нам необходимо выполнить некоторые действия с ней (добавить, вставить строки, записать информацию). Очевидно, что нам нужен будет набор функций для ее модификации.
                          Обычно во время формирования таблицы мы не знаем, сколько будет строк. Они могут добавляться в конец или вставляться в середину таблицы. Если для формирования документа мы используем шаблон таблицы и в нем уже есть, например, заголовок, то нам не обойтись без процедур добавления или вставления строк. Добавить строку в конец таблицы можно, используя метод Add коллекции Rows. Чтобы это сделать из приложения на Delphi, достаточно создать и использовать функцию. Определим ее как AddRowTableDoc.

                          Function AddRowTableDoc (table_:integer):boolean;

                          begin

                           AddRowTableDoc:=true;

                           try

                           W.ActiveDocument.Tables.Item(table_).Rows.Add;

                           except

                           AddRowTableDoc:=false;

                           end;

                          End;

                          Для того, чтобы вставлять строки в середину таблицы, удобно использовать пару операторов. Первый выделяет строку, перед которой необходимо вставить новую, второй вставляет строку (строки). Смотрите функцию InsertRowsTableDoc.

                          Function InsertRowsTableDoc(table_,position_,

                           count_:integer): boolean;

                          begin

                           InsertRowsTableDoc:=true;

                           try

                           W.ActiveDocument.Tables.Item(table_).Rows.Item(position_).Select;

                           W.Selection.InsertRows (count_);

                           except

                           InsertRowsTableDoc:=false;

                           end;

                          End;

                          Для добавления одной строки можно использовать также и метод Add коллекции Rows, но с параметром, в качестве которого выступает ссылка на строку, перед которой необходимо вставить новую. Первый оператор получает ссылку на строку, второй вставляет новую. Смотрите реализацию на Delphi (InsertRowTableDoc).

                          Function InsertRowTableDoc(table_,position_: integer):boolean;

                           var row_:variant;

                          begin

                           InsertRowTableDoc:=true;

                           try

                           row_:=W.ActiveDocument.Tables.Item(table_).Rows.Item(position_);

                           W.ActiveDocument.Tables.Item(table_).Rows.Add(row_);

                           except

                           InsertRowTableDoc:=false;

                           end;

                          End;

                          Когда мы в своем распоряжении имеем набор функций для изменения таблицы, можно приступать к решению задачи — созданию документа типа счета-фактуры на базе шаблона. Полный исходный текст и полную версию шаблона счета-фактуры можно скачать по адресу www.kornjakov.ru/st1_4.zip. Здесь мы рассмотрим фрагмент данного документа. Создадим шаблон — документ формата DOC — и разместим его на диске в каталоге нашего проекта. Внешний вид шаблона смотрите на рисунке.
                          clip0070
                          Здесь будем заполнять только табличную часть. О том, как заполнять остальное, читайте вторую часть данной статьи. Для начала наши новые функции скопируем в библиотеку MyWord, которую мы создавали, начиная с первой части статьи. Затем создадим новый проект, на форме которого разместим кнопку, а в процедуре обработки ее нажатия напишем следующий программный текст.

                          procedure TForm1.Button1Click(Sender: TObject);

                           var tablica_:integer;

                            col_,row_:integer;

                            a_:integer;

                            metki_:array[1..12] of record

                            col:integer;

                            row:integer;

                            metka:string;

                            end;

                            tovar:array[1..2,1..12] of variant;

                          begin

                          // Заполняем массив данными. Массив используется

                          //для простоты демонстрации, в реальной программе

                          //данные берутся из базы данных.

                          tovar[1,1]:=‘Стул офисный’; tovar[1,2]:=‘шт.’;

                          tovar[1,3]:=2; tovar[1,4]:=520.00; tovar[1,5]:=1040.00;

                          tovar[1,6]:=‘-‘; tovar[1,7]:=20; tovar[1,8]:=208.0;

                          tovar[1,9]:=1248.00; tovar[1,10]:=62.40;

                          tovar[1,11]:=‘Россия’; tovar[1,12]:=‘-‘;

                          tovar[2,1]:=‘Телефон’; tovar[2,2]:=‘шт.’;

                          tovar[2,3]:=3; tovar[2,4]:=315.25; tovar[2,5]:=945.75;

                          tovar[2,6]:=‘-‘; tovar[2,7]:=20; tovar[2,8]:=189.15;

                          tovar[2,9]:=1134.90; tovar[2,10]:=56.70;

                          tovar[2,11]:=‘Беларусь’; tovar[2,12]:=‘-‘;

                          if CreateWord then begin

                           VisibleWord(true);

                           If OpenDoc(ExtractFileDir (application.ExeName) +‘sf.doc’)

                           then begin

                           tablica_:=1;

                           for a_:=1 to 12 do begin

                            StartOfDoc;

                            if FindTextDoc(‘###M’+inttostr(a_)+‘&’) then

                            if GetSelectionTable then begin

                            messagebox(handle,‘Находимся в таблице, запоминаем

                            метку(переменную), номер колонки и строки!’

                          ,

                            pchar(‘Номер колонки/строки = ‘+inttostr(col_)+‘/’+inttostr(row_)),0);

                            metki_[a_].col:=col_;

                            metki_[a_].row:=row_;

                            metki_[a_].metka:=‘###M’+inttostr(a_)+‘&’;

                            end;

                            end;

                            Messagebox(handle,‘Заполняем первую строку’,»,0);

                            for a_:=1 to 12 do begin

                            SetTextToTable(tablica_,metki_[a_].row,metki_[a_].col,tovar[1,a_]);

                            end;

                            a_:=1;

                            Messagebox(handle,‘Добавляем строку’,»,0);

                            InsertRowTableDoc(tablica_, metki_[a_].row);

                            Messagebox(handle,‘Заполняем вторую строку’,»,0);

                            for a_:=1 to 12 do begin

                            SetTextToTable(tablica_,metki_[a_].row,metki_[a_].col,tovar[2,a_]);

                            end;

                            SaveDocAs(ExtractFileDir(application.ExeName)+‘Счет — фактура.doc’);

                            Messagebox(handle,‘Текст сохранен’,»,0);

                            CloseDoc;

                           end;

                           Messagebox(handle,‘ Текст закрыт’,»,0);

                           CloseWord;

                           end;

                          end;

                          Мы сформировали фрагмент сложного документа, но вы, возможно, захотите в дальнейшем сами развивать эту тему и использовать все возможности Word.Application. В следующей части я постараюсь на примерах объяснить, каким образом это сделать. По всем вопросам вы можете обратиться к автору по адресу www.kornjakov.ru или _kvn@mail.ru.
                          Василий КОРНЯКОВ
                          Литература: Н. Елманова, С. Трепалин, А. Тенцер «Delphi 6 и технология COM» «Питер» 2002.

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