views:

55

answers:

1

Hi,

is it possible to execute a crystal report (TCrpe component) from a Delphi non VCL main thread when Output = toWindow?

  • I execute reports from a background thread, and when Output is toPrinter or toExport, everything is fine.
  • I know that creating forms in a Delphi non VCL main thread generally is a bad idea.
  • When a Crystal Report is executed, and Output=toWindow, the component creates the output window on its own. So I cannot prevent that the window is created by the background thread.
  • So is there a clean way to execute the report in a background thread, and display the result in a cleanly created form?
  • Version: Crystal11VCL7

The following code does not work:

procedure TMyThread.Execute;
var
  cr: TCrpe;
begin
  inherited;
  cr:= TCrpe.Create(nil);
  cr.ReportName:= 'C:\TestReport.rpt';
  cr.Output:= toWindow;
  cr.WindowParent:= Form1; //This is the main form
  cr.Execute;
end;
  • It seems like the report will be created and immediately destroyed afterwards.
  • When I enter a message loop right after cr.Execute (while true do Application.ProcessMessages; - which is obviously a very bad idea), the report window is shown nicely.

Any idea, how to do it right? Or is it simply not possible? Thanks!

+1  A: 

I haven't had any experience with Crystal for many years (thank goodness) but in the absence of any other reply I would consider approaching the problem from a different angle.

What I do is let the report form be created in the main thread - because, as you've said, it's not a good idea to do the VCL stuff in the background - but I generate all report /data/ in a background thread. Once the data is loaded then the thread signals the main form (or whatever) via a windows message and the report goes and connects up to the dataset/datasource.

Initially I display a blank label over the client area of the report window with a message saying something like 'Report loading...' then once the message is received it hides the label and attaches the data. Works really well here and keeps the UI responsive.

shunty
Thanks, sounds good. However, the form is automatically created and then populated with data by the report component. Unfortunately I cannot execute the report (in background) and then put its result into my form afterwards.
nang
Ok. But surely you must have some control over the data that is supplied to the report component? Does it use the 'Delphi way' of [DB -> dataset -> datasource -> report]. Could you, perhaps, give it a dummy/empty query result then populate the correct query in the background then replace dataset and/or datasource references when ready (along with an appropriate refresh of the report)? I do, of course, appreciate, that Crystal may not work like this.
shunty
No, unfortunately not. When the report component executes the report it creates its own database connection and pulls the data. The only thing I pass to the report component is the report file name and some parameters, which are used within the report as query parameters.
nang
Hmmm, I'm at a loss for the moment then. I suppose you could write a separate "Reporting App" which ran the reports and you call it, along with appropriate parameters, from your main app. I'm trying desperately hard not to say something like "ditch Crystal and get something with far more control like FastReport (my favourite) or ReportBuilder". But it's not very helpful and that wasn't the question so I won't say it ;-)
shunty