Manually Set Page breaks before Split Tables

General TRichView support forum. Please post your questions here
Post Reply
MarkElder
Posts: 21
Joined: Tue Aug 28, 2012 7:43 pm

Manually Set Page breaks before Split Tables

Post by MarkElder »

Hello,

I need to keep some tables from splitting over a soft page break. From reading some of the latest posts here it sounds like that is not possible with any of the built in options.

In my case I am performing a mail merge to fill the document and no further editing is done. Is there a way I can make a pass through the document to find the split tables and then add the page breaks myself?

I've tried to find the page number of an Item. I thought I could see if the first cell in a table and the last cell are on different pages. But I can't figure out how to tell what page a specific item is on.

I tried to use the RVData.SoftPageBreaks property to see what items had soft page breaks before them, but that always seemed to be empty. Which kind of made sense since the SoftPageBreaks would be in the Tables Data, but I could not find the SoftPageBreaks property on a TRVTableItemInfo.

I found a reference GetFirstItemOnPageEx (http://www.trichview.com/forums/viewtopic.php?t=1765) but I could not figure out where to call it.

Finally I found this post:
http://www.trichview.com/forums/viewtopic.php?t=3376

That asks a very similar question back in 2009. At that time it sounded like there was not a straight forward way to get this information. Is this still true or is there a way I can accomplish this?

Thanks,

Mark[/code]
MarkElder
Posts: 21
Joined: Tue Aug 28, 2012 7:43 pm

Post by MarkElder »

By the way I am showing my output on a Scale Rich View.
MarkElder
Posts: 21
Joined: Tue Aug 28, 2012 7:43 pm

Post by MarkElder »

So as usual taking the time to write up the question made me think of a few things I had not tried yet. I'd still like to know if there is something I'm missing that is built in. Otherwise here is a working solution.

ScaleRichView has a function that will give you the page number based on a point. And you can draw the table to get the bounds. Check to see if the Top-Left and Bottom-Left corners are on the same page. If they are not then set the PageBreakBefore option.



procedure TRvViewer.FixSplitTables;
var
i: integer;

Style: integer;
RVData: TRichViewRVData;

function SamePageNo(RVData : TCustomRVFormattedData;
ItemNo, Offs : Integer): boolean;
var
DrawItemNo, DrawItemOffs: Integer;
DrawItem: TRVDrawLineInfo;
R: TRect;
PageTop: integer;
PageBottom: integer;

begin
RVData.Item2DrawItem(ItemNo, Offs, DrawItemNo, DrawItemOffs);
DrawItem := RVData.DrawItems[DrawItemNo];
R := Bounds(DrawItem.Left, DrawItem.Top, DrawItem.Width, DrawItem.Height);
RVData.RotateRectFromDocToScreen(R, rvtrbAbsRoot);

PageTop := srvOutput.GetRVPageNo( Point(R.Left, R.Top) );
PageBottom := srvOutput.GetRVPageNo( Point(R.Left, R.Bottom) );

if PageTop = PageBottom then
Result := True
else
Result := False;
end;


begin

RVData := srvOutput.RichViewEdit.RVData;

for i := 0 to RVData.ItemCount - 1 do
begin

Style := RVData.GetItemStyle(i);
if Style = rvsTable then
begin
if SamePageNo(RVData, i, 0) = false then
begin
RVData.GetItem(i).PageBreakBefore := true;
srvOutput.Format;
end;
end;

end;

end;
MarkElder
Posts: 21
Joined: Tue Aug 28, 2012 7:43 pm

Post by MarkElder »

So as usual taking the time to write up the question made me think of a few things I had not tried yet. I'd still like to know if there is something I'm missing that is built in. Otherwise here is a working solution.

ScaleRichView has a function that will give you the page number based on a point. And you can draw the table to get the bounds. Check to see if the Top-Left and Bottom-Left corners are on the same page. If they are not then set the PageBreakBefore option.

Code: Select all


procedure TRvViewer.FixSplitTables;
var
  i: integer;

  Style: integer;
  RVData: TRichViewRVData;

  function SamePageNo(RVData : TCustomRVFormattedData;
    ItemNo, Offs : Integer): boolean;
  var
    DrawItemNo, DrawItemOffs: Integer;
    DrawItem: TRVDrawLineInfo;
    R: TRect;
    PageTop: integer;
    PageBottom: integer;

  begin
    RVData.Item2DrawItem(ItemNo, Offs, DrawItemNo, DrawItemOffs);
    DrawItem := RVData.DrawItems[DrawItemNo];
    R := Bounds(DrawItem.Left, DrawItem.Top, DrawItem.Width, DrawItem.Height);
    RVData.RotateRectFromDocToScreen(R, rvtrbAbsRoot);

    PageTop := srvOutput.GetRVPageNo( Point(R.Left, R.Top) );
    PageBottom := srvOutput.GetRVPageNo( Point(R.Left, R.Bottom) );

    if PageTop = PageBottom then
      Result := True
    else
      Result := False;
  end;


begin

  RVData := srvOutput.RichViewEdit.RVData;

  for i := 0 to RVData.ItemCount - 1 do
  begin

    Style := RVData.GetItemStyle(i);
    if Style = rvsTable then
    begin
      if SamePageNo(RVData, i, 0) = false then
      begin
        RVData.GetItem(i).PageBreakBefore := true;
        srvOutput.Format;
      end;
    end;

  end;

end;

Sergey Tkachenko
Site Admin
Posts: 17569
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Post by Sergey Tkachenko »

Try excluding rvtoRowsSplit from table.PrintOptions
MarkElder
Posts: 21
Joined: Tue Aug 28, 2012 7:43 pm

Post by MarkElder »

I tried that but could not get it to work. I'm using a fairly recent version - we will be upgrading to the December release shortly.

In this post:
http://www.trichview.com/forums/viewtopic.php?t=6312
You talk about using the rvtoRowsSplit option as well but that user had the same problem I was seeing. Has this been fixed?

You say to wrap the table in an outer 1x1 table but that didn't seem to give me the desired effect either. I wondered if it was because of my use of Scale Rich View.
Sergey Tkachenko
Site Admin
Posts: 17569
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Post by Sergey Tkachenko »

SoftPageBreaks are not used by ScaleRichView, this property can be used only with TRVPrint.
Yes, the table without rvtoRowsSplit cannot be split at all, if it is higher than the page it is truncated.
Yes, ScaleRichView still have the same limitation - line breaks not in cells but between rows.

In ScaleRichView, you can use srv.GetPageStartItemNo. If the returned item is a table (srv.RichViewEdit.GetItemStyle(ItemNo)=rvsTable) check the row index returned in Offs. If it is positive, this table is split, you can assign srv.RichViewEdit.PageBreaksBeforeItems[ItemNo] := True.
But if you did it, you need to call srv.Reformat and proceed again. Because adding page breaks for subsequent tables makes no sense until the new page break is applied.
MarkElder
Posts: 21
Joined: Tue Aug 28, 2012 7:43 pm

Post by MarkElder »

Thanks Sergey. That works great. Here is my modified code in case it is useful to anyone else:

Code: Select all

 

procedure TRvViewer.FixSplitTables;
var
  CurrentPage: integer;
  ItemNo: integer;
  Offs: integer;

  RVData: TRichViewRVData;

begin
  srvOutput.Reformat;
  RVData := srvOutput.RichViewEdit.RVData;

  // Use a while loop here, not a for loop.
  // we will be calling reformat which make change the PageCount
  // so we need to reeval PageCount on each pass.
  // Start on the second page, we know the first page can't be split.
  CurrentPage := 2;
  while CurrentPage <= srvOutput.PageCount do
  begin
    srvOutput.GetPageStartItemNo(CurrentPage, ItemNo, Offs);

    // If there is a split table that is not already starting a page
    if (RVData.GetItemStyle(ItemNo) = rvsTable) and
       (Offs > 0) and
       (RVData.GetItem(ItemNo).PageBreakBefore = false) then
    begin
      RVData.GetItem(ItemNo).PageBreakBefore := true;
      // We need to reformat to find out where the new page breaks are
      srvOutput.Reformat;

      // Move to the next page - this will cause a double increment
      // but we know a table now starts the next page, so jump two pages down
      CurrentPage := CurrentPage + 1;
    end;

    CurrentPage := CurrentPage + 1;
  end;

end;
Post Reply