Excluding subsection from toc but allow proper referencing

I am involved in the later stages of a big project, in which we use the following \tocless command to exclude specific subsections from appearing in the table of contents:

\newcommand{\nocontentsline}[3]{}


However, I recently found out that this messes up the references as can be seen in the enclosed MWE. Is there a way to change the definition of \tocless to correct this behaviour?

\documentclass[12pt,a4paper]{memoir}

\setcounter{tocdepth}{2}
\usepackage[usehighlevels]{alnumsec}
\alnumsectionlevels{1}{section,subsection,subsubsection,paragraph}
\alnumsecstyle{aaaa}
\surroundarabic[{.}][]{}{}
\otherseparators{1}
\alnumsecstyle{aaaa}

\newcommand{\nocontentsline}[3]{}

\begin{document}

\tableofcontents

\section{this the first section}
\subsection{this is a normal subsection}\label{subsec:AA}
\tocless\subsection{this is a subsection not in TOC}\label{subsec:AB}

\section{this the second section}
\tocless\subsection{this is another subsection not in TOC}\label{subsec:BA}

\begin{itemize}
\item referring to 1.1: \ref{subsec:AA}
\item referring to 1.2: \ref{subsec:AB}
\item referring to 2.1: \ref{subsec:BA}
\end{itemize}

\end{document}


Here's a solution by temporarily changing the tocdepth counter (writing to .toc file and then restoring)

\documentclass[12pt,a4paper]{memoir}

\setcounter{tocdepth}{2}
\usepackage[usehighlevels]{alnumsec}
\alnumsectionlevels{1}{section,subsection,subsubsection,paragraph}
\alnumsecstyle{aaaa}
\surroundarabic[{.}][]{}{}
\otherseparators{1}
\alnumsecstyle{aaaa}

\newcommand{\nocontentsline}[3]{}
#1
}

\begin{document}

\tableofcontents

\section{this the first section}
\subsection{this is a normal subsection}\label{subsec:AA}
\tocless{\subsection{this is a subsection not in TOC}}\label{subsec:AB}

\section{this the second section}
\tocless{\subsection{this is another subsection not in TOC}}\label{subsec:BA}

\begin{itemize}
\item referring to 1.1: \ref{subsec:AA}
\item referring to 1.2: \ref{subsec:AB}
\item referring to 2.1: \ref{subsec:BA}
\end{itemize}

\end{document}


Update A slightly improved tocless command that has an optional argument, indicating a tocdepth level.

\documentclass[12pt,a4paper]{memoir}
\usepackage{etoolbox}
\setcounter{tocdepth}{2}
\usepackage[usehighlevels]{alnumsec}
\alnumsectionlevels{1}{section,subsection,subsubsection,paragraph}
\alnumsecstyle{aaaa}
\surroundarabic[{.}][]{}{}
\otherseparators{1}
\alnumsecstyle{aaaa}

\newcommand{\tocless}[2][]{%
\begingroup
\edef\temptocdepth{\number\value{tocdepth}}%
\edef\newtocdepth{\the\numexpr\value{tocdepth}-1}% Calculating a default new tocdepth
\ifblank{#1}{% Apply default
}{% Use the value from #1
}%
#2%
\endgroup
}

\begin{document}

\tableofcontents

\section{this the first section}
\subsection{this is a normal subsection}\label{subsec:AA}
\tocless{\subsection{this is a subsection not in TOC}}\label{subsec:AB}

\section{this the second section}
\tocless[2]{\subsection{this will be in in TOC}}\label{subsec:BA}

\begin{itemize}
\item referring to 1.1: \ref{subsec:AA}
\item referring to 1.2: \ref{subsec:AB}
\item referring to 2.1: \ref{subsec:BA}
\end{itemize}

\end{document}

• This solution is specific to \tocless\subsection, which one might as well replace by a single macro (say) \toclesssubsection. This will not work as expected if you're using \tocless\section. – Werner Mar 11 '16 at 18:27
• @Werner: I added another solution with specification of the toc depth counter ago -- and I did not claim that it would work for other levels ;-) – user31729 Mar 11 '16 at 18:39
• @ChristianHupfer you answered exactly the question's title ;-) – touhami Mar 11 '16 at 18:42
• @touhami: Yes -- not more, not less ;-) – user31729 Mar 11 '16 at 18:46

