# Ship only the last physical page (or the last two/three physical pages)

My question is related to and in continuation to Compiling only a page range or page selection

I would like to output only the last page (or last two/three pages) without knowing the total number of pages in advance. As in the above referred question, compilation should happen for the entire document with all the counters, page number on footers intact.

Is it possible to say something like \keeppages{-1} (from the accepted answer to the above question - https://tex.stackexchange.com/a/96258/26682) and that should do for the last page? I toyed with pageslts package but I dont see any way to achieve what I want.

Any ideas?

PS: the question is self explanatory ... a MWE is not really needed here.

• I have a solution that provides the means to use \keeppages{-3,-1} to keep only the third-to-last and final page (say), but any references to content on the discarded pages will be lost. Is this a sufficient solution?
– Werner
Jan 19 '18 at 19:57
• @Werner sure that is acceptable. in fact, the original question and solution also have the same conditions Jan 20 '18 at 1:27
• @Werner could you please post your solution of enabling \keeppages{-3,-1}? Jan 21 '18 at 17:32
• Sorry, done.
– Werner
Jan 21 '18 at 17:43

Here is a modification to Compiling only a page range or page selection that allows you to use negative numbers that counts from the last page. So, for example, you could use

\discardpages{-2,-1}


to remove the last two pages, or

\keeppages{-3,-1}


to only keep the third-to-last and final page. The adaptation relies of lastpage to place a \label{LastPage} on the last page and use the page number in calculations (thanks to refcount).

\documentclass{article}

\usepackage{lipsum,atbegshi,etoolbox}
\usepackage{lastpage,refcount}

\makeatletter
\AtBeginShipout{% At shipout, decide whether to discard page/not
\renewcommand*{\do}[1]{% How to handle each page entry in csv list
\ifnum##1<0
\ifnum\value{page}=\numexpr\getpagerefnumber{LastPage}+##1+1\relax
\gdef\do####1{}% Do nothing further
\fi
\else% ##1 >= 0
\ifnum\value{page}=##1\relax%
\gdef\do####1{}% Do nothing further
\fi
\fi
}%
}%
}

\newif\ifkeeppage
\newcommand{\keeppages}[1]{% \keeppages{<csv list>}
\xdef\keep@pages{#1}% Store pages to keep
\AtBeginShipout{% At shipout, decide whether to discard page/not
\keeppagefalse%
\renewcommand*{\do}[1]{% How to handle each page entry in csv list
\ifnum##1<0
\ifnum\value{page}=\numexpr\getpagerefnumber{LastPage}+##1+1\relax
\keeppagetrue% Page should be kept
\gdef\do####1{}% Do nothing further
\fi
\else% ##1 >= 0
\ifnum\value{page}=##1\relax%
\keeppagetrue% Page should be kept
\gdef\do####1{}% Do nothing further
\fi
\fi
}%
\expandafter\docsvlist\expandafter{\keep@pages}% Process list of pages to keep
}%
}
\makeatother

\keeppages{-3,-1}% Keep these pages.

\begin{document}

\sloppy\lipsum[1-50]\lipsum[1-50]\lipsum[1-50]\lipsum[1-50]\lipsum[1-50]

\end{document}


The LastPage reference will have to settle in order to be effective. So, you'll have to compile at least twice with every change in this \label location (or at the first go).

No further testing was done to see whether atveryend might be required.

• ...as in the previous solution, this does not preserve cross-references for pages that are removed.
– Werner
Jan 21 '18 at 17:43
• perfect! However in my real document, I had reassigned LastPage counter to one (or more, dynamically determined) lesser and the actual last page (or pages) are ununmbered and unreferenced. I tried setting a new temporary counter to keep track of these extra pages and then do this \ifnum\value{page}=\numexpr\getpagerefnumber{LastPage}+\value{unnumberedpages}+##1+1 in \keeppages. However \value{unnumberedpages} seems to only be set at the initialized value of 0. Maybe because \keeppages{1,-1} is called before \begin{document}. Is there a way out? Jan 22 '18 at 11:59

The problem with this approach is that TeX's model is built sequentially out of "boxes" and "glue." To figure out what's on the 17th page, the TeX system needs to layout the previous 16 pages. The question you linked defines some macros that remove pages after pdf generation, but those pages are still generated.

The simplest manual way is to open your generated pdf in a viewer and use the "Print to PDF" option, specifying a page range. If you want to do this in an automated way, that would be more platform-dependent.

• In fact, fully generating the pages and then discarding them is the goal ... so that one doesn't have to go through the rigmarole of post-processing the PDF file with some other software or subject to pdfpages type hack of recompiling. Jan 20 '18 at 1:33
• @magguu Ah, I see. Werner's solution is probably the best though. You'd think there would be a package that would solve this kind of thing; it doesn't seem like an uncommon thing to want. Jan 20 '18 at 4:26
• @WalterMays: You can try this code. It uses an alternative method to establish a LastPage "reference" (thanks to atveryend). You can change all references to LastPage to something that suits you better. It's just another option.
– Werner
Jan 23 '18 at 5:27
• @Werner I presume you were replying to this tex.stackexchange.com/questions/411180/… .. I followed your excellent suggestion with one change ... I defined a new token called EndPage to do the shovel work for \keeppages, while LastPage is left undisturbed. And it does work very well. Thanks a lot! Jan 23 '18 at 8:09
• @magguu: Indeed. Glad you found it.
– Werner
Jan 23 '18 at 17:07