Home Subreports
New Blog Posts: Merging Reports - Part 1 and Part 2

Dynamic subreport loading...take it to the limit!

edited March 2003 in Subreports
I'd like to invite to a general discussion on an issue I think has a great
potential.

It seems dynamic subreport loading (DSL), as explained in the
"RBuilder\Demos\3. EndUser\5. Dynamic Subreport Loading" directory, is
becoming increasingly popular. With good reason, because I have found it to
be a great help in building complex reports. I use the technique very
extensively in my apps - I have created about 60 "report components" that I
load dynamically into 140 different main reports, achieving effects that I
could never dream of without DSL.

Anyway, it seems DSL has changed a bit from RB6 to RB7. After I upgraded, my
reports started crashing with AV errors, until I found it is now required to
include the following lines after loading the template:

Subreport.Report.Engine.State := Report.Engine.State - [esInitialized];
Subreport.Init;

So I have these questions:

- Are there other changes to DSL from RB6 to RB7 that we should be aware of,
than the new need for the above Init operation?

Comments

  • edited March 2003
    We're glad you like this capability so much!

    The two lines of code change was all that is needed to convert the
    subreports to work in RB 7 from RB 6. The conversion code stems from the
    changes we made while we were fixing bugs and making the report engine
    threadsafe.


    Cheers,

    Jim Bennett
    Digital Metaphors


  • edited March 2003
    DSL offers some very nice things. We use it e.g. to have common headers and
    footers on our reports, being maintained separately and loaded at runtime.
    Below there is the component which does this. Just drop the
    supreport-component on the report and assign the name of the report you want
    to have loaded at runtime to the edit field where you usually enter the
    caption text.

    Works like a charm :-)

    Bernd


    unit SubreportSOF;

    interface

    uses
    Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
    IniFiles, ppClass, ppBands, ppSubRpt,
    ppTypes, ppVar, ppCtrls;

    type
    TBafSubReport = class(TppSubReport)
    private
    FAutomatedLoad : Boolean;
    FTemplateName : String;
    procedure LoadSubreport;
    protected
    function GetTemplateName : string;
    procedure SetTemplateName(Value: string);
    function GetCaption : string; override;
    public
    constructor Create(aOwner: TComponent); override;
    destructor Destroy; override;
    procedure Generate; override;
    procedure StartOfMainReport; override;
    published
    property AutomatedLoad : Boolean read FAutomatedLoad write
    FAutomatedLoad default True;
    property TemplateName : string read GetTemplateName write
    SetTemplateName;
    end;

    implementation

    {$R SubreportSOF.res}

    // -- Create
    constructor TBafSubReport.Create(aOwner: TComponent);
    begin
    inherited Create(aOwner);
    FAutomatedLoad:=True;
    DefaultPropName:='TemplateName';
    DefaultPropEditType:=etEdit;
    end;

    // -- Destroy
    destructor TBafSubReport.Destroy;
    begin
    inherited Destroy;
    end;

    // -- Generate
    procedure TBafSubReport.Generate;
    begin
    Report.AutoStop:=True;
    inherited Generate;
    end;

    // -- LoadSubreport
    procedure TBafSubReport.LoadSubreport;
    begin

    Report.Template.FileName:=ExtractFileDir(Report.MainReport.Template.FileName
    )+'\'+FTemplateName;
    Report.Template.LoadFromFile;

    Report.PrinterSetup.DocumentName:=Band.Report.MainReport.PrinterSetup.Docume
    ntName;
    Report.Engine.State := Report.Engine.State - [esInitialized];
    Init;
    end;

    // -- StartOfMainReport
    procedure TBafSubReport.StartOfMainReport;
    begin
    inherited StartOfMainReport;
    if (AutomatedLoad) and not (Overflow) then begin
    LoadSubreport
    end;
    end;

    // -- SetTemplateName
    procedure TBafSubReport.SetTemplateName(Value: string);
    begin
    if FTemplateName<>Value then begin
    FTemplateName:=Value
    end;
    end;

    // -- GetTemplateName
    function TBafSubReport.GetTemplateName : string;
    begin
    Result:=FTemplateName;
    end;

    // -- GetCaption
    function TBafSubReport.GetCaption : string;
    begin
    Result:='Runtime template';
    end;

    initialization
    ppRegisterComponent(TBafSubReport, 'Demo Components', 0, 0, 'Runtime
    template', 0);

    finalization
    ppUnRegisterComponent(TBafSubReport);

    end.
This discussion has been closed.