1

I have a document which pulls in an external .tex file which is procedurally generated from a database and then interpreted into a multiple page table-like graphic written in TikZ.

However, when I hit a pagebreak I need to be able to add a header line much like longtable does. At the moment I'm using the everypage package, but that is really suboptimal because it doesn't play very nice with memoir, destroys my margins, adds a third reference to deal with (separate from both memoir and TikZ current page positioning). It also runs its code after the page has been executed (as far as I can tell?) which makes it difficult to reference things that happened on the previous page.

I have tried to read longtable but didn't get very far—it's impressive but a bit cryptic without guidance.

What is the correct way to implement a longtable-like repeating header for a table-shaped graph?

Here's an MWE of something I tried:

In theory, this should check each time it makes an \exampleblock to see if there's a header on the page, and if not, then it adds one. It works fine on the first page, but is always two blocks too low after that—I don't really know why.

% !TEX TS-program = xelatex

\documentclass[showtrims]{memoir}
\usepackage{tikz}

\setstocksize{11in}{8.5in}
\settrimmedsize{8.5in}{5.5in}{*}
\settrims{1in}{1in}
\setulmarginsandblock{1in}{1in}{*}
\setlrmarginsandblock{1in}{.75in}{*}

\checkandfixthelayout

\newcounter{headeronpage}

\newcommand\exampleblock{\vfill%
    \ifnum\value{headeronpage}<\value{page}%
        \headerthing\vfill\fi%
    \noindent\tikz\draw(0,0)rectangle%
    (\linewidth,12ex)node[pos=.5]%
    {I'm a fancy TikZ drawing!};%
}

\newcommand\headerthing{%
    \setcounter{headeronpage}{\value{page}}%
    \noindent\tikz\draw (0,0)%
    rectangle (\linewidth,4ex)%
    node[pos=.5]{I'm a header thing!};%
}

\begin{document}

    \exampleblock
    \exampleblock
    \exampleblock
    \exampleblock
    \exampleblock
    \exampleblock
    \exampleblock
    \exampleblock
    \exampleblock
    \exampleblock
    \exampleblock
    \exampleblock
    \exampleblock
    \exampleblock
    \exampleblock
    \exampleblock
    \exampleblock
    \exampleblock
    \exampleblock
    \exampleblock
    \exampleblock
    \exampleblock
    \exampleblock
    \exampleblock

\end{document}

How is this challenge handled in packages like longtable?

Just to clarify: I know fancyhdr and stuff (though don't know how they work under the hood), what I'm trying to do isn't that kind of header, but more of a long table.

7
  • 1
    "It also runs its code after the page has been executed" the page breaking always happens after all macros on the page (and perhaps following pages) are executed and all text has been typeset. that is the basic mechanism of tex's page breaker which is asynchronous with respect to the macro expansion and paragraph building systems. May 12, 2015 at 9:02
  • Since you know your widths in advance (I think) the simplest is to put the heading in the page head using fancyhdr or memoir's heading facilities (if they are different). May 12, 2015 at 9:04
  • @DavidCarlisle I must admit I haven't tried putting my tikzpicture inside a fancyhdr, but that sounds like a bit of a margin calculating nightmare... I'd much prefer if I could somehow have it actually inside the typeblock—is that impossible? How did you solve this problem when you wrote longtable?
    – Ryan
    May 12, 2015 at 9:08
  • longtable replaces the standard output routine with its own so it takes control of the full page makeup including headers footers etc, and also why it doesn't work with say multicol (as that is doing the same) but also note that the longtable headers do not depend on the table content as they are set at a different time. (the dependency on column widths is handled indirectly and requires multiple latex runs) May 12, 2015 at 9:21
  • Do you think it's possible to use \pagetotal to measure if there's enough space left over for another block, and insert a \headerthing if there's not enough space?
    – Ryan
    May 12, 2015 at 9:27

1 Answer 1

2

I think I may have found a solution:

(based on this question and answer)

% !TEX TS-program = xelatex

\documentclass[showtrims]{memoir}
\usepackage{tikz}

\setstocksize{11in}{8.5in}
\settrimmedsize{8.5in}{5.5in}{*}
\settrims{1in}{1in}
\setulmarginsandblock{1in}{1in}{*}
\setlrmarginsandblock{1in}{.75in}{*}

\checkandfixthelayout

\newcounter{headeronpage}

\newlength\blockheight
\setlength\blockheight{.5in}

\newcommand\exampleblock{\vfill%
    \ifnum\dimexpr\pagetotal+\blockheight>\textheight%
        \headerthing\vfill\fi%
    \noindent\tikz\draw(0,0)rectangle%
    (\linewidth,\blockheight)node[pos=.5]%
    {Pagetotal says \the\pagetotal 
    and the text is \the\textheight};%
}

\newcommand\headerthing{%
    \setcounter{headeronpage}{\value{page}}%
    \noindent\tikz\draw (0,0)%
    rectangle (\linewidth,4ex)%
    node[pos=.5]{I'm a header thing!};%
}

\begin{document}

    \headerthing

    \exampleblock
    \exampleblock
    \exampleblock
    \exampleblock
    \exampleblock
    \exampleblock
    \exampleblock
    \exampleblock
    \exampleblock
    \exampleblock
    \exampleblock
    \exampleblock
    \exampleblock
    \exampleblock
    \exampleblock
    \exampleblock
    \exampleblock
    \exampleblock
    \exampleblock
    \exampleblock
    \exampleblock
    \exampleblock
    \exampleblock
    \exampleblock

\end{document}

The key difference is instead of checking \value{page}, I'm measuring from the top using \pagetotal and then placing a header if the next block won't fit:

\ifnum\dimexpr\pagetotal+\blockheight>\textheight\headerthing\vfill\fi%
4
  • This is safe here as the \vfill at the start of each block exercises the page builder, and the blocks themselves don't stretch so \pagegoal is more or less trustworthy. the problem in general if you have paragraphs of text is that a single paragraph is executed as a unit (and \pagegoal is not changed during that time) but after being broken into lines may cause one or more page to be filled, but that general difficulty doesn't apply in your case. May 12, 2015 at 9:55
  • To see the general case, change to \newcommand\exampleblock{\space% so all the blocks are a paragraph broken into lines, one block per line and see the value of \pagegoal and lack of header on page 2. May 12, 2015 at 9:55
  • @DavidCarlisle Thanks for the feedback, yeah, I can get away with it here because my graphics are a perfect grid (in my actual implementation). What do you mean by "exercises the page builder" though?
    – Ryan
    May 12, 2015 at 10:57
  • at certain "interesting" points (read the afterpage doc for a full list:-) TeX interrupts its processing and decides whether to invoke the output routine, which if invoked has to decide whether to make up pages out of the currently typeset material. \vfill being a vertical command forces tex into vertical mode between each of your \exampleblock and that is enough to trigger the page breaker, which doesn't decide to break the page in most cases, but it does reset \pagetotal without the \vfill \pagetotal doesn't change and so the test for a heading doesn't work. May 12, 2015 at 11:21

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .