Browse Source

* fix vpLastOnly (by Doyenne). Fixes issue #35095

Michaël Van Canneyt 6 hours ago
parent
commit
b4c70305bc
2 changed files with 147 additions and 2 deletions
  1. 104 0
      packages/fcl-report/demos/lastpageonly.pas
  2. 43 2
      packages/fcl-report/src/fpreport.pp

+ 104 - 0
packages/fcl-report/demos/lastpageonly.pas

@@ -0,0 +1,104 @@
+{
+  This program generates a PDF report. The last page should have a page header.
+  Originally part of #35095, included here as demo. Needs LiberationSerif font.
+}
+
+program bugdemo;
+
+uses dynlibs, Classes, Contnrs, fpreportcontnr, fpreport, fpttf, fpreportpdfexport, fppdf, SysUtils;
+
+type
+  TPerson = class(TPersistent)
+    private
+      FName,
+      FCity: String;
+    published
+      property Name: String read FName write FName;
+      property City: String read FCity write FCity;
+  end;
+
+var
+  OL: TFPObjectList;
+  rpt: TFPReport;
+  repdat: TFPReportObjectListData;
+  p: TFPReportPage;
+  PageHeaderBand: TFPReportPageHeaderBand;
+  DataBand: TFPReportDataBand;
+  Memo: TFPReportMemo;
+  RptExporter: TFPReportExportPDF;
+
+procedure CreateData;
+var
+  P: TPerson;
+  i: Integer;
+begin
+  OL := TFPObjectList.Create;
+  OL.OwnsObjects := true;
+  for i := 1 to 70 do
+  begin
+    P := TPerson.Create;
+    P.Name := 'John #' + IntToStr(i);
+    P.City := 'Somewhere';
+    OL.Add(P);
+  end;
+end;
+
+begin
+  CreateData;
+
+  gTTFontCache.ReadStandardFonts;
+  PaperManager.RegisterStandardSizes;
+  rpt := TFPReport.Create(nil);
+  rpt.TwoPass := true;
+
+  repdat := TFPReportObjectListData.Create(nil);
+  repdat.List := OL;
+  repdat.OwnsList := true;
+
+  p := TFPReportPage.Create(rpt);
+  p.Orientation := poPortrait;
+  p.PageSize.PaperName := 'A4';
+
+  { page margins }
+  p.Margins.Left := 30;
+  p.Margins.Top := 20;
+  p.Margins.Right := 30;
+  p.Margins.Bottom := 20;
+
+  p.Font.Name := 'LiberationSerif';
+
+  p.Data := repdat;
+
+  PageHeaderBand := TFPReportPageHeaderBand.Create(p);
+  PageHeaderBand.Layout.Height := 40;
+  PageHeaderBand.VisibleOnPage := vpLastOnly;
+
+  Memo := TFPReportMemo.Create(PageHeaderBand);
+  Memo.Layout.Left := 5;
+  Memo.Layout.Top := 0;
+  Memo.Layout.Width := 140;
+  Memo.Layout.Height := 15;
+  Memo.Text := 'Bug Demo - this band should appear on last page only (vpLastOnly)';
+  Memo.TextAlignment.Horizontal := taCentered;
+
+  DataBand := TFPReportDataBand.Create(p);
+  DataBand.Layout.Height := 10;
+  DataBand.Data := repdat;
+
+  Memo := TFPReportMemo.Create(DataBand);
+  Memo.Layout.Left := 30;
+  Memo.Layout.Top := 0;
+  Memo.Layout.Width := 100;
+  Memo.Layout.Height := 5;
+  Memo.Text := 'Person: [name], [city]';
+
+  rpt.RunReport;
+
+  RptExporter := TFPReportExportPDF.Create(nil);
+  rpt.RenderReport(RptExporter);
+
+  RptExporter.Free;
+  repdat.Free;
+  rpt.Free;
+end.
+

+ 43 - 2
packages/fcl-report/src/fpreport.pp

@@ -9663,8 +9663,30 @@ begin
     begin
       // do nothing special
     end
-    else if (FVisibleOnPage in [vpNotOnFirst, vpLastOnly, vpNotOnFirstAndLast]) then
-      Exit; // user asked to skip this band
+    else if (FVisibleOnPage in [vpNotOnFirst, vpNotOnFirstAndLast]) then
+      Exit // user asked to skip this band
+    else if Report.TwoPass and Report.IsFirstPass then
+    begin
+      if FVisibleOnPage in [vpLastOnly] then
+      begin // last page not yet known. Include on page 1 to reserve space one time in the report
+        // do nothing special
+      end
+      else if FVisibleOnPage in [vpNotOnLast] then
+        Exit // last page not yet known. Exclude on page 1 to reserve space n-1 times in the report
+    end
+    else if (not Report.IsFirstPass) then
+    begin
+      if FVisibleOnPage in [vpLastOnly] then
+      begin // second pass, exclude if page 1 is not the last page
+        if Report.FPerDesignerPageCount[Report.FRTCurDsgnPageIdx] > 1 then
+          Exit; // user asked to skip this band
+      end
+      else if FVisibleOnPage in [vpNotOnLast] then
+      begin // second pass, exclude if page 1 is the last page
+        if Report.FPerDesignerPageCount[Report.FRTCurDsgnPageIdx] = 1 then
+          Exit; // user asked to skip this band
+      end;
+    end
   end
   else if (Report.FPageNumberPerDesignerPage > 1) then
   begin  // multi-page rules
@@ -9674,6 +9696,25 @@ begin
     begin
       // do nothing special
     end
+    else if Report.TwoPass and Report.IsFirstPass then
+    begin
+      if FVisibleOnPage in [vpLastOnly] then
+        Exit // first pass: include on page 1 only, to reserve space only 1 time in the report
+      else if FVisibleOnPage in [vpFirstAndLastOnly] then
+      begin // first pass: include on pages 1-2, to reserve space 2 times in the report
+        if Report.FPageNumberPerDesignerPage > 2 then
+          Exit;  // skip this band, space has been reserved 2 times already
+      end
+      else if FVisibleOnPage in [vpNotOnLast] then
+      begin // first pass: exclude on page 1, include on other pages, to reserve space n-1 times
+        // do nothing special
+      end
+      else if FVisibleOnPage in [vpNotOnFirstAndLast] then
+      begin // first pass: exclude on pages 1-2, include on other pages, to reserve space n-2 times
+        if Report.FPageNumberPerDesignerPage <= 2 then
+          Exit; // skip this band, space will be reserved from page 3, to reserve space n-2 times
+      end;
+    end
     else if (not Report.IsFirstPass) then
     begin // last page rules
       if (FVisibleOnPage in [vpLastOnly, vpFirstAndLastOnly]) and (Report.FPageNumberPerDesignerPage < Report.FPerDesignerPageCount[Report.FRTCurDsgnPageIdx]) then