6

I have a rather large project, from which I select portions based on needs. This selection is done using a complex system of \include and \input commands. I would like to generate a list of figures and a list of tables for the output, but in the case there are no figures the list of figures should not appear. The same should happen with tables.

Here is a MWE:

\documentclass[10pt,twocolumn]{article}
\usepackage{lipsum}
\usepackage[margin=0.75in]{geometry}
\usepackage{float}
\floatstyle{boxed}


\restylefloat{figure}
\restylefloat{table}

\def\ignoreTable#1\end{table}{}
\def\ignoreFigure#1\end{figure}{}
\begin{document}

\tableofcontents
\addcontentsline{toc}{section}{List of Figures}
\listoffigures
\addcontentsline{toc}{section}{List of Table}
\listoftables

\section{First section}
\lipsum[\inputlineno]
\ignoreFigure
\begin{figure}[H]\centering
\LaTeX\LaTeX
\caption{my figure}
\end{figure}
\lipsum[\inputlineno]
\begin{figure}[H]\centering
\LaTeX\TeX
\caption{another figure}
\end{figure}
\section{Second section}
\lipsum[\inputlineno]
\ignoreTable
\begin{table}[H]\centering
\TeX\LaTeX
\caption{my table}
\end{table}
\lipsum[\inputlineno]
\ignoreTable
\begin{table}[H]\centering
\TeX\TeX
\caption{another table}
\end{table}
\lipsum[\inputlineno]
\end{document}

enter image description here

Where if I write

\def\ignoreTable{\relax}
\def\ignoreFigure{\relax}

just after \begin{document} the output is:

enter image description here


Ideally, there would be an "elegant" macro or package, that would eliminate the list of tables, including its entry in the TOC, if there are not tables.

3 Answers 3

7

Here is another approach. What it does is to check at the end of the document the values of the figure and table counters, and add to the .aux file a boolean flag setting depending on whether these values are zero or positive.

Then you have on next run \iffigures and \iftables which allow you to act conditionally.

In the code below, perhaps the \global are not really needed, I didn't check.

See also a variant at bottom which does not use the figure/table counters because they might well be reset to zero due to document sectioning (as pointed out by egreg in a comment).

\documentclass[10pt,twocolumn]{article}
\usepackage{lipsum}
\usepackage[margin=0.75in]{geometry}
\usepackage{float}
\floatstyle{boxed}

\restylefloat{figure}
\restylefloat{table}

\newif\iffigures
\newif\iftables

\makeatletter
\AtEndDocument {%
    \if@filesw
       \ifnum\value{figure}=\z@ % no figures
          \immediate\write\@mainaux {\global\string\figuresfalse}%
       \else
          \immediate\write\@mainaux {\global\string\figurestrue}%
       \fi
       \ifnum\value{table}=\z@ % no tables
          \immediate\write\@mainaux {\global\string\tablesfalse}%
       \else
          \immediate\write\@mainaux {\global\string\tablestrue}%
       \fi
    \fi
}
\makeatother 

% for the purpose of testing

% this will make a MWE without tables
\long\def\IGNORE #1\ENDIGNORE{}

% uncomment to make a MWE with tables
% \let\IGNORE\empty
% \let\ENDIGNORE\empty

\begin{document}

\tableofcontents

% 
\iffigures
   \addcontentsline{toc}{section}{List of Figures}
   \listoffigures
\fi

% 
\iftables
   \addcontentsline{toc}{section}{List of Table}
   \listoftables
\fi

\section{First section}
\lipsum[\inputlineno]
\begin{figure}[H]\centering
\LaTeX\LaTeX
\caption{my figure}
\end{figure}
\lipsum[\inputlineno]
\begin{figure}[H]\centering
\LaTeX\TeX
\caption{another figure}
\end{figure}
\section{Second section}
\lipsum[\inputlineno]
\IGNORE
\begin{table}[H]\centering
\TeX\LaTeX
\caption{my table}
\end{table}
\ENDIGNORE
\lipsum[\inputlineno]
\IGNORE
\begin{table}[H]\centering
\TeX\TeX
\caption{another table}
\end{table}
\ENDIGNORE
\lipsum[\inputlineno]
\end{document}

Here is for a document with figures but no tables:

without tables

And if tables are present:

with tables

Three compilations needed.

Variant. I don't know to what extent patching \figure and \table as here is OK, depends perhaps on float related packages. At the worst I guess doing the patches immediately after \begin{document} should be enough (at the end of preamble might not be enough if some package does stuff during At Begin Document).

\documentclass[10pt,twocolumn]{article}
\usepackage{lipsum}
\usepackage[margin=0.75in]{geometry}
\usepackage{float}
\floatstyle{boxed}

\restylefloat{figure}
\restylefloat{table}

