2

I'm interested in using the approach described in the following exchange:

Move figures around in a document with a simple command

In a nutshell, the idea is to store labeled figure and table environments in one file and position them in your master tex file by reference to their label, thus making it easier to move figures/tables around and making it easier to make repeated inclusions or to share figures across documents.

The code written by egreg and described above works well for figures and tables, but no longer works with the sidewaysfigure environment of the rotating package. Question 1: Can the code be adapted to accept a sidewaysfigure?

To make this question self-contained, I am going to copy egreg's code. I have modified the original code a little to customize it to my tastes.

I store the code in a .sty file and call it with \usepackage{floats}.

The original code expected the user to store the floats in a file named the same as the master file but with a .flo extension. I found I wanted several master documents to use/reuse the floats, so the main change I made to the original code was to allow the user to specify the name of the .tex file storing the floats. This is done with the command \loadfloats{figures}, where the floats are stored in figures.tex in the same directory as the master file.

Comments welcome, naturally. I have two more questions, which I may ask separately if they turn out to be involved.

Question 2 Can the code be adapted to allow lists? e.g. \loadfloats{figures,tables}, as one may want to organize floating environments by chapter and/or separate figures and tables

Question 3 Can the same approach can be ported to the beamer class and applied to frames?

There are 3 files named floats-template.tex (the master file), floats.sty (egreg's code renamed and packaged), and figures.tex (the floating environments). In addition, an image named placeholder with standard extensions is expected in the same directory as everything else.

floats-template.tex

    \documentclass{article}
    \usepackage{lipsum}% \lipsum prints random text
    \usepackage{floats}% provides the \includefloat and \loadfloat commands
    \loadfloat{figures}% stores labeled figure environments

    \usepackage{rotating}% provides \sidewaysfigure environment

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

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

    \section{Final section}
    \lipsum[5]
    \includefloat{fig:test3}

    \end{document}

floats.sty

    \NeedsTeXFormat{LaTeX2e}

    \ProvidesPackage{floats}[2014/12/12 custom LaTeX style]

    % https://tex.stackexchange.com/questions/118323/
    %move-figures-around-in-a-document-with-a-simple-command/

    \RequirePackage{environ}%

    \AtBeginDocument{%
      \begingroup
      \InputIfFileExists{\thefloats.tex}{\setupprefloats}{}%
      \endgroup
    }

    \makeatletter
      \newcommand{\loadfloat}[1]{%
        \newcommand{\thefloats}{#1}%
    }

    \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{\includefloat}[1]{%
    \expandafter\show\csname prefloat@#1\endcsname
      \@nameuse{prefloat@#1}%
    }
    \makeatother

    \endinput

figures.tex

    % A multi-paragraph \caption[short]{long} without a short caption option produces an error

    \begin{figure}[thbp]
      \centering%
      \includegraphics[width=\textwidth]{placeholder}%
      \caption[test]{\lipsum[2]}
      \label{fig:test1}
    \end{figure}

    \begin{figure}[thbp]
      \centering%
      \includegraphics[width=\textwidth]{placeholder}%
      \caption[test]{\lipsum[2]}
      \label{fig:test2}
    \end{figure}

    % OFFENDING PIECE OF CODE
    %\begin{sidewaysfigure}
    %  \includegraphics[width=\textwidth]{placeholder}%
    %  \caption[test]{\lipsum[2]}
    %  \label{fig:test3}
    %\end{sidewaysfigure}
  • 1
    I just added an answer to the referenced question. May or may not apply to your problem. – Steven B. Segletes Dec 10 '14 at 19:19
  • The date inside the \ProvidesPackage{floats} command is tomorrow's date, the 12/12 because I didn't know if I was expected to use the 12/11 or 11/12 style! :-) – PatrickT Dec 10 '14 at 19:20
  • @StevenB.Segletes, thanks, will look into it. To explain my purpose in different words: imagine I have a project resulting in 100 figures and 100 tables updated daily and I write several articles and beamer presentations based on different parts of the projects. I do not want to copy-paste figure/table code that could become outdated, but want to insert them on-the-fly by reference to their label. – PatrickT Dec 10 '14 at 19:28
  • 1
    I see. That's a bit more than boxhandler can do at the moment. However, it may provide a basis that can be modified. Since I wrote the package, I'll give it some thought. – Steven B. Segletes Dec 10 '14 at 19:33
  • 1
    I think that you would need a very different approach for beamer. frame environments do not float. Moreover, beamer does all kinds of special parsing and handling to deal with overlay specifications etc. Can you not use standalone in that case? – cfr Dec 10 '14 at 23:41
2

Like in the answer I referenced in my comment, I used my boxhandler package as a starting point, and modified it by creating the macros \storeFigure[label]{caption}{content} and \recallFigure[htbp]{label}.

With boxhandler, figures (and tables) are created with macros, not environments. The package provides flexible captioning options. Disclaimer: clearly, the store and recall options should not be used in conjunction with the package's \holdFigures option.

In my MWE, I define three figures in an external file beginning with a 1/2" wide figure with caption "side caption". Then I create a 1" wide figure with "caption1" followed by a 2" wide figure with "caption2". Then I recall the figures in the MWE in the order "caption2", "caption 1" "side caption", referencing them by their labels.

The MWE has been EDITED to allow the use of sidewaysfigure on the final figure.

\documentclass{article}
\usepackage{lipsum}
\usepackage[demo]{graphicx}
\usepackage{boxhandler, filecontents, rotating}

\begin{filecontents}{myfigures.tex}
% DEFINE ALL FIGURES AT THE BEGINNING
\storeFigure{fig:test3}{side caption}
{\includegraphics[width=0.5in]{testfig}}

\storeFigure{fig:test1}{caption1}
{\includegraphics[width=1in]{file1}}

\storeFigure{fig:test2}{caption2}
{\includegraphics[width=2in]{file2}}
\end{filecontents}

\makeatletter

\newcommand\storeFigure[3]{\@StoreFigure[#1]{#2}{#3}{\WrapperText}{\wrapper}}

\newcommand\@StoreFigure[5][]{%
  \addtocounter{FigureIndex}{1}%
  \setlength\DeadMargin\FigureDeadMargin%
  \def\FigureBoxLabel{fig\roman{FigureIndex}}%
  \def\FigureCaptionLabel{figcap\roman{FigureIndex}}%
  \def\FigCaptionWidthLabel{figcapwdth\roman{FigureIndex}}%
  \def\FigureWrapper{figwrap\roman{FigureIndex}}%
  \def\WrapperStatus{figwrapstatus\roman{FigureIndex}}%
  \expandafter\SaveCBox\csname\FigureBoxLabel\endcsname{#3}%
  \expandafter\def\csname\FigureCaptionLabel\endcsname{#2\label{#1}}%
  \expandafter\newlength\csname\FigCaptionWidthLabel\endcsname%
  \expandafter\setlength\csname\FigCaptionWidthLabel\endcsname%
                                              \CaptionBoxWidth%
  \expandafter\edef\csname\FigureWrapper\endcsname{#4}%
  \expandafter\edef\csname\WrapperStatus\endcsname{#5}%
%% After storing figure, reset wrapper to default value
  \global\def%
   \WrapperText{\noexpand\WrapperTextStyle\WrapperTextDefault}%
  \expandafter\def\csname FigureRefLabel\roman{FigureIndex}\endcsname{#1}%
}

\newcounter{loopfigindex}
\newcommand\recallFigure[2][ht]{%
  \setcounter{loopfigindex}{0}%
  \whiledo{\value{loopfigindex} < \value{FigureIndex}}{%
    \stepcounter{loopfigindex}%
    \ifthenelse{\equal{#2}{\csname FigureRefLabel\roman{loopfigindex}\endcsname}}{%
%%  \FigureBoxLabel:     : figi,    figii,    figiii,    figiv,    etc.
%%  \FigureCaptionLabel  : figcapi, figcapii, figcapiii, figcapiv, etc.
%%  \FigCaptionWidthLabel: figcapwdthi, figcapwdthii, figcapwdthiii,etc.
    \def\FigureBoxLabel{fig\roman{loopfigindex}}%
    \def\FigureCaptionLabel{figcap\roman{loopfigindex}}%
    \def\FigCaptionWidthLabel{figcapwdth\roman{loopfigindex}}%
    \def\FigureWrapper{figwrap\roman{loopfigindex}}%
    \def\WrapperStatus{figwrapstatus\roman{loopfigindex}}%
    \ReciteFigure[#1]{\csname\FigureCaptionLabel\endcsname}%
                     {\csname\FigureBoxLabel\endcsname}%
                     {\csname\FigCaptionWidthLabel\endcsname}%
                     {\csname\FigureWrapper\endcsname}%
                     {\csname\WrapperStatus\endcsname}%
  }{}}%
}

\newcommand\recallsidewaysFigure[2][ht]{%
  \setcounter{loopfigindex}{0}%
  \whiledo{\value{loopfigindex} < \value{FigureIndex}}{%
    \stepcounter{loopfigindex}%
    \ifthenelse{\equal{#2}{\csname FigureRefLabel\roman{loopfigindex}\endcsname}}{%
%%  \FigureBoxLabel:     : figi,    figii,    figiii,    figiv,    etc.
%%  \FigureCaptionLabel  : figcapi, figcapii, figcapiii, figcapiv, etc.
%%  \FigCaptionWidthLabel: figcapwdthi, figcapwdthii, figcapwdthiii,etc.
    \def\FigureBoxLabel{fig\roman{loopfigindex}}%
    \def\FigureCaptionLabel{figcap\roman{loopfigindex}}%
    \def\FigCaptionWidthLabel{figcapwdth\roman{loopfigindex}}%
    \def\FigureWrapper{figwrap\roman{loopfigindex}}%
    \def\WrapperStatus{figwrapstatus\roman{loopfigindex}}%
    \begin{sidewaysfigure}
    \centering
    \usebox{\csname\FigureBoxLabel\endcsname}
    \caption{\csname\FigureCaptionLabel\endcsname}
    \end{sidewaysfigure}
%    \ReciteFigure[#1]{\csname\FigureCaptionLabel\endcsname}%
%                     {\csname\FigureBoxLabel\endcsname}%
%                     {\csname\FigCaptionWidthLabel\endcsname}%
%                     {\csname\FigureWrapper\endcsname}%
%                     {\csname\WrapperStatus\endcsname}%
  }{}}%
}

\makeatother

\renewcommand\nextFigure[1][]{}% COMMENT THIS OUT TO PLACE FIGURES INLINE
\begin{document}
\input{myfigures.tex}

Figures were created in the order \ref{fig:test1} then \ref{fig:test2}.  That they
show up here as numbers means that the labeling worked.

\section{Lorem}
\lipsum[5]
\recallFigure[ht]{fig:test2}
\lipsum[3]

\section{Dolor}
\lipsum[1]
\recallFigure[ht]{fig:test1}

\section{Final section}
\lipsum[2]

\recallsidewaysFigure{fig:test3}

\lipsum[4-7]

\end{document}

enter image description here

enter image description here

enter image description here

enter image description here

| improve this answer | |
  • thanks for the answer. I'll need a bit of time to process it and test it, not least because I'm busy with other things today, but will get back to you asap, hopefully before the weekend. It looks very promising! – PatrickT Dec 11 '14 at 3:09
  • I have played around a little and this is very promising. I've had errors when trying to insert a sidewaysfigure environment (that was my OP, have you tested with a sidewaysfigure?) and/or with the siunitx package. Also it doesn't seem to take \lipsum[2] in the caption (which is not a problem). – PatrickT Dec 12 '14 at 21:02
  • 1
    I don't think boxhandler will work, as is, with sidewaysfigure. At least it was not taken into account during the package design. However, one might be able to fudge it, by designing a new command nearly identical with \recallFigure, but instead of it calling upon \ReciteFigure, one could reconstruct a sidewaysfigure from the variables like: the caption that is in \csname\FigureCaptionLabel\endcsname and the figure content that is in \usebox{\csname\FigureBoxLabel\endcsname}. – Steven B. Segletes Dec 12 '14 at 22:25
  • 1
    @PatrickT Please see edit, which implements a very simple use of sidewaysfigure into the mix. – Steven B. Segletes Dec 16 '14 at 19:21
  • 1
    @PatrickT I used boxhandler because it had a deferral capability. But that locked me into the tedious structure of that package. One might be able to do it simpler from scratch, by essentially saving each figure content & caption in unique macros identifiable by the given label. Then, use the label to reconstruct the unique macro names for the content and the caption, inserting them where needed. – Steven B. Segletes Dec 16 '14 at 20:44

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.