Работаем с Crystal Reports 6.0. (часть 4)
Сергей Маклаков, Наталия Елманова.
В четвертой, последней статье из серии о Crystal Reports будет рассмотрена
архитектура доступа к данным, функции API и способы включения отчетов
в приложения на примере Borland Delphi 3.0 и Borland C++Builder 1.0/3.0.
Архитектура Crystal Reports.
Основные модули Crystal Reports.
Crystal Reports состоит из следующих основных компонентов:
-
Report Designer (файл CRW.EXE для 16 - разрядной версии и CRW32.EXE для
32- разрядной) - основной модуль, который позволяет разрабатывать отчеты
и открывать *.rpt -файлы. Прочие компоненты (перечисленные ниже) играют
вспомогательную роль.
-
Query Designer (CQW.DLL /CQW32.DLL) - инструмент для создания SQL-
запросов (описан в третьей статье серии).
-
Data Dictionary (CDW. EXE / CDW.EXE) - словарь типовых решений для быстрой
разработки отчетов. Словари хранятся в файлах *.DC5. Работа со словарями
Crystal описана во второй статье серии.
-
Report Engine (CRPE.DLL / CRPE32.DLL) - API, дающий возможность
разработчикам интегрировать отчеты в их собственные приложения. Создав
отчет в Report Designer, можно просматривать его в приложениях, используя
Report Engine. С помощью Report Engine можно во время выполнения
устанавливать условия группировки данных, стили графиков, местоположение
БД и многое другое.
Доступ к данным.
Прямой доступ реализован для большинства форматов персональных БД (dBASE,
FoxPro, Clipper, Btrieve, Microsoft Access и др.) и некоторых реляционных
СУБД (Oracle 7, Microsoft SQL Server 6.x, Sybase System 10/11). Другими
словами Crystal имеет встроенные возможности доступа к указанным источникам.
Возможность прямого доступа появляется при инсталляции Crystal Reports.
Прямой доступ имеет три уровня:
-
Уровень Crystal Reports,
-
Уровень Data Translation, реализованный в соответствующих DLL, входящих
в поставку Crystal Reports,
-
Уровень БД.
Доступ через ODBC (Open DataBase Connectivity - стандарт, позволяющий приложению
иметь доступ к различным источникам данных) имеет пять уровней:
-
Уровень Crystal Reports. При работе с ODBC - источниками Crystal
Reports генерирует SQL - запросы, которые позволяют выбирать из БД только
те данные, которые необходимы для построения отчета.
-
Уровень ODBC Data Translation. Crystal Reports использует динамическую
библиотеку PDSODBC.DLL/P2ODBC.DLL для связи с ODBC (как для получения,
так и для передачи данных).
-
Уровень ODBC использует различные DLL - файлы и файлы настройки, входящие
в состав окружения Windows. Все ODBC-драйверы должны быть настроены либо
при помощи утилит, входящих в состав Windows, либо при помощи модуля, входящего
в состав Crystal Reports - ODBC Administrator.
-
Уровень DBMS Data Translation содержит один или несколько драйверов, обеспечивающих
доступ к БД. Большинство СУБД, поддерживающих работу с Windows, содержат
ODBC - драйвера в составе поставки. Некоторые драйвера (DB2, SQLBase,
Informix) устанавливаются при инсталляции Crystal Reports.
-
Уровень БД. Crystal Reports не должен знать о формате данных и местоположении
БД в сети, поскольку вся информация содержится в настройке ODBC - источника.
Все пять уровней используют для взаимодействия язык SQL
Crystal Reports Print Engine API
Модуль Crystal Reports Print Engine API предназначен для доступа к отчетам
из приложений Windows. Доступ реализован через вызовы функций CRPE.DLL
/ CRPE32.DLL.
Первый шаг к использованию функций - их объявление. Функции могут быть
объявлены как глобально, так и локально внутри использующей их секции кода.
Каждая функция может быть объявлена отдельно, но имеется и возможность
объявления всех функций сразу. Например, функция PEStartPrintJob
может быть объявлена в Visual Basic как:
Declare Function PEStartPrintJob Lib "CRPE.DLL" (ByVal printJob
As Integer, ByVal waitUntilDone As Integer) As Integer
Для объявления всех функций сразу необходимо воспользоваться файлами
заголовков, входящих в состав Crystal Reports. Например, для Visual Basic
имя такого файла - GLOBAL.BAS, для С - CRPE.H.
После объявления функций для начала работы с отчетом необходимо вызвать
функцию PEOpenEngine, которая возвращает значение TRUE (1), если вызов
прошел успешно, либо FALSE(0), если CRPE.DLL / CRPE32.DLL загрузить не
удалось. Функция PEOpenEngine не имеет параметров и служит только для обработки
в программном коде факта успешного подключения Print Engine.
Для печати отчета используется функция PEPrintReport. Синтаксис функции
приведен ниже:
PEPrintReport("reportName", toPrinter, toWindow, "windowTitle",
leftCoordinate, topCoordinate, windowWidth, windowHeight, windowStyle,
parentWindow)
где:
-
reportName - полное имя (включая путь) отчета. Можно использовать
строковую переменную.
-
toPrinter - TRUE (1), если отчет выводится на принтер и FALSE(0),
если в окно Windows. Для выбора принтера следует использовать функцию PESelectPrinter.
-
toWindow - если значение TRUE (1), отчет выводится в окно предварительного
просмотра. При этом toPrinter должен быть равен 0.
-
windowTitle - заголовок отчета в окне просмотра. Можно использовать
строковую переменную.
-
leftCoordinate - левая координата окна просмотра.
-
topCoordinate -верхняя координата окна просмотра.
-
windowWidth - ширина окна просмотра в пикселах.
-
windowHeight - высота окна просмотра в пикселах.
-
windowStyle - установка стиля (как определено в "Windows.h").
-
parentWindow - указатель родительского окна. Например, если два
последних параметра равны 0, Crystal Reports использует следующий стиль:
(WS_VISIBLE | WS_THICKFRAME | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX)
Функции Report Engine позволяют не только просматривать отчет в окне приложения,
но и управлять некоторыми опциями отчета. Например, можно изменить порядок
сортировки данных отчета, модифицировать формулы выборки и группировки,
модифицировать формулы отчета и т.д. Прежде чем использовать функции, управляющие
опциями отчета, необходимо вызвать шесть основных функций:
-
PEOpenEngine - начало работы с Print Engine (загрузка CRPE.DLL/
CRPE32.DLL).
-
PEOpenPrintJob - подготовка процесса печати. Возвращаемое
значение функции - указатель процесса печати, который будет использован
другими функциями Print Engine.
-
PEOutputToPrinter , PEOutputToWindow или PEExportTo - подготовка
вывода отчета на принтер, в окно просмотра или экспорта отчета соответственно.
-
PEStartPrintJob - запуск печати.
-
PEClosePrintJob - закрытие сеанса печати.
-
PECloseEngine - закрытие сеанса работы Print Engine (CRPE.DLL /
CRPE32.DLL выгружается).
Совместно с обязательным набором из шести функций можно использовать другие
функции управления отчетом. В качестве примера можно рассмотреть функцию,
устанавливающую формулу выборки - PESetSelectionFormula. Ее синтаксис:
PESetSelectionFormula (Print Job Handle, Formula String),
где Print Job Handle - указатель процесса печати, Formula String - текст
формулы Crystal Reports.
Всего Crystal Reports 6.0 содержит 125 функций Print Engine -
функции для управления данными, процессами печати, выводом
в окно просмотра, принтером, экспортом, функции управления сортировкой
, выборкой и группировкой, управлением форматом печати и т.д.
При помощи функций Print Engine можно просматривать отчет, менять его
параметры, но нельзя менять дизайн отчета. Это утверждение относится
к любым приложениям, написанным на любом языке программирования.
Встраивание отчетов в Borland Delphi и Borland C++Builder.
Существует несколько способов использования отчетов Crystal в приложениях,
написанных на Delphi и C++Builder. Во-первых, можно непосредственно использовать
функции Print Engine в коде, связанном с формой, или написать собственные
компоненты, использующие такие функции. Во-вторых, можно воспользоваться
готовым компонентом TCrpe, входящим в комплект поставки Crystal Reports
6.0, а также использовать компоненты третьих фирм. Можно использовать управляющий
элемент Crystal Reports ActiveX. Наконец, можно управлять работой Crystal
Reports Print Engine как сервером OLE Automation. Рассмотрим примеры использования
каждого способа.
Использование Crystal Reports Print Engine API в Delphi.
Для объявления функций Print Engine следует добавить в проект модуль
CRPE32.PAS (или CRPE.PAS в случае использования версии Delphi 1.0), в котором
объявлены все функции и структуры Report Engine API и сослаться на этот
модуль в предложении uses. Все эти функции содержатся в библиотеке
CRPE32 DLL ( CRPE DLL). После объявления функций их можно использовать
внутри кода обработчиков событий.
Рассмотрим простейший пример использования Print Engine API. Для этой
цели создадим форму, содержащую три кнопки и один компонент TOpenDialog
следующего вида (рис. 1).
Рис. 1. Пример использования Print Engine API
.
В качестве значения свойства Filter компонента TOpenDialog рекомендуется
выбрать расширение *.rpt.
Создадим следующий код обработчиков событий, связанных с нажатием на
кнопки:
unit crU1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls,
Forms, Dialogs,
StdCtrls, CRPE32;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
OpenDialog1: TOpenDialog;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
JN:word;
implementation
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
VAR RepNam:PChar;
begin
if OpenDialog1.Execute then
begin
If PEOpenEngine then
begin
RepNam := StrAlloc(80);
StrPCopy(RepNam,
OpenDialog1.Filename);
JN := PEOpenPrintJob(RepNam);
if JN =
0 then
ShowMessage('Ошибка
открытия отчета');
StrDispose(RepNam);
end
else
ShowMessage('Ошибка открытия
отчета');
end;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
PEClosePrintJob(JN);
PECloseEngine;
Close;
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
begin
PEOutputToWindow(jn,'Пример использования Crystal
Reports Print Engine',30,30,600,400,0,0) ;
if PEStartPrintJob(JN, True) = False then
ShowMessage('Ошибка вывода отчета');
end;
end;
end.
При нажатии на первую из кнопок производится выбор файла отчета с помощью
стандартного диалога открытия файлов. При нажатии на вторую кнопку производится
запуск Run-time-версии Crystal Reports и отображение отчета в стандартном
окне (рис. 2):
Рис. 2. Отображение отчета с помощью функции PEStartPrintJob .
Следует помнить, что строковые параметры, передаваемые в функции Print
Engine API, представляют собой тип данных PChar, а не стандартные строки,
используемые в Pascal, поэтому для передачи таких параметров, как, например,
имя отчета, следует осуществить преобразование типов с помощью функции
StrPCopy. Отметим, что с помощью функций Print Engine API можно изменять
довольно широкий спектр параметров отчета (Selection Formula, SQL Query,
условия группировки и сортировки, параметры, связанные с печатью и
отображением). Напомним также, что для успешной компиляции подобных приложений
файл CRPE32.PAS должен находиться в том же каталоге, что и разрабатываемое
приложение, либо в каталоге Delphi 3\Lib.
Использование Crystal Reports Print Engine API в C++Builder.
Для объявления функций Print Engine следует добавить в проект заголовочный
файл CRPE.H, в котором объявлены все функции и структуры Print Engine API,
и сослаться на него в тексте модуля, в котором из библиотеки CRPE32 DLL
вызываются эти функции. Исходный текст примера, подобного рассмотренному
выше примеру для Delphi, имеет следующий вид:
//-------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "U1.h"
#include "crpe.h"
//-------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
int JN;
//-------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//-------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
if (OpenDialog1->Execute())
{
PEOpenEngine();
JN=PEOpenPrintJob((OpenDialog1->FileName).c_str());
if (JN==0) ShowMessage("Ошибка открытия отчета");
}
}
//-------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
PEClosePrintJob(JN);
PECloseEngine();
Close();
}
//-------------------------------------------
void __fastcall TForm1::Button3Click(TObject *Sender)
{
PEOutputToWindow(JN,"Пример использования Crystal Reports Print
Engine",30,30,600,400,0,0) ;
if (!PEStartPrintJob(JN,1)) ShowMessage("Ошибка вывода отчета");
}
//-------------------------------------------
Отметим, что имя файла отчета, являющееся свойством компонента TOpenDialog,
принадлежит к типу ANSIString, являющемуся классом С++Builder, созданным
для совместимости с библиотекой VCL. Поэтому и в этом случае перед вызовом
функций Print Engine API также требуется преобразование к стандартному
для языка С++ строковому типу переменной, содержащей имя файла отчета.
Использование VCL-компонентов Crystal Reports 6.0 с Delphi.
В директории /SAMPAPPS/DELPHI содержится невизуальный компонент TCrpe
для версий Borland Delphi 1, 2 и 3, который в случае необходимости его
использования должен быть установлен в палитру компонентов (по умолчанию
- на страницу DataAccess). Этот компонент реализует почти все возможности,
предоставляемые Print Engine API, позволяя избежать написания соответствующего
кода. Для включения компонента в приложение следует поместить его
на форму и установить необходимые значения его свойств (которых у этого
компонента около сотни - для определения параметров, связанных с переменными
отчета, печатью и отображением данных, типом окна, в котором отображается
отчет, и т.д.). Минимально необходимым среди них является свойство ReportName
- имя файла отчета. Для отображения отчета в стандартном окне, подобном
изображенному на рис. 2, и вывода на принтер используется метод Execute
этого компонента.
Отметим, что с помощью установки значений ряда свойств этого компонента
на этапе выполнения можно менять во время выполнения характеристики отчета,
такие как значения специальных полей, текст SQL-запроса, условия отбора
данных, свойства, связанные с отображением и печатью. Рассмотрим простейший
пример подобного управления отчетом. С этой целью создадим простейший отчет
на основе таблицы Items.db из базы данных DBDEMOS, входящей в комплект
поставки Delphi. Затем создадим приложение, на главную форму которого поместим
компонент TEdit, две кнопки и, разумеется, компонент TCrpe (рис.3).
Рис. 3. Приложение для тестирования возможности управления отчетом
на этапе выполнения.
Создадим обработчик события, связанного с нажатием на кнопку "Открыть
отчет":
procedure TForm1.Button1Click(Sender: TObject);
begin
if edit1.text='' then Crpe1.SelectionFormula.Strings[0]:=''
else
Crpe1.SelectionFormula.Strings[0]:='{items.ItemNo} = ' + Edit1.Text;
if not Crpe1.execute then
ShowMessage('Ошибка
открытия отчета');
end;
В этом обработчике события на основе значения, введенного пользователем
в компонент TEdit, меняется значение свойства SelectionFormula компонента
TCrpe, и в результате пользователь получает в окне отчета не всю таблицу
целиком, а только записи, в которых значение поля ItemNo равно введенному
пользователем числу (рис.4). Для работоспособности данного кода рекомендуется
в качестве значения свойства SelectionFormula ввести хотя бы одну пустую
строку, чтобы в соответствующем строковом массиве был хотя бы один элемент.
Рис. 4. Результат установки значения поля SelectionFormula
на этапе выполнения.
Использование компонентов третьих фирм.
В качестве примера рассмотрим компоненту фирмы SupraSoft Ltd. (http://www.suprasoft.com).
Этот компонент поставляется в виде отдельного пакета. Для его включения
в палитру компонентов следует в выбрать в меню Delphi 3 пункт Component
/ Install Packages... В диалоговой панели Project Options нужно выбрать
страницу Packages, в которой нужно нажать на кнопку Add и в появившемся
диалоге Add Design Package выбрать файл crysdc15.dpc (Package collection)
из комплекта поставки компонент SupraSoft. После инсталляции и закрытия
с помощью кнопки OK диалога Project Options в палитре компонентов появится
дополнительная страница Supra с единственным компонентом TCrystalDesign
. Этот компонент, в отличие от компонента TCrpe, является визуальным
и позволяет отображать "живые" данные из отчета непосредственно на этапе
проектирования формы, которая при этом фактически заменяет собой стандартное
окно Crystal Reports Run-time на этапе выполнения. Функциональность этого
компонента и возможности динамического управления отчетом на этапе выполнения
примерно те же, что и у компонента TCrpe.
В качестве иллюстрации создадим пример, аналогичный предыдущему, поместив
на форму компонент TEdit, две кнопки и компонент TCrystalDesign. Создадим
следующий обработчик события, связанного с нажатием на одну из кнопок:
procedure TForm1.Button1Click(Sender: TObject);
begin
CrystalDesign1.ResetContent:=true;
if edit1.text='' then CrystalDesign1.SelectionFormula.Clear
else
CrystalDesign1.SelectionFormula.Add('{items.ItemNo} = ' + Edit1.Text);
CrystalDesign1.Active:=True;
end;
Отметим, что метод ResetContent компонента TCrystalDesign закрывает
отчет, чем в данном случае мы и воспользовались. Результат работы данного
примера приведен на рис. 5.
Рис. 5. Результат установки значения поля SelectionFormula на этапе
выполнения.
К сожалению, оба компонента, и TCrpe, и TCrystalDesign, поставляются
на сегодняшний день только в варианте для Delphi, и не могут быть установлены
в палитру компонентов C++Builder, так как поставляются без исходных текстов.
Однако с помощью функций Print Engine API можно также осуществить
динамическое управление отчетом, правда, с несколько меньшим комфортом,
чем при использовании готовых компонентов. Например, изменение формулы
для отбора записей в готовом отчете согласно какому-либо критерию в этом
случае осуществляется с помощью оператора примерно следующего вида:
PESetSelectionFormula(JN,"{items.ItemNo} = 2");
Отметим также, что готовые компоненты для управления отчетами также
создаются с помощью функций Print Engine API, и возможности творчества
в этом направлении поистине безграничны…
Управление Crystal Reports с помощью OLE Automation.
Еще одним вариантом использования Crystal Reports в приложениях является
использование Crystal Report Engine как OLE Automation-сервера. В справочной
системе Crystal Reports имеется подробное описание иерархии вложенных
объектов и их методов (и внушительный набор примеров для Visual Basic,
аналоги которых несложно создать и на Pascal). В этом случае пример для
Delphi, аналогичный рассмотренному выше, выглядит следующим образом:
unit Uole1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls,
Forms, Dialogs,
StdCtrls,ComObj;
type
TForm1 = class(TForm)
Button1: TButton;
Edit1: TEdit;
Button2: TButton;
Label1: TLabel;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
rep,r:variant;
implementation
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
begin
rep:=CreateOleObject('Crystal.CRPE.Application');
r:=rep.OpenReport('d:\Report2.rpt');
r.RecordSelectionFormula := '{items.ItemNo} = '+Edit1.Text;
r.Preview;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
Close;
end;
end.
Отметим, однако, что использование OLE Automation - не самый выгодный
с точки зрения производительности способ управления отчетами.
Использование Crystal Reports ActiveX.
В комплект поставки Crystal Reports Professional входят также ActiveX-компонент
для управления Run-time-версией Crystal Reports. Этот компонент
может быть установлен в палитру компонентов Delphi или С++Builder и далее
может быть использован при проектировании приложений, как и любой невизуальный
компонент. Этот компонент обладает набором свойств и методов, более или
менее сходным с соответствущим VCL-компонентом TCrpe.
В качестве иллюстрации выполним тот же пример, что и в предыдущем случае,
но с использованием Crystal Reports ActiveX. Создадим форму, содержащую
ActiveX-компонент TCrystalReport, а так же две кнопки и компонент TEdit:
Рис.6. Пример использования Crystal Reports ActiveX
Crystal Reports ActiveX обладает весьма удобным редактором свойств,
позволяющим определить ряд опций уже готового отчета.
Рис.7. Редактор свойств Crystal Reports ActiveX
Создадим обработчик события, связанного с нажатием на кнопку "Открыть
отчет"
procedure TForm1.Button1Click(Sender: TObject);
begin
if edit1.text='' then CrystalReport1.SelectionFormula:=''
else
CrystalReport1.SelectionFormula:='{items.ItemNo} = ' + Edit1.Text;
if not (CrystalReport1.PrintReport=0)
then
ShowMessage('Ошибка
открытия отчета');
end;
В результате нажатия пользователем на кнопку пользователь получает
в окне отчета записи, в которых значение поля ItemNo равно введенному
пользователем числу (то есть то же самое, что изображено на рис.4).
Отметим, что Crystal Reports ActiveX можно с успехом использовать
в приложениях, созданных с помощью любого другого средства разработки,
использующего управляющие элементы ActiveX.
Отметим также, что для пользователей Delphi 1.0 в комплекте поставки
16-разрядной версии Crystal Reports Professional имеется сходный по функциональности
управляющий элемент VBX, который также может быть установлен в палитру
компонентов и использован в 16-разрядных приложениях.
Таким образом, на сегодняшний день существует довольно богатый выбор
способов, с помощью которых можно управлять отчетами Crystal Reports из
средств разработки - как с использованием вызовов функций Print Engine
API, так и с использованием OLE-технологии.
C авторами можно связаться, обратившись
в Учебно-консалтинговый центр Interface Ltd.,
тел. (095) 135-5500, 135-2519,
mail@interface.ru
Interface Ltd.