¿Cómo puedo mostrar los informes de Crystal XI dentro de una aplicación Delphi 2007?

El componente más reciente de Crystal XI para Delphi fue lanzado para Delphi 7. Ese componente de VCL se comstack 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?

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 .

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 de la salida se sum 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.

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.