Rave - General
How do you create calculated Fields in Rave?
Most everyone knows that you can create calculated fields in Delphi and use those in your reports. However, those fields are also available to your visual form components such as DBGrids so it's not always a desirable option. Another problem is that you can't define calculated fields for memo or graphic field types. Here's a method to define calculated fields in Delphi that will only be available to your reports, won't impact the rest of your application and works fine for memo or graphic fields. (The example used demonstrates one solution for printing addresses where some of the lines may be blank and you don't want them printed. You could also do this using DataMirrors.)
First, define an OnGetCols event on your data connection component:
Delphi Example:
procedure TForm1.CustomerCXNGetCols(Connection: TRPCustomConnection);
begin
With Connection do begin
DoGetCols;
WriteField('FullAddress', dtMemo, 30, '', '');
end; { with }
end;
C++Builder Example
void __fastcall TForm1::CustomerCXNGetCols(TRPCustomConnection *Connection)
{
Connection->DoGetCols();
Connection->WriteField("FullAddress", dtMemo, 30, "", "");
}
The call to DoGetCols would create the default columns (fields) that would have been created if you hadn't defined this event. The only step left for this event is to call WriteField to define the meta-information for each field that you want to define. See Tutorial 26 in the ReportPrinter Pro manual for detailed instructions on WriteField. Next you need to define the OnGetRow event for the same data connection component.
Delphi Example:
procedure TForm1.CustomerCXNGetRow(Connection: TRPCustomConnection);
var
Stream: TMemoryStream;
Memo: TMemo;
s1, s2: string;
i1: integer;
begin
With Connection do begin
DoGetRow; // get data for table fields
For i1 := 0 to 3 do begin
case i1 of
0: s2 := Table1.FieldByName('Company').AsString;
1: s2 := Table1.FieldByName('Addr1').AsString;
2: s2 := Table1.FieldByName('Addr2').AsString;
3: begin
s2 := Table1.FieldByName('City').AsString;
s2 := s2 + ', ' + Table1.FieldByName('State').AsString +
' ' + Table1.FieldByName('Zip').AsString;
end;
end; // case
if s2 <> '' then begin
if s1 = '' then begin
s1 := s2;
end else begin
s1 := s1 + #13#10 + s2;
end;// else
end;// if
end;// for
Stream := TMemoryStream.Create;
Memo := TMemo.create(self);
try
Memo.Text := s1;
Memo.Lines.SaveToStream(Stream);
Stream.Position := 0;
WriteBlobData(Stream.Memory^, Stream.Size);
finally
Stream.Free;
Memo.Free;
end;// tryf
end; { with }
end;
C++Builder Example:
void __fastcall TForm1::CustomerCXNGetRow(TRPCustomConnection *Connection)
{
TMemoryStream* Stream;
TMemo* Memo;
AnsiString s1, s2;
Connection->DoGetRow(); // get data for table fields
for (int i1=0; i1 < 4; i1++) {
switch (i1) {
case 0: s2 = Table1->FieldByName("Company")->AsString;
break;
case 1: s2 = Table1->FieldByName("Addr1")->AsString;
break;
case 2: s2 = Table1->FieldByName("Addr2")->AsString;
break;
case 3: {
s2 = Table1->FieldByName("City")->AsString;
s2 = s2 + ", " + Table1->FieldByName("State")->AsString +
" " + Table1->FieldByName("Zip")->AsString;
}
break;
}// switch
if (s2 != "") {
if (s1 == "") {
s1 = s2;
}// if
else {
s1 = s1 + "\n" + s2;
}// else
}// if
}// for
Stream = new TMemoryStream();
Memo = new TMemo(this);
try {
Memo->Text = s1;
Memo->Lines->SaveToStream(Stream);
Stream->Position = 0;
Connection->WriteBlobData(Stream->Memory, Stream->Size);
} // try
__finally {
delete Stream;
delete Memo;
}// tryf
}
Once again we need to execute the default behavior for this event by calling DoGetRow. Then we get the address information and store it in a string variable. We then write the data for our calculated field by calling WriteBlobData (since it is a memo field). See Tutorial 26 in the ReportPrinter Pro manual for detailed instructions on WriteBlobData and the other WriteXxxxData methods. That's pretty much it. You can add more calculated fields to your data connection by adding more calls to WriteField and WriteXxxxData in each of these events. As with custom connections, you must have your application running and the data connection must be set to visible for these fields to show up since the code you have written must be executable.