Logo    
Продукты, технологии Проекты, внедрения Новости мира IT Форумы Курилка Новые публикации Учебный центр
CitForum    CITForum на CD Море(!) аналитической информации! :: CITFORUM.RU
IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware HOWTO

07.11.2004

[an error occurred while processing this directive]
Google
WWW CITForum.ru

2004 г.

Документация на основе RTF-шаблона

Александр Харьков, "Комиздат"

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

До последнего времени самым простым и широко применяемым решением представлялось применение механизма OLE. Например, для комбинации Word и VisualBasic возможна такая схема:

  • Создаем некий файл - шаблон документа. Там, где должна быть "шапка" (дата, номер документа и др.), используем закладки, а для основной части отчета создаем таблицу-заготовку соответствующей структуры. Пример такого шаблона приведен на рис. 1.
  • Пишем программу с использованием объектной модели Word:

' NumStr - кол-во строк в отчете
' NewData (5,NumStr) - массив с данными для заполнения
' таблицы, заранее приведенными к символьному виду
' Itog - сумма, приведенная к символьному виду
' Pth - путь к исходному файлу
' Str_ndoc = "BS190"
' Str_name = "Петров И.И."
.................

Dim objWord As Word.Application
Dim objDoc As Word.Document
Dim objTable As Word.Table

' создаем объект Word
Set objWord = New Word.Application
' делаем его видимым - это не обязательно,
' но очень интересно :)
objWord.Visible = True

' открываем файл шаблона
Set objDoc = objWord.Documents.Open (Pth)
' делаем его активным
objDoc.Activate

' заполняем "шапку документа" - номер и получатель
' - закладки 'ndoc' и 'name' соответственно
objDoc.Bookmarks ("ndoc").Range.Text = Str_ndoc
objDoc.Bookmarks ("name").Range.Text = Str_name

' связывам объект с таблицей
Set objTable = objWord.ActiveDocument.Tables (1)

' выделяем 2-ю строку таблицы в шаблоне
objTable.Cell (2, 1).Range.Select

' вставляем нужное кол-во строк-1
' (т.к. одна уже есть в шаблоне)
If NumStr > 0 Then objWord.Selection.InsertRows (NumStr - 1)

' для каждой строки в каждую ячейку вставляем нужные
' данные из массива
For i = 1 To NumStr
For j = 1 To 5
objTable.Cell (i + 1, j).Range.Text = NewData (j, i)
Next j
Next i

' проставляем сумму "Всего"
objTable.Cell (NumStr + 2, 5).Range.Text = Itog

  • Запускаем ее в составе всего приложения и получаем результат (см. рис. 2).
  • Пользователь, получив отчет в виде doc-файла, может легко внести в документ любые изменения, отправить его по электронной почте, распечатать - одним словом, распорядиться по своему усмотрению в привычной ему среде. Так же легко он может изменить и шаблон документа - для этого достаточно уметь работать в текстовом редакторе.

Но эту идиллическую картину омрачает несколько неприятных моментов. Во-первых, недостаточная гибкость приложения - если вы захотите перейти на другой редактор, то придется писать код заново. Во-вторых, приложение работает только в среде пакета MS Office, а он стоит немалых денег. Если приложение должно работать на 30-ти компьютерах предприятия, то установка на них MS Office обойдется примерно в 40 тыс. гривен - не каждый бюджет выдержит.

В то же время существует целый ряд бесплатных и достаточно полнофункциональных офисных пакетов: OpenOffice, StarOffice, EasyOffice и др. Для большинства операций, выполняемых обычно с документами, их возможностей вполне достаточно. Но возможна ли их простая и эффективная интеграция в прикладное программное обеспечение?

Решением этой проблемы может быть использование RTF-файлов. Этот формат, предложенный Microsoft как стандарт для обмена данными между текстовыми редакторами, поддерживается абсолютным большинством офисных пакетов. Сама Microsoft использует его в качестве формата, в котором данные передаются через буфер обмена между различными приложениями Windows.

