我即将制作一系列评估文本。其中一些评估有附件,其他没有。我希望能够定义一个特定的类,如下所示:
\documentclass{myexam}
\begin{document}
\frontmatter
\section{Easy steps}
\section{Advanced steps}
\section*{Appendix}
\end{document}
宏\frontmatter
应该打印类似这样的内容:
本文共计 5 页,另加 2 页附录。
而如果没有附录,它应该打印如下:
本文共计5页。
我尝试将标签与条件(\newif\ifannex
等等)一起使用,但似乎不起作用。有什么想法吗?
答案1
您可以使用lastpage
和refcount
包,但修改引入附录的方式。
\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
此解决方案使用\ztotpages
包zref
的模块zref-totpages
来计算总页数。此数字与页码方案无关。问题提到\frontmatter
。通常此用法\pagenumbering{roman}
和以下\mainmatter
用法一起重置页码计数器。包的\pagenumbering{arabic}
标签将不会看到之前的页面。LastPage
lastpage
\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}