Question
“The summary band of my report displays alone on the last page of my report. Is there a way to move the last detail band to the next page to prevent this behavior?”
Solution
This can be done by measuring the amount of space the last detail plus the summary band take on the last page of the report. If there is not enough space to fit both bands, manually move the drawcommands from the last detail band to the next page.
See the following example for how this can be done using the DetailBand.BeforePrint, AfterPrint, and Report.EndPage events.
Download: DetailForOrphanSummary.zip
Sample Delphi code:
1. First determine if there is enough space for both the last detail band and the summary band on the last page of the report.
procedure TForm1.ppDetailBand1BeforePrint(Sender: TObject);
var
liMarginBottom: Integer;
liMarginTop: Integer;
liAvailableSpace: Integer;
ldSpaceNeededInInches: Double;
ldAvailableSpaceInInches: Double;
begin
liAvailableSpace := ppReport1.PrinterSetup.PageDef.mmPrintableHeight - ppReport1.Engine.PrintPosRect.Top;
ldAvailableSpaceInInches := ppFromMMTHousandths(liAvailableSpace, utInches, pprtVertical, ppReport1.Printer);
ldSpaceNeededInInches := ppDetailBand1.Height + ppSummaryBand1.Height;
if (ldAvailableSpaceInInches < ldSpaceNeededInInches) then
FDetailStartingPosition := ppReport1.Engine.PrintposRect.Top;
FDrawCommandStartIndex := ppReport1.Engine.Page.DrawCommandCount;
end;
2. If there is not enough space, remove the last detail band’s drawcommands from the page and save them to a list for later use.
procedure TForm1.ppReport1EndPage(Sender: TObject);
var
I: Integer;
liIndex: Integer;
lDrawCommand: TppDrawCommand;
begin
if not(FLastDetailMoved) and ppReport1.DataPipeline.EOF then
begin
FLastDetailMoved := True;
for liIndex := FDrawCommandStartIndex to FDrawCommandEndIndex do
begin
lDrawCommand := TppDrawCommand(ppReport1.Engine.Page.DrawCommands[liIndex]);
FDrawCommands.Add(lDrawCommand);
end;
for liIndex := 0 to FDrawCommands.Count - 1 do
TppDrawCommand(FDrawCommands[liIndex]).Page := nil;
end;
end;
3. After the next page starts, add the saved drawcommands at the top and move the cursor down so the summary band will print below.
procedure TForm1.ppHeaderBand1AfterPrint(Sender: TObject);
var
liDetailHeight: Integer;
liHeaderHeight: Integer;
liRight: Integer;
liLeft: Integer;
liBottom: Integer;
liTop: Integer;
liIndex: Integer;
lDrawCommand: TppDrawCommand;
begin
if ppReport1.DataPipeline.EOF then
begin
liHeaderHeight := ppToMMThousandths(ppHeaderband1.Height, utInches, pprtVertical, nil);
liDetailHeight := ppToMMThousandths(ppDetailband1.Height, utInches, pprtVertical, nil);
for liIndex := 0 to FDrawCommands.Count - 1 do
begin
lDrawCommand := TppDrawCommand(FDrawCommands[liIndex]);
lDrawCommand.Page := ppReport1.Engine.Page;
{also need to take into account the header height in microns too if you have a header band of group header band}
lDrawCommand.Top := ppReport1.Engine.PrintPosRect.Top + lDrawCommand.Top - FDetailStartingPosition;
end;
liTop := ppReport1.Engine.PrintPosRect.Top + liDetailHeight;
liLeft := ppReport1.Engine.PrintPosRect.Left;
liBottom := ppReport1.Engine.PrintPosRect.Bottom;
liRight := ppReport1.Engine.PrintPosRect.Right;
ppReport1.Engine.SetPrintPosition(liLeft, liTop, liRight, liBottom);
end
else
FDrawCommands.Clear;
end;