Continuing Detail Band past end of dataset to end of page
Hi,
I have a report where the detailband has a lot of lines in it that form
various boxes / fields for the report.
This is populated with data. However, the user has requested that these
lines / boxes continue with blank / no data in them to 'fill' the rest
of the page if the data doesn't fill the page.
I was wondering - is this possible to achieve with the detail band, or
do I need to re-write the whole report using the Pagestyle for the lines
/ form?
Thanks & Regards
Adam.
I have a report where the detailband has a lot of lines in it that form
various boxes / fields for the report.
This is populated with data. However, the user has requested that these
lines / boxes continue with blank / no data in them to 'fill' the rest
of the page if the data doesn't fill the page.
I was wondering - is this possible to achieve with the detail band, or
do I need to re-write the whole report using the Pagestyle for the lines
/ form?
Thanks & Regards
Adam.
This discussion has been closed.
Comments
Take a look at the following article on adding lines to the end of the
report. The same concept would be used in your situation.
http://www.digital-metaphors.com/rbWiki/Delphi_Code/Formatting/How_To..._Fill_a_page_with_lines
The PageStyle option would also work as well but as you mentioned may
take more time to implement.
Nico Cizik
Digital Metaphors
http://www.digital-metaphors.com
Thanks for your reply and example. Unfortunately that's not quite what
I'm after - but it has given me an idea.
What I'd like to be able to do is replicate / repeat any lines drawn in
the detail band after the end. Using the example that was given in your
link, I've come up with the following - but I'm not sure how to get it
to work, and I was wondering if you could please advise?
Thanks & Regards
Adam.
procedure TForm1.ppReport1EndPage(Sender: TObject);
var
lDrawLine: TppDrawLine;
liTop: Integer;
liLineTop: Integer;
liBottom: Integer;
i : Integer;
begin
if (FCurrentPosition <> -1) then
begin
liTop := FCurrentPosition;
liBottom := ppReport1.Engine.PageBottom;
liLineTop := liBottom;
//Add a new set of lines until the page ends...
while liTop < liLineTop do
begin
//First find every line that exists within
//the detail band, and re-draw it underneath,
//repeating until the end of the page...
for i := 0 to self.ComponentCount - 1 do
if self.Components[i] is TppLine then
if TPPLine(self.Components[i]).Parent = ppDetailBand1 then
//We've found a line that exists in the detail band...
begin
lDrawLine := TppDrawLine.Create(nil);
lDrawLine.Page := ppReport1.Engine.Page;
//Copy the line's properties to redraw.
//Since the position are using different units of
//measurements I have attempted to cast the lines
//as TpPDrawLines to get the correct locations, but
//this doesn't appear to be working correctly
lDrawLine.Left := TppDrawLine(self.Components[i]).Left;
lDrawLine.Top := liLineTop +
TppDrawLine(self.Components[i]).top;
lDrawLine.Width := TppDrawLine(self.Components[i]).Width;
lDrawLine.Height := TppDrawLine(self.Components[i]).Height;
end;
{change 9075 to change the space between lines}
//I would like to have this changed to the height of the
//original detail band - but I'm not sure how to get the
//height in these particular units...
liLineTop := liLineTop - 9075;
end;
end;
end;
1. I recommend preforming a report object loop to find all the line
components in the detail band. See the following article on that.
http://www.digital-metaphors.com/rbWiki/Delphi_Code/Layouts/Report_Object_Loop
2. The components retrieved from the loop, or the "Report.Components"
property that you are using below returns TppComponent descendents, not
TppDrawCommands. Typecasting them as DrawCommands will likely cause an
error.
Instead use "TppLine".
lDrawLine.Left := ppToMMThousandths(TppLine(lReportComponent).Left,
utInches, pprtHorizontal, nil);
3. TppDrawCommand objects make measurements in microns only. The report
components are measured with Report units (usually inches). You will
need to convert these values so they are microns before assigning the
DrawCommand values. Use the utilities in the ppUtils.pas file for this.
-ppFromMMThousandths
-ppToMMThousandths
Nico Cizik
Digital Metaphors
http://www.digital-metaphors.com
Thanks very much for your reply. I've modified my code to the following
below, but I'm still experiencing problems with it not behaving as
expected.
The problems I am having are as follows:
1) The lines appear to start further to the left than expected
2) I'm not sure what to use to change the line's orientation from
Horizontal to Vertical for the TppLineDraw property.
I have placed an example / demo of my current files here if this is of
any help to see what I'm doing...
http://www.wsdsites.net/tmp/populatetoend.zip
Thanks & Regards
Adam.
if (FCurrentPosition <> -1) then
begin
liTop := FCurrentPosition;
liBottom := ppReport1.Engine.PageBottom;
liLineTop := liBottom;
//Add a new line until space runs out on the page.
while liTop < liLineTop do
begin
for i := 0 to ppDetailBand1.ObjectCount - 1 do
if ppDetailBand1.objects[i] is TppLine then
begin
lDrawLine := TppDrawLine.Create(nil);
lDrawLine.Page := ppReport1.Engine.Page;
lDrawLine.Left :=
ppToMMThousandths(TppLine(ppDetailBand1.objects[i]).Left, utInches,
pprtHorizontal, nil);
lDrawLine.Top :=
ppToMMThousandths(TppLine(ppDetailBand1.objects[i]).Top, utInches,
pprtVertical, nil) + liLineTop;
lDrawLine.Width :=
ppToMMThousandths(TppLine(ppDetailBand1.objects[i]).Width, utInches,
pprtHorizontal, nil);
lDrawLine.height :=
ppToMMThousandths(TppLine(ppDetailBand1.objects[i]).height, utInches,
pprtVertical, nil);
lDrawLine.Weight :=
TppLine(ppDetailBand1.objects[i]).Weight;
lDrawLine.Pen := TppLine(ppDetailBand1.objects[i]).pen;
// lDrawLine.Position :=
TppLine(ppDetailBand1.objects[i]).position;
end;
liLineTop := liLineTop -
(ppToMMThousandths(pPDetailBand1.Height, utInches, pprtVertical, nil));
// liLineTop := liLineTop - 9075;
end;
end;
end;
I've managed to solve part of my problem. I figured I needed to take
into account the report's margins, and have also found the
tPPDrawLine.Position property.
The problem I currently face though is that the additional drawing
doesn't start directly underneath the last detail band printout. There
is a gap - and I'm not sure what I need to take into account to reduce
this gap.
The updated changes I've made are still available with the previous link
given
http://www.wsdsites.net/tmp/populatetoend.zip
I've changed the events to a separate procedure too - so I can use this
on numerous reports just by making a call to the procedure.
The updated script is also below if you don't wish to download the demo
I've provided.
Best Regards
Adam.
procedure FillPageWithBlankDetailBand(DetailBand : TppDetailBand;
FCurrentPosition : Integer);
var
lDrawLine: TppDrawLine;
liTop: Integer;
liLineTop: Integer;
liBottom: Integer;
i : Integer;
Report : TppReport;
UnitType: TppUnitType;
begin
Report := TppReport(DetailBand.Report);
UnitType := Report.Units;
if (FCurrentPosition <> -1) then
begin
liTop := FCurrentPosition;
liBottom := Report.Engine.PageBottom;
liLineTop := liBottom;
//Add a new line until space runs out on the page.
while liTop < liLineTop do
begin
for i := 0 to DetailBand.ObjectCount - 1 do
if DetailBand.objects[i] is TppLine then
begin
lDrawLine := TppDrawLine.Create(nil);
lDrawLine.Page := Report.Engine.Page;
lDrawLine.Left :=
ppToMMThousandths(TppLine(DetailBand.objects[i]).Left, UnitType,
pprtHorizontal, nil) +
ppToMMThousandths(Report.PrinterSetup.marginLeft,
UnitType, pprtHorizontal, nil); //Need to account for Left Margin!
;
lDrawLine.Top :=
ppToMMThousandths(TppLine(DetailBand.objects[i]).Top, UnitType,
pprtVertical, nil) + liLineTop;
lDrawLine.LinePosition :=
TppLine(DetailBand.objects[i]).Position;
lDrawLine.Width :=
ppToMMThousandths(TppLine(DetailBand.objects[i]).Width, UnitType,
pprtHorizontal, nil);
lDrawLine.height :=
ppToMMThousandths(TppLine(DetailBand.objects[i]).height, UnitType,
pprtVertical, nil);
lDrawLine.Weight := TppLine(DetailBand.objects[i]).Weight;
lDrawLine.Pen := TppLine(DetailBand.objects[i]).pen;
// lDrawLine.Position :=
TppLine(DetailBand.objects[i]).position;
end;
liLineTop := liLineTop -
(ppToMMThousandths(DetailBand.Height, UnitType, pprtVertical, nil));
// liLineTop := liLineTop - 9075;
end;
end;
end;
procedure TForm1.ppReport1EndPage(Sender: TObject);
begin
FillPageWithBlankDetailBand(ppDetailBand1, FCurrentPosition);
end;
The example starts drawing lines at the bottom of the page then moves
up, leaving a small amount of space at the top of the report rather than
the bottom. In your case, try starting at the top and moving down.
if (FCurrentPosition <> -1) then
begin
liTop := FCurrentPosition;
liBottom := Report.Engine.PageBottom;
//Add a new line until space runs out on the page.
while liTop < liLineTop do
begin
...
lDrawLine.Top :=
ppToMMThousandths(TppLine(DetailBand.objects[i]).Top, UnitType,
pprtVertical, nil) + liTop;
...
liTop := liTop + (ppToMMThousandths(DetailBand.Height,
UnitType, pprtVertical, nil));
end;
Nico Cizik
Digital Metaphors
http://www.digital-metaphors.com
while liTop < liBottom do
...
Nico Cizik
Digital Metaphors
http://www.digital-metaphors.com
Thanks very much for your reply. I can see now that the original demo
was going in 'reverse', and have managed to get it to work.
I've also aded changes to also paint shapes as well as lines if they
exist within the detail band - and have changed the code into a
procedure of it's own, so it can be called from multiple reports.
This is the end result I have come up with, incase it's of any help to
anyone else reading this down the track.
Once again, thanks very much for your help.
Best Regards
Adam
procedure FillPageWithBlankDetailBand(DetailBand : TppDetailBand;
FCurrentPosition : Integer);
var
lDrawLine: TppDrawLine;
liTop: Integer;
liLineTop: Integer;
liBottom: Integer;
i : Integer;
Report : TppReport;
UnitType: TppUnitType;
lDrawShape : TppDrawShape;
begin
{
In order to use this, you need the following on the report itself:
private
FCurrentPosition : integer;
procedure TMyForm.ppDetailBand1AfterPrint(Sender: TObject);
begin
inherited;
FCurrentPosition := TpPDetailBand(sender).Report.Engine.PrintPosRect.Top;
end;
procedure TMyForm.PackInstDetREndPage(Sender: TObject);
begin
inherited;
FillPageWithBlankDetailBand(ppDetailBand1, FCurrentPosition);
end;
}
Report := TppReport(DetailBand.Report);
UnitType := Report.Units;
if (FCurrentPosition <> -1) then
begin
liTop := FCurrentPosition;
liBottom := Report.Engine.PageBottom;
liLineTop := FCurrentPosition;
//Add a new line until space runs out on the page.
while liLineTop < libottom -
(ppToMMThousandths(DetailBand.Height, UnitType, pprtVertical, nil))
{Give it one detail band width grace so it doesnt print over} do
begin
for i := 0 to DetailBand.ObjectCount - 1 do
begin
if DetailBand.objects[i] is TppLine then
begin
lDrawLine := TppDrawLine.Create(nil);
lDrawLine.Page := Report.Engine.Page;
lDrawLine.Left :=
ppToMMThousandths(TppLine(DetailBand.objects[i]).Left, UnitType,
pprtHorizontal, nil) +
ppToMMThousandths(Report.PrinterSetup.marginLeft,
UnitType, pprtHorizontal, nil); //Need to account for Left Margin!
;
lDrawLine.Top :=
ppToMMThousandths(TppLine(DetailBand.objects[i]).Top, UnitType,
pprtVertical, nil) + liLineTop ;
lDrawLine.LinePosition :=
TppLine(DetailBand.objects[i]).Position;
lDrawLine.Width :=
ppToMMThousandths(TppLine(DetailBand.objects[i]).Width, UnitType,
pprtHorizontal, nil);
lDrawLine.height :=
ppToMMThousandths(TppLine(DetailBand.objects[i]).height, UnitType,
pprtVertical, nil);
lDrawLine.Weight := TppLine(DetailBand.objects[i]).Weight;
lDrawLine.Pen := TppLine(DetailBand.objects[i]).pen;
// lDrawLine.Position :=
TppLine(DetailBand.objects[i]).position;
end;
if DetailBand.objects[i] is tppShape then
begin
lDrawShape := TppDrawShape.Create(nil);
lDrawShape.Page := Report.Engine.Page;
lDrawShape.Left :=
ppToMMThousandths(tppShape(DetailBand.objects[i]).Left, UnitType,
pprtHorizontal, nil) +
ppToMMThousandths(Report.PrinterSetup.marginLeft,
UnitType, pprtHorizontal, nil); //Need to account for Left Margin!
lDrawShape.Top :=
ppToMMThousandths(tppShape(DetailBand.objects[i]).Top, UnitType,
pprtVertical, nil) + liLineTop ;
lDrawShape.Width :=
ppToMMThousandths(tppShape(DetailBand.objects[i]).Width, UnitType,
pprtHorizontal, nil);
lDrawShape.height :=
ppToMMThousandths(tppShape(DetailBand.objects[i]).height, UnitType,
pprtVertical, nil);
lDrawShape.ShapeType :=
tppShape(DetailBand.objects[i]).Shape;
lDrawShape.Pen := tppShape(DetailBand.objects[i]).pen;
lDrawShape.Brush := tppShape(DetailBand.objects[i]).brush;
// lDrawShape.Position :=
TppLine(DetailBand.objects[i]).position;
end;
end;
// liLineTop := liLineTop -
(ppToMMThousandths(DetailBand.Height, UnitType, pprtVertical, nil));
liLineTop := liLineTop +
(ppToMMThousandths(DetailBand.Height, UnitType, pprtVertical, nil));
end;
end;
end;