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

Why RB don't introduce an oleobject component?

edited September 2002 in Component Writing
Hi,

I have a look the FastReport component in these days. Compare with RB, I
find the most interesting component RB don't have is the OleObject
component. FastReport can insert any Ole Object from OleContainer into the
report. That means end-user can import any graph of Excel, Word ... into
the report. It's quite cool. Is it possible DM add this feauture into RB?
Or how I can create my own OleObject RCL component?

Cheers,

Tao

Comments

  • edited September 2002
    I try to write my own RCL OleObject component. And I can't find a way to
    save the OleContainer's Stream into Report Template file when I call
    ppReport1.Template.Save.

    My code is like this:

    TtlOleObject = class(TppCustomImage)
    ...
    published
    property OleStream: TMemoryStream read GetOleStream write SetOleStream;
    end;

    procedure TpptlObject.OleEditMenuClick(Sender: TObject);
    begin
    if (Band = nil) or (Band.Report = nil) then Exit;
    begin
    FDialog.ShowModal;
    PictureChanged(Self);
    PropertyChange;
    if FDialog.OleContainer1.OleObjectInterface <> nil then
    FDialog.OleContainer1.SaveToStream(FOleStream); // Here put the
    OleContainer object into a memory stream
    end;
    end;

    And I have read the "Tech Tip: Storing Custom Information with Templates".
    It looks like RB just can save the fixed size stream into the Template
    header. But how about the unknown size stream?

    Cheers,

    Tao

  • edited September 2002
    Hi Tao,

    to save any non-published data into the component's storage you have to
    override 'DefineProperties'.
    Using the templates custom storage isn't the right place for storing
    component properties.

    HTH,
    Chris Ueberall;

  • edited September 2002
    Hi, Chris

    Thanks for your help. Now I copy the Delphi 'DefineProperties' help code,
    and change like follow:

    type
    TppOleObject = class(TppCustomImage)
    ....

    constructor TppOleObject.Create(AOwner: TComponent);
    begin
    inherited;
    FBitmap := TBitmap.Create;
    Picture.Bitmap := FBitmap;

    FDialog := TFrmOleObjectDlg.Create(Self);

    FOleContainer := TOleContainer.Create(Self);
    with FOleContainer do
    begin
    Parent := FDialog;
    Visible := False;
    Name := 'XXX';
    AllowInPlace := False;
    AutoVerbMenu := False;
    BorderStyle := bsNone;
    SizeMode := smClip;
    end;
    end;

    procedure TppOleObject.LoadCompProperty(Reader: TReader);
    begin
    if Reader.ReadBoolean then
    // OleContainer := Reader.ReadComponent(nil);
    OleContainer := TOleContainer(Reader.ReadComponent(nil));
    end;

    procedure TppOleObject.StoreCompProperty(Writer: TWriter);

    begin
    Writer.WriteBoolean(OleContainer <> nil);
    if OleContainer <> nil then
    Writer.WriteComponent(OleContainer);
    end;

    procedure TppOleObject.DefineProperties(Filer: TFiler);

    function DoWrite: Boolean;
    begin
    if Filer.Ancestor <> nil then { check Ancestor for an inherited value }
    begin
    if TppOleObject(Filer.Ancestor).OleContainer = nil then
    Result := OleContainer <> nil
    else if (OleContainer = nil) or
    (TppOleObject(Filer.Ancestor).OleContainer.Name <>
    OleContainer.Name) then
    Result := True

    else Result := False;
    end
    else { no inherited value -- check for default (nil) value }
    Result := OleContainer <> nil;
    end;
    begin
    inherited; { allow base classes to define properties }

    if (FDialog.OleContainer1.OleObjectInterface <> nil) then
    begin
    FDialog.OleContainer1.Copy;
    FOleContainer.Paste;
    end;


    Filer.DefineProperty('OleContainer', LoadCompProperty, StoreCompProperty,
    DoWrite);
    end;

    I can save the Report Template as Txt and the result like this:

    object ppOleObject1: TppOleObject
    UserName = 'OleObject1'
    MaintainAspectRatio = False
    Picture.Data = {07544269746D617000000000}
    Dialog = ppOleObject1.FrmOleObjectDlg
    mmHeight = 52388
    mmLeft = 75936
    mmTop = 12700
    mmWidth = 56092
    BandType = 4
    OleContainer = True
    TOleContainer = Null
    Left = 0
    Top = 0
    Width = 121
    Height = 121
    Caption = 'XXX'
    AllowInPlace = False
    AutoVerbMenu = False
    BorderStyle = bsNone
    TabOrder = 2
    Visible = False
    end

    I don't understand why the OleContain don't save as other objects like

    object OleContainer: TOleContainer
    ...

    Of course, I can read the report template back form the ppDesigner. It
    return a 'Read Stream error' exception.

    Could you tell me what's wrong with my code, please?

    Many thanks!

    Tao

  • edited September 2002
    Hi tao,

    I think you should use the same technique as when storing an OLE-object in a
    database. Use the streaminig methods of the component, see your own
    'TMemoryStream' example. You have to change the 'StoreCompProperty' and
    'LoadCompProperty' methods.

    HTH,
    Chris Ueberall;

  • edited September 2002
    It looks like I can not store the Ole-object into template together, doesn't
    it? At first, I have thinked about store the Oleobject in a blod field.
    But just try to make it easy for our support people can just copy a report
    template file to the customer and export oleobject from table and import the
    oleobject into the database again.

    Many thanks!!

    Tao

This discussion has been closed.