Использование в прикладных программах
Пример использования - утилита DB_REPORT
Команды и макросы языка описания отчетов
Генератор отчетов представляет собой набор классов для интеграции в прикладные программы с тем, чтобы генерация достаточно сложных отчетов из SQL баз данных выполнялась без привлечения сложных инструментов и библиотек классов (за исключением библиотеки LEM :). Впрочем, вполне возможно использовать исходный текст генератора отчетов для создания собственных инструментов - условия лицензирования предельно либеральны.
Макрогенератор получает на входе текст (текстовую строку) с исходным текстом отчета. В этом тексте кроме обычных тегов форматирования HTML (можно, конечно, обойтись без HTML-тегов, работая с простым txt-форматом) включаются макрокоманды, которые извлекают данные из БД и выполняют другие манипуляции с текстом.
Отчет интерпретируется - макрокоманды исполняются одна за другой, создаются макросы, которые тут же подставляются в тексте (см. парадигму). После интерпретации строка отчета не содержит (если, конечно, нет ошибок) макрокоманд - вместо них в тексте прописаны данные из БД. В итоге получается HTML-документ с подставленной из БД информацией.
Резонен вопрос: а как насчет PHP или, тем паче, ASP.NET? Ответ прост. Генератор отчетов на основе класса Macro_Formatter не требует установки WEB-сервера, не зависит от средств отображения HTML кода.
Исходный код макрогенератора компактен, прост, расширяем, достаточно интенсивно используется в реальных программах.
Если Вас заинтересовал сам подход - почитайте Самоприменимые программы.
Реализован в виде набора классов (класс Macro_Formatter и вспомогательные) в пространстве имен lem::macro_generator. Объявления собраны в файле macro_generator.h.
Макрогенератор отчетов сильно (практически однозначно) ориентирован на работу с форматом HTML. Это позволяет использовать любые инструменты конструирования www-страниц (типа Mozilla Composer или MS FrontPage), а также любой Web-браузер для отображения результатов. Сам макрогенератор не содержит никаких средств отображения отчетов. Фактически это голый движок, преобразующий шаблон отчета в документы, который можно отображать чем-то, а можно просто сохранить в файл на диск.
Интерпретирующая сущность движка является самым серьезным его недостатком. Из-за этого генерация отчетов происходит достаточно долго. В планах стоит создание компилятора отчетов, который позволит работать с жестко вшитыми в прикладную программу шаблонами отчетов (а не подгружать внешние htm-файлы), и генерить отчеты быстро за счет предварительной структурной обработки шаблонов (см. планы).
|
ADO.NET - новейшая технология работы с базами данных для .NET Framework, сменившая устаревающий стандарт ODBC |
Вообще говоря, мы на практике используем с генератором отчетов две технологии: ODBC и ADO.NET. Сам по себе движок генератора не зависит от используемой технологии работы с источником данных - лишь бы он понимал SQL.
Конкретный интерфейс для работы с БД строится как иерархия классов, объявленных в хидере lem_db.h: SQL_Cursor, SQL_Data_Source - абстрактный источник данных (курсор) и абстрактная сессия БД, ODBC_Cursor - источник данных (курсор) для ODBC, ADO_NET_Cursor - источник данных для технологии ADO.NET. Если Вы посмотрите на работу этих классов, то увидите, как достаточно различные технологии доступа к СУБД ODBC и ADO.NET с помощью классов-оберток приводятся к некоторому общему знаменателю. Конечно, введение еще одного уровня абстракции для работы с БД само по себе влечет дополнительные накладные расходы. Однако зачастую скорость работы с БД определяется исключительно временем отклика сервера базы данных, поэтому удобство универсальных классов доступа к БД перевешивает накладные расходы на скрытие технических различий.
|
Crystal Reports - промышленный стандарт для создания отчетов в приложениях; входит в MS VisualStudio 2003 |
Весьма бестолковое обсуждение аналогичного генератора (точнее, абстрактных планов по созданию супер-пупер гига-мега генератора отчетов) на RSDN (ищите в форумах). Читал давеча ветку форума в ма в offline на CD. Два часа потратил, хотел среди постов найти что-либо практически полезное. Не нашел. Кроме общих мыслей про плохость HTML и крутость XML (с чем я собственно и не спорю) не нашел ни одной стоящей идеи. Жаль. Хотя для общего развития полезно было. Предлагаемый мной генератор отчетов создавался как крошечный класс в составе другой программы (проприетарная, сугубо специализированная), и рос в сторону усложнения. То есть он с самого начала был работающим (причем под .NET, уж потом я его портировал и под win32 API).
Масштабный проект Apache Formatting Objects Processor (FOP). Это серьезно. В этой же струе http://sourceforge.net/projects/nfop.
Fast Report - http://www.fast-report.comt.com (на сайте есть ссылка на бесплатную обрезанную версию - FreeReport).
Итак, в нужном месте программы создается объект Macro_Formatter, параметром конструктора является текстовая строка, содержащая исходный текст отчета. Далее, создается объект провайдера данных БД (вариантов сейчас немного - либо провайдер ODBC для платформы Win32, либо провайдер ADO.NET для платформы .NET). Провайдеры данных представлены классами SQL_ODBC и SQL_ADO_NET (см. хидер lem_db.h). Провайдер передается в объект Macro_Formatter (метод Set_DB).
Вызовом метода Macro_Formatter::Build_Commands() создается контейнер с хендлерами обработчиков макрокоманд. В прикладной программе можно расширять набор макрокоманд, создавая свои классы, производные от Base_Command (для каждой новой макрокоманды), объявив свой производный от Cmd_Factory класс, и перегрузив метод Macro_Formatter::Build_Command. В принципе, в своих прикладных программах я расширяю даже синтаксис отдельных команд - например, добавив в команду организации цикла FOR специальные возможности.
Наконец, вызовом метода Macro_Formatter::Interpret() выполняется интерпретация макрокоманд в тексте отчета.
Намного более подробно и просто вся последовательность действий отражена в простой программке DB_REPORT (исходники см. в \LEM\Demo\Db\Macro), которая работает в консоли Win32, и умеет загружать текстовый файл отчета, исполнять макрокоманды и сохранять итоговый отчет в указанном текстовом файле.
Главная идея, без понимания которой невозможно эффективно использовать макрогенератор, заключается в следующем правиле подстановки макросов:
Как только макрос объявлен (явно или неявно) либо изменено его значение, текст до конца текущего блока просматривается на предмет замены макроса на его значение.
По умолчанию текущим блоком считается весь текст, но с помощью команд $BEGIN...$END можно организовывать произвольно вложенные блоки. Кроме этого, оператор цикла неявно объявляет локальный блок, в который входит тело цикла (и все вложенные в него блоки).
Для макроподстановки нет границ в виде кавычек и так далее. Поэтому макросы подставляются внутри строк "...". Благодаря этому макроязык позволяет минимумом средств реализовать весьма интересные программы. Кроме того, макрогенератор является истинным интерпретатором, то есть макрокоманды извлекаются и исполняются по ходу парсинга текста. Заранее никакие структуры не строятся, что сказывается на быстродействии, но снимает ограничения на самомодификацию скрипта. Другими словами, участок скрипта:
$DEF скока
$DEF цикл = "$FOR i=1 TO скока"
$DEF кон_цикл="$NEXT i"
цикл
ха-ха-ха
кон_цикл
вполне нормально исполнится.
Как будет показано в макрокоманде $DEF, именем макроса может быть любая цепочка символов, не обязательно составляющие одну лексему, что дает максимально широкие и опасные возможности по программированию скриптов.
В текущей версии регистр букв имеет значение.
Исходники - \LEM\Demo\Db\Macro
Проект - для IDE Borland C Builder.
В папке с исходниками находится тестовый скрипт test_odbc_connect.shtml. Для того, чтобы проверить работу с БД, необходимо настроить ODBC алиас с именем test_db на Access-базу данных (файл test_db.mdb в этом же каталоге, доступ - пользователь admin с паролем nimda). Эта БД содержит только одну таблицу REF, состоящую из 3 строк. Содержимое этой таблицы будет отображено в отчете с помощью команды $SQL.
Утилита db_report может быть использована для быстрого формирования отчетов по результатам поиска утилитой FAIND - подробное описание смотри здесь.
Преобразование числа в текстовое представление
$NUM_TO_TEXT(число)
Например, команда $NUM_TO_TEXT(12444) будет заменена на фразу 'двенадцать тысяч четыреста сорок четыре'.
Склонение слова для согласования с числом в указанном падеже
$CORR(слово,число,падеж)
- склоняет слово для согласования с числом в указанном падеже.
падеж = { им, род, тв, дат, вин, пр }
Пример использования:$SQL( "SELECT count(*) INTO n_user FROM Users" )
<p>Всего подключено: n_user $CORR( пользователь, n_user ).</p>
В результате интерпретации их двух команд будет сформирован такой участок:
Всего подключено: 21 пользователь
Для выполнения склонений используется подсистема Micro_Solaris.
Арифметические и строковые вычисленияления
$CALC("арифметическое_выражение")
– подставляет результат расчета выражения. Аргументами выражения могут быть целые числа, числа с плавающей точкой и строки.
Пример:
$CALC( "3.1415926*2+4" )
Выражение должно быть заключено в двойные кавычки. Приоритеты операций – стандартные.
Для выполнения вычислений используется класс калькулятора, который можно использовать и отдельно в своих программах (к примеру, он используется в интерпретаторе C-скриптов).
$FOR имя_переменной_цикла = нач_знач TO
кон_знач
тело циклацикла
$NEXT имя_переменной цикла
Переменная будет принимать значения от указанного начального до (включая) указанное конечное.
Пример использования цикла можно найти в файле for.shtml. После запуска отчета:
db_report for.shtml report.shtml
формируется файл с перечисленными от 1 до 1000 числами.
Цикл перебора значений из списка
$FOR имя_переменной_цикла EACH FROM ( s1, s2,
... , sn )
тело циклацикла
$NEXT имя_переменной цикла
Переменная будет принимать значения строк из списка.
$EXIT
Интерпретация команд для тела цикла прекращается и интерпретация продолжается за циклом. Обычно используется вместе с командой условного выбора:
$FOR i EACH FROM ( 0, 1, 2, 3 )
$IF eq(i,2)
$EXIT
$ENDIF
произвольные команды и текст
$NEXT i
Этот же пример можно найти в файле exit.shtml.
$IF условие
тело оператора
$ENDIF
условие - это выражение:
eq(x,y) - лексическое равенство
gt(x,y) - арифметически или лексически больше (greater than)
lt(x,y) - арифметически или лексически меньше (less than)
ge(x,y) - арифметически или лексически больше или равно (greater or equal)
le(x,y) - арифметически или лексически меньше или равно (less or equal)
neq(x,y) - лексическое равенство
and(x,y) - логическое Икое И
or(x,y) - логическое ИЛИ
like(text,pattern) - сравнение с регулярным выражением pattern. Метасимволы: * - любое количество символов, ? - один произвольный символ
not(x) - логическое отрицание
аргументами этих функций (кроме like) могут быть числа, строки (возможно - в кавычках), а также сами функции (степень вложенности не ограничена).
Пример:
$IF eq( n_user, 5 )
$IF not( like( имя, "*ля" ) )
Более сложный пример с оператором like можно найти в файле like.shtml.
$CALL proc_name
Вызов процедуры без параметров
$CALL proc_name( арг=знач, арг=знач )
Вызов процедуры со списком входных параметров. Список заключается в круглые скобочки и состоит из разделенных запятыми пар имя аргумента - его значение. Требование указывать имя формального аргумента при вызове процедуры (причем именно так, как оно указано в объявлении процедуры в БД идет от реализации ADO.NET в MS .Net Framework.
Пример:
$CALL test( id=1 )
$DEF имя_макроса = значение
Имя макроса и его содержимое могут быть заключены в кавычки – при инициализации макроса эти кавычки будут отброшены.
Пример:
$DEF "{emitent}" = "произвольное имя"
Извлечение данных из БД оператором SELECT
$SQL( "select-оператор" [, option [, option, ...] ] )
Допустимые опции:
list – строки размещать в виде списка
notable – не формировать таблицу, а размещать строки в виде как есть.
show – показывать данные даже в случае, если тело SQL-оператора содержит блок INTO.
tag="описание_тэга" – указание строки, которая в неизменной виде (но без кавычек) будет впечатана в тэг таблицы или списка. Таким образом, можно управлять внешним видом списка:
$SQL( "select id, desc FROM ttt", list, tag="ol" )
Есть специальный синтаксис этого оператора, позволяющий организовать неявный цикл:
$SQL( "SELECT ... INTO ... FROM ..." )
$BEGIN
... тело цикла
$END
После считывания очередной строки в INTO выполняется тело цикла, то есть перечисленные в INTO переменные являются локальными переменными цикла.
Пример использования оператора SQL с неявным циклом можно увидеть в файле test_odbc_connection.shtml. Данные извлекаются из файла БД Access (файл test_db.mdb).
Объявление локального блока макросов
$BEGIN ... $END
Все макросы, объявленные или созданные неявно внутри локального блока, видны только внутри этого блока (полностью аналогично правилам видимости переменных в C++).
$ODBC( alias, user, psw )
Команда реализована только для Win32-платформы. Для .NET аналогичной команды нет (просто не было практической необходимости). При использовании классов макрогенератора в прикладных программах проще создавать объект провайдера БД внутри программы и передавать указатель на этот объект в объект класса Macro_Formatter (метод Set_DB).
Пример использования можно увидеть в файле ле test_odbc_connection.shtml.
Запрос данных с терминала и создание макроса
$ASK(var,"вопрос")
На системной консоли печатается текст вопрос, затем введенный пользователем текст присваивается создаваемому макросу var. Если такой макрос уже существует, то его значение меняется на введенное.
Пример с цепочкой подстановок:
$ASK( user, "Enter your name:" )
$ASK( psw, "Hi, user, enter your code now:" )
В соответствии с правилом подстановки макросов после ввода значения макроса user все вхождения этого макроса до конца текущего блока $BEGIN...$END будут заменены – поэтому к моменту интерпретации второй команды $ASK она будет иметь такой, к примеру вид:
$ASK( psw, "Hi, eek, enter your code now:" )
Пример использования можно увидеть в файле test_odbc_connection.shtml.
$PRINT( "строка" )
Текст внутри кавычек печатается на системном терминале. Команду удобно применять для отладки макроскриптов, чтобы увидеть значения макросов по ходу интерпретации.
1. Компиляция шаблонов в специальное внутреннее представление, хранение скомпилированных шаблонов в коде прикладной программы
2. Нужно помалу прикручивать работу с XML.
последние изменения 15.06.2005
© Mental Computing 2009