Announcement

Collapse
No announcement yet.

Crystal Reports 9 und RDC (CRDataSource...)

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Crystal Reports 9 und RDC (CRDataSource...)

    Ziel ist unter Delphi 6 temporäre Anwendungsdaten in einen mit Crystal Reports 9 erstellten Report zu schreiben. Im Report werden die Felder mittels einer ttx-Datei (Data Definition File) festgelegt.

    Da die VCL-Wrapper für die Version 9 der Crystal Reports nicht vollständig hinsichtlich ActiveData funkionieren (Delphi-Komponente bei Version 9 dabei aber nicht dafür bestimmt!?), versuchte ich mein Glück mit der RDC-Schnittstelle...

    In einem ttx-File sind zwei String-Felder definiert, die in einen Report eingebunden wurden und eigentlich durch nachfolgenden Code zum Leben erweckt werden sollten:

    <PRE>
    uses CRVIEWER9Lib_TLB, CRAXDDRT_TLB, CrystalDataObject_TLB;

    procedure TfrmMain.Button1Click(Sender: TObject);
    var
    ifcApp : IApplication;
    ifcReport : IReport;
    ifcRowSet: CrystalComObject;
    ifcViewer: TCRViewer9;
    varData: OleVariant;
    begin
    ifcApp := CoApplication.Create;
    ifcReport := ifcApp.OpenReport('Myreport.rpt', crOpenReportByTempCopy);

    ifcRowSet := CoCrystalComObject.Create();
    ifcRowSet.AddField('TEXT1', '');
    ifcRowSet.AddField('TEXT2', '');
    varData := VarArrayCreate([0, 1, 0, 1], varVariant);
    varData[0, 0] := 'Aa';
    varData[0, 1] := 'Bb';
    varData[1, 0] := 'Xx';
    varData[1, 1] := 'Yy';
    ifcRowSet.AddRows(VarArrayRef(varData));
    ifcReport.Database.SetDataSource(ifcRowSet, 3, 1);

    ifcReport.Database.

    ifcViewer := TCRViewer9.Create(self);
    ifcViewer.Parent := self;
    ifcViewer.Align := alClient;
    ifcViewer.ReportSource := ifcReport;
    ifcViewer.ViewReport();
    end;
    </PRE>

    Die übergebenen Daten erscheinen aber leider nicht im Report. Dafür aber die Default-Werte aus dem ttx-File! Übergebe ich ein gefülltes ADO-Recordset erscheinen die Daten...

    Da es mir lieber wäre, dass ich die Daten nicht zunächst noch in ein Crystal-DataObject packen muss versuchte ich eine andere Möglichkeit. Nämlich die der Crystal DataSource Typelibrary. Eine Schnittstelle implementiert und man kann eine Instanz der Implementationsklasse via SetDataSource übergeben. Da meine Datenklasse die meisten geforderten Methoden ohnehin schon enthält wäre das Schreiben eines entsprechenden Wrappers eigentlich die optimale Lösung (da die Daten nicht nochmal in einem extra Data-Objekt ein zweites Mal gespeichert werden), dachte ich mir... Leider kann ich die Typelibrary (CRSOURCE.TLB) in der die Schnittstellendeklaration enthalten sein soll leider nirgends auf meinem Rechner entdecken. In einem anderen Forum hatte jemand das gleiche Problem. Es scheint fast als wäre dies in der Version 9 nicht mehr vorhanden??? Warum ist es dann in der Hilfe beschrieben?

    Bin insgesamt sehr enttäuscht über CR9, obwohl ich unter .Net beisher gute Erfahrungen damit gemacht habe. Aber in diesem Fall scheint nichts zu funktionieren was laut Lieferumfang eigentlich vermutet werden kann...

    Weiß jemand den Fahler in obigem Codefragment, oder weiß jemand ob die CRDataSource 1.0 Type Library in Version 9 noch vorhanden ist oder kennt jemand eine andere Lösung um irgendwelche Daten aus dem Hauptspeicher in den Report zu schreiben...

  • #2
    Hallo,

    ich greife in derartigen Fällen immer auf das gefüllte Recordset-Objekt von ADO zurück. Wenn die Daten nicht direkt aus einer Datenbank stammen, sondern erst vom eigenen Programm befüllt werden, kann man ja eine leere Recordset-Instanz erzeugen und die benötigte Struktur vom Programm anlegen lassen. Wenn das erledigt ist, kann man dann das Ganze mit TADODataSet weiterverarbeiten:

    <pre>

    uses ADOInt, ActiveX, ComObj;

    procedure TFormMain.FormCreate(Sender: TObject);
    var
    aRS : _Recordset;
    begin
    aRS := CoRecordset.Create;
    with aRS do
    begin
    CursorLocation := adUseClient;
    Fields.Append('INT', adInteger, 4, adFldUnspecified);
    Fields.Append('VARCHAR', adVarChar, 75, adFldUnspecified);
    Open(EmptyParam, EmptyParam, adOpenUnspecified,
    adLockUnspecified, 0);
    end;
    with ADODataSet1 do
    begin
    RecordSet := aRS;
    Active := True;
    end;
    end;

    </pre>

    Das Problem mit RDC besteht darin, sich erst einmal in die Hintergründe einarbeiten zu müssen. Diesen Aufwand gehe ich mit dem Recordset aus dem Weg :-)<br>
    Die Übergabe an CR sieht dann so aus:

    <pre>

    var
    aCRApp : IApplication;
    aCRRpt : IReport;
    aCRDB : IDatabase;
    begin
    aCRApp := CoApplication.Create;
    aCRRpt := aCRApp.OpenReport(sPath, 0);
    aCRDB := aCRRpt.Database;
    // bereits gefülltes Recordset-Objekt als Datenquelle nutzen
    aCRDB.SetDataSource(ADODataSet1.RecordSet, 3, 1);
    CRViewer91.ReportSource := aCRRpt;
    CRViewer91.ViewReport;
    end;

    </pre>
    &#10

    Comment

    Working...
    X