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

BDE to IBO conversion

edited October 2007 in End User
Delphi 7, Report Builder 10.06

I am in the process of converting an app, that was designed to utilize the
BDE to access a firebird DB, to utilize IBObjects to access the firebird DB.
I am having some serious issues with my End User Reporting solution after I
have converted it to IBO.

I have another app that was created from the beginning to utilize IBO to
access a firebird DB which works great! So to make sure that I didn't have
any issues with the way I converted the other app to IBO, I decided to
change the DB component of the app that I know works with IBO to the DB of
the app that was previously utilizing the BDE. I receive several errors
that render all existing reports useless.

When I try to design any of the existing reports, open any of the existing
reports, or load from file a report template of any of the reports created
via the BDE app I get the following error message in Delphi:
Project ReportApp.exe raised exception class EReadError with message
'Invalid property value'. Process stopped. Use Step or Run to continue.
This error ocurrs on line 1172 of ppTmplat.pas which is
lReader.ReadComponents(FRoot, nil, LoadCallback);

I then click run in Delphi and get another error message:
Project ReportApp.exe raised exception class EReadError with message
'Error reading RBReport.BeforeAutoSearchDialogCreate:
Invalid property value'. Process stopped. Use Step or Run to continue.

I then click run again and get the previous error (Error reading
RBReport.BeforeAutoSearchDialogCreate: Invalid property value) on an
error/message dialog from the report application.


I decided to try and manually move the report information over by exporting
the dataviews to file and copying the report components into a new report.
When I attampted to import from file the data views of a report that was
created via the BDE app I received the followong error:
Class TdaBDEQueryDataView not found


Is there a way to convert reports created via the BDE (daBDE) to run via IBO
(daIBO)?

Thanks All,
Branden Johnson

Comments

  • edited October 2007
    This article discusess conversion from BDE to ADO, but same concepts apply
    to any conversion...

    -------------------------------------------------
    Tech Tip: Convert BDE Template Dataviews To ADO
    -------------------------------------------------

    Currently when DADE is used to create dataviews, the DatabaseName is stored
    as part of the query definition. (This is consistent with Delphi's approach
    to specifying a database connection for a Query object).

    When you created the reports originally, the daDBBDE.pas BDE DADE plugin was
    used. Now you want to use ADO. You've already changed the
    Designer.Datasettings but this had no effect on the old reports. They still
    try to use the BDE connection. Changing the Designer.DAtaSettings only works
    for new dataviews that are created, because the new query dataviews are
    using the daADO.pas ADO DADE plugin.

    In order to convert the templates from BDE to ADO, at the minimum you have
    to change the database name and the DADE plugin class names that are stored
    in the templates. When a BDE dataview is created, its class type is a
    TdaBDEQueryDataview. When an ADO dataview is created, its class type is
    TdaADOQueryDataview. These class types are stored in the template. These
    have to be changed before the template is loaded into a report.

    First, compare a BDE report template to an ADO report template which both
    connect to the same database table. Save a BDE and an ADO based report
    template to separate ASCII text files. Now compare the dataview definitions.
    Change the TdaBDEQueryDataview class name to TdaADOQueryDataview in the BDE
    template. Change the BDE alias to your ADOConnection object. Then compare
    the table name and field names of the BDE template to the ADO template and
    change them accordingly, removing the .db extension on the table name is
    necessary. Now load the converted BDE template in your ADO end user
    application.

    The first step is to make a backup of all your templates before continuing
    with a programatic approach. You can convert the templates programatically
    by loading the ASCII template files to a TStringList object. Then loop
    through the lines of the list and change the text programatically. You can
    loop through the files in a directory using ppFileUtils.pas calling the
    GetFileNamesForDirectory procedure to load the file names.

    If you have binary report templates, you'll also be able to convert these
    with an extra couple of steps. You can load the binary template file into
    ASCII format, modify it, and then save it back to binary as shown in the
    example links below. Keep in mind the conversion is performed without
    loading the report template into a TppReport.


    This example shows how to load reports stored to the ReportExplorer database
    tables and convert them to ascii text.

    http://www.digital-metaphors.com/tips/EditTemplatesAsText.zip


    This example shows how to convert an .rtm file to asii text


    http://www.digital-metaphors.com/tips/ConvertBinaryTemplateToASCII.zip



    --
    Tech Support mailto:support@digital-metaphors.com
    Digital Metaphors http://www.digital-metaphors.com

    --
    Nard Moseley
    Digital Metaphors
    www.digital-metaphors.com

    Best regards,

    Nard Moseley
    Digital Metaphors
    www.digital-metaphors.com
  • edited October 2007
    Thank you Nard!

    The example worked. I have migrated the code to my app so that I can use
    the a TIBO table and my DB connection to convert the reports. I have also
    combined the procedures LoadTemplate and SaveTemplate so that I can run one
    procedure that will iterate through the report records, load the templates
    into the memo component (memTemplate), convert the template text, and save
    the template back to the DB.

    I am getting an access violation in the line:
    memTemplate.Lines.LoadFromStream(lTextStream);


    I am not sure why I would be getting this access violation? Any ideas?

    Thank you,
    Branden Johnson


    Here is my full code for the procedure:

    procedure TfrmMain.ConvertReportstoIBO1Click(Sender: TObject);
    const
    cReport = 1;
    var
    liItemID: Integer;
    lBinaryStream: TMemoryStream;
    lTextStream: TMemoryStream;
    lWriter: TWriter;
    memTemplate: TMemo;
    I: Integer;
    sLine: String;
    begin
    plItem.Open;
    plItem.First;

    while not plItem.EOF do
    begin
    {check that item type is a report}
    if plItem['Item_Type'] = Ord(cReport) then
    begin
    lBinaryStream := TMemoryStream.Create;
    lTextStream := TMemoryStream.Create;

    try
    {read the binary stream from the database}
    plItem.GetFieldAsStream('Template', lBinaryStream);

    lBinaryStream.Position := 0;

    {convert the binary stream to text}
    ObjectBinaryToText(lBinaryStream, lTextStream);

    lTextStream.Position := 0;

    {load the text stream to the memo control}
    memTemplate.Lines.LoadFromStream(lTextStream);

    {Replace the class declarations and database}
    for I := 0 to memTemplate.Lines.Count - 1 do
    begin
    sLine := memTemplate.Lines[I];

    sLine :=
    AnsiReplaceStr(sLine,'daBDEQueryDataView','daIBOQueryDataView');
    sLine :=
    AnsiReplaceStr(sLine,'TppChildBDEPipeline','TppChildDBPipeline');
    sLine := AnsiReplaceStr(sLine,'dbMain','euDatabase');

    memTemplate.Lines[I] := sLine;
    end;

    {load the memo control to the text stream}
    memTemplate.Lines.SaveToStream(lTextStream);

    lTextStream.Position := 0;

    {convert the binary stream to text}
    ObjectTextToBinary(lTextStream, lBinaryStream);

    lBinaryStream.Seek(0,soFromEnd);
    lWriter := TWriter.Create(lBinaryStream, 1024);

    try
    lWriter.Root := Self;
    lWriter.WriteListEnd;
    finally
    lWriter.Free;
    end;

    lBinaryStream.Position := 0;

    plItem.Edit;

    {load the binary stream from the database}
    plItem.SetFieldFromStream('Template', lBinaryStream);

    plItem.Post;
    finally
    lBinaryStream.Free;
    lTextStream.Free;
    end;
    end;

    plItem.Next;
    end;
    end;

  • edited October 2007
    Never mind Nard, I replaced the data access components in the example and it
    worked fine so then I copied the main form from the example to my app and
    that is working.

This discussion has been closed.