Using reports in run-time packages
Hi,
I had a report that was very long to generate. According to Nard Moseley,
using Delphi event-handler are faster than RAP event-handler, so I built a
run-time package and put every RAP code in event-handlers.
-Run-Time Package
- DataModuleReport (TDataModuleReport)
- Report (TppReport)
I have a exported function "GetModuleClass", that returns the TDataModule
descendant class.
interface
type
TDataModuleClass = class of TDataModule;
TDataModuleReport = class(TDataModule)
...
...
function GetModuleClass: TDataModuleClass; stdcall;
implementation
{$R *.dfm}
function GetModuleClass: TDataModuleClass;
begin
Result := TDataModuleReport;
end;
exports
GetModuleClass;
initialization
RegisterClasses([TDataModuleReport]);
finalization
UnregisterClasses([TDataModuleReport]);
I load the package, call the package function GetModuleClass and create an
instance of TDataModuleReport, which contains my Report. Then, I retrieve
the Report using FindComponent and bind my DataPipeLine, DataSet and
DataSource... everything seems to work fine, but I get an Access Violation
after a few seconds on an OnCalc event.
I don't expect anybody to solve my problem, but I just would like to have
some feedback from people that used run-time packages for report deployment.
The main goal of this is to reduce the exe size and avoiding to always
rebuild my application. Thanks!
David Caouette
I had a report that was very long to generate. According to Nard Moseley,
using Delphi event-handler are faster than RAP event-handler, so I built a
run-time package and put every RAP code in event-handlers.
-Run-Time Package
- DataModuleReport (TDataModuleReport)
- Report (TppReport)
I have a exported function "GetModuleClass", that returns the TDataModule
descendant class.
interface
type
TDataModuleClass = class of TDataModule;
TDataModuleReport = class(TDataModule)
...
...
function GetModuleClass: TDataModuleClass; stdcall;
implementation
{$R *.dfm}
function GetModuleClass: TDataModuleClass;
begin
Result := TDataModuleReport;
end;
exports
GetModuleClass;
initialization
RegisterClasses([TDataModuleReport]);
finalization
UnregisterClasses([TDataModuleReport]);
I load the package, call the package function GetModuleClass and create an
instance of TDataModuleReport, which contains my Report. Then, I retrieve
the Report using FindComponent and bind my DataPipeLine, DataSet and
DataSource... everything seems to work fine, but I get an Access Violation
after a few seconds on an OnCalc event.
I don't expect anybody to solve my problem, but I just would like to have
some feedback from people that used run-time packages for report deployment.
The main goal of this is to reduce the exe size and avoiding to always
rebuild my application. Thanks!
David Caouette
This discussion has been closed.
Comments
The idea behind packages is that you separate the classes (i.e. code) into
discreet compilable units (packages). However, there is usually not a .dll
style export function required.
You simply build your application with the 'build with runtime' packages
option enabled and it will build the smaller .exe.
The challenge is organizing the code into packages. No unit should ever be
compiled into more than one package. And units compiled into the .exe should
not be included any packages.
When package B contains units that 'use' classes defined in package A, then
package B 'requires' package A. The .pas units use the standard Delphi
'uses' clause approach.
Simple example:
I create a new unit called myClass and add ppClass to the 'uses' clause.
ppClass is a ReportBuilder unit included in the rbRCL package.
Therefore if I compile myClass into myPackage.dpk, then it will 'require'
rbRCL.
If I use myClass in myApp, then I should build with run-time packages of
myPackage and rbRCL.
--
Nard Moseley
Digital Metaphors Corporation
http://www.digital-metaphors.com
Best regards,
Nard Moseley
Digital Metaphors
www.digital-metaphors.com
thanks for the example. The way I've built the package is that it can be
dynamically loaded on report demand and unloaded afterward. I've tried to
use a kind of "plug-in" approach. Thanks for your answer.
David
For a plug-in, a typical approach would be to have the plug-in make one or
more registration calls in the Initialization section of the unit. You see
this quite a bit in our code. For an example see RBuilder\Demos\RCL.
You typically declare an abastract ancestor class and a class factory
PlugInHost.pas
----------------
TmyPluginClass - abstract ancestor
TmyPluginFactory - class factory.
The create your plug-in descendant class that will implement the
functionality (and can be placed in a separate package).
FirstPlugIn.pas
-----------------
TmyFirstPlugin - descendant that resides in a different package
Initialization
TmyPlugInFactory.Register(TMyFirstPlugin);
Finalization
TmyPlugInFactory.UnRegister(TMyFirstPlugin);
--
Nard Moseley
Digital Metaphors Corporation
http://www.digital-metaphors.com
Best regards,
Nard Moseley
Digital Metaphors
www.digital-metaphors.com
I think I misexplained what I was trying to do. My application is actually
distributing report templates. TppDBPipeLine, TDataSource and our custom
TDataSet descendant are created and executed on-the-fly, based upon report;
ex: Master - Subreport = 2 dbpipeline, 2 dataset
Master(section), Master - SubReport = 3 DBPipeLine, 3 dataset
Everything is working fine, except that now, I have some huge reports with a
lot of event-handlers (at least 70). You suggested me to build a Delphi
event-handler version instead of RAP event-handler, because it's faster. The
problem is that I don't want to include this report in a unit that is
statically linked to my application, so, I use run-time packages.
But, each time I would need to design a new report in a package, I would
need to rebuild my application using "Build with run-time packages",
including my report run-time package. So, I just built my application using
ReportBuilder run-time packages and I load my run-time package dynamically
using LoadPackage function. That's what I meant by "plug-in approach". Maybe
I should have said "modular approach".
Thanks anyway for your answer, I for sure will have to use it sooner or
later.
David Caouette