Кратко об RTF

В формате RTF используются только коды, представляемые символами из наборов ASCII, MAC и PC. Помимо текста, RTF-файл содержит команды управления в читаемой форме. Документ состоит преимущественно из команд управления настройкой программы чтения. Эти команды можно разделить на управляющие слова и управляющие символы.

Управляющее слово представляет собой последовательность символов с разделителем в конце. Например, фрагмент:

…\bkmkstart ndoc…

соответствует началу закладки ndoc.

Перед управляющим словом вводится обратная косая черта (\). В качестве разделителей могут использоваться следующие символы:

  • пробел, причем этот символ относится к управляющему слову;
  • цифра или дефис (<->). После этих символов должен следовать параметр с разделителем. В качестве разделителя может быть использован пробел или другие символы (кроме цифр и букв);
  • все символы, кроме цифр и букв. Эти символы не относятся к управляющему слову.

Для задания управляющей последовательности в RTF-формате используются буквы от А до Z и от а до z, а также цифры от 0 до 9. Национальные символы к управляющей информации не относятся.

В качестве управляющих символов используются отдельные буквы. Перед каждым управляющим символом вводится обратная косая черта (\). Например, фрагмент:

…\f1\fs20…

устанавливает шрифт № 1 размером в 20 единиц.

Фрагмент RTF-файла приведен ниже. Структура его, как можно видеть, напоминает структуру HTML-документа:

\intbl\phmrg\posy371\dxfrtext180\dfrmtxtx180\dfrmtxty0\nowrap
\aspalpha\aspnum\faauto\adjustright\rin0\lin0\f1\fs20\lang1049
\langfe1049\cgrid\langnp1049\langfenp1049{\lang1033\langfe1049
\langnp1033 11\cell 12\cell 13\cell} \pard \ql \li0\ri0\widctlpar\intbl
\aspalpha\aspnum\faauto\adjustright\rin0\lin0

В RTF-формате существует возможность объединять отдельные последовательности в группы при помощи скобок:

{группа}

Такие группы создаются, например, при описании сносок, колонтитулов, закладок и т.п.

Вот некоторые управляющие слова и символы, имеющие непосредственное отношение к теме нашей статьи:

  • \раr - конец абзаца;
  • \сеll - конец столбца;
  • \row - конец строки (или таблицы);
  • \*\bkmkstart <название закладки> \*\bkmkend - закладка. Пример: {\*\bkmkstart ndoc} BS190{\*\bkmkend ndoc};
  • \pard - устанавливает стандартную настройку для абзаца;
  • \intbl … \intbl - выделяет область таблицы;
  • \' - прямой ввод в текст шестнадцатеричных чисел. При сохранении кириллического текста он обычно сохраняется в шестнадцатеричной форме, например:
\'d1\'f2\'f0\'ee\'ea\'e0 ('строка')

Поскольку нас интересуют только определенные задачи, знания приведенных выше управляющих слов и символов вполне достаточно. Условимся для простоты называть управляющие слова и символы тегами.

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

Вставка строки на месте закладки

Пример такой закладки:

…{\*\bkmkstart ndoc}<значение закладки>{\*\bkmkend ndoc}…

Для решения данной задачи можно предложить следующий алгоритм.

  • Читаем последовательно строки входного файла (в большинстве случаев строка больше 255 символов).
  • Ищем в текущей строке тег '\bkmkstart'.
  • Если находим, то выделяем название закладки и сравниваем его с искомой.
  • Если совпадает, то записываем строковую строку данных после закрывающей скобки (}).

Алгоритм реализован в виде функции In_Zakl1(pth As String, zakl As String, data As String), где pth - имя RTF-файла, zakl - имя закладки, data - строка для добавления в файл.

Добавление строк в таблицу

Предположим, нам требуется найти m-ю строку в n-той таблице и повторить ее в этой таблице p раз. Для поиска начала строки таблицы мы будем использовать тег \intbl, а для поиска конца - тег \row. Конец самой таблицы определяется по последовательности тегов \row…\pard…\par.

