Take the 2-minute tour ×
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.

During the draft phase of an article, when the text is being developed and things move around a lot, I place all my figures at the end of the document so that I'm not greeted with sudden layout changes. Later, when I'm more comfortable with the text (but still liable to change), I bring the figures upfront one by one.

My question is: Instead of having to lug around the entire

\begin{figure}
    \centering
    \includegraphics[...]{...}
    \label{fig:test}
    \caption{...}
\end{figure}

block to reposition the figure, is it possible to leave them where they are (i.e. towards the end of the document) and "place" them where I want by simply referencing them in some custom way, such as:

\placehere{fig:test}

which will place the float (defined later in the document) at the current position? This way, I can move the figures around with a single line instead of several.

The resulting document layout would look something like:

\documentclass{article}
\usepackage{lipsum,graphicx}
\begin{document}
\section{Lorem}
\lipsum[5]
\placehere{fig:test1}

\section{Dolor}
\lipsum[5]
\placehere{fig:test2}

\section{Final section}
\lipsum[5]

\begin{figure}
    \centering
    \includegraphics[...]{...}
    \label{fig:test1}
    \caption{...}
\end{figure}

\begin{figure}
    \centering
    \includegraphics[...]{...}
    \label{fig:test2}
    \caption{...}
\end{figure}
\end{document}
share|improve this question
2  
Use the endfloat package. –  Ulrike Fischer Jun 9 '13 at 9:04
1  
Just make a macro for each figure, e.g., \newcommand{\figureone}{\begin{figure}...\end{figure}}. Then use \figureone wherever you want the figure. –  Matthew Leingang Jun 9 '13 at 11:05

2 Answers 2

up vote 5 down vote accepted

The following implementation requires that you prepare your figures and tables in a different file, which is anyway better for the application you have in mind.

In the example code the figure environments have been typed in a filecontents environment. You don't need it, just prepare a file with the same name as your main LaTeX file and extension .flo.

\begin{filecontents}{\jobname.flo}
\begin{figure}[htp]
    \centering
    ABC
    \caption{...}
    \label{fig:test1}
\end{figure}

\begin{figure}[htp]
    \centering
    DEF
    \caption{...}
    \label{fig:test2}
\end{figure}
\end{filecontents}

\documentclass{article}
\usepackage{environ}
\usepackage{lipsum}

\AtBeginDocument{%
  \begingroup
  \InputIfFileExists{\jobname.flo}{\setupprefloats}{}%
  \endgroup
}
\makeatletter
\newcommand{\setupprefloats}{%
  \let\figure\relax\let\endfigure\relax
  \let\table\relax\let\endtable\relax
  \prefloat@rename{figure}\prefloat@rename{table}%
}

\newcommand{\prefloat@rename}[1]{%
  \NewEnviron{#1}{%
    \let\label\prefloat@label
    \renewcommand\caption[2][]{####2}%
    \setbox\z@=\vbox{\BODY}
    \toks@=\expandafter{\BODY}
    \expandafter\xdef\csname prefloat@\theprefloat@label\endcsname{%
      \noexpand\begin{#1}\the\toks@\noexpand\end{#1}}%
  }%
}
\newcommand{\prefloat@label}[1]{%
  \gdef\theprefloat@label{#1}%
}
\newcommand{\placehere}[1]{%
\expandafter\show\csname prefloat@#1\endcsname
  \@nameuse{prefloat@#1}%
}
\makeatother

\begin{document}
\section{Lorem}
\lipsum[5]
\placehere{fig:test1}

\section{Dolor}
\lipsum[5]
\placehere{fig:test2}

\section{Final section}
\lipsum[5]

\end{document}

At \begin{document} the file will be read in and the figure and table environments are temporarily redefined to store their contents in a special command that is later delivered with the \placehere command.

share|improve this answer
    
Is it not good practice to have the labels inside the caption? I refer to this comment from the LaTeX wiki en.wikibooks.org/wiki/LaTeX "A label may sometimes pick up the section or list number instead of the figure number. In this case, put the label inside the caption to ensure correct numbering." –  PatrickT Dec 10 at 14:19
    
is this code still working? I'm getting ! Illegal parameter number in definition of \prefloat@rename. –  PatrickT Dec 10 at 14:20
1  
@PatrickT The code was wrong! I fixed it, thanks. Maybe it has to do with the newest version of environ. The note in the Wikibook is mysterious: the wrong number is picked up only if \label is before \caption. While \label inside the argument to \caption is legal, I find it much better placing it outside (after \caption, of course). –  egreg Dec 10 at 14:56
    
thanks for fixing it! Yes it works as is now. It didn't work with the sidewaysfigure environment of the rotating package, I think, any thoughts? –  PatrickT Dec 10 at 16:55
    
@PatrickT No. Please, add a new question with an example. –  egreg Dec 10 at 17:00

If you are willing to define your figures (and/or tables) with macros, rather than environments, the boxhandler package has figure/table deferral, using the macros \holdFigures and \clearFigures.

In both approaches, commenting a single line of code changes the figures from appearing inline to being collected at the end of the document.

APPROACH 1:

Using this approach, you just place the figure content in the document inline, using the macro \bxfigure. If \holdFigures is active, it will not print out until \clearFigures is issued.

\documentclass{article}
\usepackage{lipsum}
\usepackage[demo]{graphicx}
\usepackage{boxhandler}
\holdFigures%  COMMENT THIS LINE WILL INSERT FIGURES WHERE THEY ARE DEFINED
\begin{document}
\section{Lorem}
\lipsum[5]
\bxfigure[ht]{caption\label{fig:test1}}
{\includegraphics[width=1in]{file1}}

\section{Dolor}
\lipsum[5]
\bxfigure[ht]{caption\label{fig:test2}}
{\includegraphics[width=2in]{file2}}

\section{Final section}
\lipsum[5]

\clearFigures
\end{document}

Here we have the document with \holdFigures active:

enter image description here

and here we have it with \holdFigures commented:

enter image description here

APPROACH 2:

I sometimes find it more convenient to define all my figures at the beginning of a document and then call them as needed. With this approach, you leave \holdFigures in the preamble for both cases, define your figures all at the beginning of the document, and then use \nextFigure[] to place it inline in your document. However, you can get all the figures collected at the end by redefining \nextFigure to nothing, in which case the \clearFigures at the document's end takes care of it.

\documentclass{article}
\usepackage{lipsum}
\usepackage[demo]{graphicx}
\usepackage{boxhandler}
\holdFigures
\renewcommand\nextFigure[1][]{}% COMMENT THIS OUT TO PLACE FIGURES INLINE
\begin{document}
% DEFINE ALL FIGURES AT THE BEGINNING
\bxfigure{caption\label{fig:test1}}
{\includegraphics[width=1in]{file1}}

\bxfigure{caption\label{fig:test2}}
{\includegraphics[width=2in]{file2}}

\section{Lorem}
\lipsum[5]
\nextFigure[ht]

\section{Dolor}
\lipsum[5]
\nextFigure[ht]

\section{Final section}
\lipsum[5]

\clearFigures
\end{document}

The two outputs are the same as before, so I don't re-present them here.

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.