How To…Collate Subreport Pages

Question

“How can I can collate the pages of my subreport?”

I have two subreports and would like for the pages to alternate subreport1 page 1, subreport2 page 1, subreport1 page 2, subreport2 page 2,..

Solution

This example generate the pages to cache, then re-orders the page cache, prior to preview.

Download: CollateSubReportPages.zip

Sample Delphi code:

uses
  ppDevice,
  ppTypes;

procedure TForm1.PreviewClick(Sender: TObject);
begin

  // initialize
  FFirstReportPageCount := 0;
  FSecondReportPageCount := 0;

  // generate pages to cache
  PrintToCache;

  // collate pages
  CollatePages;

  // preview
  ppReport1.DeviceType := dtScreen;
  ppReport1.Print;

end;

procedure TForm1.ppEmpSalesEndFirstPass(Sender: TObject);
begin
  // save first child report page count
  FFirstReportPageCount := ppSubReport1.Report.AbsolutePageCount;
end;

procedure TForm1.ppCustListEndFirstPass(Sender: TObject);
begin
  // save sedcond child report page count
  FSecondReportPageCount := ppSubReport2.Report.AbsolutePageCount;
end;

procedure TForm1.PrintToCache;
var
  lDevice: TppDevice;
begin

  // create a dummy device
  lDevice := TppDevice.Create(Self);
  lDevice.PageSetting := psLastPage;
  lDevice.Publisher := ppReport1.Publisher;

  // generate the pages to cache
  ppReport1.CachePages := True;
  ppReport1.PrintToDevices;

  lDevice.Free;

end;

procedure TForm1.CollatePages;
var
  liIndex: Integer;
  lPages: TList;
  lPublisher: TppPublisher;
  lFirstReportPage: TppPage;
  lSecondReportPage: TppPage;
  liCollatedPages: Integer;
  lPage: TppPage;
begin

  lPages := TList.Create;

  lPublisher := ppReport1.Publisher;

  liIndex := 0;

  // build list of collated pages
  while (liIndex < FFirstReportPageCount) and (FSecondReportPageCount > 0) do
    begin
      // add page from first report
      lFirstReportPage := lPublisher.Pages[liIndex];
      lFirstReportPage.AbsolutePageNo := lPages.Count + 1;
      lFirstReportPage.PageNo := lPages.Count + 1;

      lPage := TppPage.Create(nil);
      lPage.Assign(lFirstReportPage);

      lPages.Add(lPage);

      // add page from second report
      lSecondReportPage := lPublisher.Pages[FFirstReportPageCount + liIndex];
      lSecondReportPage.AbsolutePageNo := lPages.Count + 1;
      lSecondReportPage.PageNo := lPages.Count + 1;

      lPage := TppPage.Create(nil);
      lPage.Assign(lSecondReportPage);
      lPages.Add(lPage);

      Inc(liIndex);
      Dec(FSecondReportPageCount);
    end;


  {add remaining pages to list}
  liCollatedPages := liIndex;

  if (FSecondReportPageCount > 0) then
    for liIndex := 0 to FSecondReportPageCount - 1 do
      begin
        lSecondReportPage := lPublisher.Pages[FFirstReportPageCount + liCollatedPages + liIndex];
        lSecondReportPage.AbsolutePageNo := lPages.Count + 1;
        lSecondReportPage.PageNo := lPages.Count + 1;

        lPage := TppPage.Create(nil);
        lPage.Assign(lSecondReportPage);
        lPages.Add(lPage);
      end

  else if (liCollatedPages < FFirstReportPageCount) then
    begin
      if (liCollatedPages > 0) then
        TppPage(lPages[lPages.Count - 1]).LastPage := False;

      for liIndex := liCollatedPages to FFirstReportPageCount - 1 do
        begin
          lFirstReportPage := lPublisher.Pages[liIndex];
          lFirstReportPage.AbsolutePageNo := lPages.Count + 1;
          lFirstReportPage.PageNo := lPages.Count + 1;

          if (liIndex = FFirstReportPageCount - 1) then
            lFirstReportPage.LastPage := True;

          lPage := TppPage.Create(nil);
          lPage.Assign(lFirstReportPage);
          lPages.Add(lPage);
        end;
    end;

  {update page cache}
  for liIndex := 0 to lPages.Count - 1 do
    begin
      lPage := TppPage(lPages[liIndex]);

      lPublisher.ReceivePage(lPage);
    end;

  {free old pages}
  for liIndex := 0 to lPages.Count - 1 do
    TppPage(lPages[liIndex]).Free;

  lPages.Free;

  {update page number of new pages}
  for liIndex := 0 to lPublisher.PageCount - 1 do
    lPublisher.Pages[liIndex].Update(nil);

end;