1

For better or for worse, I've defined the page numbers of my appendix using

\pagenumbering{arabic}\renewcommand{\thepage}{A.\arabic{page}}

If I create a label foo using \label{foo} on page A.21, then a call to \pageref{foo} expands to A.21 in the text. Ultimately, I want to determine if the page number is odd or even.

My attempt was to create a macro that strips off the "A." part and leaves the "21". I tried defining

\def \appnum A.#1 {#1}

to accomplish this. In the document, the command

\appnum A.21

returns "21" with no error. However, the command

\appnum \pageref{foo}

returns the error

! Use of \appnum doesn't match its definition.

I tried variations of \expandafter and \expand to fix this, such as

\expandafter\appnum\pageref{foo}

to no avail.

My real question is "How can I strip off the 'A.' from the page reference so the \isodd command can determine if the page number is odd or even.?" I think that if someone explains how to get my \appnum macro to read the \pageref correctly I'll be able to go from there.

  • You need to use c@page rather than the \thepage. texdoc source2e and have a look at ltpageno.dtx. The \pagenumbering also defines \thepage. Also see package ifoddpage at ctan for some pointers. – Yiannis Lazarides Jul 20 '18 at 14:00
2

You can use \refcount:

\documentclass{article}
\usepackage[paperwidth=6cm,paperheight=4cm,margin=2mm,includefoot]{geometry}
\usepackage{refcount}

\makeatletter
% we assume page numbers are either plain numbers or of the form A.<number>
\newcommand{\oddorevenpage}[1]{%
  % #1 = label for the page to check
  % #2 = text for odd page
  % #3 = text for even page
  \ifodd\expandafter\remove@A@prefix\expandafter{\romannumeral-`Q\getpagerefnumber{#1}}
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
}

\def\remove@A@prefix#1{\remove@A@prefix@aux A.#1A.#1A.\@nil}
\def\remove@A@prefix@aux A.#1A.#2A.#3\@nil{#2}

\makeatother

\begin{document}

x\label{odd}

\oddorevenpage{odd}{This page is odd}{This page is even}

\clearpage

x\label{even}

\oddorevenpage{even}{This page is odd}{This page is even}

\clearpage

\pagenumbering{arabic}
\renewcommand{\thepage}{A.\arabic{page}}

x\label{odd-app}

\oddorevenpage{odd-app}{This page is odd}{This page is even}

\clearpage

x\label{even-app}

\oddorevenpage{even-app}{This page is odd}{This page is even}

\clearpage

\setcounter{page}{21}

x\label{foo}

\oddorevenpage{foo}{This page is odd}{This page is even}

\end{document}

enter image description here

The same with expl3:

\documentclass{article}
\usepackage[paperwidth=6cm,paperheight=4cm,margin=2mm,includefoot]{geometry}
\usepackage{refcount}
\usepackage{xparse}

\ExplSyntaxOn
% we assume page numbers are either plain numbers or of the form A.<number>
\NewExpandableDocumentCommand{\oddorevenpage}{mmm}
 {% #1 = label for the page to check
  % #2 = text for odd page
  % #3 = text for even page
  \gregh_odd_even:fnn { \getpagerefnumber{#1} } { #2 } { #3 }
 }

\cs_new:Nn \gregh_odd_even:nnn
 {
  \int_if_odd:nTF { \gregh_remove_prefix:n { #1 } } { #2 } { #3 }
 }
\cs_generate_variant:Nn \gregh_odd_even:nnn { f }

\cs_new:Nn \gregh_remove_prefix:n
 {
  \__gregh_remove_prefix_aux:w A. #1 A. #1 A. \q_stop
 }

\cs_new:Npn \__gregh_remove_prefix_aux:w A. #1 A. #2 A. #3 \q_stop { #2 }

\ExplSyntaxOff

\begin{document}

x\label{odd}

\oddorevenpage{odd}{This page is odd}{This page is even}

\clearpage

x\label{even}

\oddorevenpage{even}{This page is odd}{This page is even}

\clearpage

\pagenumbering{arabic}
\renewcommand{\thepage}{A.\arabic{page}}

x\label{odd-app}

\oddorevenpage{odd-app}{This page is odd}{This page is even}

\clearpage

x\label{even-app}

\oddorevenpage{even-app}{This page is odd}{This page is even}

\clearpage

\setcounter{page}{21}

x\label{foo}

\oddorevenpage{foo}{This page is odd}{This page is even}

\end{document}
0

I just deleted my previous answer. Here is the re-write:

Using \ref/\pageref for obtaining numerals in a way where calculations are possible is not a good idea:

Reasons:

The \label-command does save away the expansion of \thepage. As you have done yourself, \thepage can be redefined to also deliver tokens not belonging to the value of the page counter in arabic numerals.

Many packages redefine referencing commands to deliver non-numeral items also.
E.g. the hyperref package redefines referencing commands to nest tokens forming numeral values within tokens that make the whole thing a hyperlink.

Another issue is:

Let's take a document for an arrangement of successive pages.

Via \pagenumbering you both reset the value of the page counter to 0 and set the way in which that value gets printed.

After resetting the page counter to 0 within the appendix, the value of the page counter will for subsequent pages not be both an ordinal number which would denote the placing of the page in question within the arrangement of all pages of the document and a nominal number/nominal value for naming the page, but will only be a nominal number/nominal value.

E.g., for detecting whether a page is a left-hand-page or a right-hand-page, looking at the nominal number/nominal value alone might not be sufficient. Therefore Heiko Oberdiek implemented in his zref package the module abspage: With this module, page numbers are counted not only in the count-register for the page-counter but also within another count-register which throughout the entire LaTeX-run will never be reset. Referencing pages by this other count-register will in any case denote the placing of the page in question within the arrangement of pages.

Solution 1—I prefer this one as there is no need of post-processing a reference for stripping possible prefix-phrases:

Use the zref package with module abspage from Heiko Oberdiek both for having another referenceable property denoting the position of the page in question within the arrangement of all pages of the document, and for introducing new referenceable properties as needed:

With the zref-based coding example below,

  • \RefPageCounterValueInArabic{foo} will deliver in arabic numerals without any additional trumpery the value the page counter had when shipping out that page which LaTeX was about to build when encountering the corresponding \zlabel{foo}-command.

  • \CheckWhetherPageCounterValueInArabicOdd{foo}{tokens if odd}{tokens if even} is a means for branching depending on whether that value is odd or even.

  • \AbsolutePageref{foo} will—regardless any resetting of the page counter and regardless any changing of the style of page-numbering—tell you which element within the arrangement of all pages of the document the page is that LaTeX was about to build when encountering the corresponding \zlabel{foo}-command.

  • \CheckWhetherAbsPageOdd{foo}{tokens if odd}{tokens if even}: When \AbsolutePageref{foo} tells you that the page which LaTeX was about to build when encountering the corresponding \zlabel{foo}-command is the n-th element of the arrangement of all the pages of the document, then \CheckWhetherAbsPageOdd{foo}{tokens if odd}{tokens if even} is a means for branching depending on the parity of n.

 

\documentclass{article}
\usepackage{hyperref}
\usepackage[user, abspage]{zref}

\makeatletter
\newcommand\MyRefUndefPhrase{%
  \nfss@text{\reset@font\bfseries??}%
}%
%
% Dealing with the value held in the page-counter's count-register:
%
\zref@newprop*{PageNumValueInArabic}[\MyRefUndefPhrase]{\arabic{page}}%
\zref@addprop{main}{PageNumValueInArabic}%
%
\newcommand\RefPageCounterValueInArabic[1]{%
  \zref@extractdefault{#1}{PageNumValueInArabic}{\MyRefUndefPhrase\refused{#1}}%
}%
\newcommand\CheckWhetherPageCounterValueInArabicOdd[1]{%
  \refused{#1}%
  \ifodd\zref@extractdefault{#1}{PageNumValueInArabic}{0} %<-This space must be!
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
}%
%
% Dealing with the position of the page in question within the
% arrangement of all pages belonging to the document:
%
\newcommand\AbsolutePageref[1]{%
  \zref@extractdefault{#1}{abspage}{\MyRefUndefPhrase\refused{#1}}%
}%
\newcommand\CheckWhetherAbsPageOdd[1]{%
  \refused{#1}%
  \ifodd\zref@extractdefault{#1}{abspage}{0} %<-This space must be!
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
}%
\makeatother    

\begin{document}
\section{page numbers without prefix}
Some text.\label{foo}\zlabel{foo}

\verb|\pageref{foo}|:
\pageref{foo}

\bigskip

\verb|\RefPageCounterValueInArabic{foo}|:
\RefPageCounterValueInArabic{foo}

\verb|\CheckWhetherPageCounterValueInArabicOdd{foo}{odd}{even}|:
\CheckWhetherPageCounterValueInArabicOdd{foo}{odd}{even}

\bigskip

\verb|\AbsolutePageref{foo}|:
\AbsolutePageref{foo}

\verb|\CheckWhetherAbsPageOdd{foo}{odd}{even}|:
\CheckWhetherAbsPageOdd{foo}{odd}{even}

\bigskip

\verb|\pageref{bar}|:
\pageref{bar}

\bigskip

\verb|\RefPageCounterValueInArabic{bar}|:
\RefPageCounterValueInArabic{bar}

\verb|\CheckWhetherPageCounterValueInArabicOdd{bar}{odd}{even}|:
\CheckWhetherPageCounterValueInArabicOdd{bar}{odd}{even}

\bigskip

\verb|\AbsolutePageref{bar}|:
\AbsolutePageref{bar}

\verb|\CheckWhetherAbsPageOdd{bar}{odd}{even}|:
\CheckWhetherAbsPageOdd{bar}{odd}{even}

\newpage

\pagenumbering{arabic}
\renewcommand{\thepage}{A.\arabic{page}}

\section{page numbers with prefix ``A.''}
Some text.\label{bar}\zlabel{bar}

\end{document}

Page 1 (1 of 2): enter image description here

Page A.1 (2 of 2): enter image description here

Solution 2:

If obtaining without any trumpery just the value the page counter had when shipping out the page which LaTeX was about to build when encountering the \label-command in question is sufficient to you, and you don't need to know exactly which element that page is within the arrangement of all pages that belong to the document, you can probably do the trick using \getrefbykeydefault from Heiko Oberdiek's refcount package.

In the coding example below, the way in which cranking out cases where page numbers are preceded by "A." might appear a bit cumbersome. It works expandable and without sentinel-tokens that must not occur within the token sequence to check. And implementing checks for other leading phrases is easy as you only need to call \UD@internaltokencheckdefiner once more before you can put the pieces together.

\documentclass{article}
\usepackage{hyperref}
\usepackage{refcount}

\makeatletter
%%----------------------------------------------------------------------
%% Check whether argument is empty:
%%......................................................................
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is empty>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
%%
\newcommand\UD@CheckWhetherNull[1]{%
  \romannumeral0\expandafter\@secondoftwo\string{\expandafter
  \@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
  \@secondoftwo\string}\expandafter\@firstoftwo\expandafter{\expandafter
  \@secondoftwo\string}\expandafter\expandafter\@firstoftwo{ }{}%
  \@secondoftwo}{\expandafter\expandafter\@firstoftwo{ }{}\@firstoftwo}%
}%
%%----------------------------------------------------------------------
%% Exchange two arguments
%%......................................................................
\newcommand\UD@Exchange[2]{#2#1}%
%%----------------------------------------------------------------------
%% Check whether argument's leading tokens form a specific 
%% token-sequence that does not contain explicit character tokens of 
%% category code 1 or 2:
%%......................................................................
%% \UD@CheckWhetherLeadingTokens{<a <token sequence> without explicit 
%%                                character tokens of category code 1 or 2>}%
%%                              {a <single non-space token> that does 
%%                                _not_ occur in <token sequence> >}%
%%                              {<internal token-check-macro>}%
%%                              {<argument which is to be checked>}%
%%                              {<tokens to be delivered in case <argument
%%                                which is to be checked> has <token sequence>
%%                                as leading tokens>}%
%%                              {<tokens to be delivered in case <argument
%%                                which is to be checked> does not have
%%                                <token sequence> as leading tokens>}%
\newcommand\UD@CheckWhetherLeadingTokens[4]{%
  \romannumeral0\UD@CheckWhetherNull{#4}%
  {\expandafter\expandafter\@firstoftwo{ }{}\@secondoftwo}%
  {\expandafter\@secondoftwo\string{\expandafter
   \UD@@CheckWhetherLeadingTokens#3#2#4#1}{}}%
}%
\newcommand\UD@@CheckWhetherLeadingTokens[1]{%
  \expandafter\UD@CheckWhetherNull\expandafter{\@firstoftwo{}#1}%
  {\UD@Exchange{\@firstoftwo}}{\UD@Exchange{\@secondoftwo}}%
  {\UD@Exchange{ }{\expandafter\expandafter\expandafter\expandafter
   \expandafter\expandafter\expandafter}\expandafter\expandafter
   \expandafter}\expandafter\@secondoftwo\expandafter{\string}%
}% 
%%----------------------------------------------------------------------
%% \UD@internaltokencheckdefiner{<internal token-check-macro>}%
%%                              {<token sequence>}%
%% Defines <internal token-check-macro> to snap everything 
%% until reaching <token sequence>-sequence and spit that out
%% nested in braces.
%%......................................................................
\newcommand\UD@internaltokencheckdefiner[2]{%
  \newcommand#1{}\long\def#1##1#2{{##1}}%
}%
\UD@internaltokencheckdefiner{\UD@CheckADot}{A.}%
%%----------------------------------------------------------------------
%% Remove leading "A."
%%......................................................................    
\newcommand\removeAdot{}
\def\removeAdot A.{}
%%----------------------------------------------------------------------
%% Check for leading "A." and remove if present:
%%......................................................................    
\newcommand\removeAdotWhenPresent[1]{%
  \romannumeral0%
  \UD@CheckWhetherLeadingTokens{A.}%
                               {:}%
                               {\UD@CheckADot}%
                               {#1}%
                               {\@firstoftwo\expandafter{} \removeAdot}%
                               { }%
                               #1%
}%
%%----------------------------------------------------------------------
%% Textual phrase for undefined references
%%......................................................................    
\newcommand\MyRefUndefPhrase{%
  \nfss@text{\reset@font\bfseries??}%
}%
%%----------------------------------------------------------------------
%% Referencing-commands:
%%......................................................................    
\newcommand\RefPageCounterValueInArabic[1]{%
  \expandafter\expandafter\expandafter\removeAdotWhenPresent
  \expandafter\expandafter\expandafter{%
    \getrefbykeydefault{#1}{page}{A.\MyRefUndefPhrase\refused{#1}}%
  }%
}%
\newcommand\CheckWhetherPageCounterValueInArabicOdd[1]{%
  \refused{#1}%
  \ifodd
    \expandafter\expandafter\expandafter\removeAdotWhenPresent
    \expandafter\expandafter\expandafter{%
      \getrefbykeydefault{#1}{page}{A.0}%
    } %<-This space must be!
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
}%
\makeatother

\begin{document}
\section{page numbers without prefix}
Some text.\label{foo}

\verb|\pageref{foo}|:
\pageref{foo}

\verb|\RefPageCounterValueInArabic{foo}|:
\RefPageCounterValueInArabic{foo}

\verb|\CheckWhetherPageCounterValueInArabicOdd{foo}{odd}{even}|:
\CheckWhetherPageCounterValueInArabicOdd{foo}{odd}{even}

\verb|\pageref{bar}|:
\pageref{bar}

\verb|\RefPageCounterValueInArabic{bar}|:
\RefPageCounterValueInArabic{bar}

\verb|\CheckWhetherPageCounterValueInArabicOdd{bar}{odd}{even}|:
\CheckWhetherPageCounterValueInArabicOdd{bar}{odd}{even}

\newpage

\pagenumbering{arabic}
\renewcommand{\thepage}{A.\arabic{page}}

\section{page numbers with prefix ``A.''}
Some text.\label{bar}

\end{document}

Page 1 (1 of 2): enter image description here

Page A.1 (2 of 2): enter image description here

Be aware that in any case during the first LaTeX-run no references are defined yet. During the first LaTeX-run all references, \pageref-references as well, are undefined.

With both solutions during the first LaTeX-run referencing the page-counter's value yielding 0 is assumed, and in the .log-file warnings about undefined references and the need to re-run LaTeX are issued.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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