usar - ¿Cómo puedo mostrar los informes de Crystal XI dentro de una aplicación Delphi 2007?
tutorial crystal reports (5)
El componente más reciente de Crystal XI para Delphi fue lanzado para Delphi 7. Ese componente de VCL se compila en D2007, pero me da errores en tiempo de ejecución. ¿Cuál es la mejor manera de mostrar Crystal Report conectado a una base de datos en una aplicación Delphi 2007?
Sé que no es su pregunta y puede que no sea una respuesta aceptable en su situación, pero he encontrado que FastReports es claramente superior a Crystal para mis propósitos. Es más ligero, incluye un lenguaje de secuencias de comandos real, incorpora manejo de eventos, puede realizar llamadas a su código nativo para obtener información y actualizaciones, y no requiere una conexión ActiveX. Puedo exportar mis informes a archivos PDF de aspecto nítido, hojas de cálculo de Excel y muchos otros formatos. La calidad del resultado se suma a la experiencia general que los usuarios obtienen de mi aplicación. Podría continuar, pero si está fuera de tema para ti, no será útil.
Por el bien de cualquier otra persona que pueda usarlo, aquí hay una clase completa que ofrece una envoltura agradable alrededor de estas viles interacciones con Crystal. Funciona para mí aproximadamente el 80% del tiempo, pero sospecho que muchas de estas cosas dependen mucho de la plataforma específica en la que se ejecutan. Publicaré las mejoras a medida que las hago.
Alguien en Business Objects realmente debería echarle un vistazo a esta API. Apesta bastante mal.
{
Class to facilitate the display of Crystal 11 Reports.
The Crystal 11 VCL component does not seem to work with Delphi 2007.
As a result, we have to use ActiveX objects, which make deployment messy.
This class is similar to CrystalReporter, but it works for Crystal 11.
However, it lacks some of the features of the old CrystalReporter.
Refer to the crystal reports activex technical reference to duplicate the
missing functionality.
Example usage is at the bottom of this unit.
//}
unit CrystalReporter11;
interface
uses
CrystalActiveXReportViewerLib11_5_TLB, OleAuto, Classes, Controls;
type
TCryExportFormat = (
XLS
,PDF
);
type
TCrystalReporter11 = class
private
FCryRpt : TCrystalActiveXReportViewer;
FRpt, FApp : variant;
FReportFile, FUsername, FPassword, FServer, FFilters : string;
FOwner : TComponent;
procedure SetLoginInfo(const username, password, server : string);
function GetFilterConds: string;
procedure SetFilterConds(const Value: string);
public
property FilterConditions : string read GetFilterConds write SetFilterConds;
procedure ExportToFile(ExportFileName : string;
FileExportFmt : TCryExportFormat; PromptForOptions : boolean);
procedure Display;
constructor Create(AOwner : TComponent; ReportFile : string); overload;
constructor Create(AOwner : TComponent; ReportFile,
Username, Password, Server : string); overload;
end;
implementation
uses
SysUtils, Forms;
const
//these are taken from pgs 246 and 247 of the technical reference
c_FmtCode_Excel = 29;
c_FmtCode_PDF = 31;
constructor TCrystalReporter11.Create(AOwner: TComponent; ReportFile: string);
begin
inherited Create;
try
FReportFile := ReportFile;
if FileExists(FReportFile) then begin
FOwner := AOwner;
FCryRpt := TCrystalActiveXReportViewer.Create(AOwner);
FApp := CreateOleObject(''CrystalRuntime.Application'');
FRpt := FApp.OpenReport(FReportFile,1);
FFilters := FRpt.RecordSelectionFormula;
end
else begin
raise Exception.Create(''Report file '' + ReportFile + '' not found!'');
end;
except on e : exception do
raise;
end; //try-except
end;
constructor TCrystalReporter11.Create(AOwner: TComponent; ReportFile, Username,
Password, Server: string);
begin
Create(AOwner,ReportFile);
FUsername := Username;
FPassword := Password;
FServer := Server;
SetLoginInfo(FUsername,FPassword,FServer);
end;
procedure TCrystalReporter11.Display;
var
rptForm : TForm;
begin
SetLoginInfo(FUsername,FPassword,FServer);
FCryRpt.ReportSource := FRpt;
rptForm := TForm.Create(FOwner);
try
FCryRpt.Parent := rptForm;
FCryRpt.Align := alClient;
FCryRpt.ViewReport;
rptForm.Position := poOwnerFormCenter;
rptForm.WindowState := wsMaximized;
rptForm.Caption := ExtractFileName(FReportFile);
rptForm.ShowModal;
finally
FreeAndNil(rptForm);
end; //try-finally
end;
procedure TCrystalReporter11.ExportToFile(ExportFileName : string;
FileExportFmt : TCryExportFormat; PromptForOptions : boolean);
begin
case FileExportFmt of
XLS : FRpt.ExportOptions.FormatType := c_FmtCode_Excel;
PDF : FRpt.ExportOptions.FormatType := c_FmtCode_PDF;
end; //case
FRpt.ExportOptions.DiskFileName := ExportFileName;
FRpt.ExportOptions.DestinationType := 1; //file destination
FCryRpt.ReportSource := FRpt;
FRpt.Export(PromptForOptions);
end;
function TCrystalReporter11.GetFilterConds: string;
begin
Result := FFilters;
end;
procedure TCrystalReporter11.SetFilterConds(const Value: string);
begin
FFilters := Value;
if 0 < Length(Trim(FFilters)) then begin
FRpt.RecordSelectionFormula := Value;
end;
end;
procedure TCrystalReporter11.SetLoginInfo(const username, password,
server : string);
var
i : integer;
begin
//set user name and password
//crystal only accepts these values if they are CONST params
for i := 1 to FRpt.Database.Tables.Count do begin
FRpt.Database.Tables[i].ConnectionProperties.Item[''User ID''] := username;
FRpt.Database.Tables[i].ConnectionProperties.Item[''Password''] := password;
try
{
Some reports use direct connections, and others use an ODBC Data Source.
Crystal XI uses a different label to refer to the database name in each
method.
I don''t know how to determine in advance which method is being used, so:
First, we try the direct connection.
If that fails, we try the "data source" method.
Reference: "Crystal Reports XI Technical Reference", pages 41 thru 46;
"Common ConnectionProperties"
}
FRpt.Database.Tables[i].ConnectionProperties.Item[''Server''] := server;
except on E: Exception do
FRpt.Database.Tables[i].ConnectionProperties.Item[''Data Source''] := server;
end;
end;
end;
{
Example usage:
procedure TForm1.btnShowRptDBClick(Sender: TObject);
var
cry : TCrystalReporter11;
begin
cry := TCrystalReporter11.Create(Self,''c:/my_report.rpt'',''username'',
''password'',''server.domain.com'');
try
cry.Display;
finally
FreeAndNil(cry);
end;
end;
}
end.
También me ha decepcionado la falta de esfuerzo de Crystal Reports con respecto a la integración de aplicaciones. Yo uso el RDC, y por lo que entiendo, esto está siendo desaprobado y se está poniendo énfasis en .Net.
Mi aplicación tiene estos archivos en la cláusula uses: CRRDC, CRAXDRT_TLB,
Funciona bien El inconveniente porque es el paso de parámetros. En mi opción, los cuadros de diálogo de parámetros que vienen con el visor son terribles. Así que uso mi propia aplicación Delphi para solicitar parámetros y pasarlos al informe.
Esta es la solución que he encontrado, usando ActiveX:
Primero, registre el control Active X así:
En Delphi, elija Componente -> Importar componente
Haga clic en "Biblioteca de tipos", haga clic en Siguiente
Elija "Crystal ActiveX Report Viewer Library 11.5"
Elija la página de paleta que desee (fui con "Acceso a datos")
Elige una ubicación de importación
Salir del asistente
Agregue la ubicación que eligió a su proyecto Ruta de búsqueda
Ahora este código debería funcionar:
...
uses
CrystalActiveXReportViewerLib11_5_TLB, OleAuto;
...
procedure TForm1.Button1Click(Sender: TObject);
var
cry : TCrystalActiveXReportViewer;
oRpt, oApp : variant;
i : integer;
frm : TForm;
begin
cry := TCrystalActiveXReportViewer.Create(Self);
oApp := CreateOleObject(''CrystalRuntime.Application'');
oRpt := oApp.OpenReport(''c:/my_report.rpt'',1);
for i := 1 to oRpt.Database.Tables.Count do begin
oRpt.Database.Tables[i].ConnectionProperties.Item[''User ID''] := ''username'';
oRpt.Database.Tables[i].ConnectionProperties.Item[''Password''] := ''password'';
end;
frm := TForm.Create(Self);
try
cry.Parent := frm;
cry.Align := alClient;
cry.ReportSource := oRpt;
cry.ViewReport;
frm.Position := poOwnerFormCenter;
frm.ShowModal;
finally
FreeAndNil(frm);
end; //try-finally
end;
procedure TForm1.btnExportClick(Sender: TObject);
var
cry : TCrystalActiveXReportViewer;
oRpt, oApp : variant;
i : integer;
begin
//Export the report to a file
cry := TCrystalActiveXReportViewer.Create(Self);
oApp := CreateOleObject(''CrystalRuntime.Application'');
oRpt := oApp.OpenReport(c_DBRpt,1);
for i := 1 to oRpt.Database.Tables.Count do begin
oRpt.Database.Tables[i].ConnectionProperties.Item[''User ID''] := ''username'';
oRpt.Database.Tables[i].ConnectionProperties.Item[''Password''] := ''password'';
end;
oRpt.ExportOptions.FormatType := 29; //excel 8
oRpt.ExportOptions.DiskFileName := ''c:/output.xls'';
oRpt.ExportOptions.DestinationType := 1; //file destination
//Export(False) => do NOT prompt.
//Export(True) will give runtime prompts for export options.
oRpt.Export(False);
end;
Si utiliza este método, esta referencia (bastante densa) será útil, especialmente porque Intellisense no funciona en objetos Ole como estos.
Editar: El enlace original a la referencia se rompió, así que lo cambié para apuntar a uno nuevo (válido a partir del 15 de diciembre de 2009). Si ese nuevo se rompe, entonces Google debería poder encontrarlo .
Aquí hay una clase más simple y limpia que resuelve el problema muy bien:
Unidad CrystalReports; utiliza Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.OleCtrls, ActiveX, ComObj, Data .DB, Data.Win.ADODB, CrystalActiveXReportViewerLib11_TLB, Vcl.OleServer, CrystalReportsControllersLib_TLB;
type
TCrystalReportForm = class(TForm)
CRV: TCrystalActiveXReportViewer;
procedure DisplayReport;
private
{ Private declarations }
public
{Public declarations }
ReportName : WideString;
ReportCaption : String;
ReportSelectionFormula : WideString;
end;
var
CRXIRuntime : Variant;
implementation
{$R *.dfm}
procedure TCrystalReportForm.DisplayReport;
var
CrystalReport : variant;
i : integer;
begin
CrystalReport := CRXIRuntime.OpenReport(ReportName);
for i := 1 to CrystalReport.Database.Tables.Count do begin
CrystalReport.Database.Tables[1].ConnectionProperties.Item[''User ID''] := ''user'';
CrystalReport.Database.Tables[1].ConnectionProperties.Item[''Password''] := ''password'';
end;
CrystalReport.FormulaSyntax := 0;
Caption := ReportCaption;
CrystalReport.RecordSelectionFormula := ReportSelectionFormula;
CRV.Align := alClient;
CRV.ReportSource := CrystalReport;
WindowState := wsMaximized;
CRV.ViewReport;
ShowModal;
end;
begin
CRXIRuntime := CreateOleObject(''CrystalRuntime.Application'');
end.