Алгоритм решения этой задачи следующий.

  • Читаем последовательно строки входного файла.
  • Ищем последовательность …\row…\pard…\par…\intbl… (не обязательно в одной строке) (n-1) раз. После этого мы находимся в начале нужной таблицы.
  • Ищем тег \row (m-1) раз. После этого находимся перед нужной строкой таблицы.
  • Ищем следующий тег \row и копируем содержимое файла от (m-1)-го до m-го тега \row (между \row и \intbl содержатся настройки строки, они нам тоже нужны).
  • Вставляем после m-го тега \row скопированную нами подстроку p раз.

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

Алгоритм реализован в виде функции In_TStr (pth As String, itbl As Integer, irow As Integer, kol As Integer), где pth - имя RTF-файла, itbl - номер таблицы, irow - номер строки, kol - количество повторов строки.

Заполнение ячейки таблицы

Представим, что требуется найти k-ю ячейку в m-й строке n-й таблицы и вставить в нее текстовую строку данных. Пример таких ячеек:

...{\lang1033\cgrid0<содержимое 1-й ячейки>
\cell<содержимое 2-й ячейки>\cell}…

Задача может быть решена по следующему алгоритму.

  • Читаем последовательно строки входного файла.
  • Ищем последовательность …\row…\pard…\par…\intbl… (не обязательно в одной строке) (n-1) раз. После этого мы находимся перед нужной нам таблицей.
  • Ищем тег \row (m-1) раз. После этого мы находимся в начале нужной строки таблицы.
  • Ищем k-e вхождение тега \cell.
  • Вставляем перед ним строку данных.

Данный алгоритм реализован в виде функции In_Tcell1(pth As String, itbl As Integer, irow As Integer, icell As Integer, ndata As String), где pth - имя RTF-файла, itbl - номер таблицы, irow - номер строки, icell - номер ячейки, data - строка для занесения в ячейку.

Программа на VisualBasic, демонстрирующая применение такой технологии и функционально идентичная программе, приведенной в начале этой статьи, выглядит так:

' NumStr - кол-во строк в отчете
' NewData (5,NumStr) - массив с данными для заполнения
' таблицы, заранее приведенными к символьному виду
' Itog - сумма, приведенная к символьному виду
' pth - путь к файлу
' Str_ndoc = "BS190"
' Str_name = "Петров И.И."

Dim res As Boolean   ' результат выполнения функций

' заполняем "шапку документа" - номер и получатель
' - закладки 'ndoc' и 'name' соответственно

res = In_Zakl1(pth, "ndoc", Str_ndoc)
res = In_Zakl1(pth, "name", Str_name)

' вставляем нужное кол-во строк-1
' (т.к. одна уже есть в шаблоне)
res = In_TStr (pth, 1, 2, NumStr - 1)

' для каждой строки в каждую ячейку вставляем
' нужные данные из массива

For i = 1 To NumStr
For j = 1 To 5
res = In_Tcell1(pth, 1, i + 1, j, NewData (j, i))
Next j
Next i

res = In_Tcell1(pth, 1, NumStr + 2, 5, Itog)
' проставляем сумму "Всего"

Заключение

Каковы преимущества и недостатки предложенной технологии? Начнем с достоинств. Во-первых, это более гибкая технология для формирования отчетов - даже если часть пользователей работает с OpenOffice, а часть с MS Office, программа создания отчетных документов универсальна. Во-вторых, несмотря на многоразовую перезапись файла шаблона во время работы, эта программа работает быстрее, чем связка OLE+Word. Тем более что приведенные выше алгоритмы могут совершенствоваться. Один из примеров кардинального повышения производительности приведен в листингах варианта для PascalDelphi. В-третьих, пользуясь свободным ПО, вы экономите деньги.

