Компьютер Пресс № 4-98

Работаем с Crystal Reports 6.0. (часть 3)

Сергей Маклаков

В предыдущих статьях были рассмотрены общие приемы работы с Crystal Reports 6.0. В настоящей статье будут рассмотрены способы применения формул Crystal Reports, приемы работы с SQL/ODBC источниками и модуль Crystal Query Designer.

Формулы

Часто необходимо представить данные существенно отличными от того вида, в котором они хранятся в БД. Например, можно включить в отчет среднее значение или процент продаж. В отчет могут быть включены достаточно сложные вычисления, отображающие реальные бизнес-правила. Crystal Reports предоставляет мощный инструмент обработки данных - поля Formula.

Вставка формул

Для вставки формул: Если в отчете уже имеются поля формул, их имена будут показаны в появившемся диалоге Insert Field. Можно изменить существующие формулы или создать новую. Для этого нужно кликнуть по кнопке New, набрать имя создаваемой формулы и кликнуть по кнопке OK.
Появляется диалог Formula Editor, который имеет четыре секции:

Функции Crystal Reports

При построении формул пользователю доступны несколько типов функций, содержащихся в соответствующих разделах списка Function Box. Всего Crystal Reports 6.0 содержит более 200 функций, ниже будут рассмотрена только часть из них.

