21

For the book I am typesetting now I need a table environment with the following abilities:

  1. Span over multiple pages;
  2. Allow \nopagebreak between two lines
  3. Do not ignore \nopagebreak before the beginning of the environment

Points 1 and 2 can be achieved with longtable environment; but recently I bumped into the situation when the code:

\section{Some section}

\begin{longtable}{...}
...

leaves the section header on one page and starts to typeset longtable on the next page. \nopagebreak between \section and \begin does not help. I found the bug filed on longtable about 9 years ago, but it seems that no-one is interested, and I do not know TeX well enough to fix it myself.

I tried supertabular package — it has the same problem, and stabular which has points 1 and 3, but does not have point 2. Is there some way to make longtable listen to \nopagebreak? Or maybe there is some other package that supports all three points? Or will it be easier to just stack \hboxs and \vboxs in a desired way?

  • Just in case: as a workaround I just put section header in the first line of the table and use \\* longtable macro (which prevents line break inside the table). A bit ugly, but works. – fjarri Mar 29 '11 at 0:41
  • 1
    One thing you could do is to break before the \section with \pagebreak. I tried several things here, but even with an increased penalty and a modified longtable (La)TeX would break at that position. – BernS Apr 26 '11 at 9:37
8

EDIT: as pointed out in a comment below, this solution sometimes produces spurious headers; I do not know how (nor have time) to fix it, sorry.

There are two problems: first, \longtable does the calculations of whether it has enough space on the current page before starting to read the material of the table. Secondly, it inserts a penalty of \z@ (read "zero"), in other words, a place where TeX is allowed to do a page break. We need to inhibit both of those, but in case there is more than one longtable in your book, the change must not be permanent.

Putting the change within a group does not seem possible (because \longtable redefines the output routine locally, I think), so I added a private switch to control whether a penalty and a \break are inserted or not. Put \normalLTfalse before and \normalLTtrue after the longtable (not within) to inhibit the page-break and penalty for that table. (Note that commenting our the line \normalLTfalse will lead to a page break there.)

It may be possible to use the "value" of \if@nobreak instead of explicitly having to use a switch, but I am not sure when \if@nobreak is \iftrue or \iffalse.

\documentclass{article}
\usepackage{longtable}
\usepackage{etoolbox}

\newif\ifnormalLT
\normalLTtrue

\makeatletter
\patchcmd {\LT@start}
          {\vfil \break}
          {\ifnormalLT \vfil \break \fi}
          {\typeout{Patching longtable succeeded!}}
          {\typeout{Patching longtable failed!}\ERROR}
\patchcmd {\LT@start}
          {\penalty \z@}
          {\ifnormalLT \penalty \z@ \fi}
          {\typeout{Patching longtable succeeded!}}
          {\typeout{Patching longtable failed!}\ERROR}
\makeatother

% "lipsum" is just used to have some dummy text.
% The vspace is there so that without patch
% we would have a bad page break. Remove all that.
\usepackage{lipsum}
\begin{document}
\lipsum[1-2]
\vspace{2.5cm}
\lipsum[3-4]

\section{XY}
\normalLTfalse
\begin{longtable}{c}
A \\
C \\
\end{longtable}
\normalLTtrue

\end{document}
  • This solution works -- mostly. Unfortunately in some cases it also results in spurious table headers which are being output in the "next page" even when all rows have already been typeset.. no idea why this is happening though :-( – Grodriguez Jan 26 '17 at 12:48
  • @Grodriguez Thanks. Unfortunately I don't know how nor have time to fix it, sorry. I've added a note to my answer. Maybe you can ask another question and link here? – Bruno Le Floch Jan 26 '17 at 20:24
  • Thank you for the answer. Looks like there's already a question using your patch and describing this problem: tex.stackexchange.com/questions/157398/… – Grodriguez Jan 27 '17 at 7:53
16
+25

Use the needspace package and put \Needspace{5\baselineskip} before the section. (The exact value depends on the class and the spaces the section inserts.)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.