The problem stems from grouping the sectional unit, which negates the referencing capability. One solution would be to place the \label inside the title, but that would require a coding change.

The following avoids grouping in the definition of \tocless by restoring the definition of \addcontentsline after the sectional unit:

\documentclass{memoir}

\setcounter{tocdepth}{2}
\usepackage[usehighlevels]{alnumsec}
\alnumsectionlevels{1}{section,subsection,subsubsection,paragraph}
\alnumsecstyle{aaaa}
\surroundarabic[{.}][]{}{}
\otherseparators{1}
\alnumsecstyle{aaaa}

\newcommand{\nocontentsline}[3]{}
\newcommand{\tocless}[2]{%
#1{#2}

\begin{document}

\tableofcontents

\section{this the first section}
\subsection{this is a normal subsection}\label{subsec:AA}
\tocless\subsection{this is a subsection not in TOC}\label{subsec:AB}

\section{this the second section}
\tocless\subsection{this is another subsection not in TOC}\label{subsec:BA}

\begin{itemize}
\item referring to 1.1: \ref{subsec:AA}
\item referring to 1.2: \ref{subsec:AB}
\item referring to 2.1: \ref{subsec:BA}
\end{itemize}

\end{document}


When a sectional unit is created, the appropriate counter is \refstep-ed, which leads to an update of a macro called \@currentlabel. \@currentlabel is updated using \def, which has a local scope and doesn't survive beyond the group.

You have to take care that \@currentlabel is the right one after the group ends. You also should be careful about the optional arguments to \subsection.

\documentclass[12pt,a4paper]{memoir}
\usepackage{xparse}

\setcounter{tocdepth}{2}
\usepackage[usehighlevels]{alnumsec}
\alnumsectionlevels{1}{section,subsection,subsubsection,paragraph}
\alnumsecstyle{aaaa}
\surroundarabic[{.}][]{}{}
\otherseparators{1}
\alnumsecstyle{aaaa}

\newcommand{\nocontentsline}[3]{}

\makeatletter
\NewDocumentCommand{\tocless}{msoom}{%
\begingroup
\IfBooleanTF{#2}
{#1{#5}}% case \subsection*{z}
{\IfNoValueTF{#3}
{#1{#5}}% case \subsection{z}
{\IfNoValueTF{#4}
{#1[#3]{#5}}% case \subsection[x]{z}
{#1[#3][#4]{#5}% case \subsection[x][y]{z}
}%
}%
}%
\edef\x{\endgroup\def\noexpand\@currentlabel{\@currentlabel}}\x
}
\makeatother

\begin{document}

\tableofcontents

\section{this the first section}
\subsection{this is a normal subsection}\label{subsec:AA}
\tocless\subsection{this is a subsection not in TOC}\label{subsec:AB}

\section{this the second section}
\tocless\subsection{this is another subsection not in TOC}\label{subsec:BA}

\begin{itemize}
\item referring to 1.1: \ref{subsec:AA}
\item referring to 1.2: \ref{subsec:AB}
\item referring to 2.1: \ref{subsec:BA}
\end{itemize}

\end{document}


The memoir class has the \settocdepth-command (which other class can get with the tocvsec2 package) to (temporarly or globally) set the toc depth:

\documentclass[12pt,a4paper]{memoir}

\setcounter{tocdepth}{2}
\usepackage[usehighlevels]{alnumsec}
\alnumsectionlevels{1}{section,subsection,subsubsection,paragraph}
\alnumsecstyle{aaaa}
\surroundarabic[{.}][]{}{}
\otherseparators{1}
\alnumsecstyle{aaaa}

\newcommand{\nocontentsline}[3]{}

\begin{document}

\tableofcontents

\section{this the first section}
\subsection{this is a normal subsection}\label{subsec:AA}

\settocdepth{section}
\subsection{this is a subsection not in TOC}\label{subsec:AB}

\section{this the second section}
\subsection{this is another subsection not in TOC}\label{subsec:BA}

\begin{itemize}
\item referring to 1.1: \ref{subsec:AA}
\item referring to 1.2: \ref{subsec:AB}
\item referring to 2.1: \ref{subsec:BA}
\end{itemize}

\settocdepth{subsection}
\subsection{this is again in the toc}
\end{document}