Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I'm about to produce a series of assessment texts. Some of these assessments have annexes, others don't. I would like to be able to define a specific class, like this :

\documentclass{myexam}
\begin{document}
\frontmatter
\section{Easy steps}
\section{Advanced steps}
\section*{Appendix}
\end{document}

And the \frontmatter macro should print something like :

This text consists of 5 pages plus an appendix of 2 pages.

while, in absence of appendix, it should print like :

This text consists of 5 pages.

I tried to use labels together with a conditional (\newif\ifannex and so on), but it doesn't seem to work. Ideas ?

share|improve this question
    
More details : I had the idea of putting a \label{append} within the appendix (easy) and to define in the preamble a macro like this : \def\apndx{\ref{append}}. When the appendix is present, \apndx gets a value, fine. Else the compiler sends a warning (normal) and \apndx seems to get the value ?? and not \relax. –  rcabane Oct 14 '12 at 18:44
    
What did you try to do? \ref and \label need a second compilation run. –  Qrrbrbirlbel Oct 14 '12 at 19:22
    
Of course, twice (or more) ! –  rcabane Oct 14 '12 at 21:01
add comment

3 Answers

You can use the lastpage and refcount packages, but modifying the way you introduce your appendix.

\documentclass{article}
\usepackage{lastpage,refcount}

