TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I want to check whether the document has any figures so as to decide whether or not to have a list of figures. Is this possible? Feasible without doing something like parsing the lof file?

Note that checking whether the lof file is empty is not a good enough solution for me, as some code may be writing things other than table lines into it (e.g. babel).

share|improve this question
    
What about checking whether the *.lof (and *.lot) file exists at all? – Thorsten Donig Oct 31 '11 at 18:08
1  
@ThorstenDonig: \listoffigures calls \@starttoc{lof} which creates/writes to \jobname.lof. So \jobname.lof only exists based the call \listoffigures. Checking for its existence is therefore "too late". – Werner Oct 31 '11 at 21:27
    
So, this is a related question from today: – einpoklum Mar 6 at 21:17
up vote 15 down vote accepted

The idea behind this attempt is to use standard LaTeX references in order to detect whether a figure was used in the document. Here are the steps involved (with some modifications by @egreg):

  1. Conjure up a label name that you won't use in your document, ever. Something like fig:was:used:in:doc.
  2. Patch the figure environment to define an empty command (say) \there@is@a@figure at the end of every figure. This is possible using the etoolbox package which provides \AtEndEnvironment. More specifically, the command

    \AtEndEnvironment{figure}{\gdef\there@is@a@figure{}} 
    

    will be perpetually redefined until the last figure in the document.

  3. At the end of the document, we check whether \there@is@a@figure exists (is defined), and define a label \label{fig:was:used:in:doc}. It doesn't really matter what this label contains (it could be the last used figure, section, table, or whatever):

    \AtEndDocument{\ifdefined\there@is@a@figure\label{fig:was:used:in:doc}\fi}
    
  4. Write your own "conditional LoF" command using

    \newcommand{\conditionalLoF}{\@ifundefined{r@fig:was:used:in:doc}{}{\listoffigures}}%
    

    The command \conditionalLoF checks whether the macro \r@fig:was:used:in:doc is defined or not. This is the standard LaTeX referencing mechanism at work, since each label <lab> has an associated macro \r@<lab> defined. \@ifundefined{<cs>}{<undef code>}{<def code>} allows execution of <undef code> if <cs> is undefined, otherwise execute <def code>.

  5. Use \conditionalLoF instead of \listoffigures.
  6. Compile your document at least 3 times.

The main idea behind (1) is to have the label fig:was:used:in:doc only exist when using a figure, and not having to worry about what it is called. (2) provides the hook to the figure environment and allows a global (re)definition of \there@is@a@figure. (3) delays the definition of the fig:was:used:in:doc label until the end of the document in order to avoid causing "Multiply defined label" warnings. (4) and (5) provides a clean interface to the conditional LoF. (6) may be the only drawback. However, this comes standard with label referencing, requiring at least two compiles to work in general.

Here's a minimal working example (MWE). It uses graphicx (with the demo package option) and lipsum merely for show and is therefore actually not necessary. Compiling this MWE

\documentclass{article}
\usepackage{etoolbox}% http://ctan.org/pkg/etoolbox
\usepackage[demo]{graphicx}% http://ctan.org/pkg/graphicx
\usepackage{lipsum}% http://ctan.org/pkg/lipsum
\makeatletter
\AtEndEnvironment{figure}{\gdef\there@is@a@figure{}} 
\AtEndDocument{\ifdefined\there@is@a@figure\label{fig:was:used:in:doc}\fi} 
\newcommand{\conditionalLoF}{\@ifundefined{r@fig:was:used:in:doc}{}{\listoffigures}}%
\makeatother
\begin{document}
\conditionalLoF% Conditionally insert List of Figures
\section{First section}
\lipsum[1]
%\begin{figure}
%  \centering\includegraphics{figure}
%  \caption{This is a caption}
%\end{figure}
\end{document}

as-is produces

enter image description here

Uncommenting the figure environment and compiling a couple of times produces

enter image description here

share|improve this answer
1  
This will cause spurious "Multiply defined label" messages. – egreg Oct 31 '11 at 17:07
1  
I've added code that won't show the problem, you can integrate it into your answer (the idea is just the same). – egreg Oct 31 '11 at 17:16
    
Absolutely correct. Is there a way to append (say) a counter to the label fig:was:used:in:doc and then only check for (say) \r@fig:was:used:in:doc:1? – Werner Oct 31 '11 at 17:17
    
You'll have seen my addition, by now. :) – egreg Oct 31 '11 at 17:17
1  
Thanks, I'll give this a try in my document, but - there are a few buts: 1. This seems only to work for figures, not for a Table of Contents or other such tables. 2. Someone might write a "myfigure" environment which adds to the list of figures using whatever sub-command used by the figure environment, and I will be none the wiser. 3. I would rather, if possible, use the mechanism the figure environment uses to add entries to the list, rather than create a new and idiosyncratic one. – einpoklum Oct 31 '11 at 21:21

