更好的解决方案

更好的解决方案

我即将制作一系列评估文本。其中一些评估有附件,其他没有。我希望能够定义一个特定的类,如下所示:

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

\frontmatter应该打印类似这样的内容:

本文共计 5 页,另加 2 页附录。

而如果没有附录,它应该打印如下:

本文共计5页。

我尝试将标签与条件(\newif\ifannex等等)一起使用,但似乎不起作用。有什么想法吗?

答案1

您可以使用lastpagerefcount包,但修改引入附录的方式。

\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}

这正确显示

本文包含 2 页正文和 1 页附录。

而如果\annex注释掉该行,则输出为

本文共计 2 页。

当然,需要进行几次编译才能使数字同步。

答案2

此解决方案使用\ztotpageszref的模块zref-totpages来计算总页数。此数字与页码方案无关。问题提到\frontmatter。通常此用法\pagenumbering{roman}和以下\mainmatter用法一起重置页码计数器。包的\pagenumbering{arabic}标签将不会看到之前的页面。LastPagelastpage\mainmatter

但是,尚不清楚基于哪个类myexam。使用\section会假设article基于类,但这并不提供\frontmatter。带有 的类 \frontmatter将使用\chapter。因此,解决方案定义\frontmatter如果没有给出 ,否则\frontmatter将扩展以打印附加文本。

附录是通过zref标签的存在来检测的StartAppendix。为方便起见,将标签设置和\section*{Appendix}放入宏中\Appendix。如果检测到标签,则将附录页数添加到文本中。

\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}

结果

答案3

更好的解决方案

了解refcount我们可以跳过使用计数器的计算(并避免遇到与hyperref其他包重新定义的问题\ref,从而使其不仅仅是一些数字)。

我现在借用了 egreg 的想法来外包计算。它使代码更加简洁。

代码

\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}

糟糕的解决方案(打破hyperref常规)

通过使用一个辅助计数器,您可以非常轻松地完成这样的事情。

\apndx

apndx使用,\clearpage以便它实际上从自己的页面开始。否则计算可能是粗略的。标签apndxstart不仅用于获取实际页码,还可以用于检查是否有附录(通过宏\r@apndxstart)。

\howmanypages

此宏检查附录是否被使用:

\ifx\r@apndxstart\@undefined

然后继续计算实际页码。

lastpage包裹

lastpage包用于获取最后一页的页码(带或不带附录)。

代码

\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}

相关内容