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

Dynamic auto-configured subreports( looong <g> )

edited December 2003 in Subreports
Hello everybody,

Scenario:

MDI App, where I need to add reports.
I created an MDI Child form which will hold a ppViewer, coupled with a
ppReport.

Now, I have several reports to be shown, and I wanted to use a report as
template,
then just load the child reports dynamically accordingly to my need.

The idea is to have a singleton list all the "child" reports will be
registered to, which
will be iterated through dinamycally at app's startup.

The main problem here is that some parts of my template can be themselves
sub-reports.

To give you an extended idea of what I'm doing, here's source code:

unit uSingleton;

interface

Type

TSingleton = class
protected
function CanCreate : Boolean;virtual;abstract;
public
constructor Create;virtual;
end;

implementation

uses SysUtils;

{ TSingleton }

constructor TSingleton.Create;
begin
inherited Create;
if Not CanCreate then
begin
raise Exception.Create( 'Singleton already exists' );
end;
end;

end.

Then I created a singleton report list:

unit uReportList;

interface

uses Contnrs, uSingleton, uReportItem;

Type

TReportList = class( TSingleton )
private
FList : TObjectList;
function GetReport(Index: Integer): TReportItem;
protected
function CanCreate : Boolean;override;
public
constructor Create;override;
destructor Destroy;override;

procedure AddReport( Rpt : TReportItem );

property Reports[ Index : Integer ] : TReportItem read GetReport;
end;

function ReportList : TReportList;

implementation

var _ReportList : TReportList;

function ReportList : TReportList;
begin
if Not Assigned( _ReportList ) then
begin
_ReportList := TReportList.Create;
end;
Result := _ReportList;
end;

{ TReportList }

procedure TReportList.AddReport(Rpt: TReportItem);
begin
FList.Add( Rpt );
end;

function TReportList.CanCreate: Boolean;
begin
Result := Not Assigned( _ReportList );
end;

constructor TReportList.Create;
begin
inherited;
FList := TObjectList.Create( True );
end;

destructor TReportList.Destroy;
begin
FList.Free;
inherited;
end;

function TReportList.GetReport(Index: Integer): TReportItem;
begin
Result := TReportItem( FList.Items[ Index ] );
end;

end.

The TReportItem class is defined here:

unit uReportItem;

interface

Type

TReportItem = class
private
FDescription: String;
procedure SetDescription(const Value: String);
public
constructor Create;virtual;
property Description : String read FDescription write SetDescription;
end;

implementation

{ TReportItem }

constructor TReportItem.Create;
begin
Inherited Create;
FDescription := '';
end;

procedure TReportItem.SetDescription(const Value: String);
begin
FDescription := Value;
end;

end.

The TReportItem class still lacks a field, which will be a class reference
for
children reports. There's in this, for me, a doubt: how should I handle it?
The problem relies in the fact that some reports can also be a part of the
report template to use AND be used as child reports.
I was thinking that the best option was to use interfaces to implement in
the
form and use a class reference to hold them, while at runtime using
different
interfaces to make them behave as I want, but I'm unsure if it wouldn't be
better to
have a base form which would "represent" the report and child forms which
would be
"seen" as actual reports... Any insight on this?

Now, I have a child form to view reports, defined as follows:

unit RepShowCode;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
BaseChildCode, Buttons, ExtCtrls, ComCtrls, ppViewr, ppDB, ppDBPipe,
ppComm, ppRelatv, ppProd, ppClass, ppReport, ppDBJIT, Db;

type
TRepShowFrm = class(TBaseChildFrm)
PnlToolBar: TPanel;
PrintBtn: TSpeedButton;
Viewer: TppViewer;
StatusBar1: TStatusBar;
InternalReport: TppReport;
InternalPipeline: TppDBPipeline;
InternalDS: TDataSource;
procedure FormShow(Sender: TObject);
private
FLogoFileName: String;
FTitle: String;
FTitleFont: TFont;
procedure SetLogoFileName(const Value: String);
procedure SetTitle(const Value: String);
procedure SetTitleFont(const Value: TFont);
{ Private declarations }
public
{ Public declarations }
property Title : String read FTitle write SetTitle;
property TitleFont : TFont read FTitleFont write SetTitleFont;
property LogoFileName : String read FLogoFileName write SetLogoFileName;
end;

var
RepShowFrm: TRepShowFrm;

implementation

{$R *.DFM}

{ TRepShowFrm }

procedure TRepShowFrm.SetLogoFileName(const Value: String);
begin
FLogoFileName := Value;
end;

procedure TRepShowFrm.SetTitle(const Value: String);
begin
FTitle := Value;
end;

procedure TRepShowFrm.SetTitleFont(const Value: TFont);
begin
FTitleFont := Value;
end;

procedure TRepShowFrm.FormShow(Sender: TObject);
begin
inherited;
Viewer.Report.PrintToDevices;
end;

end.

This one is yet to be completed, I'm unsure how I should handle the
sub-reports.
I know how to handle them technically but not conceptually. I want something
that can be easily modified and updated even if I'm not working on it( I'll
leave by
the end of the year and would like to create something easily modifiable )

Get the mess now?

Any hints on how I can make the whole thing straight-forward?

I was thinking to using interfaces, but I think it would become
quite difficult to catch conceptually and if you don't know
interfaces too good( which it may be for my colleagues ), it can
become messy.

TIA,

Andrew

Comments

  • edited December 2003

    Not sure that I completely understand, but it sounds like it is
    hierarchical:

    1. List of reports that can be printed as top level reports. These are the
    ReportItems.

    2. Each report in number 1 above, can itself contain subreports. Therefore
    the ReportItem should have a list of the childreports that it uses.




    --
    Nard Moseley
    Digital Metaphors
    http://www.digital-metaphors.com

    Best regards,

    Nard Moseley
    Digital Metaphors
    www.digital-metaphors.com
  • edited December 2003
    Nard Moseley (Digital Metaphors) wrote:

    Kind of, yeah.


    Not really.

    There's a series of hierarchical hard-coded templates and several dynamic
    "child reports". Some parts of the template can then become "child reports"
    themselves, using a lower-featured template.


    The point is exactly this: they cannot be determined at any time, the
    templates will be invoked from a menu item( or an action ) and then
    they'll be filled by the menu handler with the corresponding child report
    which will be the "detail" band of the report template.

    HTH understanding,

    Andrew
  • edited December 2003

    I still do not understand. I need a more concrete example. Can you describe
    a couple of the reports - how they are structured, whether they reside on a
    form/datamodule or are stored as .rtm files or are stored in a database.

    Somewhere there must the concept of some fundamental building blocks that
    can be dyamically combined into reports.

    You must know what the building blocks are, because you build a list of menu
    items. Correct?





    --
    Nard Moseley
    Digital Metaphors
    http://www.digital-metaphors.com

    Best regards,

    Nard Moseley
    Digital Metaphors
    www.digital-metaphors.com
  • edited December 2003
    Nard Moseley (Digital Metaphors) wrote:

    Ok.

    I'm writing an E-Commerce Web application with a Delphi client, ok?

    In this application I need to handle reports( orders, clients, etc ), but I
    want to be able to handle company info, for example, to make small
    pamphlets to distribute - for example.

    Thus, I have a template like this:
    ------------------------------------------------------------------
    | (logo) TITLE
    (shop info) |
    ------------------------------------------------------------------
    | Detail 1
    |
    | Detail 2
    |
    | etc...
    |
    -----------------------------------------------------------------
    | Footer
    |
    -----------------------------------------------------------------

    Now, Detail1,2, etc are "part" of the child report.

    Now, say I want to make a report which looks like this:

    -----------------------------------------------------------------
    | SLOGAN
    |
    -----------------------------------------------------------------
    | (logo)
    |
    | (shop info)
    |
    | Advertisment text
    |
    -----------------------------------------------------------------
    | Footer
    |
    -----------------------------------------------------------------

    Now you can see that the parts of the template in the first
    report, now act as child reports in the detail section of the
    second kind.

    That's what I mean :-)

    Rgds,

    Andrew
  • edited December 2003

    Okay so now explain structurally in RB how this is currently modelled.


    For example, the layout for Report1 looks like this?

    main
    titleband
    detailband
    subreport1 - pbChild
    footerband

    And the layout for Report2 looks like this?

    main
    titleband
    detailband
    subreport1 - pbSection - loads Report1 template?
    footerband




    --
    Nard Moseley
    Digital Metaphors
    http://www.digital-metaphors.com

    Best regards,

    Nard Moseley
    Digital Metaphors
    www.digital-metaphors.com
  • edited December 2003
    Nard Moseley (Digital Metaphors) wrote:

    Kinda :-)

    main

    ( template part 1 ) title ( template part 2 )

    detailband
    subreport1 - pbChild
    footerband


    Nope, it's like this:

    main
    titleband
    detailband
    message
    template part 1
    footerband
    template part 2

    Cheers,

    Andrew
  • edited December 2003

    I would model it as follows:

    1. Template1

    Create as a separate report. Then save it to an .rtm file or database table

    2. Template1

    Create as a separate report. Then save it to an .rtm file or database table.

    3. Report1

    Create layout such that Template1 and Template2 are dynamically loaded at
    run-time.

    4. Report2

    Create layout such that Template1 and Template2 are dynamically loaded at
    run-time.








    --
    Nard Moseley
    Digital Metaphors
    http://www.digital-metaphors.com

    Best regards,

    Nard Moseley
    Digital Metaphors
    www.digital-metaphors.com
This discussion has been closed.