A different approach is using the totalcount package:

\documentclass{article}
\usepackage[demo]{graphicx}% http://ctan.org/pkg/graphicx
\usepackage{lipsum}% http://ctan.org/pkg/lipsum

\usepackage[figure]{totalcount}

\begin{document}

% Conditionally insert List of Figures
\iftotalfigures
  \listoffigures
\fi

\section{First section}
\lipsum[1]

%\begin{figure}
%  \centering\includegraphics{figure}
%  \caption{This is a caption}
%\end{figure}

\end{document}
share|improve this answer
    
That's much nicer, I'll need to try it out... – einpoklum Mar 6 at 20:46
    
Next time I have an LoF, that is. – einpoklum Mar 6 at 20:46

Here's a combination of totcount and assoccnt (it's combined in xassoccnt now, at least some features of totcount)

xassoccnt defines counters that step with a master counter, say figure but are not reset if figure is set to zero, i.e. the totalfigures counter holds the total number of figures (unless manipulated directly).

Using the \NewTotalDocumentFeature, the value of a total counter is written to the .aux file at the end of the compilation run and read in in the next run, i.e. the number of figures is known at the start of the document.

Werner used the refcount approach together with assoccnt (which is the predecessor of xassoccnt, which is much more developed than assoccnt (I know about the states -- I am the author of (x)assoccnt ;-))

I redefined the \listof... commands slightly.

\documentclass{book}

\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{xassoccnt}
\usepackage{graphicx}
\usepackage{tabularx}

\NewTotalDocumentCounter{totalfigures}
\NewTotalDocumentCounter{totaltables}

\DeclareAssociatedCounters{figure}{totalfigures}
\DeclareAssociatedCounters{table}{totaltables}

\makeatletter
\renewcommand{\TotalValue}[1]{%  A small bug fix
  \value{xassoccnt@total@#1}%
}


\let\@@latex@@listoffigures\listoffigures
\let\@@latex@@listoftables\listoftables

\renewcommand{\listoffigures}{%
  \ifnum\TotalValue{totalfigures} > 0 
  \@@latex@@listoffigures%
  \fi
}


\renewcommand{\listoftables}{%
  \ifnum\TotalValue{totaltables} > 0 
  \@@latex@@listoftables%
  \fi
}


\makeatother





\begin{document}
\tableofcontents

\clearpage


\listoftables

\listoffigures


A figure:

\begin{figure}[htbp]
\centering
\includegraphics[width=0.25\linewidth]{example-image-a}
\caption{A picture}
\label{fig:label}
\end{figure}

A table:

\begin{table}[htbp]
\centering
%\caption{A table}
\label{tab:label}
\begin{tabularx}{\linewidth}{lX}
test & test test test test test test test test test test test test test test test test test test test test
\end{tabularx}
\end{table}


\end{document}
share|improve this answer
    
Can you explain what these two packages are about, and how your solution compares to @AxeSommerfeldt's solution? – einpoklum Mar 6 at 21:03
    
By the way, is there some special reason this question is getting attention, over 4 years after I accepted a solution? – einpoklum Mar 6 at 21:04
    
@einpoklum: There was a similar question today ;-) – Christian Hupfer Mar 6 at 21:08
    
A dupe? If not, link it please... – einpoklum Mar 6 at 21:12
    
@einpoklum: Not a real dupe, in my point of view. – Christian Hupfer Mar 6 at 21:13

One could use the assoccnt package where you can associate a counter with some other master counter, stepping it in tandem. At the end of the document, you write out a \label that would capture the existing total count of the associated counter. Then, using refcount's expandable \getrefnumber, a conditional LoF (or other Table of Contents structure) could be printed.

\documentclass{article}
\usepackage{graphicx,lipsum,assoccnt,refcount}
\newcounter{totfigure}% This will capture the total number of figures
\DeclareAssociatedCounters{figure}{totfigure}% Step totfigure with every figure
\makeatletter
\AtEndDocument{%
  \edef\@currentlabel{\arabic{totfigure}}% Update current \label value
  \label{tot:figs:used:in:doc}}% Mark \label
\newcommand{\conditionalLoF}{%
  \ifnum\getrefnumber{tot:figs:used:in:doc}>0 % Check whether 'totfigure' > 0
    \listoffigures\fi}% If so, print \listoffigures
\makeatother
\begin{document}
\conditionalLoF% Conditionally insert List of Figures
\section{First section}
\lipsum[1]
%\begin{figure}
  %\centering\includegraphics[width=.5\linewidth]{example-image}
  %\caption{This is a caption}
%\end{figure}
\end{document}
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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