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

Loose of datasource

edited December 2001 in General
I saved a report (with one subreport in it) to a template-file. Afterwards I
reloaded it (within code) and then the datasources of all fields aren't set
any more - maybe it's because I'm creating the report and its pipelines by
hand?

BTW where do I find the tips & tricks or other technical tips? In the
newsgroup I can only see 2 posts so I'd like to have a resource for more
information.

Any ideas?

TIA,
Helge.

Comments

  • edited December 2001
    Hi Helge,

    Change your news settings. There is an option to delete a message after x
    days, increase that value and reset the group to receive the messages once
    more.

    regards,
    Chris Ueberall;

  • edited December 2001
    > Change your news settings. There is an option to delete a message after x

    Ok, that worked - thanks!

    Do you have also a solution to my problem?

    Helge.
  • edited December 2001
    I haven't found a solution yet so I post a bit of source code here - maybe
    someone has an idea...

    TSpooler = class(TThread)
    constructor Create(CreateSuspended: Boolean);
    destructor Destroy; override;

    procedure UpdateStatus;
    procedure GetNextItem;
    procedure PrintItem;
    procedure Execute; override;

    private
    ActEntry : TSpoolEntry;

    public
    RBuilderContainer : TComponent;
    MasterTable : TDbf;
    MasterSource : TDataSource;
    MasterPipeline : TppDBPipeline;
    DetailTable : TDbf;
    DetailSource : TDataSource;
    DetailPipeline : TppDBPipeline;
    Report : TppReport;
    ReportDesigner : TppDesigner;
    end;

    constructor TSpooler.Create(CreateSuspended: Boolean);
    begin
    inherited Create(true);

    RBuilderContainer := TComponent.Create(nil);
    MasterTable := TDbf.Create (RBuilderContainer);
    MasterSource := TDataSource.Create (RBuilderContainer);
    MasterPipeline := TppDBPipeline.Create (RBuilderContainer);
    DetailTable := TDbf.Create (RBuilderContainer);
    DetailSource := TDataSource.Create (RBuilderContainer);
    DetailPipeline := TppDBPipeline.Create (RBuilderContainer);
    Report := TppReport.Create (RBuilderContainer);

    Report.DeviceType := dtScreen;

    ReportDesigner := TppDesigner.Create (RBuilderContainer);
    ReportDesigner.Caption := 'Beleg-Designer';
    ReportDesigner.Report := Report;

    MasterTable.ReadOnly := true;
    MasterTable.OpenMode := omAutoCreate;
    MasterTable.FilePath := DataPath;
    DetailTable.ReadOnly := true;
    DetailTable.OpenMode := omAutoCreate;
    DetailTable.FilePath := DataPath;

    MasterSource.DataSet := MasterTable;
    DetailSource.DataSet := DetailTable;
    MasterPipeline.DataSource := MasterSource;
    MasterPipeline.UserName := 'Hauptdatenstrom';
    DetailPipeline.DataSource := DetailSource;
    DetailPipeline.UserName := 'Detaildatenstrom';

    if not CreateSuspended then Resume;
    end;

    destructor TSpooler.Destroy;
    begin
    ReportDesigner.Free;
    Report.Free;
    DetailPipeline.Free;
    MasterPipeline.Free;
    DetailSource.Free;
    DetailTable.Free;
    MasterSource.Free;
    MasterTable.Free;

    inherited;
    end;

    procedure TSpooler.PrintItem;
    begin
    try
    Synchronize(UpdateStatus);
    except
    on e:Exception do MessageDlg (e.ClassName+#13+e.Message, mtError,
    [mbOk], 0);
    end;
    MasterTable.TableName := ActEntry.SpoolingNumber + '-master.dbf';
    DetailTable.TableName := ActEntry.SpoolingNumber + '-detail.dbf';
    if not FileExists (DataPath + '\' + DetailTable.TableName) then
    DetailTable.TableName := '';

    try
    Report.Template.FileName := TemplatePath + ActEntry.BelegFormular +
    '.rtm';
    Report.Template.LoadFromFile;
    except
    on E:Exception do
    MessageDlg ('Vorlage nicht gefunden!'+#13+e.ClassName+#13+e.Message,
    mtError, [mbOk], 0);
    end;
    try
    Report.PrinterSetup.PrinterName := 'Screen';
    Report.DataPipeline := MasterPipeline;

    if not ActEntry.DesignMode then
    Synchronize (Report.Print)
    else
    Synchronize (ReportDesigner.ShowModal);

    except
    on E:Exception do
    MessageDlg ('Druckvorgang fehlgeschlagen'+#13+e.ClassName+#13+e.Message,
    mtError, [mbOk], 0);
    end;
    end;

    My first thoughts were that the whole system might get in trouble when not
    having a valid parent so I came to the solution with the TComponent...

    My problem is that no matter if the Designer or the Preview is shown, all
    fields on the report loose their datasource ... I create the rtm-files with
    the Designer and save them - it is always the same table (or better: with
    the same content) and as soon as I set "Hauptdatenstrom" in the Designer as
    each field's datasource, all data is shown correctly. So it isn't the proble
    with the datalink itself - it's only that the ReportBuilder doesn't connect
    the datasources from the template properly.

    I got the hint to look in the Developers Guide but I have two differences:
    1. I'm using a template and don't create all by hand and 2. I'm in a thread
    (if that matters so much).

    Has anybody an idea? I need it quick, if possible!

    BTW I use Delphi 5 with SP1, RB 6.02 Enterprise Demo on Windows XP final -
    German versions.

    TIA,
    Helge.
  • edited December 2001
    The datapipelines just need to be reassigned to the report and subreports.
    Rb will search all of the forms and datmodules inthe application, looking
    for data pipelines by name.

    When you save a report, it saves a string property for the datapipeline
    name. (This was done to fix some Delphi 6 support issues in the Delphi 6
    IDE) In order to resolve the string into a datapipeline object reference,
    RB performs this search of the application for visible datapipeline objects.
    If none can be found, then the datapipeline refernce isn't going to get set,
    and this is probably the behavior you are getting.

    I think that RB is not able to find the datapipelines since they are owned
    by a TComponent instance with a nil owner. You'll need to manually assign
    the datapipeline's to the report, after you load a template. You can loop
    through the report looking for subreport components, in order to hook their
    datapipeline property up, also. There is a ReportObjectLoop article in the
    TechTips newsgroup in the CodeBased thread. You'll need to check if a
    report Object is TppSubreport in that example. The data aware controls
    should be automatically reassigned to the datapipeline when the
    report/subreport is reconnected.


    Cheers,

    Jim Bennett
    Digital Metaphors


  • edited December 2001
    > I think that RB is not able to find the datapipelines since they are owned

    Do I understand you right? If I make them all a owner of Application, RB
    will find them?

    their
    the

    Ok, but I've sometimes more than one pipelines - I can't decide which one is
    the right one for every control :-(

    But thanks for the explanation, I'll try it out in a second...

    Helge.
  • edited December 2001
    I should say, that normally, a form or datamodule is the datapipeline's
    owner.


    Cheers,

    Jim Bennett
    Digital Metaphors


  • edited December 2001
    > Do I understand you right? If I make them all a owner of Application, RB

    It works! It works! I could kiss you ;-)

    Many, many thanks for the hint! I though about that, too - the reason why
    that container was there... but I thought the report iterate from bottom to
    top but it it does it the other way around which is indeed more logical *g*
    So it was somehow my fault (as I assumed before)...

    Thanks again,
    Helge.
This discussion has been closed.