\newcommand{\frontmatter}{%
  % Whatever you need to put at the beginning
  \computepages
  This text consists of \pageorpages{\textpages}%
  \ifannex
    \ plus an appendix of \pageorpages{\appendixpages}%
  \fi
  .%
}
\newcommand\pageorpages[1]{#1~page\ifnum#1=1 \else s\fi}
% Just in case we need them
\newcommand\textpages{0}
\newcommand\appendixpages{0}

\makeatletter
\newcommand{\computepages}{%
  \ifannex
    \edef\textpages{\number\numexpr\getpagerefnumber{annexstart}-1\relax}%
    \edef\appendixpages{\number\numexpr\getpagerefnumber{LastPage}-\getpagerefnumber{annexstart}+1\relax}%
  \else
    \edef\textpages{\getpagerefnumber{LastPage}}%
  \fi
}

\newif\ifannex
\newcommand{\annex}[1]{%
  \immediate\write\@auxout{\noexpand\global\noexpand\annextrue}%
  \section*{#1}%
  \label{annexstart}%
}
\makeatother

\begin{document}

\frontmatter

\section{Easy steps}

\newpage
\section{Advanced steps}

\newpage
\annex{Appendix}

\end{document}

This correctly shows

This text consists of 2 pages plus an appendix of 1 page.

while, if the \annex line is commented out, the output is

This text consists of 2 pages.

Of course, a couple of compilations are needed for the numbers to synchronize.

share|improve this answer
    
Great ! I'll check this tomorrow. Anyway, I was convinced it was necessary to write and read directly to the aux file, that was the trick you just implemented. Thank you. –  rcabane Oct 14 '12 at 20:59
    
Is there any drawback in using something like \ifx\r@annexstart\@undefined (as I did in my humble attempt) to check if \annex is called, aside from the fact that the user may use the label without \annex? \label{annexstart} writes to .aux anyway, why not use it? –  Qrrbrbirlbel Oct 14 '12 at 23:20
    
@Qrrbrbirlbel Why did you delete the answer? Your method is good, but I prefer to state explicitly what I want, that's all. –  egreg Oct 14 '12 at 23:25
    
I did not know of refcount, otherwise I would've tried to use \numexpr, too. (And would have avoided running into problems with hyperref and the like.) –  Qrrbrbirlbel Oct 14 '12 at 23:33
add comment

This solution uses \ztotpages of package zref's module zref-totpages for the number of total pages. This number does not depend on the page numbering scheme. The question mentioned \frontmatter. Usually this uses \pagenumbering{roman} and a following \mainmatter uses \pagenumbering{arabic} with resetting the page counter. The label LastPage of package lastpage will not see the pages before \mainmatter.

However it is not clear, on which class myexam is based. The use of \section would assume a article based class, but that does not provide \frontmatter. Classes with \frontmatter would use \chapter. Therefore the solution defines \frontmatter if it is not given, otherwise \frontmatter is extended to print the additional text.

The appendix is detected by the presence of zref label StartAppendix. For convenience the label setting and \section*{Appendix} is put into macro \Appendix. If the label is detected, then the number of appendix pages is added to the text.

\documentclass{exam}

\usepackage{zref-totpages}
\makeatletter
\newcommand*{\AppendixStartLabel}{%
  \@bsphack
    \zref@labelbyprops{StartAppendix}{abspage}%
    \zref@refused{StartAppendix}%
  \@esphack
}
\newcommand*{\printpages}[1]{%
  \ifcase#1%
    \textbf{??}~pages%
  \or
    1~page%
  \else
    \number#1~pages%
  \fi
}
\newcommand*{\FrontmatterText}{%
  \noindent
  This text consists of \printpages{\ztotpages}%
  \zref@ifrefundefined{StartAppendix}{%
  }{%
    \newcommand*{\appendix@pages}{}%
    \edef\appendix@pages{%
      \numexpr\zref@extractdefault{LastPage}{abspage}{0}%
      -\zref@extractdefault{StartAppendix}{abspage}{0}%
      +1%
    }%
    \space including an appendix of \printpages{\appendix@pages}%
  }%
  .\par
}
\@ifundefined{frontmatter}{%
  \newcommand*{\frontmatter}{%
    \clearpage
    \FrontmatterText
  }%
}{%
  \g@addto@macro\frontmatter{\FrontmatterText}%
}
\newcommand{\Appendix}{%
  \clearpage
  \section*{\appendixname}%
  \AppendixStartLabel
}
\makeatother

\begin{document}
\frontmatter
\section{Easy steps}
\section{Advanced steps}
\Appendix
\end{document}

Result

share|improve this answer
    
Hello, I think this is the best solution (in my opinion), quite simple and elegant. –  rcabane Oct 15 '12 at 20:38
    
Works fine; I just think there is a minor error, e.g. the line \space plus an appendix of \printpages{\appendix@pages}% should be \space including an appendix of \printpages{\appendix@pages}% isn't it ? –  rcabane Oct 16 '12 at 6:59
    
@rcabane You are right, I had used the wording of the question, but with a different meaning of "text". Getting the pages without the appendix is left as exercise for the reader (not too difficult with \numexpr, for example). –  Heiko Oberdiek Oct 16 '12 at 8:36
add comment

Better solution

After finding out about refcount we can skip the calculations with counters (and avoid running into problems with hyperref and other packages that redefine \ref so that it is more than just some digits).

I have now borrowed the idea of egreg to outsource the calculations. It makes a much cleaner code.

Code

\documentclass{article}
\usepackage{lastpage}
\usepackage{refcount}
\newcounter{tempcounter}

\newcommand*{\pageorpages}[1]{#1~page\ifnum#1=1 \else s\fi}

\makeatletter
\newcommand*{\textpages}{%Calculation of _text_ pages
  \ifx\r@DontYouDareUseThisLabelApndxStart\@undefined% without appendix
    \number\numexpr\getpagerefnumber{LastPage}+1-\getpagerefnumber{FirstTextPage}\relax
  \else % with appendix
    \number\numexpr\getpagerefnumber{DontYouDareUseThisLabelApndxStart}-\getpagerefnumber{FirstTextPage}\relax
  \fi%
}

\newcommand*{\apndxpages}{% Calculation of _appendix_ pages.
\ifx\r@DontYouDareUseThisLabelApndxStart\@undefined0\else % to prevent errors if this is called accidently
  \number\numexpr\getpagerefnumber{LastPage}-\getpagerefnumber{DontYouDareUseThisLabelApndxStart}+1\relax
\fi
}

\newcommand*{\howmanypages}{% \frontmatter is already defined in some classes
  The following text consists of \pageorpages{\textpages}%
  \ifx\r@DontYouDareUseThisLabelApndxStart\@undefined\else % with appendix
    \space plus an appendix of \pageorpages{\apndxpages}%
  \fi.
  \clearpage % again, no sketchy calculations
  \label{FirstTextPage}
}
\makeatother

\newcommand*{\apndx}{
  \clearpage
  \section*{Appendix}
  \label{DontYouDareUseThisLabelApndxStart} % and I mean it!
}

\usepackage{lipsum}
\begin{document}
\lipsum
\howmanypages
\section{Easy steps}
\lipsum
\section{Advanced steps}
\lipsum
\apndx
\lipsum
\end{document}

Bad Solution (breaks with hyperref and what not)

With the use of one auxiliary counter you can accomplish something like this very easily.

\apndx

The macro apndx uses a \clearpage so that it actually starts on an own page. Otherwise the calculation may be sketchy. The label apndxstart is not only used to get the actual page number, but also to check if there is even an appendix (via the macro \r@apndxstart).

\howmanypages

This macro checks whether a appendix is used:

\ifx\r@apndxstart\@undefined

and then proceed to calculate the actual page numbers.

lastpage package

The lastpage packages is used to get the last page number (with or without appendix).

Code

\documentclass{article}
\usepackage{lastpage}
\newcounter{tempcounter}

\makeatletter
\newcommand*{\howmanypages}{% \frontmatter is already defined in some classes
  \ifx\r@apndxstart\@undefined % without appendix
    \setcounter{tempcounter}{\pageref{LastPage}}
    \addtocounter{tempcounter}{1}
  \else% with appendix
    \setcounter{tempcounter}{\pageref{apndxstart}}%
  \fi%
  \addtocounter{tempcounter}{-\pageref{FirstPage}}
  This text consists of \thetempcounter{} page\ifnum\thetempcounter=1\else s\fi
  \ifx\r@apndxstart\@undefined % without appendix
    .
  \else % with appendix
    \setcounter{tempcounter}{\pageref{LastPage}}%
    \addtocounter{tempcounter}{-\pageref{apndxstart}}%
    \addtocounter{tempcounter}{1}%
    \space plus an appendix of \thetempcounter{} page\ifnum\thetempcounter=1\else s\fi.
  \fi
  \label{FirstPage}
}
\makeatother

\newcommand*{\apndx}{
  \clearpage
  \section*{Appendix}
  \label{apndxstart}
}

\usepackage{lipsum}
\begin{document}
\lipsum
\howmanypages
\section{Easy steps}
\lipsum
\section{Advanced steps}
\lipsum
\apndx
\lipsum
\end{document}
share|improve this answer
    
OK, this works but produces an error at the first compiler pass. –  rcabane Oct 15 '12 at 20:37
    
@rcabane Which error do you get? I only get a warning encouraging me to rerun to get the references right. (And do not use the “Bad Solution”.) –  Qrrbrbirlbel Oct 15 '12 at 21:53
    
Oh it could be that I mistakenly borrowed my file from the bad solution, not from the good one. I got : No file apndx3.aux. [1{/var/lib/texmf/fonts/map/pdftex/updmap/pdftex.map}] ! Missing number, treated as zero. <to be read again> \protect l.36 \howmanypages –  rcabane Oct 16 '12 at 7:02
    
@rcabane This only happens with the “Bad Solution” (by the way, a second run helps to get it work). But as I said, my other solution won't have that problem. It does get the page number in a much cleaner and safer way. –  Qrrbrbirlbel Oct 16 '12 at 17:29
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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