\newif\iffigures
\newif\iftables

\makeatletter

\let\OLDfigure\figure
\def\figure {\figures@in@document\OLDfigure }
\let\OLDtable\table
\def\table  {\tables@in@document\OLDtable }

\def\figures@in@document {%
    \immediate\write\@mainaux {\global\string\figurestrue}%
    \global\let\figures@in@document\empty
}

\def\tables@in@document {%
    \immediate\write\@mainaux {\global\string\tablestrue}%
    \global\let\tables@in@document\empty
}

\makeatother

% for the purpose of testing

% this will make a MWE without tables
\long\def\IGNORE #1\ENDIGNORE{}

% uncomment to make a MWE with tables
%\let\IGNORE\empty
%\let\ENDIGNORE\empty

\begin{document}

\tableofcontents

% 
\iffigures
   \addcontentsline{toc}{section}{List of Figures}
   \listoffigures
\fi

% 
\iftables
   \addcontentsline{toc}{section}{List of Table}
   \listoftables
\fi

\section{First section}
\lipsum[\inputlineno]
\begin{figure}[H]\centering
\LaTeX\LaTeX
\caption{my figure}
\end{figure}
\lipsum[\inputlineno]
\begin{figure}[H]\centering
\LaTeX\TeX
\caption{another figure}
\end{figure}
\section{Second section}
\lipsum[\inputlineno]
\IGNORE
\begin{table}[H]\centering
\TeX\LaTeX
\caption{my table}
\end{table}
\ENDIGNORE
\lipsum[\inputlineno]
\IGNORE
\begin{table}[H]\centering
\TeX\TeX
\caption{another table}
\end{table}
\ENDIGNORE
\lipsum[\inputlineno]
\end{document}
4
  • There is an s missing at the end of the List of Table thing in the TOC, was copied over from OP's code.
    – user4686
    Mar 22, 2015 at 9:07
  • Good idea, but it won't work in case figure or table numbers are reset at chapter/sections and the last chapter/section has no table or figures. The totcount package may make your life easier, because it takes care of the writing in the .aux file.
    – egreg
    Mar 22, 2015 at 11:17
  • @egreg I updated my answer, I do not have time to checkout the totcount package until later.
    – user4686
    Mar 22, 2015 at 11:35
  • I tried to use several methods. Until recently the concept of adding a label at the end of the document worked fine. After some updates it stopped working, I use it in a class I created for a document I am writing. So I tried all the counter methods and several other without success, the second approach is the only one that worked for me. I expanded it, as did before, to work for the glossary build with datagidx and the Todo list. For the glossary it took a few 'redefines', but that is part of the process if you want to do something that out of the ordinary.
    – Louis
    Dec 23, 2016 at 9:26
6

In order to add the lists to the table of contents, I recommend using tocbibind, which ensures correct page numbers even if the lists go on for more than one page.

The trick is to measure the contents of the .lof or .lot files: if they don't produce any output, we omit them, but we still initiate their production.

\documentclass[10pt,twocolumn]{article}
\usepackage{lipsum}
\usepackage[margin=0.75in]{geometry}
\usepackage{float}
\usepackage[nottoc]{tocbibind}
\floatstyle{boxed}


\restylefloat{figure}
\restylefloat{table}

\def\ignoreTable#1\end{table}{}
\def\ignoreFigure#1\end{figure}{}
%\def\ignoreTable{}
%\def\ignoreFigure{}

