Multi-Page table with inter-row page breaks

1255 views
Skip to first unread message

nomeata

unread,
Dec 2, 2010, 5:57:52 AM12/2/10
to
Hi,

I’m setting a multi-line table with three columns of known, fixed
width. Each cell contains a paragraph that may consist of several
lines. With supertabular, I can set this table across several pages,
but page breaks are only inserted between table rows, so if there is a
(vertically) large row, a lot of space is wasted and the total
appearance is not good.

What I’m looking for is a way to tell LaTeX to insert page breaks even
within a row, to make full use of the page height.

I’d like to avoid having to manually break the paragraphs into
multiple rows (one per line), but I’m open for horrible TeX hacks.

Thanks,
Joachim

Oleg Paraschenko

unread,
Dec 3, 2010, 7:13:03 AM12/3/10
to
Hello Joachim,

On 2 Dez., 11:57, nomeata <nome...@gmail.com> wrote:
...


> What I’m looking for is a way to tell LaTeX to insert page breaks even
> within a row, to make full use of the page height.

I'm not sure that a typesetting system exists, which could break
within a table row.

Probably you need to find or develop a macro for your task without
using tables.

>
> I’d like to avoid having to manually break the paragraphs into
> multiple rows (one per line), but I’m open for horrible TeX hacks.

You can try to experiment with my package "cals". It first collects
cells to a row, makes something useful and only then emits the row to
TeX. You can hijack into the macro "cals@row@dispatch" and analyze the
box "cals@current@row". In a good case (no spanning over rows or
columns, no empty cells), this hbox is just a set of vboxes. You can
loop over the row content, vsplit each cells on \pagegoal-\pagetotal
and put the parts to two new hboxes: "row before break" and "row after
break". After loop is finished, put the first one to
"cals@current@row", call the old row dispatcher, force a newpage,
update the context to "first row on the page", put "row after break"
to "cals@current@row" and run the original row dispatcher again.

>
> Thanks,
> Joachim

--
Oleg Parashchenko olpa@ http://uucode.com/
http://uucode.com/blog/ XML, TeX, Python, Mac, Chess

GL

unread,
Dec 3, 2010, 10:51:40 AM12/3/10
to
Le 02/12/2010 11:57, nomeata a écrit :
> Hi,
>
> I’m setting a multi-line table with three columns of known, fixed
> width. Each cell contains a paragraph that may consist of several
> lines. With supertabular, I can set this table across several pages,
> but page breaks are only inserted between table rows, so if there is a
> (vertically) large row, a lot of space is wasted and the total
> appearance is not good.

longtable is better than supertabular.

You can't break a table "within" a row but "between two rows".
This is TeX, not LaTeX, and therefore nobody can change that.

\halign does not allow page break inside rows. rows are \hbox,
solid.

nomeata

unread,
Dec 3, 2010, 11:11:08 AM12/3/10
to
On 3 Dez., 13:13, Oleg Paraschenko <ole...@gmail.com> wrote:
> On 2 Dez., 11:57, nomeata <nome...@gmail.com> wrote:
> ...
>
> > What I’m looking for is a way to tell LaTeX to insert page breaks even
> > within a row, to make full use of the page height.
>
> I'm not sure that a typesetting system exists, which could break
> within a table row.

good to know – then I at least have an excuse :-)

> > I’d like to avoid having to manually break the paragraphs into
> > multiple rows (one per line), but I’m open for horrible TeX hacks.
>
> You can try to experiment with my package "cals". It first collects
> cells to a row, makes something useful and only then emits the row to
> TeX. You can hijack into the macro "cals@row@dispatch" and analyze the
> box "cals@current@row". In a good case (no spanning over rows or
> columns, no empty cells), this hbox is just a set of vboxes. You can
> loop over the row content, vsplit each cells on \pagegoal-\pagetotal
> and put the parts to two new hboxes: "row before break" and "row after
> break". After loop is finished, put the first one to
> "cals@current@row", call the old row dispatcher, force a newpage,
> update the context to "first row on the page", put "row after break"
> to "cals@current@row" and run the original row dispatcher again.

I expect that this would be the way to implement it. Unfortunately, I
fear that this is beyond my TeX abilities. I might give it a try
nevertheless, and learn along the way.

Thanks,
Joachim

Oleg Paraschenko

unread,
Dec 6, 2010, 7:13:10 AM12/6/10
to
Hallo Joachim,

On 3 Dez., 17:11, nomeata <nome...@gmail.com> wrote:
...


> I expect that this would be the way to implement it. Unfortunately, I
> fear that this is beyond my TeX abilities. I might give it a try
> nevertheless, and learn along the way.

The task was so interesting and challenging, that I could not avoid
playing with it. The implementation plan was more easy to say than
execute. However, in the first approximation, it worked for a lorem
ipsum example. Maybe it will work for your documents too.

http://uucode.com/download/2010/12/inrow_break/test.pdf
http://uucode.com/download/2010/12/inrow_break/test.tex

The content of the TeX document is:

\documentclass{article}
\usepackage{lipsum}
\usepackage{cals}
\usepackage[latin]{babel}
\showboxbreadth=100
\showboxdepth=100

\makeatletter
\let\oldDispatch=\cals@row@dispatch
\newbox\rowBefore
\newbox\rowAfter
\newbox\decorationCopy
\newdimen\splitHeight

\def\cals@row@dispatch{%
\cals@ifbreak\iftrue % detect that a break is required
\splitHeight=\pagegoal \advance\splitHeight -\pagetotal
\ifdim \splitHeight>50pt % break inrow only if at least 100pt left
\advance\splitHeight -5pt % avoid pagebreak due to overflows
%
% Split the current row on two: before and after the break
%
\setbox\rowBefore=\hbox{}
\setbox\rowAfter=\hbox{}
\def\next{%
\setbox0=\lastbox
\ifvoid0
\def\next{\global\setbox\rowBefore=\box\rowBefore
\global\setbox\rowAfter=\box\rowAfter }%
\else
\setbox2=\vsplit0 to\splitHeight
\setbox\rowBefore=\hbox{\box2 \unhbox\rowBefore}%
\setbox\rowAfter=\hbox{\box0 \unhbox\rowAfter}%
\fi
\next}
\setbox0=\hbox{\unhbox\cals@current@row \next}
%
% Decoration backup, typeset the first row,
% restore context, typeset the second at the end of macro
%
\setbox\decorationCopy=\copy\cals@current@cs
\setbox\cals@current@row=\box\rowBefore
\ht\cals@current@cs=\ht\cals@current@row
\oldDispatch
\cals@issue@break
\cals@thead@tokens
\setbox\cals@current@row=\box\rowAfter
\cals@reheight@cells\cals@current@row
\setbox\cals@current@cs=\box\decorationCopy
\ht\cals@current@cs=\ht\cals@current@row
\let\cals@current@context=b
\fi
\fi
\oldDispatch}

\begin{document}
\begin{calstable}
\colwidths{{150pt}{150pt}{150pt}}
\thead{\brow \bfseries \cell{header1}\cell{header2}\cell{header3}
\mdseries \erow}
\brow \cell{\lipsum[ 1]}\cell{\lipsum[ 2]}\cell{\lipsum[ 3]} \erow
\brow \cell{\lipsum[ 4]}\cell{\lipsum[ 5]}\cell{\lipsum[ 6]} \erow
\brow \cell{\lipsum[ 7]}\cell{\lipsum[ 8]}\cell{\lipsum[ 9]} \erow
\brow \cell{\lipsum[10]}\cell{\lipsum[11]}\cell{\lipsum[12]} \erow
\brow \cell{\lipsum[13]}\cell{\lipsum[14]}\cell{\lipsum[15]} \erow
\brow \cell{\lipsum[16]}\cell{\lipsum[17]}\cell{\lipsum[18]} \erow
\end{calstable}
\end{document}

GL

unread,
Dec 6, 2010, 8:44:24 AM12/6/10
to
Le 06/12/2010 13:13, Oleg Paraschenko a écrit :
> Hallo Joachim,
>
> On 3 Dez., 17:11, nomeata<nome...@gmail.com> wrote:
> ...
>> I expect that this would be the way to implement it. Unfortunately, I
>> fear that this is beyond my TeX abilities. I might give it a try
>> nevertheless, and learn along the way.
>
> The task was so interesting and challenging, that I could not avoid
> playing with it. The implementation plan was more easy to say than
> execute. However, in the first approximation, it worked for a lorem
> ipsum example. Maybe it will work for your documents too.
>
> http://uucode.com/download/2010/12/inrow_break/test.pdf
> http://uucode.com/download/2010/12/inrow_break/test.tex

Seems interesting ideed.
Your paragraphs aren't \sloppy, are they ?

Thanks.

nomeata

unread,
Dec 7, 2010, 6:38:52 AM12/7/10
to
Hi Oleg,

On 6 Dez., 13:13, Oleg Paraschenko <ole...@gmail.com> wrote:
> On 3 Dez., 17:11, nomeata <nome...@gmail.com> wrote:
> The task was so interesting and challenging, that I could not avoid
> playing with it. The implementation plan was more easy to say than
> execute. However, in the first approximation, it worked for a lorem
> ipsum example. Maybe it will work for your documents too.


thanks, it works great, even with \RaggedLeft and \RaggedRight!

I changed the 50pt limit to 5pt to suit my needs.

Are you going to add this feature to cals.sty properly? I’m looking
forward to see that (together with documentation and @-less
configuration for spacing, padding and line widths :-)) in my LaTeX
distribution someday.

Greetings,
Joachim

nomeata

unread,
Dec 16, 2010, 10:30:52 AM12/16/10
to
Hi Oleg,

one small issue: It seems that when a page break occurs within a table
row where the first cell is already finished on the first page, and
only the second cell needs to be broken, then on the next page the
remainder of the second cell is put in the first column.

I could work around the issue for now by adding \\\strut to the first
cell.

Greetings,
Joachim

Reply all
Reply to author
Forward
0 new messages