0

I originally asked for a solution which would automatically give me the range of subfigures in a caption. Skillmon came up with something which did work with my original MWE, but which gives problems with cleveref and besidecaption (from komascript).

Here's the new MWE:

\documentclass{scrartcl}
\usepackage[demo]{graphicx}
\usepackage{subcaption}
\usepackage{caption}
\usepackage{etoolbox}
\newcommand*\MySubcaptionFirst{}
\newcommand*\MySubcaptionLast{}
\makeatletter
\newcommand*\MySubcaptionRange
  {%
    \MySubcaptionFirst
    \ifx\MySubcaptionLast\@empty
    \else
      --\MySubcaptionLast
    \fi
  }
\newcommand*\SubCaptionBoxPatch
  {%
    \ifx\MySubcaptionFirst\@empty
      \expandafter\def\csname the\@captype\endcsname
        {\arabic{\@captype}\MySubcaptionRange}%
      \edef\MySubcaptionFirst{\csname thesub\@captype\endcsname}%
    \else
      \edef\MySubcaptionLast{\csname thesub\@captype\endcsname}%
    \fi
  }
\apptocmd \caption@iiibox 
  {\SubCaptionBoxPatch} 
  {}
  {\GenericError{}{Patching failed}{}{}}
\makeatother
\usepackage{cleveref}
\crefrangelabelformat{figure}%
      {\emph{#3#1#4--#5\crefstripprefix{#1}{#2}#6}}
\crefrangelabelformat{subfigure}%
      {\emph{#3#1#4--#5\crefstripprefix{#1}{#2}#6}}

\begin{document}

\begin{figure}

\subcaptionbox{\label{fig:img1}}{%
 \includegraphics[width=0.5\columnwidth]{image.jpg}}%
\subcaptionbox{\label{fig:img2}}{%
 \includegraphics[width=0.5\columnwidth]{image.jpg}}
 \subcaptionbox{\label{fig:img3}}{%
 \includegraphics[width=0.5\columnwidth]{image.jpg}}%
\subcaptionbox{\label{fig:img4}}{%
 \includegraphics[width=0.5\columnwidth]{image.jpg}}
\begin{captionbeside}
{Caption}
\subcaptionbox{\label{fig:img5}}{\includegraphics[width=0.5\columnwidth]{image.jpg}}
\end{captionbeside}
\end{figure}
\crefrange{fig:img1}{fig:img4}
\end{document}

There are several problems here:

  • This produces errors when compiling (Argument of \@cref@firsttok has an extra }.)
  • The reference produced by cleveref is wrong. It should be 1a–d, but it is instead 1a––cd.
  • The caption is missing the subcaptionbox in the the captionbeside environment and therefore only prints 1a–d instead of 1a–e.

I more or less understand what is happening in the the case of captionbeside, but the interaction with cleveref is beyond me.

  • The issue in captionbeside is easy to understand as the changes made to \MySubcaptionLast are made local and don't have any effect if used inside captionbeside. A more complicated setup with global defs and a reset at the start and end of the figure or table environments would solve this. – Skillmon Sep 20 '18 at 16:26
1

Here is a version which does work with your MWE. I changed the way it works to using global definitions and not changing the formatting of the counter it's used for but by changing the way the caption package does print its caption labels.

\documentclass{scrartcl}

\usepackage{graphicx}
\usepackage{subcaption}
\usepackage{caption}
\usepackage{etoolbox}
\usepackage{duckuments}% random pictures not every time the same, totally useless for serious documents

\AtBeginEnvironment{figure}{\ClearMySubcaptionThings}
\AtEndEnvironment{figure}{\ClearMySubcaptionThings}
\AtBeginEnvironment{table}{\ClearMySubcaptionThings}
\AtEndEnvironment{table}{\ClearMySubcaptionThings}
\newcommand*\ClearMySubcaptionThings
  {%
    \gdef\MySubcaptionFirst{}%
    \gdef\MySubcaptionLast{}%
  }
\newcommand*\MySubcaptionFirst{}
\newcommand*\MySubcaptionLast{}
\makeatletter
\newcommand*\MySubcaptionRange
  {%
    \MySubcaptionFirst
    \ifx\MySubcaptionLast\@empty
    \else
      --\MySubcaptionLast
    \fi
  }
\newcommand*\SubCaptionBoxPatch
  {%
    \ifx\MySubcaptionFirst\@empty
      \xdef\MySubcaptionFirst{\csname thesub\@captype\endcsname}%
    \else
      \xdef\MySubcaptionLast{\csname thesub\@captype\endcsname}%
    \fi
  }
\apptocmd \caption@iiibox 
  {\SubCaptionBoxPatch} 
  {}
  {\GenericError{}{Patching failed}{}{}}
\makeatother
\DeclareCaptionLabelFormat{subcaptions}
  {#1 #2\MySubcaptionRange}
\captionsetup{labelformat=subcaptions}

\usepackage{cleveref}
\crefrangelabelformat{figure}%
      {\emph{#3#1#4--#5\crefstripprefix{#1}{#2}#6}}
\crefrangelabelformat{subfigure}%
      {\emph{#3#1#4--#5\crefstripprefix{#1}{#2}#6}}

\begin{document}

\begin{figure}
  \subcaptionbox{\label{fig:img1}}
    {\includegraphics[width=0.4\columnwidth]{example-image-duck}}
  \subcaptionbox{\label{fig:img2}}
    {\includegraphics[width=0.4\columnwidth]{example-image-duck}}
  \subcaptionbox{\label{fig:img3}}
    {\includegraphics[width=0.4\columnwidth]{example-image-duck}}
  \subcaptionbox{\label{fig:img4}}
    {\includegraphics[width=0.4\columnwidth]{example-image-duck}}\linebreak
  \begin{captionbeside}{Caption}
    \subcaptionbox{\label{fig:img5}}
      {\includegraphics[width=0.4\columnwidth]{example-image-duck}}
  \end{captionbeside}
\end{figure}
\crefrange{fig:img1}{fig:img4}

\begin{figure}
  \centering
  \includegraphics[width=.8\columnwidth]{example-image-duck}
  \caption{Big duck\label{fig:big}}
\end{figure}
\end{document}

Output of multiple subcaptions: enter image description here

Output of a single caption (also to show everything is reverted correctly)): enter image description here

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.