Теперь о проблемах. Основная из них - это недостаточная стандартизация формата RTF. Производители ПО, в целом придерживаясь единого стандарта, допускают несколько свободную трактовку частных моментов. Результат - проблемы с использованием "чужих" RTF-файлов, подготовленных в других редакторах. Например, MS Word сохраняет графические изображения внутри RTF-файла в виде последовательности шестнадцатеричных кодов, а OOWriter - как внешний файл.

Впрочем, эти проблемы решаются - стоит только приложить некоторые усилия.

Подписка на новости библиотеки:

Ближайшие курсы ЦИТ:

1-4 ноября 2004, Москва
Современные технологии анализа и проектирования информационных систем

1-5 ноября 2004, Москва
Основы передачи данных

9-10 ноября 2004, Москва
Основы моделирования бизнес-процессов и спецификации требований к ПО

Новые поступления в on-line библиотеку:

26 октября

  • Руководство FreeBSD (FreeBSD Handbook)
  • Спокойная революция
  • TV-тюнинг для компьютера
  • Новое поколение DVD
  • С видеокассеты на DVD

    21 октября

  • Обзор технических решений построения городской операторской сети на базе технологии "Optical Ethernet"
  • Алгоритм Rsync
  • Заметки о Linux-консоли
  • База данных без BDE

    19 октября

  • Функциональная безопасность программных средств
  • Технологические процессы и стандарты обеспечения функциональной безопасности в жизненном цикле программных средств
  • Так как же восстановить данные таблицы?
  • Использование CAST и табличных функций в PL/SQL

    14 октября

  • Разрезая биллионы
  • Платформа, которой не существует
  • Intel 9xx: время тестов
  • Сбалансированная система показателей: краткий обзор рынка программного обеспечения
  • Кросс-браузерность: теория и практика

    12 октября

  • В борьбе за каждый миллиметр
  • Хранилища данных и семантические разрывы
  • BI и ССП: связь между ними
  • Десять заповедей резервного копирования

    7 октября

  • XML-СУБД Sedna: технические особенности и варианты использования
  • Хранилище данных: вопросы и ответы
  • Порядок разработки ETL-процессов

    5 октября

  • Использование сокетов в Delphi
    Часть первая: стандартные сокеты
    Часть вторая: сокеты Windows
  • Задачи и аналитическая платформа для ВРМ
  • Методики, технологии и инструменты ВРМ
  • Выбор системы управления эффективностью бизнеса: решающие факторы

    30 сентября

  • MySQL: Руководство разработчика
  • MySQL: Руководство по ODBC и MyODBC

    28 сентября

  • СУБД ЛИНТЕР. Технический обзор
  • Новое в СУБД ЛИНТЕР 6.1
  • Использование ЛИНТЕР в качестве встроенной СУБД

    21 сентября

  • Материалы книги П.Б.Храмцова "Система доменных имен"
  • Храните свои терабайты в ящике
  • Тестирование контроллеров iSCSI
  • Девять ошибок, которые могут помешать работе SAN

    16 сентября

  • Курс лекций В.В.Воеводина "Параллельная обработка данных"
  • Заморочки от Oracle, или знать бы, где упасть
  • Реинжиниринг: многое в малом
  • CASE-технологии: что, когда, как?

    14 сентября

  • Сильнее угроза - крепче защита (обзор 16 инструментов)
  • GnuPG - OpenSource шифрование и цифровые подписи
  • Оптимизация не-HTML-сайтов для поисковых серверов
  • Новые графические супер-карты от ATI и NVidia
  • Новая жизнь Ethernet

    Все новости >>>



  • IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware HOWTO

    Реклама на IT-портале citforum.ru

    Нестандартные PR-акции - pr@citforum.ru
    Пресс-релизы и информация в каталог компаний - manager@citforum.ru
    Послать комментарий
    Информация для авторов
    Rambler's Top100 TopList This Web server launched on February 24, 1997
    Copyright © 1997-2000 CIT, © 2001-2004 CIT Forum
    Внимание! Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав.