Migrate Existing Standard Report to End-User Report
Hi All,
Delphi Version: 5.01
R.Builder: 7.02 Professional
I am migrate the existing standard report to end-User Report. So that All
the current Printout can
be changed by the end user. But I hit the following problem, Please advise:
1. Since currently I've a datamodule containing all the data For Printing
the report. From your demos( end -user report and Custom Data View), Should
I recreate the data logic again to support end-user design? Since I've many
cacluated field in it, Can I simply use the current DataSet to Support the
End-User Design without recreate it Again.
From My Testing, I have create a custom dataView which is inherited from
TdaBDEQueryTemplateDataView( the sample of MydataVw). I can use all the
field and see the current row data at design tabset. But When I click
Preview, It show the Error "No Sql Statement is avaliable".
Can you explain it? Can I use existing Data such as offline
TclientDataSet( load it from a file without connecting to any database or
datasetprovider ) to use end-User Report?
In the Following, I attached my Class which try to use existing dataset
without executing any sql statement: Please Comment What's wrong with the
Code:
It works as expected except when click preview, it show "No Sql Statement is
avaliable".
TdvOrder = class(TdvCustomTemplateDataView)
private
FMasterTable: TClientDataSet;
FMasterDataSource: TDataSource;
FMasterDataPipeline: TppBDEPipeline;
FDetailTable: TClientDataSet;
FDetailDataSource: TDataSource;
FDetailDataPipeline: TppBDEPipeline;
FChrgTable: TClientDataSet;
FChrgDataSource: TDataSource;
FChrgDataPipeline: TppBDEPipeline;
protected
public
constructor Create(aOwner: TComponent); override;
destructor Destroy; override;
procedure DefineDataSelection; override;
class function ClassDescription: String; override;
procedure DefineSelectedFields; override;
procedure CreateDataPipelines; override;
procedure CreatePipelineFields(aDataPipeline: TppDataPipeline);
override;
procedure ConnectPipelinesToData; override;
procedure ConnectReportToPipelines;override;
published
{publish DataPipelines - must be read/write}
property MasterDataPipeline: TppBDEPipeline read FMasterDataPipeline
write FMasterDataPipeline;
property DetailDataPipeline: TppBDEPipeline read FDetailDataPipeline
write FDetailDataPipeline;
property ChrgDataPipeline: TppBDEPipeline read FChrgDataPipeline write
FChrgDataPipeline;
{publish DataSources - must be read only (i.e. do NOT declare "write
FDataSource")}
property MasterDataSource: TDataSource read FMasterDataSource;
property DetailDataSource: TDataSource read FDetailDataSource;
property ChrgDataSource: TDataSource read FChrgDataSource;
end; {class, TdvOrder}
class function TdvOrder.ClassDescription: String;
begin
Result := 'New Quotation';
end;
procedure TdvOrder.ConnectPipelinesToData;
begin
inherited;
FMasterDataPipeline.DataSource := MasterDataSource;
FMasterDataPipeline.RangeBegin := rbCurrentRecord;
FMasterDataPipeline.RangeEnd := reCurrentRecord;
FDetailDataPipeline.DataSource := DetailDataSource;
FChrgDataPipeline.DataSource := ChrgDataSource;
FMasterDataPipeline.MasterDataPipeline := DataPipeline;
end;
procedure TdvOrder.ConnectReportToPipelines;
begin
Report.DataPipeline := MasterDataPipeline;
end;
constructor TdvOrder.Create(aOwner: TComponent);
begin
inherited Create(aOwner);
DatabaseName := '_DB';
FMasterTable := Tform1(aOwner).Dm.cdsMaster;
FDetailTable := Tform1(aOwner).Dm.cdsDetail;
FChrgTable := Tform1(aOwner).Dm.cdsChrg;
FMasterDataSource := CreateDataSource;
FDetailDataSource := CreateDataSource;
FChrgDataSource := CreateDataSource;
FMasterDataSource.DataSet := FMasterTable ;
FDetailDataSource.DataSet := FDetailTable ;
FChrgDataSource.DataSet := FChrgTable ;
end;
procedure TdvOrder.CreateDataPipelines;
begin
inherited CreateDataPipelines;
FMasterDataPipeline := CreateDataPipeline;
FMasterDataPipeline.UserName := 'plMaster';
FDetailDataPipeline := CreateDataPipeline;
FDetailDataPipeline.UserName := 'plDetail';
FChrgDataPipeline := CreateDataPipeline;
FChrgDataPipeline.UserName := 'plChrg';
end;
procedure TdvOrder.CreatePipelineFields(aDataPipeline: TppDataPipeline);
var i:Integer;
begin
inherited CreatePipelineFields(aDataPipeline);
{create detail pipeline fields}
if aDataPipeline = FMasterDataPipeline then
begin
For i:= 0 to Pred(FMasterTable.FieldCount) Do
CreatePipelineField('QT_MTR',
FMasterTable.Fields[i].FieldName,
FMasterTable.Fields[i].DisplayName,
aDataPipeline, False, False);
end
else if aDataPipeline = FDetailDataPipeline then
begin
For i:= 0 to Pred(FDetailTable.FieldCount) Do
CreatePipelineField('QT_DET',
FDetailTable.Fields[i].FieldName,
FDetailTable.Fields[i].DisplayName,
aDataPipeline, False, False);
end
else if aDataPipeline = FChrgDataPipeline then
begin
For i:= 0 to Pred(FChrgTable.FieldCount) Do
CreatePipelineField('QT_CHRG_TBL',
FChrgTable.Fields[i].FieldName,
FChrgTable.Fields[i].DisplayName,
aDataPipeline, False, False);
end
end;
procedure TdvOrder.DefineDataSelection;
begin
// inherited;
end;
procedure TdvOrder.DefineSelectedFields;
var
lMasterTable: TdaTable;
lDetailTable: TdaTable;
lChrgTable: TdaTable;
i:Integer;
begin
inherited DefineSelectedFields;
{
lMasterTable := AddSelectTable('QT_MTR');
For i:= 0 to Pred(FMasterTable.FieldCount) Do
AddSelectField(lMasterTable,FMasterTable.Fields[i].FieldName,
FMasterTable.Fields[i].DisplayName,True,True);
lDetailTable := AddSelectTable('QT_DET');
For i:= 0 to Pred(FDetailTable.FieldCount) Do
AddSelectField(lDetailTable,FDetailTable.Fields[i].FieldName,
FDetailTable.Fields[i].DisplayName,True,True);
lChrgTable := AddSelectTable('QT_CHRG_TBL');
For i:= 0 to Pred(FChrgTable.FieldCount) Do
AddSelectField(lChrgTable,FChrgTable.Fields[i].FieldName,
FChrgTable.Fields[i].DisplayName,True,True);
}
end;
destructor TdvOrder.Destroy;
begin
inherited Destroy;
end;
Delphi Version: 5.01
R.Builder: 7.02 Professional
I am migrate the existing standard report to end-User Report. So that All
the current Printout can
be changed by the end user. But I hit the following problem, Please advise:
1. Since currently I've a datamodule containing all the data For Printing
the report. From your demos( end -user report and Custom Data View), Should
I recreate the data logic again to support end-user design? Since I've many
cacluated field in it, Can I simply use the current DataSet to Support the
End-User Design without recreate it Again.
From My Testing, I have create a custom dataView which is inherited from
TdaBDEQueryTemplateDataView( the sample of MydataVw). I can use all the
field and see the current row data at design tabset. But When I click
Preview, It show the Error "No Sql Statement is avaliable".
Can you explain it? Can I use existing Data such as offline
TclientDataSet( load it from a file without connecting to any database or
datasetprovider ) to use end-User Report?
In the Following, I attached my Class which try to use existing dataset
without executing any sql statement: Please Comment What's wrong with the
Code:
It works as expected except when click preview, it show "No Sql Statement is
avaliable".
TdvOrder = class(TdvCustomTemplateDataView)
private
FMasterTable: TClientDataSet;
FMasterDataSource: TDataSource;
FMasterDataPipeline: TppBDEPipeline;
FDetailTable: TClientDataSet;
FDetailDataSource: TDataSource;
FDetailDataPipeline: TppBDEPipeline;
FChrgTable: TClientDataSet;
FChrgDataSource: TDataSource;
FChrgDataPipeline: TppBDEPipeline;
protected
public
constructor Create(aOwner: TComponent); override;
destructor Destroy; override;
procedure DefineDataSelection; override;
class function ClassDescription: String; override;
procedure DefineSelectedFields; override;
procedure CreateDataPipelines; override;
procedure CreatePipelineFields(aDataPipeline: TppDataPipeline);
override;
procedure ConnectPipelinesToData; override;
procedure ConnectReportToPipelines;override;
published
{publish DataPipelines - must be read/write}
property MasterDataPipeline: TppBDEPipeline read FMasterDataPipeline
write FMasterDataPipeline;
property DetailDataPipeline: TppBDEPipeline read FDetailDataPipeline
write FDetailDataPipeline;
property ChrgDataPipeline: TppBDEPipeline read FChrgDataPipeline write
FChrgDataPipeline;
{publish DataSources - must be read only (i.e. do NOT declare "write
FDataSource")}
property MasterDataSource: TDataSource read FMasterDataSource;
property DetailDataSource: TDataSource read FDetailDataSource;
property ChrgDataSource: TDataSource read FChrgDataSource;
end; {class, TdvOrder}
class function TdvOrder.ClassDescription: String;
begin
Result := 'New Quotation';
end;
procedure TdvOrder.ConnectPipelinesToData;
begin
inherited;
FMasterDataPipeline.DataSource := MasterDataSource;
FMasterDataPipeline.RangeBegin := rbCurrentRecord;
FMasterDataPipeline.RangeEnd := reCurrentRecord;
FDetailDataPipeline.DataSource := DetailDataSource;
FChrgDataPipeline.DataSource := ChrgDataSource;
FMasterDataPipeline.MasterDataPipeline := DataPipeline;
end;
procedure TdvOrder.ConnectReportToPipelines;
begin
Report.DataPipeline := MasterDataPipeline;
end;
constructor TdvOrder.Create(aOwner: TComponent);
begin
inherited Create(aOwner);
DatabaseName := '_DB';
FMasterTable := Tform1(aOwner).Dm.cdsMaster;
FDetailTable := Tform1(aOwner).Dm.cdsDetail;
FChrgTable := Tform1(aOwner).Dm.cdsChrg;
FMasterDataSource := CreateDataSource;
FDetailDataSource := CreateDataSource;
FChrgDataSource := CreateDataSource;
FMasterDataSource.DataSet := FMasterTable ;
FDetailDataSource.DataSet := FDetailTable ;
FChrgDataSource.DataSet := FChrgTable ;
end;
procedure TdvOrder.CreateDataPipelines;
begin
inherited CreateDataPipelines;
FMasterDataPipeline := CreateDataPipeline;
FMasterDataPipeline.UserName := 'plMaster';
FDetailDataPipeline := CreateDataPipeline;
FDetailDataPipeline.UserName := 'plDetail';
FChrgDataPipeline := CreateDataPipeline;
FChrgDataPipeline.UserName := 'plChrg';
end;
procedure TdvOrder.CreatePipelineFields(aDataPipeline: TppDataPipeline);
var i:Integer;
begin
inherited CreatePipelineFields(aDataPipeline);
{create detail pipeline fields}
if aDataPipeline = FMasterDataPipeline then
begin
For i:= 0 to Pred(FMasterTable.FieldCount) Do
CreatePipelineField('QT_MTR',
FMasterTable.Fields[i].FieldName,
FMasterTable.Fields[i].DisplayName,
aDataPipeline, False, False);
end
else if aDataPipeline = FDetailDataPipeline then
begin
For i:= 0 to Pred(FDetailTable.FieldCount) Do
CreatePipelineField('QT_DET',
FDetailTable.Fields[i].FieldName,
FDetailTable.Fields[i].DisplayName,
aDataPipeline, False, False);
end
else if aDataPipeline = FChrgDataPipeline then
begin
For i:= 0 to Pred(FChrgTable.FieldCount) Do
CreatePipelineField('QT_CHRG_TBL',
FChrgTable.Fields[i].FieldName,
FChrgTable.Fields[i].DisplayName,
aDataPipeline, False, False);
end
end;
procedure TdvOrder.DefineDataSelection;
begin
// inherited;
end;
procedure TdvOrder.DefineSelectedFields;
var
lMasterTable: TdaTable;
lDetailTable: TdaTable;
lChrgTable: TdaTable;
i:Integer;
begin
inherited DefineSelectedFields;
{
lMasterTable := AddSelectTable('QT_MTR');
For i:= 0 to Pred(FMasterTable.FieldCount) Do
AddSelectField(lMasterTable,FMasterTable.Fields[i].FieldName,
FMasterTable.Fields[i].DisplayName,True,True);
lDetailTable := AddSelectTable('QT_DET');
For i:= 0 to Pred(FDetailTable.FieldCount) Do
AddSelectField(lDetailTable,FDetailTable.Fields[i].FieldName,
FDetailTable.Fields[i].DisplayName,True,True);
lChrgTable := AddSelectTable('QT_CHRG_TBL');
For i:= 0 to Pred(FChrgTable.FieldCount) Do
AddSelectField(lChrgTable,FChrgTable.Fields[i].FieldName,
FChrgTable.Fields[i].DisplayName,True,True);
}
end;
destructor TdvOrder.Destroy;
begin
inherited Destroy;
end;
This discussion has been closed.
Comments
The class hierarchy looks like this:
TdaQueryDataView
TdaBDEQueryDataView
TdaBDETemplateDataView
TdaBDEQueryTemplateDataView
All of the dataviews descend from TdaQueryDataView which requires a SQL
statement.
The ancestor class for the custom DataViews that you are creating,
TdaBDEQueryTemplateDataView defined a TQuery and DataSource and BDEPipeline
that are to be used for the master. If you want to add linked datasets then
you define additional TTables and TQueries.
Try to work towards a solution incrementally. First get a custom dataview
working that has just a single query. Once you get that working, add a
single linked detail table/query, etc.
--
Nard Moseley
Digital Metaphors
http://www.digital-metaphors.com
Best regards,
Nard Moseley
Digital Metaphors
www.digital-metaphors.com
If I've exisitng DataModule with the following setting:
ClientDataSet A Link To ClientDataSet B
Since I've many Calculated Field In it. I f I want to use current
ClientDataSet.
Please Indicate which Class I Should inherit or any way to do it
Perhaps try overriding the SQLChanged method so that it does nothing. Do not
call inherited. Connect the DataSource and DataPipeline desclared in the
ancestor to your client dataset. You do not need to use the methods such as
DefineSelectedFields that are used to build a SQL statement.
--
Nard Moseley
Digital Metaphors
http://www.digital-metaphors.com
Best regards,
Nard Moseley
Digital Metaphors
www.digital-metaphors.com