Добавить в "Избранное" Сентябрь ср. 20 2017 г. в 19:27
Навигация
Еще полезняшки (G)

    -
Счетчики
      ОБменник E-POS
      Оплата услуг с помощью WebMoney, RBK Money, Деньги@Mail.Ru, WebCreds и Яндекс.Деньги

      Raznoe


      Openstat-

      Статьи
      Кто ищет тот всегда найдет... Самая правдивая система поиска

      Формирование и обработка документов wORD и EXCEL в Delphi

      Автор: Василий КОРНЯКОВ
      Источник: Интернет
      Добавлено: 2008-03-17 08:18:53

      Формирование 
      Возможность формирования ваше программой документов непосредственно в формате Word или Excel выгодно отличало бы ее от аналогов...


      Суперфункции 
      Используя материалы первой и второй частей этой статьи, мы уже имеем возможность предоставить пользователю программу формирования документа в Word в законченном виде


      Создание таблиц 
      Тема третьей части статьи - создание таблиц в редакторе Word из приложений, написанных на Delphi


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


      Вставки 
      Используя доступ к Word.Application из приложений Delphi, можно вставлять в текст документа записи, рисунки и другие объекты...


      Отчеты Excel 
      Начинаем создавать отчеты в Excel из приложений, разрабатываемых в Delphi...


      Форматирование 
      Рассмотрим формирование формата данных ячейки листа книги Excel


      Фрматирование  
      Продолжим программирование свойств ячеек таблиц Excel...


      Настройки листа 
      Эта часть посвящена функциям настройки общих параметров листа Excel, выбора и настройки принтера, подготовки листа и функциям печати


      Диаграммы 
      В Excel есть возможность программировать отображение информации в виде диаграмм и графиков, и вы можете воспользоваться этим, чтобы сделать свою программу более информативной


      Диаграммы 
      Продолжим программирование диаграмм в Excel...


      Создание DLL  
      Создание DLL-библиотеки для работы с Word/Excel из приложений на Delphi


      Создание DLL(2) 
      Создание средствами Delphi DLL библиотек для использования в макросах Excel


      Ответы на вопросы 
      Ответы на вопросы





      Суперфункции

      Так как многие разрабатываемые приложения формируют множество выходных отчетных форм для печати, то возможность формирования ими документов непосредственно в формате Word или Excel выгодно отличало бы их от своих аналогов.


      Каждый, кто серьезно занимается разработкой программного обеспечения, заинтересован, чтобы его произведение пользовалось успехом у пользователей. Поэтому он вынужден удовлетворять постоянно растущие их требования к программному обеспечению. Не секрет, что большинство пользователей начинали свое знакомство с компьютером с изучения текстового редактора Word и электронных таблиц Excel. К тому же эти редакторы имеют огромные возможности и постоянно совершенствуются, они получили широкое распространение, для них написано сотни томов обучающей литературы, их изучают во всех учебных заведениях, и, самое главное, они - очень удобный инструмент для создания текстовых документов любой сложности. Отсюда простой вывод: большинство пользователей положительно воспримут тот факт, что ваша программа будет формировать выходные документы в формате Word или Excel.


      Теперь остановимся на постановке задачи, описанной в этой статье. Как формировать документ в формате Word? Очень просто. Текстовый редактор Word представляет собой COM-сервер и может получать и обрабатывать запросы от внешних программ. Все это позволяет организовать процесс управления и создания документа из внешней программы. Используя этот механизм, можно создать документ программно так же, как это делается вручную (посредством меню, кнопок и клавиатуры), но гораздо быстрей и эффектней.


      Приступим к решению задачи. Как было сказано выше, Word является COM-сервером и может управляться внешними программами. Для этого Word предоставляет три объекта, через которые можно получить доступ к внутренним объектам Word`а и документов. Эти объекты - Word.Application, Word.Document и Word.Basic. Ко всем остальным объектам (текст, таблицы, кнопки, меню и др.) доступ возможен только через них.


      Чтобы реализовать все эти возможности Word`а и для удобства своей работы мне пришлось разработать динамическую библиотеку процедур и функций, которую можно было использовать в различных своих приложениях для формирования и печати выходных документов. Зачем нужна такая библиотека, почему бы не вставлять программный код непосредственно в программу? Здесь причина в универсальности и гибкости использования библиотеки. Поэтому все ниже описанные коды легко могут быть оформлены в виде библиотеки для того, чтобы вы могли использовать ее непосредственно в своих приложениях, не теряя зря времени.


      Чтобы почувствовать эффективность использования объектов Word, для начала попробуем написать несколько функций, которые позволят запустить Word, создать документ, изменить документ (записать текст), сохранить документ и закрыть Word. Для создания объекта и его использования применяем переменную W типа variant и библиотеку ComObj.


      Рассмотрим следующий фрагмент кода:


      uses ComObj;
      var W:variant;
      Function CreateWord:boolean;
      begin
      CreateWord:=true;
      try
      W:=CreateOleObject('Word.Application');
      except
      CreateWord:=false;
      end;
      End;

      Для получения доступа к объекту Word.Application в нашей функции CreateWord используем конструктор CreateOleObject ('Word. Application'). Если редактор Word не установлен в системе, то будет сгенерирована ошибка, и мы получим значение функции = false, если Word установлен, и объект будет создан, то получим значение функции = true.


      Эта функция создает объект (W), свойства и методы которого мы будем использовать в дальнейшем. Если выполнить нашу функцию CreateWord, то Word будет запущен, но не появится на экране, потому что по умолчанию он запускается в фоновом режиме. Чтобы его активировать (сделать видимым) или деактивировать (сделать невидимым), используйте свойство visible объекта W. Оформим это в виде функции VisibleWord. Скобки try except везде используются для обработки исключительных ситуаций.


      Function VisibleWord (visible:boolean):boolean;
      begin
      VisibleWord:=true;
      try
      W.visible:= visible;
      except
      VisibleWord:=false;
      end;
      End;

      Используя эту функцию, мы можем показывать или прятать Word с документами.


      Следующим шагом будет создание документа. Для этого используем объект Documents объекта W. Этот объект имеет метод Add, используя который, и создаем новый документ. При этом, как альтернативный вариант, вместо двух операторов Doc_:=W.Documents; Doc_.Add; можем использовать один W.Documents.Add;.


      Function AddDoc:boolean;
      Var Doc_:variant;
      begin
      AddDoc:=true;
      try
      Doc_:=W.Documents;
      Doc_.Add;
      except
      AddDoc:=false;
      end;
      End;

      Создали документ, что дальше? Следующим шагом, естественно, является запись любого текста непосредственно в документ. Создадим для этого функцию SetTextToDoc.


      Function SetTextToDoc(text_: string;InsertAfter_: boolean): boolean;
      var Rng_:variant;
      begin
      SetTextToDoc:=true;
      try
      Rng_:=W.ActiveDocument.Range;
      if InsertAfter_
      then Rng_.InsertAfter(text_)
      else Rng_.InsertBefore(text_);
      except
      SetTextToDoc:=false;
      end;
      End;

      В этой функции используем объект Range и его методы InsertAfter и InsertBefore для того, чтобы вставить текст в документ с позиции курсора или до позиции курсора. Наша функция будет вставлять текст в активный документ в область курсора или выделенного текста.


      Фрагмент кода:


      Rng_:=W.ActiveDocument.Range;
      if InsertAfter_
      then Rng_.InsertAfter(text_)
      else Rng_.InsertBefore(text_);

      можно заменить следующим фрагментом:


      if InsertAfter_
      then W.ActiveDocument.Range. InsertAfter(text_)
      else W.ActiveDocument.Range. InsertBefore(text_);

      После того, как документ создан и в него записан текст, его необходимо сохранить. Для этого используем метод SaveAs объекта ActiveDocument. Функция SaveDocAs использует этот метод и сохраняет документ в заданный файл.


      Function SaveDocAs(file_:string):boolean;
      begin
      SaveDocAs:=true;
      try
      W.ActiveDocument.SaveAs(file_);
      except
      SaveDocAs:=false;
      end;
      End;

      Закрыть сохраненный документ можно, используя метод Close объекта ActiveDocument.


      Function CloseDoc:boolean;
      begin
      CloseDoc:=true;
      try
      W.ActiveDocument.Close;
      except
      CloseDoc:=false;
      end;
      End;

      Закрыть Word можно, используя метод Quit объекта Application(W).


      Function CloseWord:boolean;
      begin
      CloseWord:=true;
      try
      W.Quit;
      except
      CloseWord:=false;
      end;
      End;

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


      procedure TForm1.Button1Click(Sender: TObject);
      begin
      if CreateWord
      then begin
      Messagebox(0,'Word запущен.','',0);
      VisibleWord(true);
      Messagebox(0,'Word видим.','',0);
      VisibleWord(false);
      Messagebox(0,'Word невидим.','',0);
      VisibleWord(true);
      Messagebox(0,'Word видим.','',0);
      If AddDoc then begin
      Messagebox(0,'Документ создан.','',0);
      SetTextToDoc('Мой первый текст',true);
      Messagebox(0,'Добавлен текст','',0);
      SaveDocAs('c:Мой первый текст');
      Messagebox(0,'Текст сохранен','',0);
      CloseDoc;
      end;
      Messagebox(0,' Текст закрыт','',0);
      CloseWord;
      end;
      end;

      Конечно, набора данных функций недостаточно для создания полноценного отчета. Было бы эффективным создать шаблон некоего документа и затем заполнять его реальными значениями из базы данных, но для этого, как минимум, потребуется еще ряд функций. Такими функциями могут быть открытие ранее созданного документа, поиск текста, замена, копирование. Далее будут рассмотрены реализации этих функций и создание на их базе простого документа, например, платежного поручения. По всем вопросам, касающимся материала этой статьи, вы можете обратиться к автору по адресу _kvn@mail.ru.


      Василий КОРНЯКОВ


      Литература: Н. Елманова, С. Трепалин, А.Тенцер "Delphi 6 и технология COM" "Питер" 2002.


      К списку статей





      Суперфункции

      (Начало в №20)


      Часть 2

      Труд программиста оценивается только пользователями и почти всегда по конечному результату. Используя материалы первой и второй частей статьи "Суперфункции", мы уже имеем возможность предоставить пользователю свою программу формирования простого документа в редакторе Word в законченном виде.


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


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


      Одним из способов, который можно применить для подготовки простых документов, является заполнение шаблона. Шаблон представляет собой некоторый документ, часть которого выполнена в виде таблицы, определенные ячейки которой заполнены наборами символов (словами). Обозначим эти слова как переменные, вместо которых будут подставляться реальные значения из программы в момент формирования документа. Способ с использованием переменных удобен тем, что он позволяет легко изменить документ, не изменяя программу формирования. Так как мы используем шаблон (подготовленный в виде документа Word), то для работы с ним необходима функция открытия ранее созданного документа. Функции поиска текста и перевода курсора в начало документа необходима для поиска слов-переменных для дальнейшей замены их реальными данными. Также может быть необходима функция задания шрифта и вывода на печать готового документа.


      Определим функцию открытия ранее созданного документа OpenDoc. Для этого используем метод Open коллекции Documents, которая нами уже использовалась в функции создания нового документа. Функция Open, кроме обязательного аргумента (имени файла), может иметь ряд дополнительных аргументов, которые определяют режим открытия. Она возвращает ссылку на объект типа Document, но в нашем случае будем использовать только обязательный аргумент.


      Function OpenDoc (file_:string):boolean;
      Var Doc_:variant;
      begin
      OpenDoc:=true;
      try
      Doc_:=W.Documents;
      Doc_.Open(file_);
      except
      OpenDoc:=false;
      end;
      End;

      Фрагмент из двух операторов


      Doc_:=W.Documents;
      Doc_.Open(file_);

      можно заменить одним


      W.Documents.Open(file_);

      Для перевода курсора в начало документа используем свойства End и Start объекта W.Selection. Эту функцию необходимо использовать каждый раз перед началом поиска текста, чтобы поиск осуществлялся с начала документа. Свойства End и Start объекта Selection можно использовать и для выделения диапазона текста, при этом в Start записывается номер начального символа фрагмента в тексте, а в End - номер конечного. В данном случае необходимо в оба поля записать нули.


      Function StartOfDoc:boolean;
      begin
      StartOfDoc:=true;
      try
      W.Selection.End:=0;
      W.Selection.Start:=0;
      except
      StartOfDoc:=false;
      end;
      End;

      Функция поиска (FindTextDoc) фрагмента текста состоит из трех операторов. Первый и второй задают направление поиска (от начала к концу) и фрагмент для поиска, соответственно. Третий оператор выполняет поиск и возвращает результат. Функция возвращает True, если поиск удачный, и False - если нет. Во всех трех операторах используем поля и методы объекта Selection.


      Function FindTextDoc (text_:string):boolean;
      begin
      FindTextDoc:=true;
      Try
      W.Selection.Find.Forward:=true;
      W.Selection.Find.Text:=text_;
      FindTextDoc := W.Selection.Find.Execute;
      except
      FindTextDoc:=false;
      end;
      End;

      Функция FindTextDoc находит и выделяет фрагмент текста в документе. Для того, чтобы вставить новый текст вместо выделенного, создадим еще одну функцию. PasteTextDoc состоит из двух операторов, удаления выделенного фрагмента и вставки нового текста с положения курсора. Оба эти оператора используют объект Selection объекта W. Действие этой функции отличается от SetTextToDoc тем, что она вставляет изменения вместо выделенного фрагмента текста.


      Function PasteTextDoc (text_:string):boolean;
      begin
      PasteTextDoc:=true;
      Try
      W.Selection.Delete;
      W.Selection.InsertAfter (text_);
      except
      PasteTextDoc:=false;
      end;
      End;

      Но более удобной была бы функция, которая одновременно подставляла бы новый текст на место найденного фрагмента. Создадим такую функцию.


      Function FindAndPasteTextDoc
      (findtext_,pastetext_:string): boolean;
      begin
      FindAndPasteTextDoc:=true;
      try
      W.Selection.Find.Forward:=true;
      W.Selection.Find.Text:= findtext_;
      if W.Selection.Find.Execute then begin
      W.Selection.Delete;
      W.Selection.InsertAfter (pastetext_);
      end else FindAndPasteTextDoc:=false;
      except
      FindAndPasteTextDoc:=false;
      end;
      End;

      И последнее, печать документа. В данной части рассмотрим только процедуру активизации диалогового окна печати. Этот диалог активизируется через метод Show объекта Dialogs(wdDialogFilePrint).Show. С помощью объекта Dialogs можно вызвать практически любое диалоговое окно Word'а, но об этих возможностях поговорим позже.


      Функция будет выглядеть следующим образом:


      Function PrintDialogWord:boolean;
      Const wdDialogFilePrint=88;
      begin
      PrintDialogWord:=true;
      try
      W.Dialogs.Item(wdDialogFilePrint).Show;
      except
      PrintDialogWord:=false;
      end;
      End;

      Имея необходимый набор функций, можно приступать к написанию программы (процедуры) создания простого документа Word средствами Delphi. Как говорилось ранее, для формирования документа нам необходим шаблон - текст в формате Word (файл с расширением doc, rtf). Создадим вручную этот файл и разместим его, например, на диске C: "C:Шаблон платежного поручения.doc". Полный пример с исходными текстами можно взять на моей домашней странице (www.kornjakov.ru/st1_2.zip), а здесь, с целью экономии объема, представлен только фрагмент документа (см.рис.).



      Общий алгоритм формирования документа таков:




      1. Открываем шаблон, используя функцию открытия ранее созданного документа.
      2. Ищем слова-переменные и подставляем вместо них реальные значения, например, из базы данных.
      3. Сохраняем документ под новым именем.
      4. Печатаем документ, если это необходимо.
      5. Закрываем документ.

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


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


      procedure TForm1.Button2Click(Sender: TObject);
      begin
      if CreateWord then begin
      VisibleWord(true);
      If OpenDoc('c:Шаблон платежного поручения.rtf') then begin
      messagebox(0,'Переходим к заполнению шаблона','Шаблон открыт',0);
      StartOfDoc; while not
      FindAndPasteTextDoc('###№ П.П.&','21') do;
      StartOfDoc; while not
      FindAndPasteTextDoc('###Дата&','21.05.2003') do;
      StartOfDoc; while not
      FindAndPasteTextDoc('###Вид платежа&','обычный') do;
      StartOfDoc; while not
      FindAndPasteTextDoc('###Сумма прописью&','Сто пятьдесят рублей 40 коп.') do;
      SaveDocAs('c:Платежное поручение.rtf');
      messagebox(0,'Переходим к печати документа',
      'Документ сформирован и сохранен',0);
      PrintDialogWord;
      CloseDoc;
      end;
      CloseWord;
      end;
      end;

      Данная процедура сформирует документ и откроет окно диалога печати.


      Мы сформировали простой документ, но обычно сложные документы содержат таблицы, графики, рисунки и другие компоненты. Все эти компоненты также можно создавать и настраивать из внешних программ, используя объекты и коллекции объекта Application. Все эти вопросы будут рассмотрены в следующей части статьи, там же в качестве примера рассмотрим создание документа, содержащего таблицу. По всем вопросам, касающимся материала этой статьи, вы можете обратиться к автору по адресу www.kornjakov.ru или _kvn@mail.ru.


      Василий КОРНЯКОВ


      Литература: Н. Елманова, С. Трепалин, А. Тенцер "Delphi 6 и технология COM" "Питер" 2002.


      К списку статей





      Суперфункции

      (Начало в №20)


      Часть 3

      Темой этой части статьи будет создание таблиц в редакторе Word из приложений, написанных на Delphi. В прошлый раз мы рассмотрели создание простых документов, которые не содержат таблиц переменной длины, но большинство отчетов так или иначе содержит табличное представление информации. Уверен, что хоть один отчет в вашей программе содержит хоть одну таблицу. Поэтому информации двух предыдущих частей статьи было бы недостаточно для создания отчета, содержащего табличное представление информации.


      Как создать таблицу в Word'е? Так же просто, как это делается в обычном объектно-ориентированном языке. В объекте Document мы имеем коллекцию Tables, с помощью методов и объектов которой можем создать таблицу и получить доступ к ее свойствам, ячейкам и тексту в ячейках. Если в нашем отчете несколько таблиц, то к любой из них мы имеем доступ с помощью коллекции Tables и индекса таблицы.


      Чтобы более ясно представить процесс создания таблицы, используя объектные модели MS Office, создадим документ, аналог которого после простой доработки можно будет использовать в своих программах для вывода информации. Одним из самых распространенных отчетов, содержащих таблицу, является документ типа "Прайс-лист". Его мы и будем создавать. Попробуем создать его без шаблона, т.е. с чистого листа. Определимся, каким набором функций нужно владеть для создания этого документа. Во-первых, нам нужна будет функция создания таблицы, затем потребуется задать(изменить) размеры этой таблицы, вписать данные в ячейки, объединить ячейки. Возможно, потребуется еще несколько вспомогательных функций. Творчески используя материал статьи, вы сможете сами определить и создать для себя еще несколько функций для работы с таблицами.


      Определим функцию создания таблицы CreateTable. Так как количество таблиц в документе может быть больше одной, то для идентификации каждой таблицы используем ее номер. Для создания применим метод ADD коллекции Tables. Метод ADD имеет аргументы: область, где создается таблица, количество строк и количество столбцов. Наша функция будет создавать таблицу там, где расположен курсор, и иметь еще один аргумент: числовую переменную, через которую будет возвращаться порядковое значение(индекс) таблицы в документе. Функция выглядит следующим образом:


      Function CreateTable(NumRows, NumColumns:integer;
      var index:integer):boolean;
      var sel_:variant;
      begin
      CreateTable:=true;
      try
      sel_:=W.selection;
      W.ActiveDocument.Tables.Add (Range:=sel_.Range,NumRows: =NumRows,
      NumColumns:=NumColumns);
      index:=W.ActiveDocument. Tables.Count;
      except
      CreateTable:=false;
      end;
      End;

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


      Наша функция создаст таблицу произвольного размера, но для корректного представления данных необходимо задать определенные размеры строк и столбцов. Чтобы задать размер таблицы или строки(столбца), нужно получить доступ к таким свойствам таблицы, как коллекции Columns и Rows (список столбцов и строк), через которые сможем получить доступ к конкретной строке или(и) столбцу, к ячейкам и к параметрам ячейки(строки, столбца). Для этого используем объект ActiveDocument.Tables.Item(table), где table - номер таблицы в документе. Создадим функцию, которая будет задавать ширину и высоту всех ячеек таблицы.


      Function SetSizeTable(Table:integer; RowsHeight,
      ColumnsWidth:real):boolean;
      begin
      SetSizeTable:=true;
      try
      W.ActiveDocument.Tables.Item (Table).Columns.Width:=ColumnsWidth;
      W.ActiveDocument.Tables.Item(Table). Rows.Height:=RowsHeight;
      except
      SetSizeTable:=false;
      end;
      End;

      Аналогично мы можем задавать высоту любой строки или(и) ширину любого столбца на выбор. Для доступа к размерам ячейки используем также коллекции Rows, Columns объекта Table. Чтобы воспользоваться этими возможностями из нашего приложения, создадим следующие функции.


      Function SetHeightRowTable(Table,Row:integer;
      RowHeight:real):boolean;
      begin
      SetHeightRowTable:=true;
      try
      W.ActiveDocument.Tables.Item(Table).Rows.item(Row).Height:=RowHeight;
      except
      SetHeightRowTable:=false;
      end;
      End;
      Function SetWidthColumnTable(Table,Column: integer;
      ColumnWidth:real):boolean;
      begin
      SetWidthColumnTable:=true;
      try
      W.ActiveDocument.Tables.Item(Table).Columns.
      Item(Column).Width:=ColumnWidth;
      except
      SetWidthColumnTable:=false;
      end;
      End;

      Возможно, нам придется не только задавать размеры таблицы, но и определять(считывать) размеры ячеек таблицы. Для этого используем те же коллекции, объекты и свойства таблицы, что и в функции SetSizeTable, но немного изменим внутренние операторы таким образом, что в возвращаемые переменные RowsHeight и ColumnsWidth будут записываться значения размеров строк и столбцов таблицы.


      Function GetSizeTable(Table:integer;var RowsHeight,
      ColumnsWidth: real):boolean;
      begin
      GetSizeTable:=true;
      try
      ColumnsWidth:=W.ActiveDocument. Tables.Item(Table).Columns.Width;
      RowsHeight:=W.ActiveDocument. Tables.Item(Table).Rows.Height;
      except
      GetSizeTable:=false;
      end;
      End;

      Также можно считать и размеры строки или столбца на выбор, для этого достаточно использовать коллекции Rows, Columns объекта Table (Tables.Item(Table)).


      Следующим этапом формирования табличного документа определим запись текстовой информации в выбранную ячейку таблицы. Одним из способов такой записи является доступ к полю Text ячейки, но и в этом случае текст записывается не напрямую, а в объект Range ячейки таблицы. Функция SetTextToTable выполняет такую запись.


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

      И последнее действие, которое необходимо произвести над таблицей для создания простого табличного документа, это объединение ячеек. Для этого воспользуемся методом Merge объекта Cell (ячейка). Первый оператор функции объединения ячеек возвращает указатель на объект - конечную ячейку (Cel). Второй оператор объединяет начальную ячейку Row1,Column1 с конечной ячейкой, табличные координаты которой уже заданы и равны Row2,Column2.


      Function SetMergeCellsTable(Table:integer;Row1,
      Column1,Row2,Column2:integer):boolean;
      var Cel:variant;
      begin
      SetMergeCellsTable:=true;
      try
      Cel:=W.ActiveDocument.Tables.I tem(Table).Cell(Row2,Column2);
      W.ActiveDocument.Tables.Item(Table). Cell(Row1,Column1).Merge(Cel);
      except
      SetMergeCellsTable:=false;
      end;
      End;

      Переходим к заключительной стадии - созданию документа.


      Для этого все определенные в этой части статьи функции объединим с ранее созданными и перенесем во вновь созданную библиотеку процедур и функций. Например, это будет файл MyWord.pas, в разделе interface которого будут описаны заголовки всех наших функций, а в разделе implementation - сами функции (в дальнейшем будем пользоваться этой библиотекой). Не забудьте после implementation вставить строки uses ComObj; var W:variant;.


      Создадим новый проект, в программном модуле которого сделаем ссылку на нашу библиотеку uses MyWord;. На форме разместим кнопку и в процедуру обработки нажатия ее впишем следующий программный код.


      procedure TForm1.Button1Click(Sender: TObject);
      var tablica_:integer;
      begin
      if CreateWord then begin
      VisibleWord(true);
      If AddDoc then begin
      // cсоздаем таблицу
      If CreateTable(5,3,tablica_) then begin
      Messagebox(0,pchar('Таблица создана='+inttostr(tablica_)),'',0);
      // изменяем размеры таблицы
      SetSizeTable(tablica_,25,37);
      SetWidthColumnTable(tablica_,1,300);
      SetWidthColumnTable(tablica_,2,80);
      SetWidthColumnTable(tablica_,3,80);
      Messagebox(0,'Размер таблицы изменен','',0);
      // записывает информацию в ячейки таблицы
      SetTextToTable(tablica_,1,1,
      'ПРОЦЕССОРЫ (данные от 27.05.2003) ');
      SetTextToTable(tablica_,2,1,'Наименование');
      SetTextToTable(tablica_,2,2,'Стоимость');
      SetTextToTable(tablica_,2,3,'Гарантия');
      SetTextToTable(tablica_,3,1,
      'ПРОЦЕССОР AMD K7- 1333 ATHLON 266MHz (Socket-A)');
      SetTextToTable(tablica_,3,2,'47.52 $');
      SetTextToTable(tablica_,3,3,'12 мес.');
      SetTextToTable(tablica_,4,1,
      'ПРОЦЕССОР AMD K7- 800 DURON (Socket-A)');
      SetTextToTable(tablica_,4,2,'23.54 $');
      SetTextToTable(tablica_,4,3,'12 мес.');
      // объединяем необходимые ячейки таблицы
      SetMergeCellsTable(tablica_,1,1,1,3);
      end;
      SaveDocAs('c:Прайс лист');
      Messagebox(0,'Текст сохранен','',0);
      CloseDoc;
      end;
      Messagebox(0,' Текст закрыт','',0);
      CloseWord;
      end;
      end;

      В результате выполнения приведенной выше процедуры получим результат, который выглядит, как показано на рисунке.



      Полный исходный текст смотрите по адресу www.kornjakov.ru/st1_3.zip.


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


      По всем вопросам, касающимся материала этой статьи, вы можете обратиться к автору по адресу www.kornjakov.ru или _kvn@mail.ru.


      Василий КОРНЯКОВ


      Литература: Н. Елманова, С. Трепалин, А.Тенцер "Delphi 6 и технология COM" "Питер" 2002.


      К списку статей





      Суперфункции

      (Продолжение. Начало в №20)


      Часть 4

      Многие популярные информационно-правовые системы содержат шаблоны различных документов в формате 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 дает нам эту возможность через методы GoToNext и GoToPrevious, в этом случае в качестве их параметров должна использоваться константа wdGoToTable.


      Function GoToNextTable (table_:integer):boolean;
      const wdGoToTable=2;
      begin
      GoToNextTable:=true;
      try
      W.Selection.GoToNext (wdGoToTable);
      except
      GoToNextTable:=false;
      end;
      End;
      Function GoToPreviousTable (table_:integer):boolean;
      const wdGoToTable=2;
      begin
      GoToPreviousTable:=true;
      try
      W.Selection.GoToPrevious(wdGoToTable);
      except
      GoToPreviousTable:=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 - и разместим его на диске в каталоге нашего проекта. Внешний вид шаблона смотрите на рисунке.



      Здесь будем заполнять только табличную часть. О том, как заполнять остальное, читайте вторую часть данной статьи. Для начала наши новые функции скопируем в библиотеку 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.


      К списку статей





      Суперфункции

      (Начало в №20)


      Часть 5

      Используя доступ к Word.Application из приложений Delphi, можно вставлять в текст документа записи, рисунки и другие объекты. Сложные документы в формате Word обычно могут содержать не только таблицы или текст, но также записи, линии и фигуры, объекты WordArt, рисунки, графику и многое другое.


      Все эти объекты можно разделить на две группы: те, которые являются внутренними объектами Word, и внешние объекты, создаваемые внешними по отношению к самому Word серверами OLE. Все объекты, рассмотренные в 1-4 части статьи, - это внутренние объекты.


      Кто программирует в Visual Basic в среде Word и в Delphi, тот может дальше сам развивать тему "Суперфункций". Все просто. Объекты, коллекции и методы, которые работают в среде Word, переносятся почти без изменений в среду Delphi. Главное здесь - применить немного изобретательности и находчивости. Можно использовать палитру компонентов Servers, которая есть в Delphi, начиная с 5-й версии. Выбор между готовыми компонентами и работой "напрямую" с Word.Application зависит от профессионализма, сложности поставленных задач, отпущенного времени и главное - от вкусов и стиля программирования. Это индивидуально для каждого, кто занимается разработкой сложных и не очень сложных приложений на Delphi и других языках программирования. Я свой выбор остановил на работе с Word.Application, так как это дает больше гибкости и возможностей при решении сложных и нестандартных задач


      Рассмотрим еще несколько необходимых внутренних и использование некоторых внешних объектов, их создание и управление из приложений на Delphi.


      Одним из часто используемых объектов является Textbox. Для его создания используем коллекцию Shapes(формы) и ее метод AddTextbox. Объект коллекции Shapes имеет атрибут - имя, его можно считать, можно изменить и обращаться к объекту не только через индекс, но и через имя. В функцию создания объекта Textbox передаем в качестве аргументов координаты и размеры области, а возвращаем имя объекта. Она выглядит следующим образом.


      Function CreateTextBox (Left,Top,Width,Height:real;
      var name:string):boolean;
      const msoTextOrientationHorizontal=1;
      begin
      CreateTextBox:=true;
      try
      name:=W.ActiveDocument.Shapes.AddTextbox
      (msoTextOrientationHorizontal,Left,Top,Width,Height).Name;
      except
      CreateTextBox:=false;
      end;
      End;

      Следующей естественной задачей является запись текста в TextBox. Используем доступ к созданному объекту (Shapes.Item) через индекс(число) или имя(строка). Текст можно записать в свойство Text объекта TextRange. Перед записью текста проверяем тип формы (Shape). Если форма имеет тип TextRange, тогда записываем текст. Смотрите реализацию в виде функции TextToTextBox на Delphi.


      Function TextToTextBox (TextBox:variant;text: string):boolean;
      const msoTextBox=17;
      begin
      TextToTextBox:=true;
      try
      if w.ActiveDocument.Shapes.Item(TextBox).Type = msoTextBox then
      W.ActiveDocument.Shapes.Item(TextBox).TextFrame.TextRange.Text:=Text
      else TextToTextBox:=false;
      except
      TextToTextBox:=false;
      end;
      End;

      Объект - форма (Shape) - может иметь тип не только как запись, он может содержать картинку, звук, линию и др. В зависимости от типа формы, процедура ее создания различна, но некоторые поля не зависят от типа. Одним из таких полей является имя формы, которое можно получить или изменить. Создадим две функции для определения имени (индекса) формы и для его изменения.


      Function GetNameIndexShape (NameShape:variant): variant;
      begin
      try
      GetNameIndexShape:=W.ActiveDocument.Shapes.Item(NameShape).Name;
      except
      GetNameIndexShape:=false;
      end;
      End;

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


      Function SetNewNameShape (NameShape:variant;
      NewNameShape:string):string;
      begin
      try
      W.ActiveDocument.Shapes.Item(NameShape).Name:=NewNameShape;
      SetNewNameShape:=NewNameShape;
      except
      SetNewNameShape:='';
      end;
      End;

      Здесь можно было бы рассмотреть реализацию функций перемещения, изменения размеров, а также определение положения и размеров формы в документе. Можете сделать это самостоятельно. В Visual Basic для этого используются следующие операторы:


      ActiveDocument.Shapes.Item (NameShape).Left = Left
      ActiveDocument.Shapes.Item (NameShape).Top = Top
      ActiveDocument.Shapes.Item (NameShape).Width = Width
      ActiveDocument.Shapes.Item (NameShape).Height = Height

      Или наоборот


      Left = ActiveDocument.Shapes.Item (NameShape).Left
      Top = ActiveDocument.Shapes.Item (NameShape).Top
      Width = ActiveDocument.Shapes.Item (NameShape).Width
      Height = ActiveDocument.Shapes. Item(NameShape).Height

      В документах часто могут использоваться рисованные объекты, например, линии. Для их создания также используем коллекцию Shapes (формы) и ее метод AddTextbox. В функцию создания объекта Line передаем в качестве аргументов начальные и конечные координаты линии, а возвращаем имя объекта. Эта функция выглядит следующим образом:


      Function CreateLine (BeginX,BeginY,EndX,EndY: real;
      var name:string):boolean;
      begin
      CreateLine:=true;
      try
      name:=W.ActiveDocument.Shapes.AddLine(BeginX,BeginY,EndX,EndY).Name;
      except
      CreateLine:=false;
      end;
      End;

      Для прорисовки сложной фигуры необходимо использовать метод AddPolyline коллекции Shapes. Аргументом этой функции должен быть массив точек (massiv). Реализация на Visual Basic имеет следующий вид:


      ActiveDocument.Shapes.AddPolyline (massiv)

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


      Function CreatePicture(FileName:string;Left,Top: real;
      var name:string):boolean;
      begin
      CreatePicture:=true;
      try
      name:=W.ActiveDocument.Shapes.AddPicture(FileName).Name;
      W.ActiveDocument.Shapes.Item (name).Left:=Left;
      W.ActiveDocument.Shapes.Item(name). Top:=Top;
      except
      CreatePicture:=false;
      end;
      End;


      Полная версия статьи

      Оглавление   |  На верх


      Тема страницы:

      Delphi Формирование и обработка документов wORD и EXCEL в Delphi Программы от АМХ Статьи 2017-09-20 19_27_06

      Кредиты

      Статьи
      Delphi
      Вход
      Логин:

      Пароль:


      Запомнить меня
      На сайте
      Гостей: 1
      Пользователей: 0


      Полезное от Google 2017

      Топ загрузок за неделю
      Грузим...
      Copyright АМХ© 2003-2016Работает под управлением WebCodePortalSystem v. 4.2.2