Арифметические функции (Arithmetic) позволяют осуществить достаточно сложную статистическую обработку данных. В эту группу входят функции суммирования, осреднения, округления, вычисления статистических величин и т.д. Некоторые функции, например, суммирования Sum() или вычисления среднего Average(), могут иметь от одного до трех параметров. Первый параметр - это величина, по которой производится суммирование, например, поле БД. Второй параметр - признак группы, по которой производится суммирование. Третий параметр - условие суммирования. Например, функция Sum ({Customer.Last Year's Sales},{Customer.City} ) будет подсчитывать сумму продаж по каждому городу, функция
Sum({orders.AMOUNT}, {orders.DATE}, "monthly") будет суммировать поле orders.AMOUNT, предварительно сгруппировав его по месяцам по значению поля orders.DATE.

Строковые функции (Strings) предназначены для обработки текстовых полей БД. Например, функция Trim(String) удаляет пробелы справа и слева от строки String, (Trim(`' абв `') возвращает `'абв''). Функция ToText(x,y,z) конвертирует число в строку, x- константа, переменная или текстовое поле, которое необходимо конвертировать, y- число десятичных знаков после запятой, z- строка-разделитель целой и дробной части. ToText(1666.00,0,'''') возвращает значение `'1666''. Функция Mid(str,start,length) выделяет подстроку из строки, str - строка - источник, start - позиция начала подстроки, length - длина подстроки. Функция Lengt(str) возвращает длину подстроки. Функция ToWords (Number) возвращает сумму прописью (по-английски).

Функции даты и времени (Date/Time) оперируют с переменными типа дата-время. Функция Date(year,month,day) возвращает дату, year, month, day - числа, соответствующие году, месяцу и дню даты. Функция DayOfWeek (Date) возвращает номер дня недели. Функция CurrentDate - текущую дату (соответствует дате, установленной в Windows). Имеется набор функций для конвертации переменных типа дата-время в числовые переменные и наоборот.

Функции диапазона дат (Date Ranges) возвращают значение истина или ложь, если аргумент входит в заданный диапазон дат. Приведем некоторые из них:

Прочие (Other) функции. Часть из них (PrintDate, PrintTime, PageNumber, ReportTitle и т.д.) повторяют функциональность специальных полей, о которых было рассказано ранее. Функция IsNull (field) возвращает истину, если поле содержит нулевое значение (NULL, не путать с 0). Функции Previous(field), Next (field) , PreviousIsNull (field) и NextIsNull (field) позволяют обратиться к значениям полей, содержащихся в предыдущей и последующей строках отчета и проверить, не содержат ли они нулевых значений.

Функции времени выполнения (Evaluation Time). Crystal Reports является двухпроходным генератором отчетов, что означает, что данные обрабатываются дважды - во время чтения и во время печати. Все формулы, встречающиеся в отчете, выполняются в следующей последовательности:

1. Формулы, не содержащие других формул или полей БД, например 2*2 или CurrentDate. Этот этап называется "Перед чтением записей" (BeforeReadingRecords).
2. Формулы, содержащие поля БД. Этот этап называется "Во время чтения записей" (WhileReadingRecords).
3. Формулы, определяющие условия выборки (см. ниже).
4. Формулы, подсчитывающие суммирующие значения в группах.
5. Формулы, в которые входят суммарные и средние значения, проценты по отношению к суммарным
значениям, специальные функции RecordNumber, GroupNumber, Previous, Next и т.д. Этот этап называется "Во время печати записей" (WhilePrintingRecords).

Последовательность выполнения формул можно нарушить, явно указав в тексте формулы этап выполнения (BeforeReadingRecords, WhileReadingRecords, WhilePrintingRecords), либо указав имя формулы, после выполнения которой следует выполнить данную формулу (EvaluateAfter(FormulaName)). Можно "отложить" выполнение формулы, но нельзя выполнить ее раньше, чем это предписано стандартной процедурой выполнения. Например, если попытаться создать формулу

BeforeReadingRecords;
{Orders.Order ID}

она будет воспринята, как содержащая синтаксическую ошибку, поскольку формула "Перед чтением записей" не должна содержать полей БД.

В разделе Дополнительные функции (Additional Functions) содержится большой набор финансовых функций, функций конвертации данных из нестандартных форматов (например, из строки в дату-время) и просто полезных функций.

Функции, определенные пользователем (User Defined Function)

Хотя функции Crystal Reports являются мощным инструментом, позволяющим проводить очень сложную обработку данных, им присущи некоторые ограничения. (Нельзя, например, организовать цикл). Если стандартные формулы Вас не удовлетворяют, можно написать формулу на других языках программирования и включить их в среду Crystal Reports. Шестая версия Crystal Reports поддерживает включение функций, написанных на C++, Delphi и Visual Basic.
Для включения UDF необходимо создать на одном из перечисленных языков динамическую библиотеку (DLL), причем имя библиотеки должно иметь префикс UFL для 16-разрядного и U2F для 32- разрядного Crystal Reports, например, UFLPICT.DLL или U2LPICT.DLL. Скомпилированную библиотеку следует поместить в корневую директорию Crystal Reports. При очередном запуске Crystal Reports Designer подключит библиотеку и имена функций UDF появятся в списке секции Function в разделе дополнительных функций (Additional Functions).
Ниже приведен исходный текст на С, который описывает определенную пользователем функцию Picture. Отметим, что включение файлов описаний Windows.h, UFDll.h, UFMain.h и UFUser.h обязательно.

#include <Windows.h>
#include "UFDll.h"
#include "UFMain.h"
#include "UFUser.h"

#define PicturePlaceholder 'x'
ExternC UFError FAR _export PASCAL Picture

UFFunctionDefStrings FunctionDefStrings [] =
{
{"String Picture (String, String)", UFFunctionTemplates FunctionTemplates [] =
{ UFFunctionExamples FunctionExamples [] =
{ char *ErrorTable [] =

{

void InitForJob (UFTInt32u jobID)
{
}

void TermForJob (UFTInt32u jobID)
{
}

static void copyUsingPicture (char *dest,
const char *source, const char *picture)
{

}

ExternC UFError FAR _export PASCAL Picture

{ }

В дистрибутив Crystal Reports 6.0 входит директория UFL (не устанавливается при инсталляции !), в которой содержатся DLL - файлы с некоторыми полезными функциями и их описаниями. Эти файлы можно просто скопировать в директорию Seagate Crystal Reports, после чего использовать функции UDF в отчетах.

Операторы и переменные

В секции Operators диалога Formula Editor cодержатся операторы Crystal - арифметические, сравнения, строковые (конкатинации, выделения подстроки), булевы и др. Кроме того, имеется оператор ветвления if them else, допускающий множественное вложение, например, В качестве логического условия может использоваться оператор сравнения (как в предыдущем примере) или функция, возвращающая логическое значение TRUE или FALSE.
Для расширения функциональности формул Crystal Reports позволяет использовать переменные. В отличие от констант значение переменных может менятся в различных частях отчета. Для использования переменных необходимо В секции Operators содержатся шаблоны объявления переменных. Переменные могут иметь типы Boolean, Number, Currency, Date, Time, DateTime, String. Имя переменной не должно быть больше 254 символа, в качестве имен нельзя использовать зарезервированные слова и имена функций. Допускается задание диапазона значений переменной (формула с применением такой переменной может выглядеть так: numberVar range AmoVar := 1000 to 2000 ; if {Orders.Order Amount} in AmoVar then TRUE else FALSE) и использование в качестве переменной массива. Если переменная объявлена в различных формулах одного и того же отчете и при этом имеет одно и то же имя и один и тот же тип, она воспринимается Crystal как глобальная.

Параметры

Часто бывает необходимо создать отчет, который мог бы использоваться с минимальными изменениями без перекомпиляции, например, с измененными условиями выборки, сортировки или формулами. Для таких целей лучше всего использовать параметры (Parameter Field). Параметры можно обновлять при каждом запуске отчета.
Для внесения в отчет параметра следует выбрать пункт меню Insert / Parameter Field... и кликнуть в появившемся диалоге Insert Fields по кнопке New...
В появляющемся диалоге Create Parameter Field имеется несколько полей редактирования: Параметр можно использовать при установке условий выборки (в Select Expert), группировки, сортировки и в формулах. При запуске отчета или обновлении данных появляется диалог с несколькими закладками (по количеству параметров в отчете), в котором следует задать значения параметров.

Примеры использования функций

Рассмотрим несколько примеров использования функций.

Использование функций для выборки данных. При установке условий выборки записей в диалоге Select Expert результирующее условие выборки формируется в виде формулы , возвращающей значение TRUE, если запись удовлетворяет условию ( тогда она включается в отчет) и FALSE, если не удовлетворяет. Эту формулу можно просмотреть, кликнув по кнопке Show Formula и отредактировать при помощи редактора формул, кликнув по кнопке Formula Editor... По умолчанию условия выборки объединяются логическим "и", но вручную условия можно объединять любыми логическими операторами. Например, формула, которая выбирает записи, соответствующие заданным при помощи параметров ?CoutryFilter и ?RegFilter страну и регион, либо те записи, у которых значение поля {Orders.Order Amount} больше 1000, выглядит так:
({Customer.Country} = {?CoutryFilter} and
{Customer.Region} = {?RegFilter}) or {Orders.Order Amount} > 1000

Использование функций для форматирования по условию. Любое поле отчета можно отформатировать, кликнув по нему правой кнопкой мыши и выбрав из контекстного меню Format Field... В появившемся диалоге Format Editor содержится набор опций форматирования (на нескольких закладках).

У некоторых опций (на рисунке - Color) помимо элементов безусловного форматирования (у опции Color - раскрывающийся список выбора цвета), расположена кнопка , кликнув на которую можно задать формулу форматирования (при помощи того же Formula Editor). Форматирование будет выполнятся, если формула будет возвращать соответствующее значение.
Рассмотрим пример. Допустим, в отчете необходимо рядом с полем {Orders.Order Amount} поместить красную надпись "Хорошо", если значение поля больше 30000 и синюю надпись "Плохо", если значение поля меньше 1000.
1. Создадим формулу Comment1:

if {Orders.Order Amount}>30000 then "Хорошо" else
if {Orders.Order Amount}<1000 then "Плохо"

и поместим ее рядом с полем {Orders.Order Amount}

2. Отформатируем формулу Comment1, кликнув правой кнопкой мыши и выбрав из контекстного меню Format Field... В диалоге Format Editor выберем закладку Font и кликнем по кнопке опции Color. В диалоге Format Formula Editor Создадим формулу:

if {Orders.Order Amount}>30000 then Red else
if {Orders.Order Amount}<1000 then Blue

Еще один пример. Предположим, необходимо сгенерировать текст писем для рассылки, причем содержимое письма должно зависеть от значения какого-либо поля БД (для определенности- {Orders.Order Amount}). Допустим, необходимо иметь 3 варианта текста-

Для создания такого отчета нужно

1. Правой кнопкой кликнуть по заголовку секции Deteil , выбрать Format Section и дважды кликнуть по кнопке New для вставки двух дополнительных секций - Deteil b и Deteil c.
2. Выбрать в списке секцию Deteil a и кликнув по кнопке условного форматирования опции Suppress (No Drill-Down), внести формулу

{Orders.Order Amount}<30000

Аналогично для секции Deteil b формулу

{Orders.Order Amount}>=30000 or {Orders.Order Amount}<=1000

И, для секции Deteil c

{Orders.Order Amount}>1000

3. Кликнув по кнопке OK, вернуться в режим Design и внести в секции Deteil a , Deteil a и Deteil a тексты писем Text1, Test2 и Text3 соответственно. Тексты могут включать различные поля БД и формулы. Отметим, что если необходимо расположить каждое письмо на отдельной странице, при форматировании секции следует выбрать опцию New Page After.

Вычисление кумулятивного значения. Допустим, отчет содержит поле суммы заказа {Orders.Order Amount}. Необходимо пронумеровать все заказы с суммой более 1000.

1.В секцию Report Header поместим формулу @Reset

WhilePrintingRecords;
numberVar Cnt :=0 ;

2. В секцию Deteil рядом с полем {Orders.Order Amount} поместим формулу @Calculate

WhilePrintingRecords;
numberVar Cnt;
if {Orders.Order Amount}>1000 then (Cnt := Cnt+1 ; Cnt)

3. Отформатируем формулу @Calculate, указав опцию Suppress if Zero и установив Decimal = 1

В результате отчет будет выглядеть примерно так:

Order Amount Calculate
5 060 1
187
50
2 215 2
29
14 872 3
0
10 259 4
1 142 5

Вычисление суммирующих значений в "пересекающихся" группах. Предположим, в БД имеются два поля - страна и население со следующим содержанием:

Испания 39 000 000
Великобритания 57 000 000
Колумбия 30 300 000
Аргентина 31 960 000
Бразилия 144 300 000

Необходимо подсчитать население испаноговорящих стран и население стран, расположенных в Южной Америке. Если сгруппировать страны по признаку континентов, можно внести в отчет поле Subtotal и подсчитать население стран, находящихся на различных континентах. Но при этом нельзя одновременно (используя Subtotal) подсчитать население испаноговорящих стран, поскольку Испания, Аргентина и Колумбия будут входить в разные группы. Решить задачу можно используя формулы.

1. Создадим отчет с полями {Country} и {Population}
2. В секцию Deteil поместим формулу @SAm

if {Country} in ["Колумбия ", " Аргентина", "Бразилия "] then {Population} else 0

и формулу @SpainL

if {Country} in ["Колумбия ", " Аргентина", "Испания "] then {Population} else 0

3. В секции Report Footer суммирующие поля Grand Total по формулам @SAm (население стран, расположенных в Южной Америке) и @SpainL (население испаноговорящих стран)

SQL/ODBC источники данных

Язык SQL (Structured Query Language, структурированный язык запросов) - это стандартный язык, используемый для работы с реляционными СУБД (или РСУБД), то есть с СУБД, основанными на реляционной математической модели. Для работы с РСУБД Crystal Reports использует механизм ODBC (Microsoft Open DataBase Connectivity API), который позволяет единообразно работать с СУБД (не только реляционными, но с любыми, имеющими ODBC драйвер, например, dBASE, FoxPro, Btrieve, Paradox, Access и т.д.) различных производителей, не вдаваясь в специфические особенности конкретных БД.
Первым шагом для работы с РСУБД является установка сеанса связи с сервером БД. Необходимым условием для этого является наличие инсталлированной клиентской части РСУБД, драйверов протоколов (например, TCP/IP) и соответствующего предварительно настроенного ODBC - драйвера. В состав поставки Crystal Reports 6.0 входят драйверы для Oracle 7, Microsoft SQL Server, Centura SQLBase, Informix, Sybase, DB2 (для Oracle 7, Sybase System 10/11 и Microsoft SQL Server 6.x реализован прямой доступ). Предварительную настройку ODBC можно осуществить при помощи модуля ODBC Administrator (устанавливается в программную группу Seagate Crystal Reports 6.0 при инсталляции).
Для создания отчета с использованием SQL/ODBC источников нужно в Create Report Expert кликнуть по кнопке, появится диалог Log On Server,
в котором необходимо выбрать требуемый источник данных. Для работаеты с РСУБД в дополнительном диалоге нужно указать имя пользователя, сервера или БД и пароль. После установления связи с источником появляется диалог Choose SQL Table, в котором нужно указать таблицы для включения в отчет. Дальнейшая работа по созданию отчета лишь немногим отличается от работы с обычными файлами БД. Отметим некоторые особенности.

1. По умолчанию Visual Liking Expert устанавливает связи по одинаковым именам колонок, что не имеет никакого отношения к реальным связям, определенным в РСУБД (по первичным и внешним ключам). Как правило, необходимо вручную редактировать установленные по умолчанию связи. В отличие от Data File - источников здесь связи можно устанавливать между любыми, не обязательно индексированными полями.

2. Помимо таблиц, в качестве источников данных можно использовать записанные процедуры. В настройке (меню File|Options, закладка SQL) нужно включить опцию Stored Procedures, после чего в диалоге Choose SQL Table в списке таблиц появятся имена записанных процедур. При включении процедуры в отчет необходимо указать входные параметры. Их можно поменять, выбрав в меню Database / Stored Procedure Parameters. Выходные параметры можно использовать так же, как поля БД.

3. Результирующий SQL - запрос можно просмотреть, выбрав из меню Database / Show SQL Query. В данной статье не рассматривается синтаксис языка SQL. Неопытным пользователям можно порекомендовать книгу Мартина Грабера "Введение в SQL" (Перевод, издательство "Лори", 1996 г.)

Crystal Query Designer

Модуль Crystal Query Designer предназначен для создания и сохранения SQL - запросов к реляционным БД. Используя инструменты Crystal Query Designer, разработчик может создать библиотеку запросов, пользуясь которой неопытные пользователи могут быстро создавать сложные отчеты, ничего не зная о структуре РСУБД и языке SQL.
Для построения запроса нужно запустить Crystal Query Designer из программной группы Seagate Crystal Reports 6.0 и выбрать из меню пункт File / New...
Запросы в Crystal Query Designer можно писать вручную (кнопка Enter SQL statement directly), можно создать запрос модернизируя существующий (при этом запрос-образец не будет испорчен - кнопка Start from existing Crystal Query) , но если Вы не очень хорошо знаете SQL, то можно воспользоваться встроенным построителем запросов - Crystal Query Expert.
Диалог Crystal Query Expert имеет 6 закладок.

На закладке Tables следует указать таблицы, которые будут входить в SQL- запрос. Для этого можно непосредственно указать ODBC-источник, либо воспользоваться словарем (работа со словарями Crystal была описана в предыдущей статье). При этом возникнет диалог Logon, в котором нужно указать имя пользователя и пароль. Таблицы, указанные на закладке Tables, включаются в предложение FROM.
На закладке Links необходимо указать связи между таблицами. Интерфейс закладки аналогичен Visual Liking Expert модуля Crystal Reports Designer (см. первую статью серии).

Закладка Fields выбора служит для указания полей, которые будут включены в запрос. В левой части закладки перечислены таблицы, которые предварительно были выбраны в закладке Tables. Дважды кликнув по названию таблицы, можно свернуть или развернуть список полей таблицы. В правой нижней части закладки расположен раскрывающийся список Total, который позволяет включить в запрос агрегативные функции языка SQL (не путать с функциями Crystal). Кликнув по кнопке Brose, можно просмотреть значения полей в БД. Будут показаны первые 100 неповторяющихся значений.

Закладки Sort и Select служат для установки условий сортировки (предложение ORDER BY) и выборки (предложение WHERE). Интерфейс закладок аналогичен диалогам Record Sort Order и Select Expert модуля Crystal Reports Designer.

После задания таблиц, полей, условий выборки и сортировки на закладке SQL, можно просмотреть результирующий запрос. Запрос можно выполнить и просмотреть результирующий набор данных, кликнув по кнопке Preview Query. Если результат не удовлетворителен, запрос можно отредактировать вручную, выбрав из меню Edit /Query... Появляется диалог Enter SQL Statement.

Тот же диалог появляется, если Вы захотите набрать запрос вручную ( кнопка Enter SQL statement directly). Crystal Reports поддерживает как ANSI SQL, так и Jet SQL, в зависимости от ODBC - источника.

Отметим одну особенность применения агрегативных функций. На рисунке видно, что Crystal Query Expert автоматически присвоил имя колонке, отображающей значение функции (Expr_1), что не всегда удобно. Для переименования результирующих колонок необходимо воспользоваться синонимами. Аналогичный приведенному на рисунке запрос, написанный вручную, выглядит так:

SELECT b.DESCRIPTION, AVG( a.LIST_PRICE) AS AVERAGES
FROM demo.PRICE a, demo.PRODUCT b
WHERE a.PRODUCT_ID = b.PRODUCT_ID
GROUP BY b.DESCRIPTION

Колонка с результатами осреднения получит имя AVERAGES.
Запросу можно присвоить имя , выбрав из меню Edit /Query Title... Сохранив запрос (File / Save), можно использовать его при создании отчетов в Crystal Reports Designer. Запрос сохраняется как файл с расширением qry. При создании нового отчета с помощью Reports Expert необходимо просто указать в качестве источника Query и выбрать нужный файл с сохраненным запросом.

В следующей статье будет рассмотрена архитектура доступа к данным и способы включения отчетов Crystal Reports в приложения, написанные на Borland Delphi 3.0 и SQLWindows (Centura).

Координаты автора:
Учебно-консалтинговый центр Interface Ltd.,
Тел. (095)135-55-00, 135-25-19, 135-77-81,
e-mail: mail@interface.ru
http://www.interface.ru


Interface Ltd.

Ваши замечания и предложения направляйте по адресу: webmaster@interface.ru

Reklama.Ru. The Banner Network.