\makeatletter
\let\tocbibind@tocfile\tocfile
\renewcommand{\tocfile}[2]{%
  \setbox\z@=\vbox{\@input{\jobname.#2}}
  \ifdim\ht\z@>\z@
    \tocbibind@tocfile{#1}{#2}%
  \else
    % do the same as \@starttoc without the \@input instruction
    \begingroup
    \makeatletter
    \if@filesw
      \expandafter\newwrite\csname tf@#2\endcsname
      \immediate\openout \csname tf@#2\endcsname \jobname.#2\relax
    \fi
    \@nobreakfalse
    \endgroup
  \fi
}
\makeatother


\begin{document}

\tableofcontents
\listoffigures
\listoftables

\section{First section}
\lipsum[\inputlineno]
\ignoreFigure
\begin{figure}[H]\centering
\LaTeX\LaTeX
\caption{my figure}
\end{figure}
\lipsum[\inputlineno]
\ignoreFigure
\begin{figure}[H]\centering
\LaTeX\TeX
\caption{another figure}
\end{figure}
\section{Second section}
\lipsum[\inputlineno]
\ignoreTable
\begin{table}[H]\centering
\TeX\LaTeX
\caption{my table}
\end{table}
\lipsum[\inputlineno]
\ignoreTable
\begin{table}[H]\centering
\TeX\TeX
\caption{another table}
\end{table}
\lipsum[\inputlineno]
\end{document}

With the uncommented definitions of \ignoreTable and \ignoreFigure we get none of them and the output is

enter image description here

If I enable figures but not tables, the output is

enter image description here

Finally, if I enable tables and figures, I get

enter image description here


Alternative method

With an up-to-date TeX distribution, the assoccnt package is available and a much safer test can be used using it along with totcount.

Change the code above into

\documentclass[10pt,twocolumn]{article}
\usepackage{lipsum}
\usepackage[margin=0.75in]{geometry}
\usepackage{float}
\usepackage[nottoc]{tocbibind}
\floatstyle{boxed}

\usepackage{totcount,assoccnt}
\newtotcounter{totallof}
\newtotcounter{totallot}
\DeclareAssociatedCounters{figure}{totallof}
\DeclareAssociatedCounters{table}{totallot}

\restylefloat{figure}
\restylefloat{table}

\def\ignoreTable#1\end{table}{}
\def\ignoreFigure#1\end{figure}{}
%\def\ignoreTable{}
%\def\ignoreFigure{}

\makeatletter
\let\tocbibind@tocfile\tocfile
\renewcommand{\tocfile}[2]{%
  \ifnum\totvalue{total#2}>\z@ % there are figures or tables
    \tocbibind@tocfile{#1}{#2}%
  \else
    % do the same as \@starttoc without the \@input instruction
    \begingroup
    \makeatletter
    \if@filesw
      \expandafter\newwrite\csname tf@#2\endcsname
      \immediate\openout \csname tf@#2\endcsname \jobname.#2\relax
    \fi
    \@nobreakfalse
    \endgroup
  \fi
}
\makeatother


\begin{document}

\tableofcontents
\listoffigures
\listoftables

\section{First section}
\lipsum[\inputlineno]
\ignoreFigure
\begin{figure}[H]\centering
\LaTeX\LaTeX
\caption{my figure}
\end{figure}
\lipsum[\inputlineno]
\ignoreFigure
\begin{figure}[H]\centering
\LaTeX\TeX
\caption{another figure}
\end{figure}
\section{Second section}
\lipsum[\inputlineno]
\ignoreTable
\begin{table}[H]\centering
\TeX\LaTeX
\caption{my table}
\end{table}
\lipsum[\inputlineno]
\ignoreTable
\begin{table}[H]\centering
\TeX\TeX
\caption{another table}
\end{table}
\lipsum[\inputlineno]
\end{document}
0
5

You can measure the lists and discard them if they only have a heading:

\documentclass[10pt,twocolumn]{article}
\usepackage{lipsum}
\usepackage[margin=0.75in]{geometry}
\usepackage{float}
\floatstyle{boxed}

\def\wheninteresting#1{%
\setbox0\vbox{#1}%
\ifdim\ht0>35pt
\unvbox0
\fi}

\restylefloat{figure}
\restylefloat{table}

\def\ignoreTable#1\end{table}{}
\def\ignoreFigure#1\end{figure}{}
\begin{document}

\tableofcontents
\wheninteresting{
\addcontentsline{toc}{section}{List of Figures}
\listoffigures
}

\wheninteresting{
\addcontentsline{toc}{section}{List of Table}
\listoftables
}
\section{First section}
\lipsum[\inputlineno]
\ignoreFigure
\begin{figure}[H]\centering
\LaTeX\LaTeX
\caption{my figure}
\end{figure}
\lipsum[\inputlineno]
\begin{figure}[H]\centering
\LaTeX\TeX
\caption{another figure}
\end{figure}
\section{Second section}
\lipsum[\inputlineno]
\ignoreTable
\begin{table}[H]\centering
\TeX\LaTeX
\caption{my table}
\end{table}
\lipsum[\inputlineno]
\ignoreTable
\begin{table}[H]\centering
\TeX\TeX
\caption{another table}
\end{table}
\lipsum[\inputlineno]
\end{document}
4
  • Did you leave @Yossi's \def\ignoreTable#1\end{table}{} as is on purpose, despite the fact that it results in tabletable in the output (the first from the \def the second from the fact that only up to and included the \end was gobbled) ?
    – user4686
    Mar 22, 2015 at 8:23
  • David Carlisle, is safe use the value 35pt on \ifdim\ht0>35pt? Because my empty header could be bigger than 35pt, or my header plus a list only with one item could be smaller than 35pt. Is there a way to compute the header size, so there is not need to use a hard coded value of 35pt?
    – user
    Nov 10, 2019 at 0:43
  • @user sorry I don't know what you mean, it is much better to make a real complete example and post as a new question than ask as a comment on a 4 year old answer. Nov 10, 2019 at 0:47

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .