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

"Proper" way to create and delete report components?

edited November 2013 in General
We are using ReportBuilder 14.08 with Delphi XE3, and have this old
report that I'm not sure ever worked. It's attempting to fashion a
particular sort of chart on a subreport by adding labels and shapes.

So we have the main report that is driven per person. Inside that main
report detail is just a subreport. That subreport is grouped by date
(each date is a new page). Then the developer is creating TppLabels in
the subreport detail band's BeforeGenerate event. Also inside that
method, prior to the label creation- they attempt to free any existing
labels first and this results in Access Violations.

So the code looks something like this:

procedure TMyActivityDM.ClearGraph;
begin
for i := ComponentCount - 1 downto 0 do begin
if ((Components[i] is TppLabel) or (Components[i] is TppShape)) and
(Components[i].Tag = GraphTag) then
Components[i].Free;
end;
end;

procedure TMyActivityDM.DrawActivityMark(ActivityType: string;
DetailBand: TppDetailBand;
ActivityTime: TDateTime; y: Single; Color: TColor);
var
x1, y1: Single;
begin
CalcPosition(ActivityTime, x1, y1);
with TppLabel.Create(Self) do begin
Band := DetailBand;
SetParentComponent(DetailBand);
Left := x1;
Top := y - 0.05;
Font.Size := 6;
Font.Name := 'Arial';
Caption := MnemonicList.Values[ActivityType];
Transparent := True;
Tag := GraphTag;
end;
end;

procedure TMyActivityDM.DrawActivity(DetailBand: TppDetailBand;
ActivityFilter: string; Y: Single; Color: TColor);
begin
with ActivitYDS do begin
Filtered := False;
Filter := Format(ActivityDataFilter, QuotedStr(ActivityFilter)]);
Filtered := True;
First;
while not EOF do begin
DrawActivityMark(ActivityType, DetailBand,
FieldByName('activitydatetime').AsDateTime, Y + 0.05, Color);
Next;
end;
end;
end;

procedure TMyActivityDM.ppSubReportDetailBandBeforeGenerate(Sender:
TObject);
begin
inherited;

ClearGraph; //AV's occur here when attempting to free components. If
this is commented out, then every subreport shows the same labels on
every page.

//For each activity date: draw a mark on the graph for each type of
activity
DrawActivity(ppGraphBand, 'TypeA', ALabel.top, clBlack)
DrawActivity(ppGraphBand, 'TypeB', ALabel.top, clBlack)
DrawActivity(ppGraphBand, 'TypeC', ALabel.top, clBlack)
DrawActivity(ppGraphBand, 'TypeD', ALabel.top, clBlack)
DrawActivity(ppGraphBand, 'TypeE', ALabel.top, clBlack)
//... draw rest of types, similar methods for TppShape etc
end;


I don't think this will work because I suspect once RB components are
added to the report then RB is doing some management of them under the
hood for pagination, printing, etc.- so we can't really free them. So
when they are attempted to be freed then maybe the RB engine is still
trying to reference them and that may cause the AVs?

So if that guess is close, then I'm not sure if it's possible to create
and free components (like labels) on a report- if so what is the
"proper" way? Or, is the only alternative to create the labels once-
then set the visibility in the ppSubReportDetailBandBeforePrint?

Comments

  • edited November 2013
    Hi Janice,

    When looping through report objects it's best to use a Report Object
    Loop rather than the Components list. See the following article and the
    sample code below on how this is done.

    procedure TForm1.RemoveComponents(aBand: TppBand);
    var
    liObject: Integer;
    lObject: TppComponent;
    begin

    for liObject := 0 to aBand.ObjectCount - 1 do
    begin
    lObject := aBand.Objects[liObject];

    if (lObject is TppCustomText) then
    lObject).Free;

    end;

    end;

    http://www.digital-metaphors.com/rbWiki/Delphi_Code/Layouts/Report_Object_Loop

    ReportBuilder is however not designed to handle the creation and
    destruction of report components during report generation. I would
    suggest perhaps creating the labels and graphics you need before the
    report prints, then simply updating their values, visibility, and
    location as needed for each detail band.

    Best Regards,

    Nico Cizik
    Digital Metaphors
    http://www.digital-metaphors.com
This discussion has been closed.