Page 1 of 1
Manually Set Page breaks before Split Tables
Posted: Tue Jan 06, 2015 4:24 am
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]
Posted: Tue Jan 06, 2015 4:25 am
by MarkElder
By the way I am showing my output on a Scale Rich View.
Posted: Tue Jan 06, 2015 5:35 am
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;
Posted: Tue Jan 06, 2015 5:37 am
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;
Posted: Tue Jan 06, 2015 7:09 am
by Sergey Tkachenko
Try excluding rvtoRowsSplit from table.PrintOptions
Posted: Tue Jan 06, 2015 1:55 pm
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.
Posted: Thu Jan 08, 2015 11:32 am
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.
Posted: Thu Jan 15, 2015 1:53 am
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;