3

I'm using this answer to control the appearance and order of float captions in a document. The relevant part is:

\renewcommand{\thetable}{S\arabic{table}}
\usepackage{tocloft}
\makeatletter
\newcommand{\listfloatname}{\normalsize Contents:}
\newlistof{float}{flt}{\listfloatname}
\long\def\@caption#1[#2]#3{%
\par
\refstepcounter{float}%
\addcontentsline{\csname ext@#1\endcsname}{#1}%
 {\protect\numberline{\csname the#1\endcsname}{\ignorespaces #2}}%
\addcontentsline{flt}{#1}%
 {\protect\numberline{\csname the#1\endcsname}{ #2}}%
\begingroup
\@parboxrestore
\if@minipage
  \@setminipage
\fi
\normalsize
\@makecaption{\csname fnum@#1\endcsname}{\ignorespaces #3}\par
\endgroup}
\makeatother

This is used to label floats in order of appearance in a certain document. However, when I try and use \ref to reference a float, the additional S character does not appear. It works perfectly if I remove the above section, but I need to retain the functionality.

Here is a MWE:

\documentclass{article}
\usepackage{tocloft}
\renewcommand{\thetable}{S\arabic{table}}
%% TOC handling
\makeatletter
\newcommand{\listfloatname}{\normalsize Contents:}
\newlistof{float}{flt}{\listfloatname}
\long\def\@caption#1[#2]#3{%
\par
\refstepcounter{float}%
\addcontentsline{\csname ext@#1\endcsname}{#1}%
 {\protect\numberline{\csname the#1\endcsname}{\ignorespaces #2}}%
\addcontentsline{flt}{#1}%
 {\protect\numberline{\csname the#1\endcsname}{ #2}}%
\begingroup
\@parboxrestore
\if@minipage
  \@setminipage
\fi
\normalsize
\@makecaption{\csname fnum@#1\endcsname}{\ignorespaces #3}\par
\endgroup}
\makeatother


\begin{document}
    \begin{table}
    \caption[Short title]{A table \label{table:a_label}}
    \begin{tabular}{c|c}
        1 & 2 \\
        3 & 4
    \end{tabular}
    \end{table}
    As in \ref{table:a_label}
\end{document}
  • As I can see the \@caption is totally changed for all floats then? Why should \thetable be called by your 'float' counter caption at all? This is weird! – user31729 Jan 4 '17 at 17:35
  • @ChristianHupfer I confess I don't really understand how the \caption is redefined. It is supposed to count the total number of floats, so that it can produce a sorted contents list in order of appearance in the document. But the caption label (in the table) does have the S, so it must call the \thetable... – JP Janet Jan 4 '17 at 17:54
  • With 'order of appearance' you mean the order in the output document, not in the order of specification? – user31729 Jan 4 '17 at 19:27
  • Yes, in the output document. I needed to make a single contents list for all floats, in the order in which they appear in the final document. I got this code from Jagath's answer to the linked question, and it does exactly what is required, but it breaks \ref – JP Janet Jan 4 '17 at 19:34
  • The answer is quite easy (after thinking :D) – user31729 Jan 4 '17 at 19:40
3

This took me some minutes to understand why the reference is wrong.

Well, the table counter is increased already by the \caption command, before \@caption is called, so \refstepcounter{float} will overwrite the \@currentlabel definition, which is used by \label to write the relevant information to the .aux file.

Solution: As long as your particular float shall not be referred to as float don't use \refstepcounter but \stepcounter.

\documentclass{article}
\usepackage{tocloft}
\renewcommand{\thetable}{S\arabic{table}}
%% TOC handling
\makeatletter
\newcommand{\listfloatname}{\normalsize Contents:}
\newlistof{float}{flt}{\listfloatname}
\long\def\@caption#1[#2]#3{%
\par
\stepcounter{float}% No refstepcounter here!
\addcontentsline{\csname ext@#1\endcsname}{#1}%
 {\protect\numberline{\csname the#1\endcsname}{\ignorespaces #2}}%
\addcontentsline{flt}{#1}%
 {\protect\numberline{\csname the#1\endcsname}{ #2}}%
\begingroup
\@parboxrestore
\if@minipage
  \@setminipage
\fi
\normalsize
\@makecaption{\csname fnum@#1\endcsname}{\ignorespaces #3}\par
\endgroup}
\makeatother


\begin{document}
\listoffloat
\begin{table}
  \caption[Short title]{A table \label{table:a_label}}
  \begin{tabular}{c|c}
    1 & 2 \\
    3 & 4
  \end{tabular}
\end{table}
As in \ref{table:a_label}
\end{document}

enter image description here

1

If the only thing you're doing is creating a .flt file to contain each of your floats (perhaps a combination of figures and/or tables), you don't have to redefine the entire \@caption. Instead, insert the relevant contents addition using an etoolbox patch; it's much cleaner:

enter image description here

\documentclass{article}

\usepackage{tocloft,etoolbox}

\renewcommand{\thetable}{S\arabic{table}}

\newcommand{\listfloatname}{\normalsize Contents:}
\newlistof{float}{flt}{\listfloatname}

\makeatletter
\patchcmd{\@caption}% <cmd>
  {\addcontentsline}% <search>
  {\addcontentsline{flt}{#1}{\protect\numberline{\csname the#1\endcsname}{#2}}%
   \addcontentsline}% <replace>
  {}{}% <success><failure>
\makeatother

\begin{document}

\listoffloat

\begin{table}
  \centering
  \caption[Short title]{A table \label{table:a_label}}
  \begin{tabular}{c|c}
    1 & 2 \\
    3 & 4
  \end{tabular}
\end{table}
As in \ref{table:a_label}.

\end{document}

You may even get away with adapting \addcontentsline to insert content into an .flt file every time it is sent content that should go into the .lof or .lot:

enter image description here

\documentclass{article}

\usepackage{tocloft}

\renewcommand{\thetable}{T\arabic{table}}
\renewcommand{\thefigure}{F\arabic{figure}}

\newcommand{\listfloatname}{\normalsize Contents:}
\newlistof{float}{flt}{\listfloatname}

\let\oldaddcontentsline\addcontentsline
\renewcommand{\addcontentsline}[3]{%
  \oldaddcontentsline{#1}{#2}{#3}% Default addition to contents file
  \ifnum\pdfmatch{#1}{lot,lof}=1 % A table or figure...
    \oldaddcontentsline{flt}{#2}{#3}% ...also add to .flt
  \fi
}

\begin{document}

\listoffloat

\section{A section}

A table~\ref{tbl:table} and figure~\ref{fig:figure}.

\begin{table}
  \centering
  \caption[Short title]{A table \label{tbl:table}}
\end{table}

\begin{figure}
  \centering
  \caption[Short figure]{A Figure \label{fig:figure}}
\end{figure}

\end{document}

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.